name: Build on: create: tags: push: branches: - main pull_request: jobs: build: name: Native runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: os: - ubuntu-latest - ubuntu-24.04-arm - macos-latest steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Install deps (Linux) run: | sudo apt-get update sudo apt-get install libedit-dev xxd libffi-dev libssl-dev if: startsWith(matrix.os, 'ubuntu-') - name: Install deps (macOS) run: | brew update brew install vim libffi openssl make coreutils bash echo "$(brew --prefix)/opt/make/libexec/gnubin" >> $GITHUB_PATH if: matrix.os == 'macos-latest' - name: Fetch tags run: git fetch --tags --force origin - name: Build run: make release - name: Test run: make test - name: Upload artifacts uses: actions/upload-artifact@v4 with: name: ${{ format('tpl-{0}-{1}', runner.os, runner.arch) }} path: | tpl LICENSE ATTRIBUTION README.md windows: name: Windows runs-on: windows-latest defaults: run: shell: msys2 {0} steps: - uses: msys2/setup-msys2@v2 - name: Install deps run: | pacman --noconfirm -S make mingw-w64-x86_64-gcc mingw-w64-x86_64-headers-git mingw-w64-x86_64-libffi mingw-w64-x86_64-dlfcn pacman --noconfirm -S mingw-w64-x86_64-openssl mingw-w64-x86_64-libwinpthread vim diffutils git - name: Configure line endings run: git config --global core.autocrlf input - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Fetch tags run: git fetch --tags --force origin - name: Build run: make WIN=1 release - name: Test run: make test - name: Make Windows-friendly run: | cp ${MINGW_PREFIX}/bin/{libcrypto-3-x64.dll,libssl-3-x64.dll,libffi-8.dll,libdl.dll,libwinpthread-1.dll} . echo -e "\n\nOpenSSL (libcrypto-3-x64.dll, libssl-3-x64.dll):\n" >> ATTRIBUTION cat ${MINGW_PREFIX}/share/licenses/openssl/LICENSE >> ATTRIBUTION echo -e "\n\nlibffi: (libffi-8.dll)\n" >> ATTRIBUTION cat ${MINGW_PREFIX}/share/licenses/libffi/LICENSE >> ATTRIBUTION echo -e "\n\ndlfcn: (libdl.dll)\n" >> ATTRIBUTION cat ${MINGW_PREFIX}/share/licenses/dlfcn/LICENSE >> ATTRIBUTION echo -e "\n\nlibwinpthread:\n" >> ATTRIBUTION cat ${MINGW_PREFIX}/share/licenses/libwinpthread/COPYING >> ATTRIBUTION echo -e "\n\nisocline:\n" >> ATTRIBUTION cat src/isocline/LICENSE >> ATTRIBUTION if [ ! -f "tpl.exe" ]; then mv tpl tpl.exe fi mv ATTRIBUTION ATTRIBUTION.txt mv LICENSE LICENSE.txt - name: Upload artifacts uses: actions/upload-artifact@v4 with: name: ${{ format('tpl-{0}-{1}', runner.os, runner.arch) }} path: | tpl.exe LICENSE.txt ATTRIBUTION.txt README.md libcrypto-3-x64.dll libssl-3-x64.dll libffi-8.dll libdl.dll libwinpthread-1.dll windows-arm64: name: Windows ARM64 runs-on: windows-11-arm defaults: run: shell: msys2 {0} steps: - uses: msys2/setup-msys2@v2 with: msystem: CLANGARM64 update: true - name: Install deps run: | pacman --noconfirm -S make file mingw-w64-clang-aarch64-clang mingw-w64-clang-aarch64-headers-git pacman --noconfirm -S mingw-w64-clang-aarch64-libffi mingw-w64-clang-aarch64-dlfcn mingw-w64-clang-aarch64-openssl pacman --noconfirm -S mingw-w64-clang-aarch64-winpthreads mingw-w64-clang-aarch64-libwinpthread vim diffutils git - name: Configure line endings run: git config --global core.autocrlf input - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Fetch tags run: git fetch --tags --force origin - name: Build run: make WIN=1 CC=clang HOST_CC=clang AR=llvm-ar release - name: Verify architecture run: | llvm-readobj --file-headers tpl.exe | grep -q 'Machine: IMAGE_FILE_MACHINE_ARM64' - name: Test run: make test - name: Make Windows-friendly run: | cp ${MINGW_PREFIX}/bin/{libcrypto-3-arm64.dll,libssl-3-arm64.dll,libffi-8.dll,libdl.dll,libwinpthread-1.dll} . echo -e "\n\nOpenSSL (libcrypto-3-arm64.dll, libssl-3-arm64.dll):\n" >> ATTRIBUTION cat ${MINGW_PREFIX}/share/licenses/openssl/LICENSE >> ATTRIBUTION echo -e "\n\nlibffi: (libffi-8.dll)\n" >> ATTRIBUTION cat ${MINGW_PREFIX}/share/licenses/libffi/LICENSE >> ATTRIBUTION echo -e "\n\ndlfcn: (libdl.dll)\n" >> ATTRIBUTION cat ${MINGW_PREFIX}/share/licenses/dlfcn/LICENSE >> ATTRIBUTION echo -e "\n\nlibwinpthread:\n" >> ATTRIBUTION cat ${MINGW_PREFIX}/share/licenses/winpthreads/COPYING >> ATTRIBUTION echo -e "\n\nisocline:\n" >> ATTRIBUTION cat src/isocline/LICENSE >> ATTRIBUTION mv ATTRIBUTION ATTRIBUTION.txt mv LICENSE LICENSE.txt - name: Upload artifacts uses: actions/upload-artifact@v4 with: name: tpl-Windows-ARM64 path: | tpl.exe LICENSE.txt ATTRIBUTION.txt README.md libcrypto-3-arm64.dll libssl-3-arm64.dll libffi-8.dll libdl.dll libwinpthread-1.dll linux32: name: Linux x86 (32-bit) runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Install 32-bit dependencies run: | sudo dpkg --add-architecture i386 sudo apt-get update sudo apt-get install file gcc-multilib libedit-dev:i386 libffi-dev:i386 libssl-dev:i386 xxd - name: Fetch tags run: git fetch --tags --force origin - name: Build run: make OPT=-m32 release - name: Verify architecture run: file tpl | grep -q 'ELF 32-bit.*Intel 80386' - name: Test run: make test - name: Upload artifacts uses: actions/upload-artifact@v4 with: name: tpl-Linux-X86 path: | tpl LICENSE ATTRIBUTION README.md s390x: name: Linux s390x (big-endian, experimental) runs-on: ubuntu-24.04 continue-on-error: true timeout-minutes: 60 steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Set up QEMU uses: docker/setup-qemu-action@v4 with: platforms: s390x - name: Build and test under s390x run: | docker run --rm --platform linux/s390x \ --volume "$GITHUB_WORKSPACE:/workspace" \ --workdir /workspace \ --env LANG=C.UTF-8 \ --env LC_ALL=C.UTF-8 \ ubuntu:24.04 \ bash -euxo pipefail -c ' export DEBIAN_FRONTEND=noninteractive apt-get update apt-get install -y build-essential file git libedit-dev libffi-dev libssl-dev xxd git config --global --add safe.directory /workspace make clean make release file tpl | grep -q "ELF 64-bit MSB.*IBM S/390" make test ' - name: Upload artifacts uses: actions/upload-artifact@v4 with: name: tpl-Linux-S390X path: | tpl LICENSE ATTRIBUTION README.md cosmo: name: Cosmopolitan runs-on: ubuntu-latest env: COSMOCC_VERSION: 4.0.2 steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Cache cosmocc id: cache-cosmocc uses: actions/cache@v4 with: path: ${{ runner.temp }}/cosmocc key: cosmocc-${{ runner.os }}-${{ env.COSMOCC_VERSION }} - name: Install cosmocc if: steps.cache-cosmocc.outputs.cache-hit != 'true' run: | mkdir -p "${RUNNER_TEMP}/cosmocc" curl -fsSL "https://cosmo.zip/pub/cosmocc/cosmocc-${COSMOCC_VERSION}.zip" -o "${RUNNER_TEMP}/cosmocc.zip" unzip -q "${RUNNER_TEMP}/cosmocc.zip" -d "${RUNNER_TEMP}/cosmocc" - name: Add cosmocc to PATH run: echo "${RUNNER_TEMP}/cosmocc/bin" >> "$GITHUB_PATH" - name: Build run: make cosmo - name: Upload artifacts uses: actions/upload-artifact@v4 with: name: tpl-cosmopolitan path: | tpl tpl.aarch64.elf tpl.com.dbg LICENSE ATTRIBUTION README.md freebsd: name: FreeBSD runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Build and test in FreeBSD uses: vmactions/freebsd-vm@v1.5.3 with: release: "14" cache-after-prepare: true prepare: pkg install -y bash git gmake libedit libffi run: | make release make test - name: Upload artifacts uses: actions/upload-artifact@v4 with: name: tpl-FreeBSD-X64 path: | tpl LICENSE ATTRIBUTION README.md openbsd: name: OpenBSD runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Build and test in OpenBSD uses: vmactions/openbsd-vm@v1.4.6 with: release: "7.9" cache-after-prepare: true prepare: | pkg_add bash coreutils gdiff git gmake libffi ln -sf /usr/local/bin/gtimeout /usr/local/bin/timeout ln -sf /usr/local/bin/gdiff /usr/local/bin/diff run: | export PATH="/usr/local/bin:$PATH" git config --global --add safe.directory "$GITHUB_WORKSPACE" gmake release gmake test - name: Upload artifacts uses: actions/upload-artifact@v4 with: name: tpl-OpenBSD-X64 path: | tpl LICENSE ATTRIBUTION README.md netbsd-x64: name: NetBSD 11 X64 (experimental) runs-on: ubuntu-latest continue-on-error: true timeout-minutes: 90 steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Build and test in NetBSD uses: vmactions/netbsd-vm@v1.4.6 with: release: "11.0" arch: x86_64 sync: scp usesh: true cache-after-prepare: true prepare: | /usr/sbin/pkg_add -u bash coreutils gmake ln -sf /usr/pkg/bin/gtimeout /usr/pkg/bin/timeout run: | export PATH="/usr/pkg/bin:$PATH" # Trealla documents a UTF-8 locale as a requirement, and this # VM starts in C. Without one, test0252 and test0556 differ: # writeq only quotes a non-ASCII atom when the C library calls # its characters alphabetic, which is locale-dependent. The # other BSD runners are already UTF-8, which is why only this # one shows it. if locale -a 2>/dev/null | grep -qx 'C.UTF-8'; then LC_ALL=C.UTF-8 elif locale -a 2>/dev/null | grep -qx 'en_US.UTF-8'; then LC_ALL=en_US.UTF-8 else LC_ALL=C echo "WARNING: no UTF-8 locale on this image; encoding tests will differ" fi export LC_ALL echo "using LC_ALL=$LC_ALL" version=$(printf '%s' "$GITHUB_SHA" | cut -c1-7) gmake "GIT_VERSION=\"$version\"" CC=gcc HOST_CC=gcc ISOCLINE=1 NOFFI=1 NOSSL=1 release ./tpl -q -g 'writeln(netbsd_x64_ok),halt' gmake test - name: Upload artifacts uses: actions/upload-artifact@v4 with: name: tpl-NetBSD-X64 path: | tpl LICENSE ATTRIBUTION README.md solaris: name: Solaris 11.4 CBE (experimental) runs-on: ubuntu-latest continue-on-error: true timeout-minutes: 60 steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Build and test in Solaris uses: vmactions/solaris-vm@v1.3.8 with: release: "11.4-gcc-14" cache-after-prepare: true prepare: | rc=0 pkg install --accept bash git gnu-coreutils gnu-diffutils gnu-make || rc=$? case "$rc" in 0|3|4) ;; *) exit "$rc" ;; esac run: | export PATH="/usr/gnu/bin:$PATH" git config --global --add safe.directory "$GITHUB_WORKSPACE" gmake CC=gcc HOST_CC=gcc ISOCLINE=1 NOFFI=1 NOSSL=1 release ./tpl -q -g 'writeln(solaris_ok),halt' gmake test - name: Upload artifacts uses: actions/upload-artifact@v4 with: name: tpl-Solaris-X64 path: | tpl LICENSE ATTRIBUTION README.md openindiana: name: OpenIndiana Hipster 2026.04 (experimental) runs-on: ubuntu-latest continue-on-error: true timeout-minutes: 60 steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Build and test in OpenIndiana uses: vmactions/openindiana-vm@v1.1.5 with: release: "202604-build" cache-after-prepare: true prepare: | rc=0 pkg install --accept build-essential git gnu-coreutils gnu-diffutils gnu-make || rc=$? case "$rc" in 0|3|4) ;; *) exit "$rc" ;; esac run: | export PATH="/usr/gnu/bin:$PATH" git config --global --add safe.directory "$GITHUB_WORKSPACE" gmake CC=gcc HOST_CC=gcc ISOCLINE=1 NOFFI=1 NOSSL=1 release ./tpl -q -g 'writeln(openindiana_ok),halt' gmake test - name: Upload artifacts uses: actions/upload-artifact@v4 with: name: tpl-OpenIndiana-X64 path: | tpl LICENSE ATTRIBUTION README.md riscos: name: RISC OS ARM EABI (experimental) runs-on: ubuntu-24.04 continue-on-error: true timeout-minutes: 30 env: RISCOS_TOOLCHAIN_URL: https://github.com/netsurf-browser/toolchains/releases/download/gh-master-unstable/arm-riscos-gnueabi.tar.gz RISCOS_TOOLCHAIN_SHA256: 1b7aaa8b4a35e8de9e263d7bd36e52e6f960b360a4ffb0e5c0068de5a07fb102 GCCSDK_INSTALL_CROSSBIN: /opt/netsurf/arm-riscos-gnueabi/cross/bin GCCSDK_INSTALL_ENV: /opt/netsurf/arm-riscos-gnueabi/env steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Install RISC OS cross-toolchain run: | curl --fail --location --retry 3 \ --output "${RUNNER_TEMP}/arm-riscos-gnueabi.tar.gz" \ "$RISCOS_TOOLCHAIN_URL" echo "$RISCOS_TOOLCHAIN_SHA256 ${RUNNER_TEMP}/arm-riscos-gnueabi.tar.gz" | sha256sum --check sudo tar -xzf "${RUNNER_TEMP}/arm-riscos-gnueabi.tar.gz" -C / - name: Cross-build for RISC OS run: | export PATH="$GCCSDK_INSTALL_CROSSBIN:$PATH" make CC=arm-riscos-gnueabi-gcc HOST_CC=cc \ ISOCLINE=1 NOFFI=1 NOSSL=1 NOTHREADS=1 NOPIC=1 NOLIB=1 release cp tpl 'tpl,e1f' file 'tpl,e1f' - name: Upload artifacts uses: actions/upload-artifact@v4 with: name: tpl-RISCOS-ARM-EABI path: | tpl,e1f LICENSE ATTRIBUTION README.md haiku: name: Haiku (experimental) runs-on: ubuntu-latest continue-on-error: true steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Build and smoke-test in Haiku uses: vmactions/haiku-vm@v1.1.3 with: release: "r1beta5" usesh: true run: | make ISOCLINE=1 NOFFI=1 NOSSL=1 release ./tpl -q -g 'writeln(haiku_ok),halt' - name: Upload artifacts uses: actions/upload-artifact@v4 with: name: tpl-Haiku-X64 path: | tpl LICENSE ATTRIBUTION README.md # Roughly matches https://github.com/WebAssembly/wasi-sdk#install wasm: name: WebAssembly runs-on: ubuntu-latest env: WASI_VERSION: 19 BINARYEN_VERSION: 109 steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Fetch tags run: git fetch --tags --force origin - name: Set environment (1/3) run: | echo "WASI_VERSION_FULL=${WASI_VERSION}.0" >> $GITHUB_ENV - name: Set environment (2/3) run: | echo "WASI_SDK_PATH=`pwd`/wasi-sdk-${WASI_VERSION_FULL}" >> $GITHUB_ENV - name: Set environment (3/3) run: | echo "WASI_CC=${WASI_SDK_PATH}/bin/clang --sysroot=${WASI_SDK_PATH}/share/wasi-sysroot" >> $GITHUB_ENV - name: Add Homebrew to $PATH run: echo "/home/linuxbrew/.linuxbrew/bin:/home/linuxbrew/.linuxbrew/sbin" >> $GITHUB_PATH - name: Install WASI SDK run: | wget https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${WASI_VERSION}/wasi-sdk-${WASI_VERSION_FULL}-linux.tar.gz tar xvf wasi-sdk-${WASI_VERSION_FULL}-linux.tar.gz - name: Install Binaryen run: | brew install binaryen - name: Setup Wasmtime uses: mwilliamson/setup-wasmtime-action@v2 with: wasmtime-version: "12.0.1" - name: Build run: make clean wasm - name: Test run: | echo 'wasmtime run --max-wasm-stack 8388608 --dir . tpl.wasm -- $@' > tpl chmod +x tpl make test - name: Upload artifacts uses: actions/upload-artifact@v4 with: name: tpl-wasm-wasi path: | tpl.wasm LICENSE ATTRIBUTION README.md release: if: startsWith(github.ref, 'refs/tags/') needs: [build, windows, windows-arm64, linux32, cosmo, freebsd, openbsd, wasm] name: Release binaries runs-on: ubuntu-latest steps: - name: Download artifacts uses: actions/download-artifact@v4 with: path: artifacts - name: List files run: ls -R - name: Zip releases run: | cd artifacts chmod +x */tpl* */*.wasm for i in */; do dir=${i%/} lower=${dir,,} if [ "$dir" != "$lower" ] then mv "$dir" "$lower" fi zip -r "${lower}.zip" "$lower" done - name: Publish uses: softprops/action-gh-release@v1 with: files: 'artifacts/*.zip'