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

compile WebAssembly in CI #486

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
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
39 changes: 39 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@ jobs:
run: |
make build/libllhttp.a

- name: Upload build
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
with:
name: build-${{ runner.os }}
path: build/

test:
name: Run tests
runs-on: ${{ matrix.os }}
Expand Down Expand Up @@ -116,3 +122,36 @@ jobs:

- name: Run lint command
run: npm run lint

build-wasm:
name: Build WebAssembly
runs-on: ubuntu-latest
steps:
- name: Fetch code
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
fetch-depth: 1

- name: Restore node_modules cache for Linux
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
if: runner.os == 'Linux'
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-

- name: Install dependencies
run: npm ci --ignore-scripts

- name: Prepare build
run: npm run prebuild-wasm

- name: Build
run: npm run build-wasm

- name: Upload build
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
with:
name: build-wasm
path: build/
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ FROM node:22-alpine@sha256:ed9736a13b88ba55cbc08c75c9edac8ae7f72840482e40324670b
ARG UID=1000
ARG GID=1000

RUN apk add -U clang lld wasi-sdk && mkdir /home/node/llhttp
RUN apk add -U clang lld wasi-sdk bash && mkdir /home/node/llhttp

WORKDIR /home/node/llhttp

Expand Down
88 changes: 88 additions & 0 deletions bin/build_wasm.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
#!/usr/bin/env bash

set -e

cd "$(dirname "$0")/../"

if [[ -z "$WASM_PLATFORM" && -n "$1" ]]; then
WASM_PLATFORM=$(docker info -f "{{.OSType}}/{{.Architecture}}")
fi

case "$1" in
--prebuild)
exec docker build --platform="$WASM_PLATFORM" -t llhttp_wasm_builder . --load
;;
--setup)
mkdir -p build
exit 0
;;
--docker)
cmd=(docker run --rm --platform="$WASM_PLATFORM")
if [[ -z "$CI" ]]; then
cmd+=(-it)
fi
# Try to avoid root permission problems on compiled assets
# when running on linux.
# It will work flawessly if uid === gid === 1000
# there will be some warnings otherwise.
if [[ "$(uname)" == Linux ]]; then
cmd+=(--user "$(id -u):$(id -g)")
fi
cmd+=(--mount "type=bind,source=./build,target=/home/node/llhttp/build" llhttp_wasm_builder npm run wasm)

echo "> ${cmd[*]}"
exec "${cmd[@]}"
;;
esac

out=build/wasm
mkdir -p "$out"

npm run build

# shellcheck disable=SC2054 # the commas are intentional
CFLAGS=(
--sysroot=/usr/share/wasi-sysroot
-target wasm32-unknown-wasi
-Ofast
-fno-exceptions
-fvisibility=hidden
-mexec-model=reactor
-Wl,-error-limit=0
-Wl,-O3
-Wl,--lto-O3
-Wl,--strip-all
-Wl,--allow-undefined
-Wl,--export-dynamic
-Wl,--export-table
-Wl,--export=malloc
-Wl,--export=free
-Wl,--no-entry
build/c/*.c
src/native/*.c
-Ibuild
)

clang "${CFLAGS[@]}" -mno-bulk-memory -mno-multivalue -mno-relaxed-simd -mno-sign-ext -mno-simd128 -o "$out/llhttp_baseline.wasm"
clang "${CFLAGS[@]}" -mbulk-memory -mmultivalue -mrelaxed-simd -msign-ext -msimd128 -o "$out/llhttp_opt.wasm"

js_template="'use strict'
const { Buffer } = require('node:buffer')
const wasmBase64 = '%s'
let wasmBuffer
Object.defineProperty(module, 'exports', {
get: () => {
return wasmBuffer
? wasmBuffer
: (wasmBuffer = Buffer.from(wasmBase64, 'base64'))
}
})
"


# shellcheck disable=SC2059 # I want to use the variable
printf "$js_template" "$(base64 -w0 "$out/llhttp_baseline.wasm")" > "$out/llhttp_baseline.js"
# shellcheck disable=SC2059
printf "$js_template" "$(base64 -w0 "$out/llhttp_opt.wasm")" > "$out/llhttp_opt.js"

cp lib/llhttp/{constants,utils}.* "$out/"
97 changes: 0 additions & 97 deletions bin/build_wasm.ts

This file was deleted.

5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,16 @@
"types": "lib/llhttp.d.ts",
"files": [
"lib",
"src"
"src",
"build"
],
"scripts": {
"bench": "ts-node bench/",
"build": "ts-node bin/generate.ts",
"build-ts": "tsc",
"prebuild-wasm": "npm run wasm -- --prebuild && npm run wasm -- --setup",
"build-wasm": "npm run wasm -- --docker",
"wasm": "ts-node bin/build_wasm.ts",
"wasm": "bash bin/build_wasm.sh",
"clean": "rm -rf lib && rm -rf test/tmp",
"prepare": "npm run clean && npm run build-ts",
"test": "node -r ts-node/register/type-check ./test/md-test.ts",
Expand Down
31 changes: 8 additions & 23 deletions src/native/api.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,29 +57,14 @@ static int wasm_on_headers_complete_wrap(llhttp_t* p) {
}

const llhttp_settings_t wasm_settings = {
wasm_on_message_begin,
wasm_on_url,
wasm_on_status,
NULL,
NULL,
wasm_on_header_field,
wasm_on_header_value,
NULL,
NULL,
wasm_on_headers_complete_wrap,
wasm_on_body,
wasm_on_message_complete,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
.on_message_begin = wasm_on_message_begin,
.on_url = wasm_on_url,
.on_status = wasm_on_status,
.on_header_field = wasm_on_header_field,
.on_header_value = wasm_on_header_value,
.on_headers_complete = wasm_on_headers_complete_wrap,
.on_body = wasm_on_body,
.on_message_complete = wasm_on_message_complete,
};


Expand Down