Skip to content

Commit cb9eaa6

Browse files
cipolleschifacebook-github-bot
authored andcommitted
Refactor hermes logic to make it branch agnostic (react#35709)
Summary: Pull Request resolved: react#35709 This change refactors the logic to choose which version of hermes we have to pick ## Changelog: [iOS][Changed] - Refactor hermes choosing logic Reviewed By: cortinico, dmytrorykun Differential Revision: D42211405 fbshipit-source-id: d19c0f2c523c5596d18a1f904e3b26d96ea1a77a
1 parent fee9510 commit cb9eaa6

3 files changed

Lines changed: 122 additions & 34 deletions

File tree

.circleci/config.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,8 @@ executors:
132132
macos:
133133
xcode: *xcode_version
134134
resource_class: macos.x86.medium.gen2
135+
environment:
136+
- BUILD_FROM_SOURCE: true
135137

136138
# -------------------------
137139
# COMMANDS
@@ -1142,6 +1144,7 @@ jobs:
11421144
environment:
11431145
- HERMES_WS_DIR: *hermes_workspace_root
11441146
- HERMES_VERSION_FILE: "sdks/.hermesversion"
1147+
- BUILD_FROM_SOURCE: true
11451148
steps:
11461149
- run:
11471150
name: Install dependencies

sdks/hermes-engine/hermes-engine.podspec

Lines changed: 3 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -17,42 +17,13 @@ version = package['version']
1717

1818
# sdks/.hermesversion
1919
hermestag_file = File.join(react_native_path, "sdks", ".hermesversion")
20-
isInCI = ENV['CI'] === 'true'
20+
build_from_source = ENV['BUILD_FROM_SOURCE'] === 'true'
2121

22-
source = {}
2322
git = "https://github.com/facebook/hermes.git"
2423

25-
isInMain = version.include?('1000.0.0')
26-
isNightly = version.start_with?('0.0.0-')
24+
abort_if_invalid_tarball_provided!
2725

28-
if ENV.has_key?('HERMES_ENGINE_TARBALL_PATH')
29-
if !File.exist?(ENV['HERMES_ENGINE_TARBALL_PATH'])
30-
abort "[Hermes] HERMES_ENGINE_TARBALL_PATH is set, but points to a non-existing file: \"#{ENV['HERMES_ENGINE_TARBALL_PATH']}\"\nIf you don't want to use tarball, run `unset HERMES_ENGINE_TARBALL_PATH`"
31-
end
32-
end
33-
34-
if ENV.has_key?('HERMES_ENGINE_TARBALL_PATH')
35-
Pod::UI.puts "[Hermes] Using pre-built Hermes binaries from local path: #{ENV['HERMES_ENGINE_TARBALL_PATH']}".yellow if Object.const_defined?("Pod::UI")
36-
source[:http] = "file://#{ENV['HERMES_ENGINE_TARBALL_PATH']}"
37-
elsif isInMain
38-
Pod::UI.puts '[Hermes] Installing hermes-engine may take slightly longer, building Hermes compiler from source...'.yellow if Object.const_defined?("Pod::UI")
39-
source[:git] = git
40-
source[:commit] = `git ls-remote https://github.com/facebook/hermes main | cut -f 1`.strip
41-
elsif isNightly
42-
Pod::UI.puts '[Hermes] Nightly version, download pre-built for Hermes'.yellow if Object.const_defined?("Pod::UI")
43-
destination_path = download_nightly_hermes(react_native_path, version)
44-
# set tarball as hermes engine
45-
source[:http] = "file://#{destination_path}"
46-
elsif File.exists?(hermestag_file) && isInCI
47-
Pod::UI.puts '[Hermes] Detected that you are on a React Native release branch, building Hermes from source but fetched from tag...'.yellow if Object.const_defined?("Pod::UI")
48-
hermestag = File.read(hermestag_file).strip
49-
source[:git] = git
50-
source[:tag] = hermestag
51-
else
52-
# Sample url from Maven:
53-
# https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/0.71.0/react-native-artifacts-0.71.0-hermes-ios-debug.tar.gz
54-
source[:http] = "https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/#{version}/react-native-artifacts-#{version}-hermes-ios-#{build_type.to_s}.tar.gz"
55-
end
26+
source = compute_hermes_source(build_from_source, hermestag_file, git, version, build_type, react_native_path)
5627

5728
Pod::Spec.new do |spec|
5829
spec.name = "hermes-engine"

sdks/hermes-engine/hermes-utils.rb

Lines changed: 116 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,98 @@
66
require 'net/http'
77
require 'rexml/document'
88

9+
# This function abort the build if the `HERMES_ENGINE_TARBALL_PATH` ENV variable is set with an invalid path
10+
def abort_if_invalid_tarball_provided!()
11+
if ENV.has_key?('HERMES_ENGINE_TARBALL_PATH') && !File.exist?(ENV['HERMES_ENGINE_TARBALL_PATH'])
12+
abort "[Hermes] HERMES_ENGINE_TARBALL_PATH is set, but points to a non-existing file: \"#{ENV['HERMES_ENGINE_TARBALL_PATH']}\"\nIf you don't want to use tarball, run `unset HERMES_ENGINE_TARBALL_PATH`"
13+
end
14+
end
15+
16+
# It computes the right value for the hermes-engine.podspec's source.
17+
# - To use a specific tarball, install the dependencies with:
18+
# `HERMES_ENGINE_TARBALL_PATH=<path_to_tarball> bundle exec pod install`
19+
# - To force a build from source, install the dependencies with:
20+
# `BUILD_FROM_SOURCE=true bundle exec pod install`
21+
# If none of the two are provided, Cocoapods will check whether there is a tarball for the current version
22+
# (either release or nightly). If not, it will fall back building from source (the latest commit on main).
23+
#
24+
# Parameters:
25+
# - build_from_source: boolean to force a build from source.
26+
# - hermestag_file: path to the hermes tag file.
27+
# - git: uri to the hermes repository
28+
# - version: current version of the pod
29+
# - build_type: build type of the hermes engine. It can be `:release` or `:debug`
30+
# - react_native_path: path to react native
31+
#
32+
# Returns: a properly configured source object
33+
def compute_hermes_source(build_from_source, hermestag_file, git, version, build_type, react_native_path)
34+
source = {}
35+
36+
if ENV.has_key?('HERMES_ENGINE_TARBALL_PATH')
37+
use_tarball(source)
38+
elsif build_from_source
39+
if File.exists?(hermestag_file)
40+
build_from_tagfile(source, git, hermestag_file)
41+
else
42+
build_hermes_from_source(source, git)
43+
end
44+
elsif hermes_artifact_exists(release_tarball_url(version, build_type))
45+
use_release_tarball(source, version, build_type)
46+
elsif hermes_artifact_exists(nightly_tarball_url(version).gsub("\\", ""))
47+
use_nightly_tarball(source, react_native_path, version)
48+
else
49+
build_hermes_from_source(source, git)
50+
end
51+
52+
return source
53+
end
54+
55+
def use_tarball(source)
56+
tarball_path = ENV['HERMES_ENGINE_TARBALL_PATH']
57+
putsIfPodPresent("[Hermes] Using pre-built Hermes binaries from local path: #{tarball_path}")
58+
source[:http] = "file://#{tarball_path}"
59+
end
60+
61+
def build_from_tagfile(source, git, hermestag_file)
62+
hermestag = File.read(hermestag_file).strip
63+
putsIfPodPresent("[Hermes] Building Hermes from source from tag #{hermestag}...")
64+
source[:git] = git
65+
source[:tag] = hermestag
66+
end
67+
68+
def use_release_tarball(source, version, build_type)
69+
# Sample url from Maven:
70+
# https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/0.71.0/react-native-artifacts-0.71.0-hermes-ios-debug.tar.gz
71+
putsIfPodPresent('[Hermes] Using the release tarball from Maven Central', 'info')
72+
source[:http] = release_tarball_url(version, build_type)
73+
end
74+
75+
def release_tarball_url(version, build_type)
76+
return "https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/#{version}/react-native-artifacts-#{version}-hermes-ios-#{build_type.to_s}.tar.gz"
77+
end
78+
79+
def use_nightly_tarball(source, react_native_path, version)
80+
putsIfPodPresent('[Hermes] Nightly version, download pre-built for Hermes')
81+
destination_path = download_nightly_hermes(react_native_path, version)
82+
# set tarball as hermes engine
83+
source[:http] = "file://#{destination_path}"
84+
end
85+
86+
def putsIfPodPresent(message, level = 'warning')
87+
unless Object.const_defined?("Pod::UI")
88+
return
89+
end
90+
91+
case level
92+
when 'info'
93+
Pod::UI.puts message.green
94+
when 'error'
95+
Pod::UI.puts message.red
96+
else
97+
Pod::UI.puts message.yellow
98+
end
99+
end
100+
9101
# This function downloads the nightly prebuilt version of Hermes based on the passed version
10102
# and save it in the node_module/react_native/sdks/downloads folder
11103
# It then returns the path to the hermes tarball
@@ -15,12 +107,34 @@
15107
# - version: the version of React Native that requires the Hermes tarball
16108
# Returns: the path to the downloaded Hermes tarball
17109
def download_nightly_hermes(react_native_path, version)
18-
params = "r=snapshots\&g=com.facebook.react\&a=react-native-artifacts\&c=hermes-ios-debug\&e=tar.gz\&v=#{version}-SNAPSHOT"
19-
tarball_url = "http://oss.sonatype.org/service/local/artifact/maven/redirect\?#{params}"
110+
tarball_url = nightly_tarball_url(version)
20111

21112
destination_folder = "#{react_native_path}/sdks/downloads"
22113
destination_path = "#{destination_folder}/hermes-ios.tar.gz"
23114

24115
`mkdir -p "#{destination_folder}" && curl "#{tarball_url}" -Lo "#{destination_path}"`
25116
return destination_path
26117
end
118+
119+
def nightly_tarball_url(version)
120+
params = "r=snapshots\&g=com.facebook.react\&a=react-native-artifacts\&c=hermes-ios-debug\&e=tar.gz\&v=#{version}-SNAPSHOT"
121+
return "http://oss.sonatype.org/service/local/artifact/maven/redirect\?#{params}"
122+
end
123+
124+
def build_hermes_from_source(source, git)
125+
putsIfPodPresent('[Hermes] Installing hermes-engine may take slightly longer, building Hermes compiler from source...')
126+
source[:git] = git
127+
source[:commit] = `git ls-remote https://github.com/facebook/hermes main | cut -f 1`.strip
128+
end
129+
130+
# This function checks that Hermes artifact exists.
131+
# As of now it should check it on the Maven repo.
132+
#
133+
# Parameters
134+
# - version: the version of React Native
135+
# - build_type: debug or release
136+
def hermes_artifact_exists(tarball_url)
137+
# -L is used to follow redirects, useful for the nightlies
138+
# I also needed to wrap the url in quotes to avoid escaping & and ?.
139+
return (`curl -o /dev/null --silent -Iw '%{http_code}' -L "#{tarball_url}"` == "200")
140+
end

0 commit comments

Comments
 (0)