From 234486068e7f547450829d17e8d5db111a1571bc Mon Sep 17 00:00:00 2001 From: Dmitry Rykun Date: Tue, 13 Dec 2022 08:42:09 -0800 Subject: [PATCH] Prepare dummy hermes.xcframework before pod install Summary: This diff adds prepare command to hermes-engine.podspec. That command creates dummy `universal/hermes.xcframework` and `maocosx/hermes.framework`. This allow us to utilise CocoaPods auto-linking, and remove manual linking/cleanup code. Also we now do not pollute user project with "Copy Hermes Framework" script phase. Which was quite bad on its own, and also caused annoying bugs on the CI. allow-large-files Changelog: [iOS][Changed] - Prepare dummy hermes.xcframework before pod install. Reviewed By: cipolleschi Differential Revision: D41533994 fbshipit-source-id: d7d098ba5e882ac2d036335c23d7cda447d75b8d --- packages/rn-tester/Podfile.lock | 6 +-- scripts/cocoapods/__tests__/jsengine-test.rb | 26 ------------ scripts/cocoapods/jsengine.rb | 42 ------------------- scripts/react_native_pods.rb | 6 --- sdks/hermes-engine/hermes-engine.podspec | 10 ++--- .../hermes-engine/utils/build-hermes-xcode.sh | 7 ++++ sdks/hermes-engine/utils/copy-hermes-xcode.sh | 17 +------- .../utils/create-dummy-hermes-xcframework.sh | 30 +++++++++++++ 8 files changed, 46 insertions(+), 98 deletions(-) create mode 100644 sdks/hermes-engine/utils/create-dummy-hermes-xcframework.sh diff --git a/packages/rn-tester/Podfile.lock b/packages/rn-tester/Podfile.lock index 681fd3dd0f6a8a..b0c3b5a186de83 100644 --- a/packages/rn-tester/Podfile.lock +++ b/packages/rn-tester/Podfile.lock @@ -932,7 +932,7 @@ SPEC CHECKSUMS: CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99 DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54 FBLazyVector: d68947eddece25638eb0f642d1b957c90388afd1 - FBReactNativeSpec: 0ded2dec004001d5888590a9c13df3e0c357a59f + FBReactNativeSpec: c530d2df977f98d0d72ce4440c074cb73bff6289 Flipper: 26fc4b7382499f1281eb8cb921e5c3ad6de91fe0 Flipper-Boost-iOSX: fd1e2b8cbef7e662a122412d7ac5f5bea715403c Flipper-DoubleConversion: 2dc99b02f658daf147069aad9dbd29d8feb06d30 @@ -944,7 +944,7 @@ SPEC CHECKSUMS: FlipperKit: cbdee19bdd4e7f05472a66ce290f1b729ba3cb86 fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9 glog: 04b94705f318337d7ead9e6d17c019bd9b1f6b1b - hermes-engine: 62aa33fe860de4c9fde92adea000ce2e56c70370 + hermes-engine: b5817966bad2f5e14014102dbf97e26a17fe256e libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 OpenSSL-Universal: ebc357f1e6bc71fa463ccb2fe676756aff50e88c RCT-Folly: 424b8c9a7a0b9ab2886ffe9c3b041ef628fd4fb1 @@ -958,7 +958,7 @@ SPEC CHECKSUMS: React-cxxreact: 97903bdac0fb53409663fd312e2183ae1dd730e5 React-Fabric: 4d08ce0b0f15513b2724ae1000c2aaedf73ebc32 React-graphics: cb8a85648695c60f33a00d732b985f734d1470d8 - React-hermes: e35ea664b36773a2ce84c583febf1396080e59f7 + React-hermes: 73a4f97e9cd712476f9b93ae4838a576279feb78 React-jsi: e4c75a1cf727c8761908ac2eeb1084e47ba88a26 React-jsiexecutor: dcc8c2b89b6e0b5abb9bbbfb6df86adf44e3e877 React-jsinspector: 9b56a373a6797114e1d89a7dffa98ee98af67a8f diff --git a/scripts/cocoapods/__tests__/jsengine-test.rb b/scripts/cocoapods/__tests__/jsengine-test.rb index ef18a72c6be0fb..bccbaa8d9479c4 100644 --- a/scripts/cocoapods/__tests__/jsengine-test.rb +++ b/scripts/cocoapods/__tests__/jsengine-test.rb @@ -125,30 +125,4 @@ def test_setupHermes_installsPods_installsFabricSubspecWhenFabricEnabled assert_equal($podInvocation["libevent"][:version], "~> 2.1.12") end - # ================================= # - # TEST - isBuildingHermesFromSource # - # ================================= # - def test_isBuildingHermesFromSource_whenTarballIsNilAndVersionIsNotNightly_returnTrue - assert_true(is_building_hermes_from_source("1000.0.0", '../..')) - end - - def test_isBuildingHermesFromSource_whenTarballIsNilAndInReleaseBranch_returnTrue - ENV['CI'] = 'true' - File.mocked_existing_files(['../../sdks/.hermesversion']) - assert_true(is_building_hermes_from_source("0.999.0", '../..')) - end - - def test_isBuildingHermesFromSource_whenTarballIsNotNil_returnFalse - ENV['HERMES_ENGINE_TARBALL_PATH'] = "~/Downloads/hermes-ios-debug.tar.gz" - assert_false(is_building_hermes_from_source("1000.0.0", '../..')) - end - - def test_isBuildingHermesFromSource_whenIsNigthly_returnsFalse - assert_false(is_building_hermes_from_source("0.0.0-", '../..')) - end - - def test_isBuildingHermesFromSource_whenIsStbleRelease_returnsFalse - assert_false(is_building_hermes_from_source("0.71.0", '../..')) - end - end diff --git a/scripts/cocoapods/jsengine.rb b/scripts/cocoapods/jsengine.rb index 17941930fc5824..25ed410bb4c9d3 100644 --- a/scripts/cocoapods/jsengine.rb +++ b/scripts/cocoapods/jsengine.rb @@ -34,45 +34,3 @@ def setup_hermes!(react_native_path: "../node_modules/react-native", fabric_enab pod 'React-hermes', :path => "#{react_native_path}/ReactCommon/hermes" pod 'libevent', '~> 2.1.12' end - -def add_copy_hermes_framework_script_phase(installer, react_native_path) - utils_dir = File.join(react_native_path, "sdks", "hermes-engine", "utils") - phase_name = "[RN] Copy Hermes Framework" - project = installer.generated_aggregate_targets.first.user_project - target = project.targets.first - if target.shell_script_build_phases.none? { |phase| phase.name == phase_name } - phase = target.new_shell_script_build_phase(phase_name) - phase.shell_script = ". #{utils_dir}/copy-hermes-xcode.sh" - project.save() - end -end - -def remove_copy_hermes_framework_script_phase(installer, react_native_path) - utils_dir = File.join(react_native_path, "sdks", "hermes-engine", "utils") - phase_name = "[RN] Copy Hermes Framework" - project = installer.generated_aggregate_targets.first.user_project - target = project.native_targets.first - target.shell_script_build_phases.each do |phase| - if phase.name == phase_name - target.build_phases.delete(phase) - end - end - project.save() -end - -# TODO: Use this same function in the `hermes-engine.podspec` somehow -def is_building_hermes_from_source(react_native_version, react_native_path) - if ENV['HERMES_ENGINE_TARBALL_PATH'] != nil - return false - end - - isInMain = react_native_version.include?('1000.0.0') - - hermestag_file = File.join(react_native_path, "sdks", ".hermesversion") - isInCI = ENV['CI'] === 'true' - - isReleaseBranch = File.exist?(hermestag_file) && isInCI - - - return isInMain || isReleaseBranch -end diff --git a/scripts/react_native_pods.rb b/scripts/react_native_pods.rb index a5c9ba576f68dc..1ad9ac372fbd66 100644 --- a/scripts/react_native_pods.rb +++ b/scripts/react_native_pods.rb @@ -205,12 +205,6 @@ def react_native_post_install(installer, react_native_path = "../node_modules/re package = JSON.parse(File.read(File.join(react_native_path, "package.json"))) version = package['version'] - if ReactNativePodsUtils.has_pod(installer, 'hermes-engine') && is_building_hermes_from_source(version, react_native_path) - add_copy_hermes_framework_script_phase(installer, react_native_path) - else - remove_copy_hermes_framework_script_phase(installer, react_native_path) - end - ReactNativePodsUtils.exclude_i386_architecture_while_using_hermes(installer) ReactNativePodsUtils.fix_library_search_paths(installer) ReactNativePodsUtils.set_node_modules_user_settings(installer, react_native_path) diff --git a/sdks/hermes-engine/hermes-engine.podspec b/sdks/hermes-engine/hermes-engine.podspec index 517bc1b247167a..0018605af03238 100644 --- a/sdks/hermes-engine/hermes-engine.podspec +++ b/sdks/hermes-engine/hermes-engine.podspec @@ -73,6 +73,9 @@ Pod::Spec.new do |spec| "CLANG_CXX_LIBRARY" => "compiler-default" }.merge!(build_type == :debug ? { "GCC_PREPROCESSOR_DEFINITIONS" => "HERMES_ENABLE_DEBUGGER=1" } : {}) + spec.ios.vendored_frameworks = "destroot/Library/Frameworks/ios/hermes.framework" + spec.osx.vendored_frameworks = "destroot/Library/Frameworks/macosx/hermes.framework" + if source[:http] then spec.subspec 'Pre-built' do |ss| @@ -111,14 +114,11 @@ Pod::Spec.new do |spec| end spec.user_target_xcconfig = { - 'FRAMEWORK_SEARCH_PATHS' => '"$(PODS_ROOT)/hermes-engine/destroot/Library/Frameworks/iphoneos" ' + - '"$(PODS_ROOT)/hermes-engine/destroot/Library/Frameworks/iphonesimulator" ' + - '"$(PODS_ROOT)/hermes-engine/destroot/Library/Frameworks/macosx" ' + - '"$(PODS_ROOT)/hermes-engine/destroot/Library/Frameworks/catalyst"', - 'OTHER_LDFLAGS' => '-framework "hermes"', 'HERMES_CLI_PATH' => "#{hermesc_path}/bin/hermesc" } + spec.prepare_command = ". #{react_native_path}/sdks/hermes-engine/utils/create-dummy-hermes-xcframework.sh" + CMAKE_BINARY = %x(command -v cmake | tr -d '\n') # NOTE: Script phases are sorted alphabetically inside Xcode project spec.script_phases = [ diff --git a/sdks/hermes-engine/utils/build-hermes-xcode.sh b/sdks/hermes-engine/utils/build-hermes-xcode.sh index 37faee32506029..5093976b2cc4ca 100755 --- a/sdks/hermes-engine/utils/build-hermes-xcode.sh +++ b/sdks/hermes-engine/utils/build-hermes-xcode.sh @@ -63,3 +63,10 @@ echo "Build Apple framework" --build "${PODS_ROOT}/hermes-engine/build/${PLATFORM_NAME}" \ --target "install/strip" \ -j "$(sysctl -n hw.ncpu)" + +echo "Copy Apple framework to destroot/Library/Frameworks" + +cp -pfR \ + "${PODS_ROOT}/hermes-engine/destroot/Library/Frameworks/${PLATFORM_NAME}/hermes.framework" \ + "${PODS_ROOT}/hermes-engine/destroot/Library/Frameworks/ios" +rm -rf "${PODS_ROOT}/hermes-engine/destroot/Library/Frameworks/${PLATFORM_NAME}" diff --git a/sdks/hermes-engine/utils/copy-hermes-xcode.sh b/sdks/hermes-engine/utils/copy-hermes-xcode.sh index 1b14941e6a14b3..c09464e01bd1ef 100755 --- a/sdks/hermes-engine/utils/copy-hermes-xcode.sh +++ b/sdks/hermes-engine/utils/copy-hermes-xcode.sh @@ -4,19 +4,4 @@ # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. -set -x - -src="${PODS_ROOT}/hermes-engine/destroot/Library/Frameworks/${PLATFORM_NAME}/hermes.framework" - -if [[ ! -e "$src" ]]; then - echo "$src does not exist." - exit 1 -fi - -dst1="${PODS_XCFRAMEWORKS_BUILD_DIR}/hermes" -[ ! -f "$dst1" ] && mkdir -p "$dst1" -cp -R "$src" "$dst1" - -dst2="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" -[ ! -f "$dst2" ] && mkdir -p "$dst2" -cp -R "$src" "$dst2" +echo "This file is no-op now. Remove \"[RN] Copy Hermes Framework\" script phase from your main target if you don't want to see this message." diff --git a/sdks/hermes-engine/utils/create-dummy-hermes-xcframework.sh b/sdks/hermes-engine/utils/create-dummy-hermes-xcframework.sh new file mode 100644 index 00000000000000..0e453746cded5a --- /dev/null +++ b/sdks/hermes-engine/utils/create-dummy-hermes-xcframework.sh @@ -0,0 +1,30 @@ +#!/bin/bash +# Copyright (c) Meta Platforms, Inc. and affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +set -x + +# CocoaPods requires vendored frameworks to exist before `pod install` is run, +# and to be proper Moch-O binaries in order to auto-link them to the user's Xcode project. +# This script creates dummy hermes.framework for macosx and ios. +# They are then get rewritten by `build-hermes-xcode.sh` during Xcode build. + +rm -rf destroot + +mkdir -p destroot/Library/Frameworks + +pushd destroot/Library/Frameworks > /dev/null || exit 1 + +echo '' > dummy.c + +mkdir -p macosx/hermes.framework +clang dummy.c -dynamiclib -o macosx/hermes.framework/hermes + +mkdir -p ios/hermes.framework +clang dummy.c -dynamiclib -o ios/hermes.framework/hermes + +rm dummy.c + +popd > /dev/null || exit 1