Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: build wasm in common wasm-builder #105

Merged
merged 1 commit into from
Nov 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 3 additions & 15 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ on:
branches: main

env:
WASI_VERSION: 12
WASI_VERSION_FULL: "12.0"
WABT_VERSION: "1.0.24"
EMCC_VERSION: "1.40.1-fastcomp"

Expand All @@ -25,22 +23,12 @@ jobs:
export PWD=$(pwd);
echo "::set-output name=PROJ_ROOT::$PWD";

- name: Set up Docker
uses: docker/setup-buildx-action@c47758b77c9736f4b2ef4073d4d51994fabfe349 # v3.7.1

- name: Install
run: npm install

- name: Install wasi-sdk
env:
PROJ_ROOT: ${{ steps.preparation.outputs.PROJ_ROOT }}
run: |
cd $PROJ_ROOT;
cd ../;
export WASI_OS="linux"
curl -sL https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${WASI_VERSION}/wasi-sdk-${WASI_VERSION_FULL}-${WASI_OS}.tar.gz -O
# check if package downloaded
ls -la
tar xvf wasi-sdk-${WASI_VERSION_FULL}-${WASI_OS}.tar.gz
# print clang version
./wasi-sdk-${WASI_VERSION_FULL}/bin/clang --version
- name: Install wabt
env:
PROJ_ROOT: ${{ steps.preparation.outputs.PROJ_ROOT }}
Expand Down
19 changes: 1 addition & 18 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,33 +1,16 @@
# These flags depend on the system and may be overridden
WASM_CC := ../wasi-sdk-12.0/bin/clang
WASM_CFLAGS := --sysroot=../wasi-sdk-12.0/share/wasi-sysroot
WASM_LDFLAGS := -nostartfiles

WASM2WAT := ../wabt/bin/wasm2wat
WASM_OPT := ../binaryen/bin/wasm-opt

# These are project-specific and are expected to be kept intact
WASM_EXTRA_CFLAGS := -I include-wasm/ -Wno-logical-op-parentheses -Wno-parentheses -Oz
WASM_EXTRA_LDFLAGS := -Wl,-z,stack-size=13312,--no-entry,--compress-relocations,--strip-all
WASM_EXTRA_LDFLAGS += -Wl,--export=__heap_base,--export=parseCJS,--export=sa
WASM_EXTRA_LDFLAGS += -Wl,--export=e,--export=re,--export=es,--export=ee
WASM_EXTRA_LDFLAGS += -Wl,--export=rre,--export=ree,--export=res,--export=ru,--export=us,--export=ue

.PHONY: optimize clean

lib/lexer.wat: lib/lexer.wasm
$(WASM2WAT) lib/lexer.wasm -o lib/lexer.wat

lib/lexer.wasm: include-wasm/cjs-module-lexer.h src/lexer.c | lib/
$(WASM_CC) $(WASM_CFLAGS) $(WASM_EXTRA_CFLAGS) \
src/lexer.c -o lib/lexer.wasm \
$(WASM_LDFLAGS) $(WASM_EXTRA_LDFLAGS)
node build/wasm.js --docker

lib/:
@mkdir -p $@

optimize: lib/lexer.wasm
$(WASM_OPT) -Oz lib/lexer.wasm -o lib/lexer.wasm

clean:
$(RM) lib/*
16 changes: 9 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -442,17 +442,19 @@ test/samples/*.js (3635 KiB)

### Wasm Build Steps

To build download the WASI SDK from https://github.com/WebAssembly/wasi-sdk/releases.
The build uses docker and make, they must be installed first.

The Makefile assumes the existence of "wasi-sdk-11.0" and "wabt" (optional) as sibling folders to this project.
To build the lexer wasm run `npm run build-wasm`.

The build through the Makefile is then run via `make lib/lexer.wasm`, which can also be triggered via `npm run build-wasm` to create `dist/lexer.js`.
Optimization passes are run with [Binaryen](https://github.com/WebAssembly/binaryen)
prior to publish to reduce the Web Assembly footprint.

On Windows it may be preferable to use the Linux subsystem.
After building the lexer wasm, build the final distribution components
(lexer.js and lexer.mjs) by running `npm run build`.

After the Web Assembly build, the CJS build can be triggered via `npm run build`.

Optimization passes are run with [Binaryen](https://github.com/WebAssembly/binaryen) prior to publish to reduce the Web Assembly footprint.
If you need to build lib/lexer.wat (optional) you must first install
[wabt](https://github.com/WebAssembly/wabt) as a sibling folder to this
project. The wat file is then build by running `make lib/lexer.wat`

### License

Expand Down
13 changes: 13 additions & 0 deletions build/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
lib/lexer.wasm: include-wasm/cjs-module-lexer.h src/lexer.c
@mkdir -p lib
clang --sysroot=/usr/share/wasi-sysroot -target wasm32-unknown-wasi src/lexer.c -I include-wasm -o lib/lexer.wasm -nostartfiles \
-Wl,-z,stack-size=13312,--no-entry,--compress-relocations,--strip-all,--export=__heap_base,\
--export=parseCJS,--export=sa,--export=e,--export=re,--export=es,--export=ee,--export=rre,--export=ree,--export=res,--export=ru,--export=us,--export=ue \
-Wno-logical-op-parentheses -Wno-parentheses \
-Oz

optimize: lib/lexer.wasm
${WASM_OPT} -Oz lib/lexer.wasm -o lib/lexer.wasm

clean:
rm lib/*
54 changes: 54 additions & 0 deletions build/wasm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
'use strict'

const WASM_BUILDER_CONTAINER = 'ghcr.io/nodejs/wasm-builder@sha256:975f391d907e42a75b8c72eb77c782181e941608687d4d8694c3e9df415a0970' // v0.0.9

const WASM_OPT = './wasm-opt'

const { execSync } = require('node:child_process')
const { writeFileSync, readFileSync, existsSync, mkdirSync } = require('node:fs')
const { join, resolve } = require('node:path')

const ROOT = resolve(__dirname, '../')

let platform = process.env.WASM_PLATFORM
if (!platform && process.argv[2]) {
platform = execSync('docker info -f "{{.OSType}}/{{.Architecture}}"').toString().trim()
}

if (process.argv[2] === '--docker') {
let cmd = `docker run --rm --platform=${platform.toString().trim()} `
if (process.platform === 'linux') {
cmd += ` --user ${process.getuid()}:${process.getegid()}`
}

if (!existsSync(`${ROOT}/dist`)){
mkdirSync(`${ROOT}/dist`);
}

cmd += ` --mount type=bind,source=${ROOT}/lib,target=/home/node/build/lib \
--mount type=bind,source=${ROOT}/src,target=/home/node/build/src \
--mount type=bind,source=${ROOT}/dist,target=/home/node/build/dist \
--mount type=bind,source=${ROOT}/node_modules,target=/home/node/build/node_modules \
--mount type=bind,source=${ROOT}/build/wasm.js,target=/home/node/build/wasm.js \
--mount type=bind,source=${ROOT}/build/Makefile,target=/home/node/build/Makefile \
--mount type=bind,source=${ROOT}/build.js,target=/home/node/build/build.js \
--mount type=bind,source=${ROOT}/package.json,target=/home/node/build/package.json \
--mount type=bind,source=${ROOT}/include-wasm,target=/home/node/build/include-wasm \
-t ${WASM_BUILDER_CONTAINER} node wasm.js`
console.log(`> ${cmd}\n\n`)
execSync(cmd, { stdio: 'inherit' })
process.exit(0)
}

const hasOptimizer = (function () {
try { execSync(`${WASM_OPT} --version`); return true } catch (error) { return false }
})()

// Build wasm binary
console.log('Building wasm');
execSync(`make lib/lexer.wasm`, { stdio: 'inherit' })
if (hasOptimizer) {
console.log('Optimizing wasm');
execSync(`make optimize`, { stdio: 'inherit' })
}
execSync(`node build.js`, { stdio: 'inherit' })
Binary file modified lib/lexer.wasm
Binary file not shown.
Loading