name: CI on: push: tags: - 'wasi-sdk-*' branches: - main pull_request: workflow_dispatch: jobs: build: name: Build ${{ matrix.artifact }} runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: include: - artifact: x86_64-linux os: ubuntu-latest - artifact: arm64-linux os: ubuntu-latest rust_target: aarch64-unknown-linux-gnu - artifact: arm64-macos os: macos-latest llvm_cmake_flags: -DCMAKE_OSX_DEPLOYMENT_TARGET=10.12 -DCMAKE_OSX_ARCHITECTURES=arm64 rust_target: aarch64-apple-darwin - artifact: x86_64-macos os: macos-latest llvm_cmake_flags: -DCMAKE_OSX_DEPLOYMENT_TARGET=10.12 -DCMAKE_OSX_ARCHITECTURES=x86_64 rust_target: x86_64-apple-darwin skip_sysroot: 1 - artifact: x86_64-windows os: windows-latest # TODO: tests are pretty close to passing on Windows but need some # final tweaks, namely testing the exit code doesn't work since # exit codes are different on Windows and the `mmap.c` tests seems # to have issues probably with line endings. Needs someone with a # Windows checkout tot test further. skip_tests: 1 steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - run: git fetch --tags --force name: Force-fetch tags to work around actions/checkout#290 # We can't use `--depth 1` here sadly because the GNU config # submodule is not pinned to a particular tag/branch. Please # bump depth (or even better, the submodule), in case of "error: # Server does not allow request for unadvertised object" in the # future. - run: git submodule update --init --depth 32 --jobs 3 # Persist ccache-based caches across builds. This directory is configured # via the CCACHE_DIR env var below for ccache to use. # # Bump the prefix number to evict all previous caches and enforce a clean # build, in the unlikely case that some weird build error occur and ccache # becomes a potential suspect. - uses: actions/cache@v4 id: cache-restore with: path: ${{ runner.tool_cache }}/ccache key: 0-cache-${{ matrix.artifact }}-${{ github.run_id }} restore-keys: | 0-cache-${{ matrix.artifact }}- - run: | mkdir -p '${{ runner.tool_cache }}/ccache' echo 'CCACHE_DIR=${{ runner.tool_cache }}/ccache' >> $GITHUB_ENV shell: bash # Configure CMake flags for `ci/build.sh` as necessary for each # matrix entry. - run: echo WASI_SDK_CI_TOOLCHAIN_LLVM_CMAKE_ARGS=${{ matrix.llvm_cmake_flags }} >> $GITHUB_ENV if: matrix.llvm_cmake_flags != '' shell: bash - run: | cmake_args=-DWASI_SDK_ARTIFACT=${{ matrix.artifact }} if [ "${{ matrix.rust_target }}" != "" ]; then rustup target add ${{ matrix.rust_target }} cmake_args="$cmake_args -DRUST_TARGET=${{ matrix.rust_target }}" fi echo WASI_SDK_CI_TOOLCHAIN_CMAKE_ARGS="$cmake_args" >> $GITHUB_ENV shell: bash - run: echo WASI_SDK_CI_SKIP_SYSROOT=1 >> $GITHUB_ENV shell: bash if: matrix.skip_sysroot != '' - run: echo WASI_SDK_CI_SKIP_TESTS=1 >> $GITHUB_ENV shell: bash if: matrix.skip_tests != '' # Add some extra installed software on each runner as necessary. - name: Setup `wasmtime` for tests uses: bytecodealliance/actions/wasmtime/setup@v1 with: version: "18.0.2" - name: Install ccache, ninja (macOS) run: brew install ccache ninja if: runner.os == 'macOS' - name: Install ccache, ninja (Windows) run: choco install ccache ninja if: runner.os == 'Windows' - name: Install ccache, ninja (Linux) run: sudo apt install ccache if: runner.os == 'Linux' - name: Build and test (macOS) run: ./ci/build.sh if: runner.os == 'macOS' - name: Build and test (Linux) run: ./ci/docker-build.sh ${{ matrix.artifact }} if: runner.os == 'Linux' # Use a shorter build directory than the default on Windows to avoid # hitting path length and command line length limits. - name: Build and test (Windows) run: ./ci/build.sh C:/wasi-sdk shell: bash if: runner.os == 'Windows' # Upload the `dist` folder from the build as the artifacts for this # runner. - name: Upload artifacts uses: actions/upload-artifact@v4 with: name: ${{ format( 'dist-{0}', matrix.artifact) }} path: build/dist # Help debug ccache issues by showing what happened. - if: always() name: Show ccache statistics run: ccache --show-stats # Always save a cache, even if the build failed. This ensures that if # live-debugging via CI the build gets to pick up where it left off last # time instead of having to recreate everything each time a failure # happens. - if: always() && steps.cache-restore.outputs.cache-hit != 'true' uses: actions/cache/save@v4 with: path: ${{ runner.tool_cache }}/ccache key: 0-cache-${{ matrix.artifact }}-${{ github.run_id }} # Once all of the above matrix entries have completed this job will run and # assemble the final `wasi-sdk-*` artifacts by fusing the toolchain/sysroot # artifacts. finalize: name: Finalize wasi-sdk artifacts needs: build runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - run: git fetch --tags --force name: Force-fetch tags to work around actions/checkout#290 # Download all artifacts from all platforms in `build`, merge them into # final wasi-sdk-* artifacts, and then upload them. - uses: actions/download-artifact@v4 - run: ./ci/merge-artifacts.sh - uses: actions/upload-artifact@v4 with: name: release-artifacts path: dist # Use the `wasi-sdk-*` artifacts just created to create a docker image # with a toolchain pre-installed. - uses: docker/login-action@v2 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - uses: docker/setup-qemu-action@v2 - uses: docker/setup-buildx-action@v2 - uses: docker/metadata-action@v4 id: meta with: images: ghcr.io/${{ github.repository }} tags: | type=schedule type=ref,event=branch type=ref,event=tag type=ref,event=pr type=sha - name: Build and push wasi-sdk docker image uses: docker/build-push-action@v3 with: context: . file: docker/Dockerfile push: ${{ github.event_name != 'pull_request' && github.event_name != 'workflow_dispatch' }} platforms: linux/amd64,linux/arm64 tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} cache-from: type=gha cache-to: type=gha,mode=max - name: Publish a draft release if: startsWith(github.ref, 'refs/tags') run: gh release create --draft --prerelease --generate-notes ${{ github.ref_name }} ./dist/* env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}