Hermes: Add scripts to package, remove shelljs

Summary:
The new Hermes scripts need to be included in the `react-native` npm.

The `shelljs` dependency that was used by the Hermes scripts is a dev dependency, so instead of adding to the `react-native` npm size, we refactored its use out of hermes-utils.js.

Changelog:
[General][Added] - Add Hermes scripts to package

Reviewed By: cortinico

Differential Revision: D36387135

fbshipit-source-id: 12d0bc29d365c4cb18d33a0d390e6e7d34864b7a
This commit is contained in:
Héctor Ramos
2022-05-24 14:08:48 -07:00
committed by fortmarek
parent 27751babe6
commit ea6706e166
3 changed files with 306 additions and 31 deletions
+5
View File
@@ -41,6 +41,11 @@
"scripts/generate-artifacts.js",
"scripts/generate-provider-cli.js",
"scripts/generate-specs-cli.js",
"scripts/codegen/codegen-utils.js",
"scripts/codegen/generate-artifacts-executor.js",
"scripts/codegen/generate-specs-cli-executor.js",
"scripts/hermes/hermes-utils.js",
"scripts/hermes/prepare-hermes-for-build.js",
"scripts/ios-configure-glog.sh",
"scripts/xcode/with-environment.sh",
"scripts/launchPackager.bat",
+254
View File
@@ -0,0 +1,254 @@
/**
* 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.
*
* @format
*/
import * as path from 'path';
const {
copyBuildScripts,
downloadHermesTarball,
expandHermesTarball,
getHermesTagSHA,
readHermesTag,
setHermesTag,
} = require('../hermes/hermes-utils');
const hermesTag =
'hermes-2022-04-28-RNv0.69.0-15d07c2edd29a4ea0b8f15ab0588a0c1adb1200f';
const tarballContents = 'dummy string';
const hermesTagSha = '5244f819b2f3949ca94a3a1bf75d54a8ed59d94a';
const ROOT_DIR = path.normalize(path.join(__dirname, '..', '..'));
const SDKS_DIR = path.join(ROOT_DIR, 'sdks');
const MemoryFs = require('metro-memory-fs');
let execCalls;
let fs;
jest.mock('child_process', () => ({
execSync: jest.fn(command => {
if (command.startsWith('curl')) {
fs.writeFileSync(
path.join(SDKS_DIR, 'download', `hermes-${hermesTagSha}.tgz`),
tarballContents,
);
execCalls.curl = true;
return {code: 0};
}
if (command.startsWith('git')) {
execCalls.git = true;
return hermesTagSha + '\n';
}
if (command.startsWith('tar')) {
fs.mkdirSync(path.join(SDKS_DIR, 'hermes', 'utils'), {
recursive: true,
});
fs.writeFileSync(path.join(SDKS_DIR, 'hermes', `package.json`), '{}');
execCalls.tar = true;
return {code: 0};
}
}),
}));
function populateMockFilesystem() {
fs.mkdirSync(path.join(SDKS_DIR, 'hermes-engine', 'utils'), {
recursive: true,
});
fs.writeFileSync(
path.join(
ROOT_DIR,
'sdks',
'hermes-engine',
'utils',
'build-apple-framework.sh',
),
'Dummy file',
);
fs.writeFileSync(
path.join(
ROOT_DIR,
'sdks',
'hermes-engine',
'utils',
'build-ios-framework.sh',
),
'Dummy file',
);
fs.writeFileSync(
path.join(
ROOT_DIR,
'sdks',
'hermes-engine',
'utils',
'build-mac-framework.sh',
),
'Dummy file',
);
fs.writeFileSync(
path.join(SDKS_DIR, 'hermes-engine', 'hermes-engine.podspec'),
'Dummy file',
);
}
describe('hermes-utils', () => {
beforeEach(() => {
jest.resetModules();
jest.mock(
'fs',
() =>
new MemoryFs({
platform: process.platform === 'win32' ? 'win32' : 'posix',
}),
);
fs = require('fs');
fs.reset();
populateMockFilesystem();
execCalls = Object.create(null);
});
describe('readHermesTag', () => {
it('should return main if .hermesversion does not exist', () => {
expect(readHermesTag()).toEqual('main');
});
it('should fail if hermes tag is empty', () => {
fs.writeFileSync(path.join(SDKS_DIR, '.hermesversion'), '');
expect(() => {
readHermesTag();
}).toThrow('[Hermes] .hermesversion file is empty.');
});
it('should return tag from .hermesversion if file exists', () => {
fs.writeFileSync(path.join(SDKS_DIR, '.hermesversion'), hermesTag);
expect(readHermesTag()).toEqual(hermesTag);
});
});
describe('setHermesTag', () => {
it('should write tag to .hermesversion file', () => {
setHermesTag(hermesTag);
expect(
fs.readFileSync(path.join(SDKS_DIR, '.hermesversion'), {
encoding: 'utf8',
flag: 'r',
}),
).toEqual(hermesTag);
});
it('should set Hermes tag and read it back', () => {
setHermesTag(hermesTag);
expect(readHermesTag()).toEqual(hermesTag);
});
});
describe('getHermesTagSHA', () => {
it('should return trimmed commit SHA for Hermes tag', () => {
expect(getHermesTagSHA(hermesTag)).toEqual(hermesTagSha);
expect(execCalls.git).toBeTruthy();
});
});
describe('downloadHermesTarball', () => {
it('should download Hermes tarball to download dir', () => {
fs.writeFileSync(path.join(SDKS_DIR, '.hermesversion'), hermesTag);
downloadHermesTarball();
expect(execCalls.curl).toBeTruthy();
expect(
fs.readFileSync(
path.join(SDKS_DIR, 'download', `hermes-${hermesTagSha}.tgz`),
{
encoding: 'utf8',
flag: 'r',
},
),
).toEqual(tarballContents);
});
it('should not re-download Hermes tarball if tarball exists', () => {
fs.mkdirSync(path.join(SDKS_DIR, 'download'), {recursive: true});
fs.writeFileSync(
path.join(SDKS_DIR, 'download', `hermes-${hermesTagSha}.tgz`),
tarballContents,
);
downloadHermesTarball();
expect(execCalls.curl).toBeUndefined();
});
});
describe('expandHermesTarball', () => {
it('should expand Hermes tarball to Hermes source dir', () => {
fs.mkdirSync(path.join(SDKS_DIR, 'download'), {recursive: true});
fs.writeFileSync(
path.join(SDKS_DIR, 'download', `hermes-${hermesTagSha}.tgz`),
tarballContents,
);
expect(fs.existsSync(path.join(SDKS_DIR, 'hermes'))).toBeFalsy();
expandHermesTarball();
expect(execCalls.tar).toBe(true);
expect(fs.existsSync(path.join(SDKS_DIR, 'hermes'))).toBeTruthy();
});
it('should fail if Hermes tarball does not exist', () => {
expect(() => {
expandHermesTarball();
}).toThrow('[Hermes] Failed to expand 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',
),
{
encoding: 'utf8',
flag: 'r',
},
),
).toEqual(
fs.readFileSync(
path.join(
ROOT_DIR,
'sdks',
'hermes-engine',
'utils',
'build-mac-framework.sh',
),
{
encoding: 'utf8',
flag: 'r',
},
),
);
expect(
fs.readFileSync(
path.join(SDKS_DIR, 'hermes', 'hermes-engine.podspec'),
{
encoding: 'utf8',
flag: 'r',
},
),
).toEqual(
fs.readFileSync(
path.join(SDKS_DIR, 'hermes-engine', 'hermes-engine.podspec'),
{
encoding: 'utf8',
flag: 'r',
},
),
);
});
});
});
+47 -31
View File
@@ -11,7 +11,7 @@
const fs = require('fs');
const path = require('path');
const {echo, exec, exit} = require('shelljs');
const {execSync} = require('child_process');
const SDKS_DIR = path.normalize(path.join(__dirname, '..', '..', 'sdks'));
const HERMES_DIR = path.join(SDKS_DIR, 'hermes');
@@ -41,14 +41,21 @@ function prepareFileSystem() {
function readHermesTag() {
if (fs.existsSync(HERMES_TAG_FILE_PATH)) {
const data = fs.readFileSync(HERMES_TAG_FILE_PATH, {
encoding: 'utf8',
flag: 'r',
});
return data.trim();
} else {
return 'main';
const data = fs
.readFileSync(HERMES_TAG_FILE_PATH, {
encoding: 'utf8',
flag: 'r',
})
.trim();
if (data.length > 0) {
return data;
} else {
throw new Error('[Hermes] .hermesversion file is empty.');
}
}
return 'main';
}
function setHermesTag(hermesTag) {
@@ -64,10 +71,11 @@ function setHermesTag(hermesTag) {
}
function getHermesTagSHA(hermesTag) {
return exec(
return execSync(
`git ls-remote https://github.com/facebook/hermes ${hermesTag} | cut -f 1`,
{silent: true},
).trim();
)
.toString()
.trim();
}
function getHermesTarballDownloadPath(hermesTag) {
@@ -87,11 +95,13 @@ function downloadHermesTarball() {
return;
}
echo(`[Hermes] Downloading Hermes source code for commit ${hermesTagSHA}`);
if (exec(`curl ${hermesTarballUrl} -Lo ${hermesTarballDownloadPath}`).code) {
echo('[Hermes] Failed to download Hermes tarball.');
exit(1);
return;
console.info(
`[Hermes] Downloading Hermes source code for commit ${hermesTagSHA}`,
);
try {
execSync(`curl ${hermesTarballUrl} -Lo ${hermesTarballDownloadPath}`);
} catch (error) {
throw new Error(`[Hermes] Failed to download Hermes tarball. ${error}`);
}
}
@@ -103,26 +113,26 @@ function expandHermesTarball() {
prepareFileSystem();
if (!fs.existsSync(hermesTarballDownloadPath)) {
echo(
`[Hermes] Failed to expand Hermes tarball, no file found at ${hermesTarballDownloadPath}.`,
);
exit(1);
return;
throw new Error(`[Hermes] Failed to expand Hermes tarball.`);
}
echo(`[Hermes] Expanding Hermes tarball for commit ${hermesTagSHA}`);
if (
exec(
console.info(`[Hermes] Expanding Hermes tarball for commit ${hermesTagSHA}`);
try {
execSync(
`tar -zxf ${hermesTarballDownloadPath} --strip-components=1 --directory ${HERMES_DIR}`,
).code
) {
echo('[Hermes] Failed to expand Hermes tarball.');
exit(1);
return;
);
} catch (error) {
throw new Error('[Hermes] Failed to expand Hermes tarball.');
}
}
function copyBuildScripts() {
if (!fs.existsSync(HERMES_DIR)) {
throw new Error(
'[Hermes] Failed to copy Hermes build scripts, no Hermes source directory found.',
);
}
fs.copyFileSync(
`${SDKS_DIR}/hermes-engine/hermes-engine.podspec`,
`${HERMES_DIR}/hermes-engine.podspec`,
@@ -155,8 +165,14 @@ set_target_properties(native-hermesc PROPERTIES
IMPORTED_LOCATION "${MACOS_HERMESC_PATH}"
)`;
fs.mkdirSync(MACOS_BIN_DIR, {recursive: true});
fs.writeFileSync(MACOS_IMPORT_HERMESC_PATH, IMPORT_HERMESC_TEMPLATE);
try {
fs.mkdirSync(MACOS_BIN_DIR, {recursive: true});
fs.writeFileSync(MACOS_IMPORT_HERMESC_PATH, IMPORT_HERMESC_TEMPLATE);
} catch (error) {
console.warn(
`[Hermes] Re-compiling hermesc. Unable to configure make: ${error}`,
);
}
}
module.exports = {