diff --git a/.github/workflows/build-emhermesc.yml b/.github/workflows/build-emhermesc.yml new file mode 100644 index 0000000000..1a17fab9ca --- /dev/null +++ b/.github/workflows/build-emhermesc.yml @@ -0,0 +1,105 @@ +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" + +permissions: + contents: write + pull-requests: write + +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: + repository: ${{ github.event.pull_request.head.repo.full_name }} + ref: ${{ github.head_ref }} + path: metro + + - name: Checkout code (Push) + uses: actions/checkout@v2.0.0 + if: github.event_name == 'push' + with: + path: metro + + - name: Determine target revision from packages/metro-hermes-compiler/hermes-github-ref + run: echo "HERMES_GITHUB_REF=`head -n 1 metro/packages/metro-hermes-compiler/hermes-github-ref`" >> $GITHUB_ENV + + - name: Checkout facebook/hermes at ${{ env.HERMES_GITHUB_REF }} + uses: actions/checkout@v3 + with: + repository: facebook/hermes + ref: ${{ env.HERMES_GITHUB_REF }} + path: hermes + + - name: Setup Ninja + uses: seanmiddleditch/gha-setup-ninja@856654e80dd21909aec244cd01bb96e5c841d64f + + - name: Configure build_host_hermesc + run: python3 ./hermes/utils/build/configure.py ./build_host_hermesc + + - name: Build build_host_hermesc + run: cmake --build ./build_host_hermesc --target hermesc + + - name: Setup Emscripten SDK + uses: mymindstorm/setup-emsdk@v11 + + - name: Configure Emscripten hermes build + run: | + cmake hermes \ + -B 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="$GITHUB_WORKSPACE/build_host_hermesc/ImportHermesc.cmake" + + - name: Build emhermesc + run: cmake --build embuild --target emhermesc + + - name: Concatenate with emhermesc.js.header and move to packages/metro-hermes-compiler/src/emhermesc.js + run: | + cat metro/packages/metro-hermes-compiler/src/emhermesc.js.header embuild/bin/emhermesc.js \ + > metro/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: metro/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 }}" + repository: 'metro' + + - name: Fail if emhermesc.js is out of sync with hermes-revision + run: if [ -n "$(cd metro && 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..fd2726c91d --- /dev/null +++ b/packages/metro-hermes-compiler/hermes-github-ref @@ -0,0 +1 @@ +v0.11.0 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 */