diff --git a/NativeScript/CMakeLists.txt b/NativeScript/CMakeLists.txt index de245ba..e462fba 100644 --- a/NativeScript/CMakeLists.txt +++ b/NativeScript/CMakeLists.txt @@ -21,6 +21,14 @@ set(TARGET_ENGINE "v8" CACHE STRING "Target JS engine for the NativeScript runti set(METADATA_SIZE 0 CACHE STRING "Size of embedded metadata in bytes") set(BUILD_CLI_BINARY OFF CACHE BOOL "Build the NativeScript CLI binary") +if(CMAKE_OSX_SYSROOT STREQUAL "iphoneos") + set(TARGET_PLATFORM "ios") +elseif(CMAKE_OSX_SYSROOT STREQUAL "iphonesimulator") + set(TARGET_PLATFORM "ios-sim") +elseif(CMAKE_OSX_SYSROOT STREQUAL "macosx") + set(TARGET_PLATFORM "macos") +endif() + if(TARGET_PLATFORM STREQUAL "ios") set(CMAKE_XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET "13.0") set(CMAKE_XCODE_ATTRIBUTE_TARGETED_DEVICE_FAMILY "1,2") @@ -305,16 +313,16 @@ if(TARGET_PLATFORM_MACOS) # Convert the Info.plist from binary format to XML format. # This seemed to unblock a build error when using in React Native. - add_custom_command(TARGET ${NAME} POST_BUILD - COMMAND plutil -convert xml1 $/Resources/Info.plist - ) + # add_custom_command(TARGET ${NAME} POST_BUILD + # COMMAND plutil -convert xml1 $/Resources/Info.plist + # ) set(METADATA_FILE "metadata.macos.nsmd") elseif(TARGET_PLATFORM_IOS) # Convert the Info.plist from binary format to XML format. # This seemed to unblock a build error when using in React Native. - add_custom_command(TARGET ${NAME} POST_BUILD - COMMAND plutil -convert xml1 $/Info.plist - ) + # add_custom_command(TARGET ${NAME} POST_BUILD + # COMMAND plutil -convert xml1 $/Info.plist + # ) if(TARGET_PLATFORM_SIM) set(METADATA_FILE "metadata.ios-sim.nsmd") diff --git a/build_nativescript.sh b/build_nativescript.sh index c9e58ec..5de6bd3 100755 --- a/build_nativescript.sh +++ b/build_nativescript.sh @@ -79,6 +79,8 @@ function cmake_build () { cmake --build $DIST/intermediates/$platform --config $CONFIG_BUILD } +TRIPLETS=() + if $BUILD_CATALYST; then checkpoint "Building NativeScript for Mac Catalyst" @@ -86,36 +88,51 @@ checkpoint "Building NativeScript for Mac Catalyst" fi -if $BUILD_SIMULATOR; then -checkpoint "Building NativeScript for iPhone (simulator)" +if [[ $BUILD_SIMULATOR && "$TARGET_ENGINE" == "none" ]]; then + # TODO: Add x86_64-apple-ios-sim once supported + TRIPLETS+=("arm64-apple-ios-sim") +elif $BUILD_SIMULATOR; then + checkpoint "Building NativeScript for iPhone (simulator)" -cmake_build ios-sim x86_64 arm64 + cmake_build ios-sim x86_64 arm64 fi -if $BUILD_IPHONE; then -checkpoint "Building NativeScript for iPhone (physical)" +if [[ $BUILD_IPHONE && "$TARGET_ENGINE" == "none" ]]; then + TRIPLETS+=("arm64-apple-ios") + +elif $BUILD_IPHONE; then + checkpoint "Building NativeScript for iPhone (physical)" -cmake_build ios arm64 + cmake_build ios arm64 fi -if $BUILD_MACOS; then -checkpoint "Building NativeScript for macOS" +if [[ $BUILD_MACOS && "$TARGET_ENGINE" == "none" ]]; then + TRIPLETS+=("arm64;x86_64-apple-darwin") -cmake_build macos x86_64 arm64 +elif $BUILD_MACOS; then + checkpoint "Building NativeScript for macOS" + cmake_build macos x86_64 arm64 fi -if $BUILD_VISION; then +if [[ $BUILD_VISION && "$TARGET_ENGINE" == "none" ]]; then + # TRIPLETS+=("arm64-apple-visionos") + # TODO: Add x86_64-apple-visionos-sim once supported + # TRIPLETS+=("x86_64-apple-visionos-sim") + # TRIPLETS+=("arm64-apple-visionos-sim") + echo "Skipping visionOS prebuilds for React Native Node-API as they are not yet supported." + +elif $BUILD_VISION; then -checkpoint "Building NativeScript for visionOS (physical)" + checkpoint "Building NativeScript for visionOS (physical)" -# cmake_build visionos arm64 + # cmake_build visionos arm64 -checkpoint "Building NativeScript for visionOS (simulator)" + checkpoint "Building NativeScript for visionOS (simulator)" -# cmake_build visionos-sim x86_64 arm64 + # cmake_build visionos-sim x86_64 arm64 fi @@ -151,22 +168,26 @@ if $BUILD_VISION; then -debug-symbols "$DIST/intermediates/visionos-sim/$CONFIG_BUILD-xros/NativeScript.framework.dSYM" ) fi -if [[ -n "${XCFRAMEWORKS[@]}" ]]; then - if [[ "$TARGET_ENGINE" == "none" ]]; then - checkpoint "Creating the XCFramework for iOS (NativeScript.apple.node)" - - # We adhere to the prebuilds standard as described here: - # https://github.com/callstackincubator/react-native-node-api/blob/9b231c14459b62d7df33360f930a00343d8c46e6/docs/PREBUILDS.md - OUTPUT_DIR="packages/ios/build/$CONFIG_BUILD/NativeScript.apple.node" - rm -rf $OUTPUT_DIR - deno run -A ./scripts/build_xcframework.mts --output "$OUTPUT_DIR" ${XCFRAMEWORKS[@]} - else - checkpoint "Creating NativeScript.xcframework" - - OUTPUT_DIR="$DIST/NativeScript.xcframework" - rm -rf $OUTPUT_DIR - xcodebuild -create-xcframework ${XCFRAMEWORKS[@]} -output "$OUTPUT_DIR" - fi +if [[ -n "${XCFRAMEWORKS[@]}" && "$TARGET_ENGINE" != "none" ]]; then + checkpoint "Creating NativeScript.xcframework" + + OUTPUT_DIR="$DIST/NativeScript.xcframework" + rm -rf $OUTPUT_DIR + xcodebuild -create-xcframework ${XCFRAMEWORKS[@]} -output "$OUTPUT_DIR" +fi + +if [[ -n "${TRIPLETS[@]}" && "$TARGET_ENGINE" == "none" ]]; then + checkpoint "Building NativeScript prebuilt for React Native Node-API (NativeScript.apple.node)" + + TRIPLET_ARGS=() + for triplet in "${TRIPLETS[@]}"; do + TRIPLET_ARGS+=(--triplet "$triplet") + done + + # We adhere to the prebuilds standard as described here: + # https://github.com/callstackincubator/react-native-node-api/blob/9b231c14459b62d7df33360f930a00343d8c46e6/docs/PREBUILDS.md + OUTPUT_DIR="packages/ios/build/$CONFIG_BUILD" + cmake-rn --source ./NativeScript --build "$DIST/intermediates" --out "$OUTPUT_DIR" -D TARGET_ENGINE=$TARGET_ENGINE "${TRIPLET_ARGS[@]}" fi # We're currently distributing two separate packages: @@ -174,22 +195,19 @@ fi # 2. AppKit-based (@nativescript/macos-node-api) # As such, there's no point bundling both UIKit-based and AppKit-based into a # single XCFramework. -if $BUILD_MACOS; then +if [[ $BUILD_MACOS && "$TARGET_ENGINE" == "none" ]]; then + checkpoint "Creating the XCFramework for macOS (NativeScript.apple.node)" + + OUTPUT_DIR="packages/macos/build/$CONFIG_BUILD" + cmake-rn --source ./NativeScript --build "$DIST/intermediates" --out "$OUTPUT_DIR" -D TARGET_ENGINE=$TARGET_ENGINE --triplet 'arm64;x86_64-apple-darwin' + +elif $BUILD_MACOS; then XCFRAMEWORKS=( -framework "$DIST/intermediates/macos/$CONFIG_BUILD/NativeScript.framework" -debug-symbols "$DIST/intermediates/macos/$CONFIG_BUILD/NativeScript.framework.dSYM" ) - if [[ "$TARGET_ENGINE" == "none" ]]; then - checkpoint "Creating the XCFramework for macOS (NativeScript.apple.node)" - - # We adhere to the prebuilds standard as described here: - # https://github.com/callstackincubator/react-native-node-api/blob/9b231c14459b62d7df33360f930a00343d8c46e6/docs/PREBUILDS.md - OUTPUT_DIR="packages/macos/build/$CONFIG_BUILD/NativeScript.apple.node" - rm -rf $OUTPUT_DIR - deno run -A ./scripts/build_xcframework.mts --output "$OUTPUT_DIR" ${XCFRAMEWORKS[@]} - else - checkpoint "Creating NativeScript.node for macOS" - cp -r "$DIST/intermediates/macos/$CONFIG_BUILD/libNativeScript.dylib" "$DIST/NativeScript.node" - fi + + checkpoint "Creating NativeScript.node for macOS" + cp -r "$DIST/intermediates/macos/$CONFIG_BUILD/libNativeScript.dylib" "$DIST/NativeScript.node" fi if $BUILD_MACOS_CLI; then diff --git a/package.json b/package.json index 7b29a12..c449ece 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ }, "license": "Apache-2.0", "devDependencies": { + "cmake-rn": "^0.5.1", "conventional-changelog-cli": "^2.1.1", "dayjs": "^1.11.7", "husky": "^9.0.11", diff --git a/scripts/build_xcframework.mts b/scripts/build_xcframework.mts deleted file mode 100644 index 120ba4d..0000000 --- a/scripts/build_xcframework.mts +++ /dev/null @@ -1,124 +0,0 @@ -import path from "node:path"; -import process from "node:process"; -import yargsParser from "yargs-parser"; -import { createXCframework } from "react-native-node-api"; - -main(); - -/** - * Builds an XCFramework in the style that `react-native-node-api` expects, - * following the [prebuilds standard](https://github.com/callstackincubator/react-native-node-api/blob/9b231c14459b62d7df33360f930a00343d8c46e6/docs/PREBUILDS.md). - * - * This is really just an XCFramework renamed with a `.node` extension, - * containing an extra file named `react-native-api-module`. Once `cmake-rn` - * supports it, we may be able to replace this whole script with a simple - * `cmake-rn` call. - */ -async function main() { - const __dirname = import.meta.dirname; - if (!__dirname) { - throw new Error("Expected import.meta.dirname to be truthy."); - } - - const monorepoRoot = path.resolve(__dirname, ".."); - - // Args are designed to match the names of the args from cmake we're - // interested in. - const args = yargsParser(process.argv.slice(2), { - configuration: { - "short-option-groups": false, - }, - string: ["output", "framework", "debug-symbols"], - array: ["framework", "debug-symbols"], - boolean: ["help"], - alias: { - h: "help", - }, - default: { - help: false, - }, - }); - - const { - output, - framework: frameworks = new Array(), - "debug-symbols": debugSymbols = new Array(), - help, - } = args; - - const helpText = ` -Typical usage: - -$ deno run -A ./scripts/build_xcframework.mts --output packages/ios/build/Release/NativeScript.apple.node -framework dist/intermediates/ios/RelWithDebInfo-iphoneos/NativeScript.framework -debug-symbols dist/intermediates/ios/RelWithDebInfo-iphoneos/NativeScript.framework.dSYM - -$ deno run -A ./scripts/build_xcframework.mts --output packages/macos/build/Release/NativeScript.apple.node -framework dist/intermediates/macos/RelWithDebInfo/NativeScript.framework -debug-symbols dist/intermediates/macos/RelWithDebInfo/NativeScript.framework.dSYM -`.trim(); - - if (help) { - console.log(helpText); - process.exit(0); - } - - if (!output) { - console.log( - `Please specify the output directory by passing the \`--output\` arg.\n\n${helpText}` - ); - process.exit(1); - } - - if (!isStringArray(frameworks) || !isStringArray(debugSymbols)) { - console.log( - `Expected -framework and -debug-symbols to be parsed as arrays.\n\n${helpText}` - ); - process.exit(1); - } - - if (!frameworks?.length) { - console.log( - `Please specify at least one framework to bundle into the xcframework by passing the \`-framework\` arg one or more times.\n\n${helpText}` - ); - process.exit(1); - } - - const outputPath = path.resolve(monorepoRoot, output); - const frameworkPaths = frameworks.map((framework) => - path.resolve(monorepoRoot, framework) - ); - // TODO: Pass this to the createXCFramework() options, once supported. - const _dsymPaths = - debugSymbols?.map((dsym) => path.resolve(monorepoRoot, dsym)) ?? []; - - try { - await createXCframework({ - outputPath, - frameworkPaths, - // dsymPaths, - autoLink: true, - }); - } catch (error) { - const errorMessage = error instanceof Error ? error.message : ""; - console.error(`Failed to assemble XCFramework: ${errorMessage}`, error); - process.exit(1); - } - - console.log( - `\x1b[32m✔\x1b[0m XCFramework assembled into \x1b[2m${path.relative( - monorepoRoot, - outputPath - )}\x1b[22m` - ); -} - -function isStringArray(value: unknown): value is Array { - if (!Array.isArray(value)) { - return false; - } - - for (const element of value) { - if (typeof element !== "string") { - return false; - } - } - - return true; -}