Skip to content

Commit 3167024

Browse files
chrfalchclaude
andcommitted
feat(spm): wire ReactNativeDependenciesHeaders as the 5th binaryTarget
ReactNativeHeaders is pure-RN after the deps-headers split: the third-party namespaces (folly/glog/boost/fmt/double-conversion/ fast_float/SocketRocket) ship in the ReactNativeDependenciesHeaders sidecar the deps prebuild emits (the binary deps xcframework is framework-type — invisible to SwiftPM binaryTargets). - download-spm-artifacts: headers-only companions are staged out of their parent tarball (ReactNativeHeaders from the ReactCore tarball, the sidecar from the deps tarball) on fresh extracts, with fast-path backfill — generalizing the hermes-headers pattern. This retires the --headers-tarball priming workaround for ReactNativeHeaders; the override remains for testing, joined by --deps-headers-tarball / RN_DEPS_HEADERS_TARBALL_PATH. Both companions register in artifacts.json fail-closed (pre-companion tarballs die with actionable advice). REQUIRED_ARTIFACTS now lists all five artifacts, fixing the inconsistency where generate-spm-package hard-required ReactNativeHeaders but cache validation never checked it. - generate-spm-package needs no code change: it renders one product + binaryTarget per artifacts.json entry. - Product consumers add the ReactNativeDependenciesHeaders product wherever deps namespaces must resolve: reactProductDeps() (autolinking), the codegen Package.swift template, and scaffolded community-library manifests (SCAFFOLDER_VERSION 17 -> 18 so existing scaffolds regenerate). Verified: fresh-app E2E (verdaccio -> cli init -> spm add -> build), rn-tester and helloworld in-place migrations, 350 spm jest tests. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 3c0248c commit 3167024

7 files changed

Lines changed: 270 additions & 26 deletions

File tree

packages/react-native/scripts/codegen/templates/Package.swift.spm-template

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,14 @@ import PackageDescription
1414

1515
// React headers need NO search paths: React/react namespaces come from the
1616
// React binaryTarget (auto -F; headers + module map inside the framework),
17-
// every other namespace from the ReactNativeHeaders binaryTarget, and the
18-
// per-app generated headers from the ReactAppHeaders target below — all
19-
// auto-served by SPM through product/target dependencies.
17+
// every other RN namespace from the ReactNativeHeaders binaryTarget
18+
// (pure-RN), the third-party deps namespaces (folly/glog/boost/...) from the
19+
// ReactNativeDependenciesHeaders sidecar, and the per-app generated headers
20+
// from the ReactAppHeaders target below — all auto-served by SPM through
21+
// product/target dependencies.
2022
let headersDep: [Target.Dependency] = [
2123
.product(name: "ReactNativeHeaders", package: "ReactNative"),
24+
.product(name: "ReactNativeDependenciesHeaders", package: "ReactNative"),
2225
"ReactAppHeaders",
2326
]
2427

packages/react-native/scripts/spm/__tests__/download-spm-artifacts-test.js

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -708,7 +708,9 @@ describe('validateArtifactsCache', () => {
708708
it('returns null when the cache is complete and on disk', () => {
709709
seedCache({
710710
React: true,
711+
ReactNativeHeaders: true,
711712
ReactNativeDependencies: true,
713+
ReactNativeDependenciesHeaders: true,
712714
'hermes-engine': true,
713715
});
714716
seedHermesHeaders();
@@ -718,7 +720,9 @@ describe('validateArtifactsCache', () => {
718720
it('reports unstaged Hermes public headers', () => {
719721
seedCache({
720722
React: true,
723+
ReactNativeHeaders: true,
721724
ReactNativeDependencies: true,
725+
ReactNativeDependenciesHeaders: true,
722726
'hermes-engine': true,
723727
});
724728
// No hermes-headers/hermes dir.
@@ -727,6 +731,21 @@ describe('validateArtifactsCache', () => {
727731
);
728732
});
729733

734+
it('reports a missing headers companion (pure-RN split)', () => {
735+
// ReactNativeDependenciesHeaders is the deps sidecar — without it no
736+
// <folly/...>-style include resolves (ReactNativeHeaders is pure-RN).
737+
seedCache({
738+
React: true,
739+
ReactNativeHeaders: true,
740+
ReactNativeDependencies: true,
741+
'hermes-engine': true,
742+
});
743+
seedHermesHeaders();
744+
expect(validateArtifactsCache(tempDir)).toMatch(
745+
/missing entry for "ReactNativeDependenciesHeaders"/,
746+
);
747+
});
748+
730749
it('reports a missing artifacts.json', () => {
731750
expect(validateArtifactsCache(tempDir)).toMatch(/artifacts.json missing/);
732751
});
@@ -737,7 +756,12 @@ describe('validateArtifactsCache', () => {
737756
});
738757

739758
it('reports a missing required entry', () => {
740-
seedCache({React: true, ReactNativeDependencies: true});
759+
seedCache({
760+
React: true,
761+
ReactNativeHeaders: true,
762+
ReactNativeDependencies: true,
763+
ReactNativeDependenciesHeaders: true,
764+
});
741765
expect(validateArtifactsCache(tempDir)).toMatch(
742766
/missing entry for "hermes-engine"/,
743767
);
@@ -746,7 +770,9 @@ describe('validateArtifactsCache', () => {
746770
it('reports an entry whose xcframework dir is gone', () => {
747771
seedCache({
748772
React: true,
773+
ReactNativeHeaders: true,
749774
ReactNativeDependencies: true,
775+
ReactNativeDependenciesHeaders: true,
750776
'hermes-engine': false,
751777
});
752778
expect(validateArtifactsCache(tempDir)).toMatch(

packages/react-native/scripts/spm/__tests__/generate-spm-package-test.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ describe('main', () => {
179179
'ReactNativeDependencies',
180180
'hermes-engine',
181181
'ReactNativeHeaders',
182+
'ReactNativeDependenciesHeaders',
182183
]);
183184
try {
184185
run(artifactsDir);
@@ -194,6 +195,15 @@ describe('main', () => {
194195
expect(fs.existsSync(pkgSwift)).toBe(true);
195196
const contents = fs.readFileSync(pkgSwift, 'utf8');
196197
expect(contents).toContain('.binaryTarget(name: "React"');
198+
// All five artifacts render as binary targets + products — the two
199+
// headers-only companions included.
200+
expect(contents).toContain('.binaryTarget(name: "ReactNativeHeaders"');
201+
expect(contents).toContain(
202+
'.binaryTarget(name: "ReactNativeDependenciesHeaders"',
203+
);
204+
expect(contents).toContain(
205+
'.library(name: "ReactNativeDependenciesHeaders"',
206+
);
197207
// The slot comment is derived from the artifacts dir's trailing path
198208
// segments (version/flavor), not the --version flag.
199209
expect(contents).toContain('Cache slot:');
@@ -217,6 +227,7 @@ describe('main', () => {
217227
const artifactsDir = writeArtifacts([
218228
'React',
219229
'ReactNativeDependencies',
230+
'ReactNativeDependenciesHeaders',
220231
'hermes-engine',
221232
]);
222233
try {

0 commit comments

Comments
 (0)