Skip to content

Commit c7eedc7

Browse files
SaadnajmiCopilot
andcommitted
build(bazel): link complete RNTester against source React
Model Package.swift's React product as the aggregate of all generated regular targets, add the missing DevTools runtime settings targets, and preserve required macOS frameworks. The default-off rn_from_source mode now builds and launches RNTester without embedding React.framework while retaining prebuilt Hermes and ReactNativeDependencies as bootstrap inputs. Complete application resources as part of the same end-to-end milestone: save Metro assets returned by runBuild, compile the macOS asset catalog and storyboard, and embed app icons, privacy manifest, and entitlements. Verified both source and prebuilt modes build; source mode launches offline with the real native-example bundle and tab icons. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 67e3ca3 commit c7eedc7

8 files changed

Lines changed: 226 additions & 13 deletions

File tree

docs/bazel.md

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,14 @@ prebuilt-XCFramework link. Specifically:
159159
and the RCTLinking/RCTPushNotification modules built from source (not in the prebuilt
160160
framework). Its embedded `main.jsbundle` contains the real native-example JS (no
161161
stubs), and no rn-tester source is modified or `#ifdef`'d out.
162+
* **React can be linked from source** with
163+
`bazel build //packages/rn-tester/RNTester-macOS:app --//:rn_from_source=true`.
164+
This mode builds the generated 58-target SwiftPM graph, links the resulting static
165+
libraries into RNTester (no `React.framework` in the app), and launches offline.
166+
Hermes and ReactNativeDependencies remain prebuilt bootstrap inputs.
167+
* **Resources are complete**: Metro copies its 45 image/XML assets (including all six
168+
bottom-nav icons), while rules_apple compiles the macOS asset catalog/storyboard and
169+
embeds `Assets.car`, `AppIcon.icns`, entitlements, and `PrivacyInfo.xcprivacy`.
162170

163171
### Consuming the prebuilt XCFrameworks from Bazel (the header problem)
164172

@@ -278,10 +286,11 @@ the repo's `enableScripts: false`), which is inert for Yarn and not published.
278286
`swift package dump-package`, normalizes the resolved macOS target metadata, and writes
279287
`packages/react-native/bazel/spm_targets.bzl`. `rn_spm_native_graph()` turns those 56
280288
targets into `spm_*` Bazel libraries without adding BUILD files throughout the React
281-
source tree. The graph now compiles through `spm_React_RCTAppDelegate` (including a
289+
source tree. The graph now compiles through the complete `spm_React` product (including a
282290
Bazel-generated `FBReactNativeSpec`) using a canonical header projection generated
283-
from source. `--//:rn_from_source=true` is an experimental, default-off app wiring
284-
while that source mode is validated end to end. Then output the same `.xcframework`s via
291+
from source. `--//:rn_from_source=true` builds and launches RNTester but remains
292+
default-off until Hermes and ReactNativeDependencies are available from a fresh checkout.
293+
Then output the same `.xcframework`s via
285294
`apple_static_xcframework`, swapped in behind the P3 alias + `--//:rn_from_source`:
286295

287296
* **FA — Hermes**: keep the prebuilt Hermes (`http_archive`) initially; optionally wrap

packages/react-native/BUILD.bazel

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -91,16 +91,19 @@ cc_library(
9191
objc_library(
9292
name = "rntester_extra_rn_modules",
9393
srcs = [
94-
"Libraries/LinkingIOS/RCTLinkingManager.mm",
95-
"Libraries/LinkingIOS/RCTLinkingPlugins.h",
9694
"Libraries/PushNotificationIOS/RCTPushNotificationManager.mm",
9795
"Libraries/PushNotificationIOS/RCTPushNotificationPlugins.h",
9896
"Libraries/PushNotificationIOS/RCTPushNotificationPlugins.mm",
99-
],
97+
] + select({
98+
"//:rn_from_source_enabled": [],
99+
"//conditions:default": [
100+
"Libraries/LinkingIOS/RCTLinkingManager.mm",
101+
"Libraries/LinkingIOS/RCTLinkingPlugins.h",
102+
],
103+
}),
100104
tags = ["manual"],
101105
visibility = ["//visibility:public"],
102106
deps = [
103-
":rct_linking_hdrs",
104107
":rct_pushnotification_hdrs",
105108
":rn_cxx_headers",
106109
"@rn_prebuilt_xcframeworks//:ReactNativeDependencies_headers",
@@ -110,6 +113,7 @@ objc_library(
110113
"@rn_source_headers//:headers",
111114
],
112115
"//conditions:default": [
116+
":rct_linking_hdrs",
113117
"@rn_prebuilt_xcframeworks//:React",
114118
"@rn_prebuilt_xcframeworks//:React_headers",
115119
],

packages/react-native/Package.swift

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,11 +277,23 @@ let reactTurboModuleCore = RNTarget(
277277
dependencies: [.reactNativeDependencies, .reactDebug, .reactFeatureFlags, .reactUtils, .reactPerfLogger, .reactCxxReact, .reactTurboModuleBridging, .yoga, .reactRuntimeExecutor]
278278
)
279279

280+
let reactDevToolsRuntimeSettings = RNTarget(
281+
name: .reactDevToolsRuntimeSettings,
282+
path: "ReactCommon/devtoolsruntimesettings",
283+
dependencies: [.jsi]
284+
)
285+
286+
let reactDevToolsRuntimeSettingsModule = RNTarget(
287+
name: .reactDevToolsRuntimeSettingsModule,
288+
path: "ReactCommon/react/nativemodule/devtoolsruntimesettings",
289+
dependencies: [.jsi, .reactDevToolsRuntimeSettings, .reactTurboModuleCore]
290+
)
291+
280292
/// React-defaultsnativemodule.podspec
281293
let reactTurboModuleCoreDefaults = RNTarget(
282294
name: .reactTurboModuleCoreDefaults,
283295
path: "ReactCommon/react/nativemodule/defaults",
284-
dependencies: [.reactNativeDependencies, .jsi, .reactJsiExecutor, .reactTurboModuleCore]
296+
dependencies: [.reactNativeDependencies, .jsi, .reactJsiExecutor, .reactTurboModuleCore, .reactDevToolsRuntimeSettingsModule]
285297
)
286298

287299
/// React-microtasknativemodule.podspec
@@ -603,6 +615,8 @@ let targets = [
603615
reactCoreModules,
604616
reactTurboModuleBridging,
605617
reactTurboModuleCore,
618+
reactDevToolsRuntimeSettings,
619+
reactDevToolsRuntimeSettingsModule,
606620
reactTurboModuleCoreDefaults,
607621
reactTurboModuleCoreMicrotasks,
608622
reactIdleCallbacksNativeModule,
@@ -779,6 +793,8 @@ extension String {
779793
static let reactCoreModules = "React-CoreModules"
780794
static let reactTurboModuleBridging = "ReactCommon/turbomodule/bridging"
781795
static let reactTurboModuleCore = "ReactCommon/turbomodule/core"
796+
static let reactDevToolsRuntimeSettings = "ReactCommon/devtoolsruntimesettings"
797+
static let reactDevToolsRuntimeSettingsModule = "ReactCommon/turbomodule/devtoolsruntimesettings"
782798
static let reactTurboModuleCoreDefaults = "ReactCommon/turbomodule/core/defaults"
783799
static let reactTurboModuleCoreMicrotasks = "ReactCommon/turbomodule/core/microtasks"
784800
static let reactIdleCallbacksNativeModule = "React-idlecallbacksnativemodule"

packages/react-native/bazel/spm_targets.bzl

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3924,6 +3924,51 @@ SPM_TARGETS = {
39243924
"CoreFoundation",
39253925
],
39263926
},
3927+
"ReactCommon/devtoolsruntimesettings": {
3928+
"bazel_name": "spm_ReactCommon_devtoolsruntimesettings",
3929+
"type": "regular",
3930+
"path": "ReactCommon/devtoolsruntimesettings",
3931+
"deps": [
3932+
"React-jsi",
3933+
],
3934+
"srcs": [
3935+
"ReactCommon/devtoolsruntimesettings/**/*.c",
3936+
"ReactCommon/devtoolsruntimesettings/**/*.cc",
3937+
"ReactCommon/devtoolsruntimesettings/**/*.cpp",
3938+
"ReactCommon/devtoolsruntimesettings/**/*.m",
3939+
"ReactCommon/devtoolsruntimesettings/**/*.mm",
3940+
],
3941+
"hdrs": [
3942+
"ReactCommon/devtoolsruntimesettings/**/*.def",
3943+
"ReactCommon/devtoolsruntimesettings/**/*.h",
3944+
"ReactCommon/devtoolsruntimesettings/**/*.hh",
3945+
"ReactCommon/devtoolsruntimesettings/**/*.hpp",
3946+
"ReactCommon/devtoolsruntimesettings/**/*.inc",
3947+
],
3948+
"excludes": [],
3949+
"copts": [
3950+
"-std=c++20",
3951+
],
3952+
"defines": [
3953+
"USE_HERMES=1",
3954+
],
3955+
"debug_defines": [
3956+
"DEBUG",
3957+
],
3958+
"release_defines": [
3959+
"NDEBUG",
3960+
],
3961+
"includes": [
3962+
".build/headers",
3963+
".build/headers/React",
3964+
"ReactCommon",
3965+
"ReactCommon/devtoolsruntimesettings",
3966+
"ReactCommon/jsi",
3967+
"third-party/ReactNativeDependencies.xcframework",
3968+
"third-party/ReactNativeDependencies.xcframework/Headers",
3969+
],
3970+
"sdk_frameworks": [],
3971+
},
39273972
"ReactCommon/turbomodule/bridging": {
39283973
"bazel_name": "spm_ReactCommon_turbomodule_bridging",
39293974
"type": "regular",
@@ -4073,6 +4118,7 @@ SPM_TARGETS = {
40734118
"React-jsi",
40744119
"React-jsiexecutor",
40754120
"ReactCommon/turbomodule/core",
4121+
"ReactCommon/turbomodule/devtoolsruntimesettings",
40764122
"ReactNativeDependencies",
40774123
],
40784124
"srcs": [
@@ -4110,6 +4156,7 @@ SPM_TARGETS = {
41104156
"ReactCommon",
41114157
"ReactCommon/callinvoker",
41124158
"ReactCommon/cxxreact",
4159+
"ReactCommon/devtoolsruntimesettings",
41134160
"ReactCommon/jsi",
41144161
"ReactCommon/jsiexecutor",
41154162
"ReactCommon/jsinspector-modern",
@@ -4123,6 +4170,7 @@ SPM_TARGETS = {
41234170
"ReactCommon/react/nativemodule/core",
41244171
"ReactCommon/react/nativemodule/core/platform/ios",
41254172
"ReactCommon/react/nativemodule/defaults",
4173+
"ReactCommon/react/nativemodule/devtoolsruntimesettings",
41264174
"ReactCommon/react/utils",
41274175
"ReactCommon/react/utils/platform/ios",
41284176
"ReactCommon/reactperflogger",
@@ -4205,6 +4253,74 @@ SPM_TARGETS = {
42054253
],
42064254
"sdk_frameworks": [],
42074255
},
4256+
"ReactCommon/turbomodule/devtoolsruntimesettings": {
4257+
"bazel_name": "spm_ReactCommon_turbomodule_devtoolsruntimesettings",
4258+
"type": "regular",
4259+
"path": "ReactCommon/react/nativemodule/devtoolsruntimesettings",
4260+
"deps": [
4261+
"React-jsi",
4262+
"ReactCommon/devtoolsruntimesettings",
4263+
"ReactCommon/turbomodule/core",
4264+
],
4265+
"srcs": [
4266+
"ReactCommon/react/nativemodule/devtoolsruntimesettings/**/*.c",
4267+
"ReactCommon/react/nativemodule/devtoolsruntimesettings/**/*.cc",
4268+
"ReactCommon/react/nativemodule/devtoolsruntimesettings/**/*.cpp",
4269+
"ReactCommon/react/nativemodule/devtoolsruntimesettings/**/*.m",
4270+
"ReactCommon/react/nativemodule/devtoolsruntimesettings/**/*.mm",
4271+
],
4272+
"hdrs": [
4273+
"ReactCommon/react/nativemodule/devtoolsruntimesettings/**/*.def",
4274+
"ReactCommon/react/nativemodule/devtoolsruntimesettings/**/*.h",
4275+
"ReactCommon/react/nativemodule/devtoolsruntimesettings/**/*.hh",
4276+
"ReactCommon/react/nativemodule/devtoolsruntimesettings/**/*.hpp",
4277+
"ReactCommon/react/nativemodule/devtoolsruntimesettings/**/*.inc",
4278+
],
4279+
"excludes": [],
4280+
"copts": [
4281+
"-std=c++20",
4282+
],
4283+
"defines": [
4284+
"USE_HERMES=1",
4285+
],
4286+
"debug_defines": [
4287+
"DEBUG",
4288+
],
4289+
"release_defines": [
4290+
"NDEBUG",
4291+
],
4292+
"includes": [
4293+
".build/headers",
4294+
".build/headers/React",
4295+
"Libraries/FBLazyVector",
4296+
"React/FBReactNativeSpec",
4297+
"ReactCommon",
4298+
"ReactCommon/callinvoker",
4299+
"ReactCommon/cxxreact",
4300+
"ReactCommon/devtoolsruntimesettings",
4301+
"ReactCommon/jsi",
4302+
"ReactCommon/jsinspector-modern",
4303+
"ReactCommon/jsinspector-modern/network",
4304+
"ReactCommon/jsinspector-modern/tracing",
4305+
"ReactCommon/logger",
4306+
"ReactCommon/oscompat",
4307+
"ReactCommon/react/bridging",
4308+
"ReactCommon/react/debug",
4309+
"ReactCommon/react/featureflags",
4310+
"ReactCommon/react/nativemodule/core",
4311+
"ReactCommon/react/nativemodule/core/platform/ios",
4312+
"ReactCommon/react/nativemodule/devtoolsruntimesettings",
4313+
"ReactCommon/react/utils",
4314+
"ReactCommon/react/utils/platform/ios",
4315+
"ReactCommon/reactperflogger",
4316+
"ReactCommon/runtimeexecutor",
4317+
"ReactCommon/runtimeexecutor/platform/ios",
4318+
"ReactCommon/yoga",
4319+
"third-party/ReactNativeDependencies.xcframework",
4320+
"third-party/ReactNativeDependencies.xcframework/Headers",
4321+
],
4322+
"sdk_frameworks": [],
4323+
},
42084324
"ReactNativeDependencies": {
42094325
"bazel_name": "spm_ReactNativeDependencies",
42104326
"type": "binary",

packages/rn-tester/BUILD.bazel

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,10 +127,16 @@ objc_library(
127127
# (mirrors how Buck2's apple prelude ingests a js_bundle as an AppleResource).
128128
macos_application(
129129
name = "RNTesterMacBazel",
130+
app_icons = ["//packages/rn-tester/RNTester-macOS:app_icons"],
130131
bundle_id = "org.reactjs.native.RNTesterMacBazel",
132+
entitlements = "//packages/rn-tester/RNTester-macOS:RNTester_macOS.entitlements",
131133
infoplists = ["bazel/Info.plist"],
132134
minimum_os_version = "14.0",
133-
resources = [":rntester_macos_jsbundle"],
135+
resources = [
136+
":rntester_macos_jsbundle",
137+
"PrivacyInfo.xcprivacy",
138+
"//packages/rn-tester/RNTester-macOS:native_resources",
139+
],
134140
tags = ["manual"],
135141
deps = [":rntester_macos_minimal_host"],
136142
)
@@ -164,7 +170,7 @@ objc_library(
164170
"@rn_prebuilt_xcframeworks//:hermes",
165171
] + select({
166172
"//:rn_from_source_enabled": [
167-
"//packages/react-native:spm_React_RCTAppDelegate",
173+
"//packages/react-native:spm_React",
168174
"@rn_source_headers//:headers",
169175
],
170176
"//conditions:default": [
@@ -176,10 +182,16 @@ objc_library(
176182

177183
macos_application(
178184
name = "RNTesterMacBazelFull",
185+
app_icons = ["//packages/rn-tester/RNTester-macOS:app_icons"],
179186
bundle_id = "org.reactjs.native.RNTesterMacBazelFull",
187+
entitlements = "//packages/rn-tester/RNTester-macOS:RNTester_macOS.entitlements",
180188
infoplists = ["bazel/Info.plist"],
181189
minimum_os_version = "14.0",
182-
resources = [":rntester_macos_jsbundle"],
190+
resources = [
191+
":rntester_macos_jsbundle",
192+
"PrivacyInfo.xcprivacy",
193+
"//packages/rn-tester/RNTester-macOS:native_resources",
194+
],
183195
tags = ["manual"],
184196
visibility = ["//packages/rn-tester/RNTester-macOS:__pkg__"],
185197
deps = [":rntester_macos_full_host"],

packages/rn-tester/RNTester-macOS/BUILD.bazel

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,18 @@
22

33
package(default_visibility = ["//visibility:public"])
44

5+
filegroup(
6+
name = "app_icons",
7+
srcs = glob(["Assets.xcassets/**"]),
8+
)
9+
10+
filegroup(
11+
name = "native_resources",
12+
srcs = ["Base.lproj/Main.storyboard"],
13+
)
14+
15+
exports_files(["RNTester_macOS.entitlements"])
16+
517
alias(
618
name = "app",
719
actual = "//packages/rn-tester:RNTesterMacBazelFull",

packages/rn-tester/bazel/bundle.js

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,25 @@ function resolveAssetFiles(filePath) {
216216
.map(name => path.join(dir, name));
217217
return filePaths.length ? {type: 'assetFiles', filePaths} : null;
218218
}
219+
220+
function saveAssets(assets, assetsDest) {
221+
for (const asset of assets) {
222+
asset.scales.forEach((scale, index) => {
223+
const suffix = scale === 1 ? '' : `@${scale}x`;
224+
const relativeDir = asset.httpServerLocation
225+
.slice(1)
226+
.replace(/\.\.\//g, '_');
227+
const destination = path.join(
228+
assetsDest,
229+
relativeDir,
230+
`${asset.name}${suffix}.${asset.type}`,
231+
);
232+
fs.mkdirSync(path.dirname(destination), {recursive: true});
233+
fs.copyFileSync(asset.files[index], destination);
234+
});
235+
}
236+
}
237+
219238
const originalGetOrComputeSha1 = DependencyGraph.prototype.getOrComputeSha1;
220239
DependencyGraph.prototype.getOrComputeSha1 = async function (filename) {
221240
try {
@@ -277,7 +296,7 @@ async function main() {
277296
// Use `bundleOut` (verbatim) rather than `out`; Metro's runBuild rewrites
278297
// `out` through `.replace(/(\.js)?$/, '.js')`, which would turn our declared
279298
// Bazel output `RNTesterApp.macos.jsbundle` into `...jsbundle.js`.
280-
await Metro.runBuild(config, {
299+
const result = await Metro.runBuild(config, {
281300
entry: entryFile,
282301
platform: 'macos',
283302
dev: false,
@@ -286,6 +305,12 @@ async function main() {
286305
assets: Boolean(assetsDest),
287306
assetsDest,
288307
});
308+
if (assetsDest != null) {
309+
if (result.assets == null) {
310+
throw new Error("Assets missing from Metro's runBuild result");
311+
}
312+
saveAssets(result.assets, assetsDest);
313+
}
289314
}
290315

291316
main().catch(err => {

0 commit comments

Comments
 (0)