Split Hermes build for iOS on different executors to speed up CI and Releases (#38619)

Summary:
This PR splits the build of Hermes for iOS in multiple jobs.

Before, we were building all the slices of Hermes serially. So, we were:
- building the hermesc
- building hermes for iPhone
- building hermes for iPhonesimulator
- building hermes for Macos
- building hermes for Catalyst
- packaging the framework
This job was taking up to 45-50 minutes.

The the four slices (iPhone, iPhonesimulator, Macos, Catalyst) can be parallelized to harvest a speedup in execution.
The following tables contains the executions before and after this change.

- Full Clean Build -> Before:  51' 35" | After:  17'33" ( 3x improvement)

| BEFORE | AFTER |
| --- | --- |
| <img width="1164" alt="Screenshot 2023-07-28 at 11 48 24" src="https://github.com/facebook/react-native/assets/11162307/49cc519c-16f0-4868-b847-602b1cb21f3e"> | <img width="1120" alt="Screenshot 2023-07-28 at 11 16 32" src="https://github.com/facebook/react-native/assets/11162307/85034cd7-751e-4056-ae4f-ed09ac8343e8"> |
| Total time (critical path): `build_hermes_macos-Debug` = 51' 35" | Total time (critical path): `build_hermesc_apple` (2' 56") + `build_apple_slices_hermes-Debug-macosx` (9'23") + `build_hermes_macos-Debug` (5'14") = 17'33" |

- Fully Cached Build -> Before:  4'35" | After:  32" ( 9x improvement)

| BEFORE | AFTER |
| --- | --- |
| <img width="497" alt="Screenshot 2023-07-28 at 14 38 12" src="https://github.com/facebook/react-native/assets/11162307/978eba4d-3524-45ab-bfa5-d9cb9ba63df1"> | <img width="1099" alt="Screenshot 2023-07-28 at 16 12 17" src="https://github.com/facebook/react-native/assets/11162307/f2a8f0bb-545c-4d6f-9b81-cda87151bb62"> |
| Total Time (critical path): `build_hermes_macos-Debug` (4'35") | Total Time (critical path): `build_hermesc_apple` (7") + `build_apple_slices_hermes-Debug-macosx` (7") + `build_hermes_macos-Debug` (32") = 46" |

## Changelog:

[Internal] - Split hermes build to speedup CI and Release

Pull Request resolved: https://github.com/facebook/react-native/pull/38619

Test Plan:
- CircleCI stays green
- Hermes artifact still works for RNTester and app from the template

Reviewed By: cortinico, dmytrorykun

Differential Revision: D47896833

Pulled By: cipolleschi

fbshipit-source-id: 3b9e8d5de9b2a6fb6671444fda09d77b96123ac2
This commit is contained in:
Riccardo Cipolleschi
2023-08-02 09:42:56 -07:00
committed by Facebook GitHub Bot
parent a7510a8e7a
commit 79122abe8a
4 changed files with 487 additions and 158 deletions
+376 -126
View File
@@ -65,8 +65,12 @@ references:
hermes_workspace_release_cache_key: &hermes_workspace_release_cache_key v2-hermes-{{ .Environment.CIRCLE_JOB }}-release-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}-{{ checksum "packages/react-native/sdks/hermes-engine/utils/build-apple-framework.sh" }}
hermes_linux_cache_key: &hermes_linux_cache_key v1-hermes-{{ .Environment.CIRCLE_JOB }}-linux-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}
hermes_windows_cache_key: &hermes_windows_cache_key v2-hermes-{{ .Environment.CIRCLE_JOB }}-windows-{{ checksum "/Users/circleci/project/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}
hermesc_apple_cache_key: &hermesc_apple_cache_key v2-hermesc-apple-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}
hermes_apple_slices_cache_key: &hermes_apple_slices_cache_key v2-hermes-apple-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}-{{ checksum "packages/react-native/sdks/hermes-engine/utils/build-apple-framework.sh" }}
hermes_tarball_debug_cache_key: &hermes_tarball_debug_cache_key v4-hermes-tarball-debug-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}
hermes_tarball_release_cache_key: &hermes_tarball_release_cache_key v3-hermes-tarball-release-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}
hermes_macosx_bin_release_cache_key: &hermes_macosx_bin_release_cache_key v1-hermes-release-macosx-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}
hermes_macosx_bin_debug_cache_key: &hermes_macosx_bin_debug_cache_key v1-hermes-debug-macosx-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}
pods_cache_key: &pods_cache_key v10-pods-{{ .Environment.CIRCLE_JOB }}-{{ checksum "packages/rn-tester/Podfile.lock.bak" }}-{{ checksum "packages/rn-tester/Podfile" }}
windows_yarn_cache_key: &windows_yarn_cache_key v1-win-yarn-cache-{{ arch }}-{{ checksum "yarn.lock" }}
windows_choco_cache_key: &windows_choco_cache_key v1-win-choco-cache-{{ .Environment.CIRCLE_JOB }}
@@ -427,69 +431,116 @@ commands:
key: *hermes_tarball_release_cache_key
paths: *hermes_tarball_cache_paths
with_hermesc_span:
description: "Makes hermesc available to the provided steps, if hermesc is present."
store_hermes_apple_artifacts:
description: Stores the tarball and the osx binaries
parameters:
flavor:
default: "Debug"
description: The Hermes build type. Must be one of "Debug", "Release".
type: enum
enum: ["Debug", "Release"]
steps:
type: steps
steps:
- export_hermesc:
flavor: << parameters.flavor >>
- steps: << parameters.steps >>
- export_hermesc:
flavor: << parameters.flavor >>
- when:
condition:
equal: [ << parameters.flavor >>, "Debug"]
steps:
- store_artifacts:
path: /tmp/hermes/hermes-runtime-darwin/hermes-ios-debug.tar.gz
- when:
condition:
equal: [ << parameters.flavor >>, "Release"]
steps:
- store_artifacts:
path: /tmp/hermes/hermes-runtime-darwin/hermes-ios-release.tar.gz
- store_artifacts:
path: /tmp/hermes/osx-bin/<< parameters.flavor >>/hermesc
export_hermesc:
description: "Configures hermesc for use in Hermes builds when possible. The binary is built by either of the macOS or iOS builds, and may be cached by previous builds."
stop_job_if_apple_artifacts_are_there:
description: Stops the current job if there are already the required artifacts
parameters:
flavor:
default: "All"
description: The flavor of artifacts to check. Must be one of "Debug", "Release" or "All"
type: enum
enum: ["Debug", "Release", "All"]
steps:
- when:
condition:
equal: [ << parameters.flavor >>, "All"]
steps:
- run:
name: "Stop if tarballs are present"
command: |
if [[ -f /tmp/hermes/Release_tarball_present && -f /tmp/hermes/Debug_tarball_present && -f /tmp/hermes/Release_osx_bin && -f /tmp/hermes/Debug_osx_bin ]]; then
echo "Tarball and osx-bin present. Halting this job"
circleci-agent step halt
fi
- when:
condition:
not:
equal: [ << parameters.flavor >>, "All"]
steps:
- run:
name: "Stop if tarballs are present"
command: |
TARBALL_PATH=/tmp/hermes/<< parameters.flavor >>_tarball_present
OSX_BIN_PATH=/tmp/hermes/<< parameters.flavor >>_osx_bin
if [[ -f "$OSX_BIN_PATH" && -f "$TARBALL_PATH" ]]; then
echo "[HERMES] Tarball and hermesc binary present. Halting this job"
circleci-agent step halt
else
echo "[HERMES] Tarball not found. Building."
fi
check_if_tarball_is_present:
description: "Checks if the tarball of a specific Flavor is present and adds a marker file"
parameters:
flavor:
default: "Debug"
description: The Hermes build type. Must be one of "Debug", "Release".
description: The flavor of artifacts to check. Must be one of "Debug" or "Release"
type: enum
enum: ["Debug", "Release"]
artifacts_dir:
type: string
default: *hermes_osxbin_artifacts_dir
steps:
- run:
name: "Export path to HermesC if available"
name: Check if << parameters.flavor >> tarball is there
command: |
# Although the hermesc binary built by debug and release jobs is
# identical, we need to store it in distinct paths as Circle CI
# cannot have two different jobs write to the same path in
# artifacts.
mkdir -p << parameters.artifacts_dir >>/Debug << parameters.artifacts_dir >>/Release
hermesc_artifacts_path=<< parameters.artifacts_dir >>/<< parameters.flavor >>/hermesc
hermesc_bin_path=bin/hermesc
hermes_build_dir_macos=$(pwd)/packages/react-native/sdks/hermes/build_macosx
hermes_build_dir_ios=$(pwd)/packages/react-native/sdks/hermes/build_iphoneos
function export_hermesc_cmake_path {
build_dir=$1
hermesc_bin=$build_dir/$hermesc_bin_path
cmake_path=$build_dir/ImportHermesc.cmake
if [[ -f $cmake_path ]]; then
echo "export HERMES_OVERRIDE_HERMESC_PATH=$cmake_path" >> $BASH_ENV
fi
if [[ ! -f $hermesc_artifacts_path ]]; then
cp $hermesc_bin $hermesc_artifacts_path
fi
}
if [[ -f $hermes_build_dir_macos/$hermesc_bin_path ]]; then
export_hermesc_cmake_path $hermes_build_dir_macos
elif [[ -f $hermes_build_dir_ios/$hermesc_bin_path ]]; then
export_hermesc_cmake_path $hermes_build_dir_ios
FLAVOR=debug
if [[ << parameters.flavor >> == "Release" ]]; then
FLAVOR=release
fi
if [[ -f "/tmp/hermes/hermes-runtime-darwin/hermes-ios-$FLAVOR.tar.gz" ]]; then
echo "[HERMES TARBALL] Found the << parameters.flavor >> tarball"
touch /tmp/hermes/<< parameters.flavor >>_tarball_present
fi
check_if_osx_bin_is_present:
description: "Checks if the osx bin of a specific Flavor is present and adds a marker file"
parameters:
flavor:
default: "Debug"
description: The flavor of artifacts to check. Must be one of "Debug" or "Release"
type: enum
enum: ["Debug", "Release"]
steps:
- run:
name: Check if macosx binary is there
command: |
if [[ -d /tmp/hermes/osx-bin/<< parameters.flavor >> ]]; then
echo "[HERMES MACOSX BIN] Found the osx bin << parameters.flavor >>"
touch /tmp/hermes/<< parameters.flavor >>_osx_bin
fi
setup_hermes_workspace:
description: "Setup Hermes Workspace"
steps:
- run:
name: Set up workspace
command: |
mkdir -p $HERMES_OSXBIN_ARTIFACTS_DIR ./packages/react-native/sdks/hermes
cp -r $HERMES_WS_DIR/hermes/* ./packages/react-native/sdks/hermes/.
cp -r ./packages/react-native/sdks/hermes-engine/utils ./packages/react-native/sdks/hermes/.
# -------------------------
# JOBS
# -------------------------
@@ -1253,12 +1304,12 @@ jobs:
name: Install dependencies
command: |
apt update
apt install -y wget git curl
apt install -y wget git curl jq
curl -sL https://deb.nodesource.com/setup_18.x | bash -
apt install -y nodejs
npm install --global yarn
- checkout
- run_yarn
- run:
name: Set up Hermes workspace and caching
command: |
@@ -1274,8 +1325,10 @@ jobs:
echo $HERMES_TAG_SHA > /tmp/hermes/hermesversion
fi
cat /tmp/hermes/hermesversion
- get_react_native_version
- restore_cache:
key: *hermes_workspace_cache_key
- run_yarn
- run:
name: Download Hermes tarball
command: |
@@ -1289,12 +1342,44 @@ jobs:
paths:
- /tmp/hermes/download/
- /tmp/hermes/hermes/
# Check if we already built the tarball
# if yes, we can skip the building and we can skip some jobs building
- restore_cache:
keys:
- *hermes_tarball_release_cache_key
- check_if_tarball_is_present:
flavor: Release
- restore_cache:
keys:
- *hermes_tarball_debug_cache_key
- check_if_tarball_is_present:
flavor: Debug
- restore_cache:
keys:
- *hermes_macosx_bin_release_cache_key
- check_if_osx_bin_is_present:
flavor: Release
- restore_cache:
keys:
- *hermes_macosx_bin_debug_cache_key
- check_if_osx_bin_is_present:
flavor: Debug
- persist_to_workspace:
root: *hermes_workspace_root
paths:
- download
- hermes
- hermes-runtime-darwin
- osx-bin
- hermesversion
- Release_tarball_present
- Debug_tarball_present
- Release_osx_bin
- Debug_osx_bin
- persist_to_workspace:
root: /tmp
paths:
- react-native-version
build_hermesc_linux:
docker:
@@ -1341,8 +1426,104 @@ jobs:
paths:
- linux64-bin
build_hermesc_apple:
executor: reactnativeios
environment:
- HERMES_WS_DIR: *hermes_workspace_root
- HERMES_TARBALL_ARTIFACTS_DIR: *hermes_tarball_artifacts_dir
steps:
- *attach_hermes_workspace
- stop_job_if_apple_artifacts_are_there:
flavor: "All"
- checkout_code_with_cache
- get_react_native_version
- setup_hermes_workspace
- restore_cache:
key: *hermesc_apple_cache_key
- brew_install:
package: cmake
- run:
name: "Build HermesC Apple"
command: |
cd ./packages/react-native/sdks/hermes || exit 1
. ./utils/build-apple-framework.sh
build_host_hermesc_if_needed
- save_cache:
key: *hermesc_apple_cache_key
paths:
- ./packages/react-native/sdks/hermes/build_host_hermesc
- persist_to_workspace:
root: ./packages/react-native/sdks/hermes/
paths:
- build_host_hermesc
build_apple_slices_hermes:
parameters:
slice_base_cache_key:
default: *hermes_apple_slices_cache_key
type: string
flavor:
default: "Debug"
description: The Hermes build type. Must be one of "Debug", "Release".
type: enum
enum: ["Debug", "Release"]
slice:
default: "iphoneos"
description: The Hermes Slice that this job has to build
type: enum
enum: ["macosx", "iphoneos", "iphonesimulator", "catalyst"]
executor: reactnativeios
environment:
- HERMES_WS_DIR: *hermes_workspace_root
- HERMES_TARBALL_ARTIFACTS_DIR: *hermes_tarball_artifacts_dir
- HERMES_OSXBIN_ARTIFACTS_DIR: *hermes_osxbin_artifacts_dir
steps:
- *attach_hermes_workspace
- stop_job_if_apple_artifacts_are_there:
flavor: << parameters.flavor >>
- checkout_code_with_cache
- get_react_native_version
- setup_hermes_workspace
- restore_cache:
key: *hermesc_apple_cache_key
- brew_install:
package: cmake
- restore_cache:
key: << parameters.slice_base_cache_key >>-<< parameters.slice >>-<< parameters.flavor >>
- run:
name: Build the Hermes << parameters.slice >> frameworks
command: |
cd ./packages/react-native/sdks/hermes || exit 1
SLICE=<< parameters.slice >>
FLAVOR=<< parameters.flavor >>
FINAL_PATH=build_"$SLICE"_"$FLAVOR"
echo "Final path for this slice is: $FINAL_PATH"
if [[ -d "$FINAL_PATH" ]]; then
echo "[HERMES] Skipping! Found the requested slice at $FINAL_PATH".
exit 0
fi
if [[ "$SLICE" == "macosx" ]]; then
echo "[HERMES] Building Hermes for MacOS"
BUILD_TYPE="<< parameters.flavor >>" ./utils/build-mac-framework.sh
else
echo "[HERMES] Building Hermes for iOS: $SLICE"
BUILD_TYPE="<< parameters.flavor >>" ./utils/build-ios-framework.sh "$SLICE"
fi
echo "Moving from build_$SLICE to $FINAL_PATH"
mv build_"$SLICE" "$FINAL_PATH"
- save_cache:
key: << parameters.slice_base_cache_key >>-<< parameters.slice >>-<< parameters.flavor >>
paths:
- ./packages/react-native/sdks/hermes/build_<< parameters.slice >>_<< parameters.flavor >>
build_hermes_macos:
parameters:
slice_base_cache_key:
default: *hermes_apple_slices_cache_key
type: string
flavor:
default: "Debug"
description: The Hermes build type. Must be one of "Debug", "Release".
@@ -1352,94 +1533,98 @@ jobs:
environment:
- HERMES_WS_DIR: *hermes_workspace_root
- HERMES_TARBALL_ARTIFACTS_DIR: *hermes_tarball_artifacts_dir
- HERMES_OSXBIN_ARTIFACTS_DIR: *hermes_osxbin_artifacts_dir
steps:
- *attach_hermes_workspace
# Try to store the artifacts if they are already in the workspace
- store_hermes_apple_artifacts:
flavor: << parameters.flavor >>
- stop_job_if_apple_artifacts_are_there:
flavor: << parameters.flavor >>
- checkout_code_with_cache
- run_yarn
- *attach_hermes_workspace
- get_react_native_version
- brew_install:
package: cmake
- setup_hermes_workspace
- restore_cache:
key: << parameters.slice_base_cache_key >>-macosx-<< parameters.flavor >>
- restore_cache:
key: << parameters.slice_base_cache_key >>-iphoneos-<< parameters.flavor >>
- restore_cache:
key: << parameters.slice_base_cache_key >>-iphonesimulator-<< parameters.flavor >>
- restore_cache:
key: << parameters.slice_base_cache_key >>-catalyst-<< parameters.flavor >>
- run:
name: "Move back build folders"
command: |
cd ./packages/react-native/sdks/hermes || exit 1
mv build_macosx_<< parameters.flavor >> build_macosx
mv build_iphoneos_<< parameters.flavor >> build_iphoneos
mv build_iphonesimulator_<< parameters.flavor >> build_iphonesimulator
mv build_catalyst_<< parameters.flavor >> build_catalyst
- run:
name: "Prepare destroot folder"
command: |
cd ./packages/react-native/sdks/hermes || exit 1
. ./utils/build-apple-framework.sh
prepare_dest_root_for_ci
- run:
name: "Create fat framework for iOS"
command: |
cd ./packages/react-native/sdks/hermes || exit 1
echo "[HERMES] Creating the universal framework"
./utils/build-ios-framework.sh build_framework
- run:
name: Package the Hermes Apple frameworks
command: |
BUILD_TYPE="<< parameters.flavor >>"
echo "Packaging Hermes Apple frameworks for $BUILD_TYPE build type"
TARBALL_OUTPUT_DIR=$(mktemp -d /tmp/hermes-tarball-output-XXXXXXXX)
TARBALL_FILENAME=$(node ./packages/react-native/scripts/hermes/get-tarball-name.js --buildType "$BUILD_TYPE")
echo "Packaging Hermes Apple frameworks for $BUILD_TYPE build type"
TARBALL_OUTPUT_PATH=$(node ./packages/react-native/scripts/hermes/create-tarball.js \
--inputDir ./packages/react-native/sdks/hermes \
--buildType "$BUILD_TYPE" \
--outputDir $TARBALL_OUTPUT_DIR)
echo "Hermes tarball saved to $TARBALL_OUTPUT_PATH"
mkdir -p $HERMES_TARBALL_ARTIFACTS_DIR
cp $TARBALL_OUTPUT_PATH $HERMES_TARBALL_ARTIFACTS_DIR/.
mkdir -p /tmp/hermes/osx-bin/<< parameters.flavor >>
cp ./packages/react-native/sdks/hermes/build_macosx/bin/* /tmp/hermes/osx-bin/<< parameters.flavor >>
- when:
condition:
equal: [ << parameters.flavor >>, "Debug"]
steps:
- restore_cache:
keys:
- *hermes_workspace_debug_cache_key
- save_cache:
key: *hermes_tarball_debug_cache_key
paths: *hermes_tarball_cache_paths
- save_cache:
key: *hermes_macosx_bin_debug_cache_key
paths: /tmp/hermes/osx-bin/Debug
- when:
condition:
equal: [ << parameters.flavor >>, "Release"]
steps:
- restore_cache:
keys:
- *hermes_workspace_release_cache_key
- run:
name: Set up workspace
command: |
mkdir -p $HERMES_OSXBIN_ARTIFACTS_DIR ./packages/react-native/sdks/hermes
cp -r $HERMES_WS_DIR/hermes/* ./packages/react-native/sdks/hermes/.
cp -r ./packages/react-native/sdks/hermes-engine/utils ./packages/react-native/sdks/hermes/.
- brew_install:
package: cmake
- with_hermes_tarball_cache_span:
- save_cache:
key: *hermes_tarball_release_cache_key
paths: *hermes_tarball_cache_paths
- save_cache:
key: *hermes_macosx_bin_release_cache_key
paths: /tmp/hermes/osx-bin/Release
- store_hermes_apple_artifacts:
flavor: << parameters.flavor >>
steps:
- with_hermesc_span:
flavor: << parameters.flavor >>
steps:
- run:
name: Build the Hermes Mac frameworks
command: |
cd ./packages/react-native/sdks/hermes || exit 1
BUILD_TYPE="<< parameters.flavor >>" ./utils/build-mac-framework.sh
- run:
name: Build the Hermes iOS frameworks
command: |
cd ./packages/react-native/sdks/hermes || exit 1
BUILD_TYPE="<< parameters.flavor >>" ./utils/build-ios-framework.sh
- run:
name: Package the Hermes Apple frameworks
command: |
BUILD_TYPE="<< parameters.flavor >>"
echo "Packaging Hermes Apple frameworks for $BUILD_TYPE build type"
TARBALL_OUTPUT_DIR=$(mktemp -d /tmp/hermes-tarball-output-XXXXXXXX)
TARBALL_FILENAME=$(node ./packages/react-native/scripts/hermes/get-tarball-name.js --buildType "$BUILD_TYPE")
echo "Packaging Hermes Apple frameworks for $BUILD_TYPE build type"
TARBALL_OUTPUT_PATH=$(node ./packages/react-native/scripts/hermes/create-tarball.js \
--inputDir ./packages/react-native/sdks/hermes \
--buildType "$BUILD_TYPE" \
--outputDir $TARBALL_OUTPUT_DIR)
echo "Hermes tarball saved to $TARBALL_OUTPUT_PATH"
mkdir -p $HERMES_TARBALL_ARTIFACTS_DIR
cp $TARBALL_OUTPUT_PATH $HERMES_TARBALL_ARTIFACTS_DIR/.
- when:
condition:
equal: [ << parameters.flavor >>, "Debug"]
steps:
- save_cache:
key: *hermes_workspace_debug_cache_key
paths: *hermes_workspace_macos_cache_paths
- when:
condition:
equal: [ << parameters.flavor >>, "Release"]
steps:
- save_cache:
key: *hermes_workspace_release_cache_key
paths: *hermes_workspace_macos_cache_paths
- store_artifacts:
path: *hermes_tarball_artifacts_dir
- store_artifacts:
path: *hermes_osxbin_artifacts_dir
- persist_to_workspace:
root: /tmp/hermes/
paths:
- hermes-runtime-darwin
- osx-bin
- persist_to_workspace:
root: /tmp/hermes/
paths:
- hermes-runtime-darwin
- osx-bin
build_hermesc_windows:
executor:
@@ -1742,13 +1927,23 @@ workflows:
latest : false
dryrun: true
- prepare_hermes_workspace
- test_ios_rntester_hermes_xcode_integration
# - test_ios_rntester_hermes_xcode_integration
- build_hermesc_linux:
requires:
- prepare_hermes_workspace
- build_hermes_macos:
- build_hermesc_apple:
requires:
- prepare_hermes_workspace
- build_apple_slices_hermes:
requires:
- build_hermesc_apple
matrix:
parameters:
flavor: ["Debug", "Release"]
slice: ["macosx", "iphoneos", "iphonesimulator", "catalyst"]
- build_hermes_macos:
requires:
- build_apple_slices_hermes
matrix:
parameters:
flavor: ["Debug", "Release"]
@@ -1906,17 +2101,24 @@ workflows:
filters: *only_release_tags
requires:
- prepare_hermes_workspace
- build_hermes_macos:
- build_apple_slices_hermes:
filters: *only_release_tags
requires:
- prepare_hermes_workspace
matrix:
parameters:
flavor: ["Debug", "Release"]
slice: ["macosx", "iphoneos", "iphonesimulator", "catalyst"]
- build_hermesc_windows:
filters: *only_release_tags
requires:
- prepare_hermes_workspace
- build_hermes_macos:
requires:
- build_apple_slices_hermes
matrix:
parameters:
flavor: ["Debug", "Release"]
# This job will trigger when a version tag is pushed (by package_release)
- build_npm_package:
name: build_and_publish_npm_package
@@ -1927,6 +2129,47 @@ workflows:
- build_hermes_macos
- build_hermesc_windows
package_and_publish_release_dryrun:
when:
and:
- equal: [ false, << pipeline.parameters.run_release_workflow >> ]
- equal: [ false, << pipeline.parameters.run_nightly_workflow >> ]
jobs:
- prepare_package_for_release:
name: prepare_package_for_release
version: ''
latest : false
dryrun: true
- prepare_hermes_workspace:
requires:
- prepare_package_for_release
- build_hermesc_linux:
requires:
- prepare_hermes_workspace
- build_apple_slices_hermes:
requires:
- prepare_hermes_workspace
matrix:
parameters:
flavor: ["Debug", "Release"]
slice: ["macosx", "iphoneos", "iphonesimulator", "catalyst"]
- build_hermesc_windows:
requires:
- prepare_hermes_workspace
- build_hermes_macos:
requires:
- build_apple_slices_hermes
matrix:
parameters:
flavor: ["Debug", "Release"]
- build_npm_package:
name: build_and_publish_npm_package
release_type: "dry-run"
requires:
- build_hermesc_linux
- build_hermes_macos
- build_hermesc_windows
analysis:
when:
and:
@@ -1947,15 +2190,22 @@ workflows:
- build_hermesc_linux:
requires:
- prepare_hermes_workspace
- build_hermes_macos:
- build_apple_slices_hermes:
requires:
- prepare_hermes_workspace
matrix:
parameters:
flavor: ["Debug", "Release"]
slice: ["macosx", "iphoneos", "iphonesimulator", "catalyst"]
- build_hermesc_windows:
requires:
- prepare_hermes_workspace
- build_hermes_macos:
requires:
- build_apple_slices_hermes
matrix:
parameters:
flavor: ["Debug", "Release"]
- build_npm_package:
release_type: "nightly"
requires:
@@ -31,7 +31,7 @@ Pod::Spec.new do |spec|
spec.license = package['license']
spec.author = "Facebook"
spec.source = source
spec.platforms = { :osx => "10.13", :ios => min_ios_version_supported }
spec.platforms = { :osx => "10.13", :ios => "13.4" }
spec.preserve_paths = '**/*.*'
spec.source_files = ''
@@ -105,25 +105,30 @@ Pod::Spec.new do |spec|
spec.prepare_command = ". #{react_native_path}/sdks/hermes-engine/utils/create-dummy-hermes-xcframework.sh"
CMAKE_BINARY = Pod::Executable::which!('cmake')
# NOTE: Script phases are sorted alphabetically inside Xcode project
spec.script_phases = [
{
:name => '[RN] [1] Build Hermesc',
:script => <<-EOS
. "${REACT_NATIVE_PATH}/scripts/xcode/with-environment.sh"
export CMAKE_BINARY=${CMAKE_BINARY:-#{CMAKE_BINARY}}
. ${REACT_NATIVE_PATH}/sdks/hermes-engine/utils/build-hermesc-xcode.sh #{hermesc_path}
EOS
},
{
:name => '[RN] [2] Build Hermes',
:script => <<-EOS
. "${REACT_NATIVE_PATH}/scripts/xcode/with-environment.sh"
export CMAKE_BINARY=${CMAKE_BINARY:-#{CMAKE_BINARY}}
. ${REACT_NATIVE_PATH}/sdks/hermes-engine/utils/build-hermes-xcode.sh #{version} #{hermesc_path}/ImportHermesc.cmake
EOS
}
]
# This podspec is also run in CI to build Hermes without using Pod install
# and sometimes CI fails because `Pod::Executable` does not exist if it is not run with Pod Install.
if defined?(Pod::Executable.to_s)
puts "Const Defined!"
CMAKE_BINARY = Pod::Executable::which!('cmake')
# NOTE: Script phases are sorted alphabetically inside Xcode project
spec.script_phases = [
{
:name => '[RN] [1] Build Hermesc',
:script => <<-EOS
. "${REACT_NATIVE_PATH}/scripts/xcode/with-environment.sh"
export CMAKE_BINARY=${CMAKE_BINARY:-#{CMAKE_BINARY}}
. ${REACT_NATIVE_PATH}/sdks/hermes-engine/utils/build-hermesc-xcode.sh #{hermesc_path}
EOS
},
{
:name => '[RN] [2] Build Hermes',
:script => <<-EOS
. "${REACT_NATIVE_PATH}/scripts/xcode/with-environment.sh"
export CMAKE_BINARY=${CMAKE_BINARY:-#{CMAKE_BINARY}}
. ${REACT_NATIVE_PATH}/sdks/hermes-engine/utils/build-hermes-xcode.sh #{version} #{hermesc_path}/ImportHermesc.cmake
EOS
}
]
end
end
end
@@ -87,11 +87,18 @@ function configure_apple_framework {
popd > /dev/null || exit 1
}
function build_host_hermesc_if_needed {
if [[ ! -f "$IMPORT_HERMESC_PATH" ]]; then
build_host_hermesc
else
echo "[HermesC] Skipping! Found an existent hermesc already at: $IMPORT_HERMESC_PATH"
fi
}
# Utility function to build an Apple framework
function build_apple_framework {
# Only build host HermesC if no file found at $IMPORT_HERMESC_PATH
[ ! -f "$IMPORT_HERMESC_PATH" ] &&
build_host_hermesc
build_host_hermesc_if_needed
# Confirm ImportHermesc.cmake is now available.
[ ! -f "$IMPORT_HERMESC_PATH" ] &&
@@ -121,6 +128,22 @@ function build_apple_framework {
popd > /dev/null || exit 1
}
function prepare_dest_root_for_ci {
mkdir -p "destroot/Library/Frameworks/macosx" "destroot/bin" "destroot/Library/Frameworks/iphoneos" "destroot/Library/Frameworks/iphonesimulator" "destroot/Library/Frameworks/catalyst"
cp -R "./build_macosx/API/hermes/hermes.framework"* "destroot/Library/Frameworks/macosx"
cp -R "./build_iphoneos/API/hermes/hermes.framework"* "destroot/Library/Frameworks/iphoneos"
cp -R "./build_iphonesimulator/API/hermes/hermes.framework"* "destroot/Library/Frameworks/iphonesimulator"
cp -R "./build_catalyst/API/hermes/hermes.framework"* "destroot/Library/Frameworks/catalyst"
cp "./build_macosx/bin/"* "destroot/bin"
mkdir -p destroot/include/hermes/Public destroot/include/jsi
cp public/hermes/Public/*.h destroot/include/hermes/Public
cp API/hermes/*.h destroot/include/hermes
cp "$JSI_PATH"/jsi/*.h destroot/include/jsi
}
# Accepts an array of frameworks and will place all of
# the architectures into an universal folder and then remove
# the merged frameworks from destroot
@@ -4,18 +4,69 @@
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
# shellcheck source=xplat/js/react-native-github/sdks/hermes-engine/utils/build-apple-framework.sh
CURR_SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)"
. "${CURR_SCRIPT_DIR}/build-apple-framework.sh"
# Given a specific target, retrieve the right architecture for it
# $1 the target you want to build. Allowed values: iphoneos, iphonesimulator, catalyst
function get_architecture {
if [[ $1 == "iphoneos" ]]; then
echo "arm64"
elif [[ $1 == "iphonesimulator" ]]; then
echo "x86_64;arm64"
elif [[ $1 == "catalyst" ]]; then
echo "x86_64;arm64"
else
echo "Error: unknown arkitecture passed $1"
exit 1
fi
}
if [ ! -d destroot/Library/Frameworks/universal/hermes.xcframework ]; then
# build a single framework
# $1 is the target to build
function build_framework {
if [ ! -d destroot/Library/Frameworks/universal/hermes.xcframework ]; then
ios_deployment_target=$(get_ios_deployment_target)
build_apple_framework "iphoneos" "arm64" "$ios_deployment_target"
build_apple_framework "iphonesimulator" "x86_64;arm64" "$ios_deployment_target"
build_apple_framework "catalyst" "x86_64;arm64" "$ios_deployment_target"
architecture=$(get_architecture "$1")
create_universal_framework "iphoneos" "iphonesimulator" "catalyst"
else
build_apple_framework "$1" "$architecture" "$ios_deployment_target"
else
echo "Skipping; Clean \"destroot\" to rebuild".
fi
}
# group the frameworks together to create a universal framework
function build_universal_framework {
if [ ! -d destroot/Library/Frameworks/universal/hermes.xcframework ]; then
create_universal_framework "iphoneos" "iphonesimulator" "catalyst"
else
echo "Skipping; Clean \"destroot\" to rebuild".
fi
}
# single function that builds sequentially iphoneos, iphonesimulator and catalyst
# this is used to preserve backward compatibility
function create_framework {
if [ ! -d destroot/Library/Frameworks/universal/hermes.xcframework ]; then
ios_deployment_target=$(get_ios_deployment_target)
build_framework "iphoneos"
build_framework "iphonesimulator"
build_framework "catalyst"
build_universal_framework
else
echo "Skipping; Clean \"destroot\" to rebuild".
fi
}
CURR_SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)"
# shellcheck source=xplat/js/react-native-github/sdks/hermes-engine/utils/build-apple-framework.sh
. "${CURR_SCRIPT_DIR}/build-apple-framework.sh"
if [[ -z $1 ]]; then
create_framework
elif [[ $1 == "build_framework" ]]; then
build_universal_framework
else
build_framework "$1"
fi