Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 30 additions & 20 deletions NativeScript/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
cmake_minimum_required(VERSION 3.15)

# Metadata

project(NativeScript CXX OBJCXX)

set(NAME NativeScript)
Expand All @@ -17,7 +16,6 @@ set(COMMON_FLAGS "-O3 -Wno-shorten-64-to-32")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COMMON_FLAGS}")

# Arguments

set(TARGET_PLATFORM "macos" CACHE STRING "Target platform for the Objective-C bridge")
set(TARGET_ENGINE "v8" CACHE STRING "Target JS engine for the NativeScript runtime")
set(METADATA_SIZE 0 CACHE STRING "Size of embedded metadata in bytes")
Expand Down Expand Up @@ -56,6 +54,10 @@ elseif(TARGET_PLATFORM STREQUAL "macos")
set(TARGET_PLATFORM_SPEC "macos-arm64_x86_64")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DTARGET_PLATFORM_MACOS")

# Unlike "ios", "macos" doesn't seem to produce a NativeScript.framework.dSYM
# by default. We can produce it by setting these variables.
set(CMAKE_XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT "dwarf-with-dsym")
set(CMAKE_XCODE_ATTRIBUTE_DWARF_DSYM_FOLDER_PATH "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>")
else()
message(FATAL_ERROR "Unknown target platform: ${TARGET_PLATFORM}")
return()
Expand Down Expand Up @@ -87,18 +89,16 @@ endif()
if(ENABLE_JS_RUNTIME)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DENABLE_JS_RUNTIME")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DENABLE_JS_RUNTIME")
elseif(TARGET_PLATFORM_MACOS)
# If building a generic library for macOS, we'll build a dylib instead of a framework
unset(BUILD_FRAMEWORK)
else()
Comment on lines -90 to +92
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ℹ️ Now we do want to build a .framework instead of a .dylib.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With no other condition unsetting BUILD_FRAMEWORK, we would always produce a framework instead of dylib, is that right? How does it affect distribution of the macOS .node binary build? As of now, we produce a .dylib for macOS, and simply rename it to NativeScript.node.

set(GENERIC_NAPI TRUE)
endif()

message(STATUS "TARGET_PLATFORM = ${TARGET_PLATFORM}")
message(STATUS "TARGET_ENGINE = ${TARGET_ENGINE}")
message(STATUS "ENABLE_JS_RUNTIME = ${ENABLE_JS_RUNTIME}")
message(STATUS "GENERIC_NAPI = ${GENERIC_NAPI}")

# Set up sources

include_directories(
./
../metadata-generator/include
Expand Down Expand Up @@ -201,12 +201,14 @@ if(ENABLE_JS_RUNTIME)
)

set(SOURCE_FILES ${SOURCE_FILES}

# quickjs
napi/quickjs/source/cutils.c
napi/quickjs/source/libregexp.c
napi/quickjs/source/libbf.c
napi/quickjs/source/libunicode.c
napi/quickjs/source/quickjs.c

# napi
napi/quickjs/quickjs-api.c
napi/quickjs/jsr.cpp
Expand All @@ -223,7 +225,6 @@ if(ENABLE_JS_RUNTIME)
napi/jsc/jsc-api.cpp
napi/jsc/jsr.cpp
)

endif()
else()
include_directories(
Expand All @@ -239,7 +240,6 @@ if(BUILD_CLI_BINARY)
endif()

# Find SDK

find_program(XCODEBUILD_EXECUTABLE xcodebuild)

if(METADATA_SIZE EQUAL 0)
Expand All @@ -265,7 +265,6 @@ set(CMAKE_OSX_SYSROOT "${CMAKE_OSX_SYSROOT_INT}" CACHE INTERNAL "")
message(STATUS "SDK = ${CMAKE_OSX_SYSROOT}")

# Build targets

if(BUILD_CLI_BINARY)
add_executable(${NAME} ${SOURCE_FILES})
else()
Expand Down Expand Up @@ -301,11 +300,22 @@ endif()

if(TARGET_PLATFORM_MACOS)
# add_custom_command(TARGET ${NAME} POST_BUILD
# COMMAND /usr/libexec/PlistBuddy -c "Add :LSMinimumSystemVersion string ${CMAKE_OSX_DEPLOYMENT_TARGET}" $<TARGET_FILE_DIR:${NAME}>/Resources/Info.plist
# COMMAND /usr/libexec/PlistBuddy -c "Add :LSMinimumSystemVersion string ${CMAKE_OSX_DEPLOYMENT_TARGET}" $<TARGET_FILE_DIR:${NAME}>/Resources/Info.plist
# )

# 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 $<TARGET_FILE_DIR:${NAME}>/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 $<TARGET_FILE_DIR:${NAME}>/Info.plist
)

if(TARGET_PLATFORM_SIM)
set(METADATA_FILE "metadata.ios-sim.nsmd")
else()
Expand Down Expand Up @@ -362,7 +372,7 @@ if(TARGET_ENGINE_JSC)
endif()

if(TARGET_ENGINE_V8)
if (TARGET_PLATFORM_MACOS)
if(TARGET_PLATFORM_MACOS)
target_link_directories(
${NAME}
PRIVATE
Expand Down Expand Up @@ -414,12 +424,12 @@ if(TARGET_ENGINE_QUICKJS)
)
endif()

# if (GENERIC_NAPI)
target_link_options(
${NAME}
PRIVATE
"-Wl"
"-undefined"
"dynamic_lookup"
)
# endif()
if(GENERIC_NAPI)
target_link_options(
${NAME}
PRIVATE
"-Wl"
"-undefined"
"dynamic_lookup"
)
endif()
Comment on lines -417 to +435
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ℹ️ As we're prebuilding this binary on its own and bringing the Node-API implementation separately later, we need to restore GENERIC_NAPI.

This may have consequences for the Node-API distribution of @nativescript/ios. If so, please adjust it as needed so that it works for both targets.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is the right change to make as not all builds would require this flag anymore. Since making it backwards compatible, we don't make separate NS FFI and runtime frameworks - its all in one binary and linking should work fine unless building for platforms that dynamically load NativeScript later (GENERIC_NAPI: Node.js and co, React Native). Would be good to test a build against V8 once to make sure it compiles.

62 changes: 58 additions & 4 deletions build_all_ios.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,29 @@
#!/bin/bash
set -e
source "$(dirname "$0")/build_utils.sh"

TARGET_ENGINE=${TARGET_ENGINE:=some}
BUILD_IPHONE=$(to_bool ${BUILD_IPHONE:=true})
BUILD_SIMULATOR=$(to_bool ${BUILD_SIMULATOR:=true})
BUILD_MACOS=$(to_bool ${BUILD_MACOS:=false})
EMBED_METADATA=$(to_bool ${EMBED_METADATA:=false})

# See build_nativescript.sh for all supported flags. This parent script is only
# interested in intercepting a subset of them.
for arg in $@; do
case $arg in
--v8|--quickjs|--jsc|--hermes) TARGET_ENGINE=some ;;
--sim|--simulator) BUILD_SIMULATOR=true ;;
--no-sim|--no-simulator) BUILD_SIMULATOR=false ;;
--iphone|--device) BUILD_IPHONE=true ;;
--no-iphone|--no-device) BUILD_IPHONE=false ;;
--macos) BUILD_MACOS=true ;;
--no-macos) BUILD_MACOS=false ;;
--no-engine) TARGET_ENGINE=none ;;
--embed-metadata) EMBED_METADATA=true ;;
*) ;;
esac
done

rm -rf ./dist
# don't run if NO_UPDATE_VERSION is set
Expand All @@ -8,7 +32,37 @@ rm -rf ./dist
# ./update_version.sh
# fi
./build_metadata_generator.sh
./build_nativescript.sh --no-vision $1 $2
./build_tklivesync.sh --no-vision
./prepare_dSYMs.sh
./build_npm_ios.sh

if $EMBED_METADATA; then
checkpoint "Generating metadata, as --embed-metadata was passed..."

if $BUILD_IPHONE; then
checkpoint "Generating metadata for iOS (physical device)..."
npm run metagen ios
fi
if $BUILD_SIMULATOR; then
checkpoint "Generating metadata for iOS (simulator)..."
npm run metagen ios-sim
fi
if $BUILD_MACOS; then
checkpoint "Generating metadata for macOS..."
npm run metagen macos
fi

checkpoint "... All metadata generated!"
fi

./build_nativescript.sh --no-vision $1 $2 $3 $4 $5 $6 $7 $8 $9

if [[ "$TARGET_ENGINE" == "none" ]]; then
# If you're building *with* --no-engine, you're trying to make an npm release
# of a workspace under ./packages/*, like @nativescript/ios-node-api.
echo "Skipping build_npm_ios.sh due to --no-engine flag."
echo "build_all_ios.sh finished!"
else
# If you're building *without* --no-engine, you're trying to make an npm
# release of the root-level workspace, @nativescript/ios.
./build_tklivesync.sh --no-vision
./prepare_dSYMs.sh
./build_npm_ios.sh
fi
3 changes: 3 additions & 0 deletions build_all_react_native.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/bash

./build_all_ios.sh --no-engine --embed-metadata --macos
96 changes: 49 additions & 47 deletions build_nativescript.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,6 @@
set -e
source "$(dirname "$0")/build_utils.sh"

function to_bool() {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ℹ️ This now comes from build_utils.sh.

local arg="$1"
case "$(echo "$arg" | tr '[:upper:]' '[:lower:]')" in
[0-9]+)
if [ $arg -eq 0 ]; then
echo false
else
echo true
fi
;;
n|no|f|false) echo false ;;
y|yes|t|true) echo true ;;
* )
if [ -n "$arg" ]; then
echo "warning: invalid boolean argument ('$arg'). Expected true or false" >&2
fi
echo false
;;
esac;
}

BUILD_CATALYST=$(to_bool ${BUILD_CATALYST:=false}) # disable by default for now
BUILD_IPHONE=$(to_bool ${BUILD_IPHONE:=true})
BUILD_SIMULATOR=$(to_bool ${BUILD_SIMULATOR:=true})
Expand Down Expand Up @@ -74,6 +53,8 @@ mkdir -p $DIST/intermediates

function cmake_build () {
local platform="$1"
shift
local archs=("$@")
local is_macos_cli=false

if [ "$platform" == "macos-cli" ]; then
Expand All @@ -85,7 +66,7 @@ function cmake_build () {

if $EMBED_METADATA || $is_macos_cli; then

for arch in x86_64 arm64; do
for arch in "${archs[@]}"; do

METADATA_SIZE=$(($METADATA_SIZE > $(stat -f%z "./metadata-generator/metadata/metadata.$platform.$arch.nsmd") ? $METADATA_SIZE : $(stat -f%z "./metadata-generator/metadata/metadata.$platform.$arch.nsmd")))

Expand All @@ -101,50 +82,48 @@ function cmake_build () {
if $BUILD_CATALYST; then
checkpoint "Building NativeScript for Mac Catalyst"

# cmake_build catalyst
# cmake_build catalyst x86_64 arm64

fi

if $BUILD_SIMULATOR; then
checkpoint "Building NativeScript for iphone simulators (multi-arch)"
checkpoint "Building NativeScript for iPhone (simulator)"

cmake_build ios-sim
cmake_build ios-sim x86_64 arm64

fi

if $BUILD_IPHONE; then
checkpoint "Building NativeScript for ARM64 device"
checkpoint "Building NativeScript for iPhone (physical)"

cmake_build ios
cmake_build ios arm64

fi

if $BUILD_MACOS; then
checkpoint "Building NativeScript for macOS"

cmake_build macos

cp "$DIST/intermediates/macos/$CONFIG_BUILD/libNativeScript.dylib" "$DIST/../packages/macos/dist/macos/NativeScript.node"
cmake_build macos x86_64 arm64

fi

if $BUILD_VISION; then

checkpoint "Building NativeScript for visionOS Device"
checkpoint "Building NativeScript for visionOS (physical)"

# cmake_build visionos
# cmake_build visionos arm64

checkpoint "Building NativeScript for visionOS Simulators"
checkpoint "Building NativeScript for visionOS (simulator)"

# cmake_build visionos-sim
# cmake_build visionos-sim x86_64 arm64

fi

if $BUILD_MACOS_CLI; then

checkpoint "Building NativeScript for macOS CLI"

cmake_build macos-cli
cmake_build macos-cli x86_64 arm64

fi

Expand All @@ -164,7 +143,6 @@ if $BUILD_IPHONE; then
-debug-symbols "$DIST/intermediates/ios/$CONFIG_BUILD-iphoneos/NativeScript.framework.dSYM" )
fi


if $BUILD_VISION; then
XCFRAMEWORKS+=( -framework "$DIST/intermediates/visionos/$CONFIG_BUILD-xros/NativeScript.framework"
-debug-symbols "$DIST/intermediates/visionos/$CONFIG_BUILD-xros/NativeScript.framework.dSYM" )
Expand All @@ -174,20 +152,44 @@ if $BUILD_VISION; then
fi

if [[ -n "${XCFRAMEWORKS[@]}" ]]; then

checkpoint "Creating NativeScript.xcframework"
OUTPUT_DIR="$DIST/NativeScript.xcframework"
rm -rf $OUTPUT_DIR
xcodebuild -create-xcframework ${XCFRAMEWORKS[@]} -output "$OUTPUT_DIR"

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
fi

# We're currently distributing two separate packages:
# 1. UIKit-based (@nativescript/ios-node-api)
# 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

checkpoint "Creating NativeScript.node"

cp -r "$DIST/intermediates/macos/$CONFIG_BUILD/libNativeScript.dylib" "$DIST/NativeScript.node"

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
fi

if $BUILD_MACOS_CLI; then
Expand Down
Loading
Loading