diff --git a/scripts/__tests__/hermes-utils-test.js b/scripts/__tests__/hermes-utils-test.js index 279a4bd5cd0..f9534797bf6 100644 --- a/scripts/__tests__/hermes-utils-test.js +++ b/scripts/__tests__/hermes-utils-test.js @@ -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'), diff --git a/scripts/hermes/hermes-utils.js b/scripts/hermes/hermes-utils.js index 53098a03f77..763eb862145 100644 --- a/scripts/hermes/hermes-utils.js +++ b/scripts/hermes/hermes-utils.js @@ -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( - `${SDKS_DIR}/hermes-engine/hermes-engine.podspec`, - `${HERMES_DIR}/hermes-engine.podspec`, - ); + if (!fs.existsSync(HERMES_DIR)) { + fs.mkdirSync(path.join(HERMES_DIR, 'utils'), {recursive: true}); + } + fs.copyFileSync( `${SDKS_DIR}/hermes-engine/utils/build-apple-framework.sh`, `${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, }; diff --git a/scripts/hermes/prepare-hermes-for-build.js b/scripts/hermes/prepare-hermes-for-build.js index 3a244225800..29a5d9ae27a 100644 --- a/scripts/hermes/prepare-hermes-for-build.js +++ b/scripts/hermes/prepare-hermes-for-build.js @@ -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); +}); diff --git a/scripts/react_native_pods.rb b/scripts/react_native_pods.rb index 8db56d769f1..d00ee6ea2fb 100644 --- a/scripts/react_native_pods.rb +++ b/scripts/react_native_pods.rb @@ -113,6 +113,8 @@ def use_react_native! (options={}) pod 'React-hermes', :path => "#{prefix}/ReactCommon/hermes" pod 'hermes-engine', :path => "#{prefix}/sdks/hermes/hermes-engine.podspec" pod 'libevent', '~> 2.1.12' + system("(cd #{prefix} && node scripts/hermes/prepare-hermes-for-build)") + pod 'hermes-engine', :path => "#{prefix}/sdks/hermes/hermes-engine.podspec" end pods_to_update = LocalPodspecPatch.pods_to_update(options) diff --git a/sdks/hermes-engine/hermes-engine.podspec b/sdks/hermes-engine/hermes-engine.podspec index 96f2bd5249a..7d66fcabb45 100644 --- a/sdks/hermes-engine/hermes-engine.podspec +++ b/sdks/hermes-engine/hermes-engine.podspec @@ -3,30 +3,39 @@ # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. -hermes_tag = 'main' -hermes_tag_file = File.join(__dir__, ".hermesversion") -if (File.exist?(hermes_tag_file)) - hermes_tag = File.read(hermes_tag_file) +require "json" + +# sdks/hermesc/osx-bin/ImportHermesc.cmake +import_hermesc_file=File.join(__dir__, "..", "hermesc", "osx-bin", "ImportHermesc.cmake") + +# package.json +package_file = File.join(__dir__, "..", "..", "package.json") +package = JSON.parse(File.read(package_file)) +version = package['version'] + +source = {} +git = "https://github.com/facebook/hermes.git" + +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[:commit] = `git ls-remote https://github.com/facebook/hermes main | cut -f 1`.strip +else + source[:http] = `https://github.com/facebook/react-native/releases/download/v#{version}/hermes-runtime-darwin-v#{version}.tar.gz` end -hermes_tag_sha = `git ls-remote https://github.com/facebook/hermes #{hermes_tag} | cut -f 1`.strip -source = { :git => 'https://github.com/facebook/hermes.git', :commit => hermes_tag_sha } module HermesHelper # BUILD_TYPE = :debug BUILD_TYPE = :release end -Pod::UI.puts '[Hermes] Hermes needs to be compiled, installing hermes-engine may take a while...'.yellow if Object.const_defined?("Pod::UI") - -import_hermesc_path=File.join(__dir__, "../hermesc/osx-bin/ImportHermesc.cmake") - Pod::Spec.new do |spec| spec.name = "hermes-engine" - spec.version = "1000.0.0-#{hermes_tag_sha.slice(0,6)}" + 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" } @@ -40,19 +49,21 @@ 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" } - spec.prepare_command = <<-EOS - # When true, debug build will be used. - # See `build-apple-framework.sh` for details - DEBUG=#{HermesHelper::BUILD_TYPE == :debug} + if source[:git] then + spec.prepare_command = <<-EOS + # When true, debug build will be used. + # See `build-apple-framework.sh` for details + DEBUG=#{HermesHelper::BUILD_TYPE == :debug} - # Set HERMES_OVERRIDE_HERMESC_PATH if pre-built HermesC is available - #{File.exist?(import_hermesc_path) ? "export HERMES_OVERRIDE_HERMESC_PATH=#{import_hermesc_path}" : ""} - #{File.exist?(import_hermesc_path) ? "echo \"Overriding HermesC path...\"" : ""} + # Set HERMES_OVERRIDE_HERMESC_PATH if pre-built HermesC is available + #{File.exist?(import_hermesc_path) ? "export HERMES_OVERRIDE_HERMESC_PATH=#{import_hermesc_path}" : ""} + #{File.exist?(import_hermesc_path) ? "echo \"Overriding HermesC path...\"" : ""} - # Build iOS framework - ./utils/build-ios-framework.sh + # Build iOS framework + ./utils/build-ios-framework.sh - # Build Mac framework - ./utils/build-mac-framework.sh - EOS + # Build Mac framework + ./utils/build-mac-framework.sh + EOS + end end