diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3231523..ef0213c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -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" @@ -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 }} diff --git a/Makefile b/Makefile index 961b336..9a75850 100755 --- a/Makefile +++ b/Makefile @@ -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/* diff --git a/README.md b/README.md index 2716709..cc7ca50 100755 --- a/README.md +++ b/README.md @@ -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 diff --git a/build/Makefile b/build/Makefile new file mode 100755 index 0000000..f13c390 --- /dev/null +++ b/build/Makefile @@ -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/* diff --git a/build/wasm.js b/build/wasm.js new file mode 100644 index 0000000..58fb640 --- /dev/null +++ b/build/wasm.js @@ -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' }) diff --git a/lib/lexer.wasm b/lib/lexer.wasm index 261b415..ae6ac5a 100755 Binary files a/lib/lexer.wasm and b/lib/lexer.wasm differ