Skip to content

Commit 49cb7d9

Browse files
Saadnajmiclaude
andcommitted
feat: add macOS and visionOS support to SPM build system
- Add macOS and visionOS platforms to ios-prebuild CLI and type definitions - Build Hermes from source at the merge base with facebook/react-native when no prebuilt artifacts are available (main branch / 1000.0.0) - Fix host hermesc cmake build by setting CMAKE_OSX_DEPLOYMENT_TARGET to prevent -Werror=unguarded-availability-new failures in LLVM config checks - Map ReactNativeDependencies version to upstream RN via peerDependencies, with fallback to latest stable release for main branch - Conditionally include macOS-specific platform view sources in Package.swift using #if os(macOS) to avoid compiling macOS C++ on iOS/visionOS - Allow skipping ReactNativeDependencies download via SKIP_REACT_NATIVE_DEPENDENCIES env var for CI jobs that only build Hermes Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent a885ae6 commit 49cb7d9

File tree

6 files changed

+385
-15
lines changed

6 files changed

+385
-15
lines changed

packages/react-native/Package.swift

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ let reactJsErrorHandler = RNTarget(
246246
let reactGraphicsApple = RNTarget(
247247
name: .reactGraphicsApple,
248248
path: "ReactCommon/react/renderer/graphics/platform/ios",
249-
linkedFrameworks: ["UIKit", "CoreGraphics"],
249+
linkedFrameworks: ["CoreGraphics"],
250250
dependencies: [.reactDebug, .jsi, .reactUtils, .reactNativeDependencies]
251251
)
252252

@@ -360,12 +360,21 @@ let reactCore = RNTarget(
360360
"ReactCommon/react/runtime/platform/ios", // explicit header search path to break circular dependency. RCTHost imports `RCTDefines.h` in ReactCore, ReacCore needs to import RCTHost
361361
],
362362
linkedFrameworks: ["CoreServices"],
363-
excludedPaths: ["Fabric", "Tests", "Resources", "Runtime/RCTJscInstanceFactory.mm", "I18n/strings", "CxxBridge/JSCExecutorFactory.mm", "CoreModules"],
364-
dependencies: [.reactNativeDependencies, .reactCxxReact, .reactPerfLogger, .jsi, .reactJsiExecutor, .reactUtils, .reactFeatureFlags, .reactRuntimeScheduler, .yoga, .reactJsInspector, .reactJsiTooling, .rctDeprecation, .reactCoreRCTWebsocket, .reactRCTImage, .reactTurboModuleCore, .reactRCTText, .reactRCTBlob, .reactRCTAnimation, .reactRCTNetwork, .reactFabric, .hermesPrebuilt],
363+
excludedPaths: ["Fabric", "Tests", "Resources", "Runtime/RCTJscInstanceFactory.mm", "I18n/strings", "CxxBridge/JSCExecutorFactory.mm", "CoreModules", "RCTUIKit"],
364+
dependencies: [.reactNativeDependencies, .reactCxxReact, .reactPerfLogger, .jsi, .reactJsiExecutor, .reactUtils, .reactFeatureFlags, .reactRuntimeScheduler, .yoga, .reactJsInspector, .reactJsiTooling, .rctDeprecation, .reactCoreRCTWebsocket, .reactRCTImage, .reactTurboModuleCore, .reactRCTText, .reactRCTBlob, .reactRCTAnimation, .reactRCTNetwork, .reactFabric, .hermesPrebuilt, .reactRCTUIKit],
365365
sources: [".", "Runtime/RCTHermesInstanceFactory.mm"]
366366
)
367367

368368
/// React-Fabric.podspec
369+
// [macOS: conditionally include macOS-specific platform sources for view components
370+
#if os(macOS)
371+
let reactFabricViewPlatformSources = ["components/view/platform/macos"]
372+
let reactFabricViewPlatformExcludes = ["components/view/platform/cxx"]
373+
#else
374+
let reactFabricViewPlatformSources = ["components/view/platform/cxx"]
375+
let reactFabricViewPlatformExcludes = ["components/view/platform/macos"]
376+
#endif
377+
// macOS]
369378
let reactFabric = RNTarget(
370379
name: .reactFabric,
371380
path: "ReactCommon/react/renderer",
@@ -376,7 +385,6 @@ let reactFabric = RNTarget(
376385
"components/view/tests",
377386
"components/view/platform/android",
378387
"components/view/platform/windows",
379-
"components/view/platform/macos",
380388
"components/scrollview/tests",
381389
"components/scrollview/platform/android",
382390
"mounting/tests",
@@ -399,9 +407,9 @@ let reactFabric = RNTarget(
399407
"components/unimplementedview",
400408
"components/virtualview",
401409
"components/root/tests",
402-
],
410+
] + reactFabricViewPlatformExcludes, // [macOS]
403411
dependencies: [.reactNativeDependencies, .reactJsiExecutor, .rctTypesafety, .reactTurboModuleCore, .jsi, .logger, .reactDebug, .reactFeatureFlags, .reactUtils, .reactRuntimeScheduler, .reactCxxReact, .reactRendererDebug, .reactGraphics, .yoga],
404-
sources: ["animations", "attributedstring", "core", "componentregistry", "componentregistry/native", "components/root", "components/view", "components/view/platform/cxx", "components/scrollview", "components/scrollview/platform/cxx", "components/legacyviewmanagerinterop", "dom", "scheduler", "mounting", "observers/events", "telemetry", "consistency", "leakchecker", "uimanager", "uimanager/consistency"]
412+
sources: ["animations", "attributedstring", "core", "componentregistry", "componentregistry/native", "components/root", "components/view", "components/scrollview", "components/scrollview/platform/cxx", "components/legacyviewmanagerinterop", "dom", "scheduler", "mounting", "observers/events", "telemetry", "consistency", "leakchecker", "uimanager", "uimanager/consistency"] + reactFabricViewPlatformSources // [macOS]
405413
)
406414

407415
/// React-RCTFabric.podspec
@@ -420,16 +428,13 @@ let reactFabricComponents = RNTarget(
420428
"components/modal/platform/cxx",
421429
"components/view/platform/android",
422430
"components/view/platform/windows",
423-
"components/view/platform/macos",
424431
"components/textinput/platform/android",
425432
"components/text/platform/android",
426-
"components/textinput/platform/macos",
427433
"components/text/tests",
428434
"textlayoutmanager/tests",
429435
"textlayoutmanager/platform/android",
430436
"textlayoutmanager/platform/cxx",
431437
"textlayoutmanager/platform/windows",
432-
"textlayoutmanager/platform/macos",
433438
"conponents/rncore", // this was the old folder where RN Core Components were generated. If you ran codegen in the past, you might have some files in it that might make the build fail.
434439
],
435440
dependencies: [.reactNativeDependencies, .reactCore, .reactJsiExecutor, .reactTurboModuleCore, .jsi, .logger, .reactDebug, .reactFeatureFlags, .reactUtils, .reactRuntimeScheduler, .reactCxxReact, .yoga, .reactRendererDebug, .reactGraphics, .reactFabric, .reactTurboModuleBridging],
@@ -524,6 +529,16 @@ let reactSettings = RNTarget(
524529
dependencies: [.reactTurboModuleCore, .yoga]
525530
)
526531

532+
// [macOS
533+
/// React-RCTUIKit.podspec
534+
/// UIKit/AppKit compatibility layer for React Native macOS.
535+
let reactRCTUIKit = RNTarget(
536+
name: .reactRCTUIKit,
537+
path: "React/RCTUIKit",
538+
excludedPaths: ["README.md"]
539+
)
540+
// macOS]
541+
527542
// MARK: Target list
528543
let targets = [
529544
reactDebug,
@@ -581,13 +596,14 @@ let targets = [
581596
reactAppDelegate,
582597
reactSettings,
583598
reactRuntimeExecutor,
599+
reactRCTUIKit, // [macOS]
584600
]
585601

586602
// MARK: Package object
587603

588604
let package = Package(
589605
name: react,
590-
platforms: [.iOS(.v15), .macCatalyst(SupportedPlatform.MacCatalystVersion.v13)],
606+
platforms: [.iOS(.v15), .macOS(.v14), .macCatalyst(SupportedPlatform.MacCatalystVersion.v13)],
591607
products: [
592608
.library(
593609
name: react,
@@ -753,6 +769,7 @@ extension String {
753769
static let reactNativeModuleDom = "React-domnativemodule"
754770
static let reactAppDelegate = "React-RCTAppDelegate"
755771
static let reactSettings = "React-RCTSettings"
772+
static let reactRCTUIKit = "React-RCTUIKit" // [macOS]
756773
}
757774

758775
func relativeSearchPath(_ depth: Int, _ path: String) -> String {
@@ -792,6 +809,14 @@ extension Target {
792809
.define("USE_HERMES", to: "1"),
793810
] + defines + cxxCommonHeaderPaths
794811

812+
// [macOS] Platform-specific framework linking for targets that need UIKit (iOS/visionOS) vs AppKit (macOS)
813+
var conditionalLinkerSettings: [LinkerSetting] = linkerSettings
814+
if name == "React-graphics-Apple" || name == "React-RCTUIKit" {
815+
conditionalLinkerSettings.append(.linkedFramework("UIKit", .when(platforms: [.iOS, .visionOS])))
816+
conditionalLinkerSettings.append(.linkedFramework("AppKit", .when(platforms: [.macOS])))
817+
}
818+
// macOS]
819+
795820
return .target(
796821
name: name,
797822
dependencies: dependencies,
@@ -800,7 +825,7 @@ extension Target {
800825
sources: sources,
801826
publicHeadersPath: publicHeadersPath,
802827
cxxSettings: cxxSettings,
803-
linkerSettings: linkerSettings
828+
linkerSettings: conditionalLinkerSettings
804829
)
805830
}
806831
}

packages/react-native/scripts/ios-prebuild/cli.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,21 @@ import type {BuildFlavor, Destination, Platform} from './types';
1717
const platforms /*: $ReadOnlyArray<Platform> */ = [
1818
'ios',
1919
'ios-simulator',
20+
'macos', // [macOS]
2021
'mac-catalyst',
22+
'visionos', // [macOS]
23+
'visionos-simulator', // [macOS]
2124
];
2225

2326
// CI can't use commas in cache keys, so 'macOS,variant=Mac Catalyst' was creating troubles
2427
// This map that converts from platforms to valid Xcodebuild destinations.
2528
const platformToDestination /*: $ReadOnly<{|[Platform]: Destination|}> */ = {
2629
ios: 'iOS',
2730
'ios-simulator': 'iOS Simulator',
31+
macos: 'macOS', // [macOS]
2832
'mac-catalyst': 'macOS,variant=Mac Catalyst',
33+
visionos: 'xrOS', // [macOS]
34+
'visionos-simulator': 'xrOS Simulator', // [macOS]
2935
};
3036

3137
const cli = yargs

0 commit comments

Comments
 (0)