diff --git a/.ado/jobs/build-test-rntester.yml b/.ado/jobs/build-test-rntester.yml index ed7eda63d74c64..f72e2869ae22cb 100644 --- a/.ado/jobs/build-test-rntester.yml +++ b/.ado/jobs/build-test-rntester.yml @@ -50,6 +50,54 @@ parameters: packager_platform: 'ios' new_arch_enabled: '1' use_hermes: '0' + - name: macos_debug_oldarch_hermes + friendly_name: 'macOS, Old Arch, Hermes' + sdk: macosx + configuration: Debug + scheme: RNTester-macOS + packager_platform: 'macos' + new_arch_enabled: '0' + use_hermes: '1' + - name: macos_debug_newarch_hermes + friendly_name: 'macOS, New Arch, Hermes' + sdk: macosx + configuration: Debug + scheme: RNTester-macOS + packager_platform: 'macos' + new_arch_enabled: '1' + use_hermes: '1' + - name: ios_debug_oldarch_hermes + friendly_name: 'iOS, Old Arch, Hermes' + sdk: iphonesimulator + configuration: Debug + scheme: RNTester + packager_platform: 'ios' + new_arch_enabled: '0' + use_hermes: '1' + - name: ios_debug_newarch_hermes + friendly_name: 'iOS, New Arch, Hermes' + sdk: iphonesimulator + configuration: Debug + scheme: RNTester + packager_platform: 'ios' + new_arch_enabled: '1' + use_hermes: '1' + - name: xros_debug_oldarch_hermes + friendly_name: 'xrOS, Old Arch, Hermes' + sdk: xrsimulator + configuration: Debug + scheme: RNTester-visionOS + packager_platform: 'ios' + new_arch_enabled: '0' + use_hermes: '1' + - name: xros_debug_newarch_hermes + friendly_name: 'xrOS, New Arch, Hermes' + sdk: xrsimulator + configuration: Debug + scheme: RNTester-visionOS + packager_platform: 'ios' + new_arch_enabled: '1' + use_hermes: '1' jobs: - ${{ each slice in parameters.appleBuildMatrix }}: diff --git a/packages/react-native/scripts/cocoapods/utils.rb b/packages/react-native/scripts/cocoapods/utils.rb index 63639792740eae..e10da4744deacc 100644 --- a/packages/react-native/scripts/cocoapods/utils.rb +++ b/packages/react-native/scripts/cocoapods/utils.rb @@ -195,16 +195,22 @@ def self.apply_xcode_15_patch(installer, xcodebuild_manager: Xcodebuild) private def self.add_build_settings_to_pod(installer, settings_name, settings_value, target_pod_name, configuration_type) + # [macOS + # Since some RN projects might combine multiple platforms into the same Xcode project, + # we'll be much more forgiving with the pod name matching in react-native-macos. + # Could be upstreamed as part of https://github.com/microsoft/react-native-macos/issues/2526. + valid_suffixes = ["", "-iOS", "-macOS", "-visionOS"] + # macOS] installer.target_installation_results.pod_target_installation_results.each do |pod_name, target_installation_result| - if pod_name.to_s == target_pod_name + if valid_suffixes.any? { |suffix| pod_name.to_s == "#{target_pod_name}#{suffix}" } # [macOS] target_installation_result.native_target.build_configurations.each do |config| - if configuration_type == nil || (configuration_type != nil && config.type == configuration_type) - config.build_settings[settings_name] ||= '$(inherited) ' - config.build_settings[settings_name] << settings_value - end + if configuration_type == nil || (configuration_type != nil && config.type == configuration_type) + config.build_settings[settings_name] ||= '$(inherited) ' + config.build_settings[settings_name] << settings_value end end end + end end def self.fix_library_search_path(config) diff --git a/packages/react-native/sdks/hermes-engine/hermes-engine.podspec b/packages/react-native/sdks/hermes-engine/hermes-engine.podspec index b3b59893acb2b4..91ad1d191b6d6c 100644 --- a/packages/react-native/sdks/hermes-engine/hermes-engine.podspec +++ b/packages/react-native/sdks/hermes-engine/hermes-engine.podspec @@ -23,7 +23,7 @@ end package = JSON.parse(File.read(File.join(react_native_path, "package.json"))) # [macOS rn_version = package['version'] -version = findLastestVersionWithArtifact(rn_version) || rn_version +version = findLatestVersionWithArtifact(rn_version) || rn_version # macOS] source_type = hermes_source_type(version, react_native_path) diff --git a/packages/react-native/sdks/hermes-engine/hermes-utils.rb b/packages/react-native/sdks/hermes-engine/hermes-utils.rb index acf7a81edb7c5f..5c9a1810f62eca 100644 --- a/packages/react-native/sdks/hermes-engine/hermes-utils.rb +++ b/packages/react-native/sdks/hermes-engine/hermes-utils.rb @@ -7,6 +7,7 @@ require 'rexml/document' require 'open3' # [macOS] require 'json' # [macOS] +require 'tmpdir' # [macOS] HERMES_GITHUB_URL = "https://github.com/facebook/hermes.git" ENV_BUILD_FROM_SOURCE = "RCT_BUILD_HERMES_FROM_SOURCE" @@ -177,8 +178,18 @@ def podspec_source_build_from_github_tag(react_native_path) end def podspec_source_build_from_github_main() - hermes_log("Using the latest commit from main.") - return {:git => HERMES_GITHUB_URL, :commit => `git ls-remote #{HERMES_GITHUB_URL} main | cut -f 1`.strip} + # hermes_log("Using the latest commit from main.") + # return {:git => HERMES_GITHUB_URL, :commit => `git ls-remote #{HERMES_GITHUB_URL} main | cut -f 1`.strip} + + # [macOS + # The logic for this is a bit different on macOS. + # Since react-native-macos lags slightly behind facebook/react-native, we can't always use + # the latest Hermes commit because Hermes and JSI don't always guarantee backwards compatibility. + # Instead, we take the commit hash of Hermes at the time of the merge base with facebook/react-native. + commit = hermes_commit_at_merge_base() + hermes_log("Using Hermes commit from the merge base with facebook/react-native: #{commit}") + return {:git => HERMES_GITHUB_URL, :commit => commit} + # macOS] end def podspec_source_download_prebuild_release_tarball(react_native_path, version) @@ -201,6 +212,51 @@ def artifacts_dir() return File.join(Pod::Config.instance.project_pods_root, "hermes-engine-artifacts") end +# [macOS +def hermes_commit_at_merge_base() + # We don't need ls-remote because react-native-macos is a fork of facebook/react-native + fetch_result = `git fetch -q https://github.com/facebook/react-native.git` + if $?.exitstatus != 0 + abort <<-EOS + [Hermes] Failed to fetch facebook/react-native into the local repository. + EOS + end + + merge_base = `git merge-base FETCH_HEAD HEAD`.strip + if merge_base.empty? + abort <<-EOS + [Hermes] Unable to find the merge base between our HEAD and upstream's HEAD. + EOS + end + + timestamp = `git show -s --format=%ci #{merge_base}`.strip + if timestamp.empty? + abort <<-EOS + [Hermes] Unable to extract the timestamp for the merge base (#{merge_base}). + EOS + end + + commit = nil + Dir.mktmpdir do |tmpdir| + hermes_git_dir = File.join(tmpdir, "hermes.git") + # Unfortunately we can't use git rev-list on HERMES_GITHUB_URL directly since we're not in that repo. + # Instead, we create a shallow clone to avoid downloading the entire history. + `git clone -q --bare --shallow-since="#{timestamp}" #{HERMES_GITHUB_URL} "#{hermes_git_dir}"` + `git --git-dir="#{hermes_git_dir}" fetch -q --deepen=1` + + # If all goes well, this will be the commit hash of Hermes at the time of the merge base + commit = `git --git-dir="#{hermes_git_dir}" rev-list -1 --before="#{timestamp}" HEAD`.strip + if commit.empty? + abort <<-EOS + [Hermes] Unable to find the Hermes commit hash at time #{timestamp}. + EOS + end + end + + return commit +end +# macOS] + def hermestag_file(react_native_path) return File.join(react_native_path, "sdks", ".hermesversion") end @@ -242,7 +298,12 @@ def resolve_url_redirects(url) # [macOS react-native-macos does not publish macos specific hermes artifacts # so we attempt to find the latest patch version of the iOS artifacts and use that -def findLastestVersionWithArtifact(version) +def findLatestVersionWithArtifact(version) + if version == "1000.0.0" + # The main branch builds from source, so skip the artifact check + return nil + end + # See https://central.sonatype.org/search/rest-api-guide/ for details on query params versionWithoutPatch = "#{version.match(/^(\d+\.\d+)/)}" res, = Open3.capture3("curl -s https://search.maven.org/solrsearch/select?q=g:com.facebook.react+AND+a:react-native-artifacts+AND+v:#{versionWithoutPatch}.*&core=gav&rows=1&wt=json") diff --git a/packages/rn-tester/Podfile b/packages/rn-tester/Podfile index 037ff88d2c5669..36de2659c76c89 100644 --- a/packages/rn-tester/Podfile +++ b/packages/rn-tester/Podfile @@ -107,5 +107,6 @@ end # visionOS] post_install do |installer| + $RN_PLATFORMS = %w[iOS macOS visionOS] # [macOS] react_native_post_install(installer, @prefix_path, :mac_catalyst_enabled => false) end