Hermes: Use pre-built artifacts in hermes-engine

Summary:
Update `hermes-engine.podspec` to use pre-built Hermes artifacts from the corresponding React Native GitHub Release when targeting a specific React Native release.
Otherwise, fallback to building Hermes from source.

Changelog: [Internal]

Reviewed By: cortinico, cipolleschi

Differential Revision: D36609257

fbshipit-source-id: 6179c9e255558c7eaf1417ff46a2e7db120295f0
This commit is contained in:
Héctor Ramos 2022-05-25 03:30:57 -07:00 коммит произвёл Facebook GitHub Bot
Родитель a70968807b
Коммит 38b70653b2
5 изменённых файлов: 98 добавлений и 102 удалений

Просмотреть файл

@ -11,6 +11,7 @@ import * as path from 'path';
const {
copyBuildScripts,
copyPodSpec,
downloadHermesTarball,
expandHermesTarball,
getHermesTagSHA,
@ -193,45 +194,42 @@ describe('hermes-utils', () => {
it('should fail if Hermes tarball does not exist', () => {
expect(() => {
expandHermesTarball();
}).toThrow('[Hermes] Failed to expand Hermes tarball.');
}).toThrow('[Hermes] Could not locate Hermes tarball.');
expect(execCalls.tar).toBeUndefined();
});
});
describe('copyBuildScripts', () => {
it('should copy React Native Hermes build scripts to Hermes source directory', () => {
fs.mkdirSync(path.join(SDKS_DIR, 'hermes', 'utils'), {
recursive: true,
});
copyBuildScripts();
expect(
fs.readFileSync(
path.join(
ROOT_DIR,
'sdks',
'hermes',
'utils',
'build-mac-framework.sh',
[
'build-apple-framework.sh',
'build-ios-framework.sh',
'build-mac-framework.sh',
].forEach(buildScript => {
expect(
fs.readFileSync(
path.join(ROOT_DIR, 'sdks', 'hermes', 'utils', buildScript),
{
encoding: 'utf8',
flag: 'r',
},
),
{
encoding: 'utf8',
flag: 'r',
},
),
).toEqual(
fs.readFileSync(
path.join(
ROOT_DIR,
'sdks',
'hermes-engine',
'utils',
'build-mac-framework.sh',
).toEqual(
fs.readFileSync(
path.join(ROOT_DIR, 'sdks', 'hermes-engine', 'utils', buildScript),
{
encoding: 'utf8',
flag: 'r',
},
),
{
encoding: 'utf8',
flag: 'r',
},
),
);
);
});
});
});
describe('copyPodSpec', () => {
it('should copy React Native Hermes Podspec to Hermes source directory', () => {
copyPodSpec();
expect(
fs.readFileSync(
path.join(SDKS_DIR, 'hermes', 'hermes-engine.podspec'),

Просмотреть файл

@ -15,6 +15,7 @@ const {execSync} = require('child_process');
const SDKS_DIR = path.normalize(path.join(__dirname, '..', '..', 'sdks'));
const HERMES_DIR = path.join(SDKS_DIR, 'hermes');
const DEFAULT_HERMES_TAG = 'main';
const HERMES_TAG_FILE_PATH = path.join(SDKS_DIR, '.hermesversion');
const HERMES_TARBALL_BASE_URL = 'https://github.com/facebook/hermes/tarball/';
const HERMES_TARBALL_DOWNLOAD_DIR = path.join(SDKS_DIR, 'download');
@ -25,20 +26,6 @@ const MACOS_IMPORT_HERMESC_PATH = path.join(
'ImportHermesc.cmake',
);
function prepareFileSystem() {
if (!fs.existsSync(SDKS_DIR)) {
fs.mkdirSync(SDKS_DIR, {recursive: true});
}
if (!fs.existsSync(HERMES_DIR)) {
fs.mkdirSync(HERMES_DIR, {recursive: true});
}
if (!fs.existsSync(HERMES_TARBALL_DOWNLOAD_DIR)) {
fs.mkdirSync(HERMES_TARBALL_DOWNLOAD_DIR, {recursive: true});
}
}
function readHermesTag() {
if (fs.existsSync(HERMES_TAG_FILE_PATH)) {
const data = fs
@ -64,8 +51,9 @@ function setHermesTag(hermesTag) {
return;
}
prepareFileSystem();
if (!fs.existsSync(SDKS_DIR)) {
fs.mkdirSync(SDKS_DIR, {recursive: true});
}
fs.writeFileSync(HERMES_TAG_FILE_PATH, hermesTag.trim());
console.log('Hermes tag has been updated. Please commit your changes.');
}
@ -89,12 +77,14 @@ function downloadHermesTarball() {
const hermesTarballDownloadPath = getHermesTarballDownloadPath(hermesTag);
let hermesTarballUrl = HERMES_TARBALL_BASE_URL + hermesTag;
prepareFileSystem();
if (fs.existsSync(hermesTarballDownloadPath)) {
return;
}
if (!fs.existsSync(HERMES_TARBALL_DOWNLOAD_DIR)) {
fs.mkdirSync(HERMES_TARBALL_DOWNLOAD_DIR, {recursive: true});
}
console.info(
`[Hermes] Downloading Hermes source code for commit ${hermesTagSHA}`,
);
@ -110,12 +100,13 @@ function expandHermesTarball() {
const hermesTagSHA = getHermesTagSHA(hermesTag);
const hermesTarballDownloadPath = getHermesTarballDownloadPath(hermesTag);
prepareFileSystem();
if (!fs.existsSync(hermesTarballDownloadPath)) {
throw new Error(`[Hermes] Failed to expand Hermes tarball.`);
throw new Error('[Hermes] Could not locate Hermes tarball.');
}
if (!fs.existsSync(HERMES_DIR)) {
fs.mkdirSync(HERMES_DIR, {recursive: true});
}
console.info(`[Hermes] Expanding Hermes tarball for commit ${hermesTagSHA}`);
try {
execSync(
@ -127,16 +118,16 @@ function expandHermesTarball() {
}
function copyBuildScripts() {
if (!fs.existsSync(HERMES_DIR)) {
if (!fs.existsSync(SDKS_DIR)) {
throw new Error(
'[Hermes] Failed to copy Hermes build scripts, no Hermes source directory found.',
'[Hermes] Failed to copy Hermes build scripts, no SDKs directory found.',
);
}
fs.copyFileSync(
path.join(SDKS_DIR, 'hermes-engine', 'hermes-engine.podspec'),
path.join(HERMES_DIR, 'hermes-engine.podspec'),
);
if (!fs.existsSync(HERMES_DIR)) {
fs.mkdirSync(path.join(HERMES_DIR, 'utils'), {recursive: true});
}
fs.copyFileSync(
path.join(SDKS_DIR, 'hermes-engine', 'utils', 'build-apple-framework.sh'),
path.join(HERMES_DIR, 'utils', 'build-apple-framework.sh'),
@ -151,6 +142,27 @@ function copyBuildScripts() {
);
}
function copyPodSpec() {
if (!fs.existsSync(SDKS_DIR)) {
throw new Error(
'[Hermes] Failed to copy Hermes Podspec, no SDKs directory found.',
);
}
if (!fs.existsSync(HERMES_DIR)) {
fs.mkdirSync(HERMES_DIR, {recursive: true});
}
fs.copyFileSync(
path.join(SDKS_DIR, 'hermes-engine', 'hermes-engine.podspec'),
path.join(HERMES_DIR, 'hermes-engine.podspec'),
);
}
function shouldBuildHermesFromSource() {
const hermesTag = readHermesTag();
return hermesTag === DEFAULT_HERMES_TAG;
}
function shouldUsePrebuiltHermesC(os) {
if (os === 'macos') {
return fs.existsSync(MACOS_HERMESC_PATH);
@ -178,10 +190,12 @@ set_target_properties(native-hermesc PROPERTIES
module.exports = {
configureMakeForPrebuiltHermesC,
copyBuildScripts,
copyPodSpec,
downloadHermesTarball,
expandHermesTarball,
getHermesTagSHA,
readHermesTag,
setHermesTag,
shouldBuildHermesFromSource,
shouldUsePrebuiltHermesC,
};

Просмотреть файл

@ -16,16 +16,30 @@
const {
configureMakeForPrebuiltHermesC,
copyBuildScripts,
copyPodSpec,
downloadHermesTarball,
expandHermesTarball,
shouldUsePrebuiltHermesC,
shouldBuildHermesFromSource,
} = require('./hermes-utils');
downloadHermesTarball();
expandHermesTarball();
copyBuildScripts();
async function main() {
if (!shouldBuildHermesFromSource()) {
copyPodSpec();
return;
}
if (shouldUsePrebuiltHermesC('macos')) {
console.log('[Hermes] Using pre-built HermesC');
configureMakeForPrebuiltHermesC();
downloadHermesTarball();
expandHermesTarball();
copyPodSpec();
copyBuildScripts();
if (shouldUsePrebuiltHermesC('macos')) {
console.log('[Hermes] Using pre-built HermesC');
configureMakeForPrebuiltHermesC();
}
}
main().then(() => {
process.exit(0);
});

Просмотреть файл

@ -107,25 +107,8 @@ def use_react_native! (options={})
if hermes_enabled
pod 'React-hermes', :path => "#{prefix}/ReactCommon/hermes"
pod 'libevent', '~> 2.1.12'
sdks_dir = Pod::Config.instance.installation_root.join(prefix, "sdks")
hermes_tag_file = sdks_dir.join(".hermesversion")
if (File.exist?(hermes_tag_file))
# Use published pod with pre-builts.
Pod::UI.puts "[Hermes] Tag file exists at path: #{hermes_tag_file}"
package = JSON.parse(File.read(File.join(__dir__, "..", "package.json")))
hermes_version = package['version']
Pod::UI.puts "[Hermes] Loading version: #{hermes_version}"
pod 'hermes-engine', hermes_version
else
# Use local podspec and build from source.
path_to_hermes = "#{prefix}/sdks/hermes/hermes-engine.podspec"
Pod::UI.puts "[Hermes] Use local version from #{path_to_hermes}"
system("(cd #{prefix} && node scripts/hermes/prepare-hermes-for-build)")
pod 'hermes-engine', :path => path_to_hermes
end
system("(cd #{prefix} && node scripts/hermes/prepare-hermes-for-build)")
pod 'hermes-engine', :path => "#{prefix}/sdks/hermes/hermes-engine.podspec"
end
if flipper_configuration.flipper_enabled && !production

Просмотреть файл

@ -5,9 +5,6 @@
require "json"
# sdks/.hermesversion
hermes_tag_file = File.join(__dir__, "..", ".hermesversion")
# sdks/hermesc/osx-bin/ImportHermesc.cmake
import_hermesc_file=File.join(__dir__, "..", "hermesc", "osx-bin", "ImportHermesc.cmake")
@ -18,19 +15,13 @@ version = package['version']
source = {}
git = "https://github.com/facebook/hermes.git"
building_from_source = false
if ENV['hermes-artifact-url'] then
source[:http] = ENV['hermes-artifact-url']
elsif File.exist?(hermes_tag_file) then
building_from_source = true
if version == '1000.0.0'
Pod::UI.puts '[Hermes] Hermes needs to be compiled, installing hermes-engine may take a while...'.yellow if Object.const_defined?("Pod::UI")
source[:git] = git
source[:tag] = File.read(hermes_tag_file)
source[:commit] = `git ls-remote https://github.com/facebook/hermes main | cut -f 1`.strip
else
building_from_source = true
source[:git] = git
hermes_commit_sha = `git ls-remote https://github.com/facebook/hermes main | cut -f 1`.strip
source[:commit] = hermes_commit_sha
source[:http] = `https://github.com/facebook/react-native/releases/download/v#{version}/hermes-runtime-darwin-v#{version}.tar.gz`
end
module HermesHelper
@ -38,17 +29,13 @@ module HermesHelper
BUILD_TYPE = :release
end
if building_from_source
Pod::UI.puts '[Hermes] Hermes needs to be compiled, installing hermes-engine may take a while...'.yellow if Object.const_defined?("Pod::UI")
end
Pod::Spec.new do |spec|
spec.name = "hermes-engine"
spec.version = version
spec.summary = "Hermes is a small and lightweight JavaScript engine optimized for running React Native."
spec.description = "Hermes is a JavaScript engine optimized for fast start-up of React Native apps. It features ahead-of-time static optimization and compact bytecode."
spec.homepage = "https://hermesengine.dev"
spec.license = { type: "MIT", file: "LICENSE" }
spec.license = package["license"]
spec.author = "Facebook"
spec.source = source
spec.platforms = { :osx => "10.13", :ios => "11.0" }
@ -62,7 +49,7 @@ Pod::Spec.new do |spec|
spec.xcconfig = { "CLANG_CXX_LANGUAGE_STANDARD" => "c++17", "CLANG_CXX_LIBRARY" => "compiler-default", "GCC_PREPROCESSOR_DEFINITIONS" => "HERMES_ENABLE_DEBUGGER=1" }
unless ENV['hermes-artifact-url']
if source[:git] then
spec.prepare_command = <<-EOS
# When true, debug build will be used.
# See `build-apple-framework.sh` for details