diff --git a/.github/workflows/build-emhermesc.yml b/.github/workflows/build-emhermesc.yml new file mode 100644 index 0000000000..deab163333 --- /dev/null +++ b/.github/workflows/build-emhermesc.yml @@ -0,0 +1,98 @@ +name: Build and commit/verify emhermesc.js + +on: + push: + branches: + - "main" + paths: + - "packages/metro-hermes-compiler/**" + - ".github/workflows/build-emhermesc.yml" + pull_request: + paths: + - "packages/metro-hermes-compiler/**" + - ".github/workflows/build-emhermesc.yml" + +jobs: + build-emhermesc-js: + runs-on: ubuntu-latest + + steps: + - name: Checkout code (PR) + uses: actions/checkout@v2.0.0 + # https://github.com/stefanzweifel/git-auto-commit-action#checkout-the-correct-branch + if: github.event_name == 'pull_request' + with: + ref: ${{ github.head_ref }} + + - name: Checkout code (Push) + uses: actions/checkout@v2.0.0 + if: github.event_name == 'push' + + - name: Determine target revision from packages/metro-hermes-compiler/hermes-github-ref + run: echo "HERMES_GITHUB_REF=`cat packages/metro-hermes-compiler/hermes-github-ref`" >> $GITHUB_ENV + + - name: Download hermes at ${{ env.HERMES_GITHUB_REF }} + run: | + mkdir $RUNNER_TEMP/hermes && curl \ + -L https://api.github.com/repos/facebook/hermes/tarball/${{ env.HERMES_GITHUB_REF }} \ + | tar xzf - -C $RUNNER_TEMP/hermes \ + && echo "HERMES_CHECKOUT=`ls -d $RUNNER_TEMP/hermes/*`" >> $GITHUB_ENV + + - name: Setup Ninja + uses: seanmiddleditch/gha-setup-ninja@856654e80dd21909aec244cd01bb96e5c841d64f + with: + destination: ${{ runner.temp }}/ninja + + - name: Configure build_host_hermes + run: python3 $HERMES_CHECKOUT/utils/build/configure.py $RUNNER_TEMP/build_host_hermes + + - name: Build build_host_hermes + run: cmake --build $RUNNER_TEMP/build_host_hermes --target hermesc + + - name: Setup Emscripten SDK + uses: mymindstorm/setup-emsdk@v11 + + - name: Configure Emscripten hermes build + run: | + cmake $HERMES_CHECKOUT \ + -B $RUNNER_TEMP/embuild \ + -DCMAKE_TOOLCHAIN_FILE=$EMSDK/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_EXE_LINKER_FLAGS=" \ + -s BINARYEN_ASYNC_COMPILATION=0 \ + -s ENVIRONMENT=node \ + -s EXPORT_NAME=createHermesc \ + -s EXTRA_EXPORTED_RUNTIME_METHODS=[cwrap,ccall] \ + -s MODULARIZE=1 \ + -s NODERAWFS=1 \ + -s WASM=1 \ + -s ALLOW_MEMORY_GROWTH=1 \ + -s NODEJS_CATCH_EXIT=0 \ + -s NODEJS_CATCH_REJECTION=0 \ + -s WASM_ASYNC_COMPILATION=0 \ + -s SINGLE_FILE=1 \ + " \ + -DIMPORT_HERMESC:PATH="$RUNNER_TEMP/build_host_hermes/ImportHermesc.cmake" + + - name: Build emhermesc + run: cmake --build $RUNNER_TEMP/embuild --target emhermesc + + - name: Concatenate with emhermesc.js.header and move to packages/metro-hermes-compiler/src/emhermesc.js + run: | + cat packages/metro-hermes-compiler/src/emhermesc.js.header $RUNNER_TEMP/embuild/bin/emhermesc.js \ + > packages/metro-hermes-compiler/src/emhermesc.js + + - name: Upload emhermesc.js as a CI artifact + uses: actions/upload-artifact@v3 + with: + name: emhermesc.js + path: packages/metro-hermes-compiler/src/emhermesc.js + + - name: Commit updated emhermesc.js (PR only) + uses: stefanzweifel/git-auto-commit-action@d0487b9fa3a792b5e90562c27541eedecc2548b4 + if: github.event_name == 'pull_request' + with: + commit_message: "Auto: Build emhermesc.js from hermes/${{ env.HERMES_REVISION }}" + + - name: Fail if emhermesc.js is out of sync with hermes-revision + run: if [ -n "$(git status --porcelain)" ]; then exit 1; fi diff --git a/packages/metro-hermes-compiler/README.md b/packages/metro-hermes-compiler/README.md index 57f6368242..9775ae466d 100644 --- a/packages/metro-hermes-compiler/README.md +++ b/packages/metro-hermes-compiler/README.md @@ -4,15 +4,14 @@ This experimental module provides a high-level API to work with the Hermes bytec ## How to build HBC -A pre-configured emscripten environment can be used through this [Docker image](https://hub.docker.com/r/trzeci/emscripten/). Docker can be installed via its [desktop app](https://docs.docker.com/docker-for-mac/). Make sure to increase resource limits (16G RAM, as much CPU as possible). +[`./src/emhermesc.js`](https://github.com/rh389/metro/blob/main/packages/metro-hermes-compiler/src/emhermesc.js) is built by a [GitHub action on the Metro repository](https://github.com/rh389/metro/blob/main/.github/workflows/build-emhermesc.yml). It works by: -``` -cd path/to/hermes/checkout -docker run -i -t --rm -v `pwd`:`pwd` trzeci/emscripten bash -apt-get update -y && apt-get install -y icu-devtools -cd path/to/hermes/checkout -cmake . -DCMAKE_TOOLCHAIN_FILE=/emsdk_portable/emscripten/sdk/cmake/Modules/Platform/Emscripten.cmake -DCMAKE_BUILD_TYPE=Release -make -j emhermesc -``` +1. Checking out the [`facebook/hermes`](https://github.com/facebook/hermes) repo at a particular GitHub `ref` (commit or tag) specified by [`./hermes-github-ref`](https://github.com/rh389/metro/blob/main/packages/metro-hermes-compiler/hermes-github-ref) +2. Following the two stage process outlined at [`facebook/hermes/doc/Emscripten.md`](https://github.com/facebook/hermes/blob/17d632d0802a0a3fb97a962ede6a6291e5029c84/doc/Emscripten.md) to build with Emscripten and CMake, and +3. Prepending our custom header from [`./src/emhermesc.js.header`](https://github.com/rh389/metro/blob/main/packages/metro-hermes-compiler/src/emhermesc.js.header). -After the build process finishes the Hermes Bytecode Compiler JavaScript file will be available in the `bin` folder. +To update the build, open a GitHub PR (or export one from Phabricator) that changes the contents of `hermes-github-ref` to the new target `ref`. The GH action should run on the PR and then push a new commit to the PR branch (if it has access) with the updated `emhermesc.js` - that's it! + +The PR can then be (re-)imported and pushed. The action will run again on a push to `main` to verify that `hermes-github-ref` and `emhermesc.js` are in sync. + +**If** the action is able to build `emhermesc.js` but doesn't have permission to push to the PR branch, or fails validation on `main`, you can still use the build output and update it manually - you'll find it uploaded as an artifact on the action instance. \ No newline at end of file diff --git a/packages/metro-hermes-compiler/hermes-github-ref b/packages/metro-hermes-compiler/hermes-github-ref new file mode 100644 index 0000000000..4d7676e774 --- /dev/null +++ b/packages/metro-hermes-compiler/hermes-github-ref @@ -0,0 +1 @@ +45e487103aa121bdaab14653abe29d720702d930 \ No newline at end of file diff --git a/packages/metro-hermes-compiler/src/emhermesc.js.header b/packages/metro-hermes-compiler/src/emhermesc.js.header new file mode 100644 index 0000000000..6b1a60620d --- /dev/null +++ b/packages/metro-hermes-compiler/src/emhermesc.js.header @@ -0,0 +1,10 @@ +/** + * 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. + * + * @generated + */ + +/* eslint-disable */