diff --git a/.dockerignore b/.dockerignore index 75b24d6..b7f711c 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,3 +1,3 @@ -# We don't need any files to for build image. -# Without this `docker build` will everything in this directory. -* +# Our docker builds do not require the submodule sources so exclude them as +# they can be very big. +/src diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 296a7a4..e1fe6be 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -7,6 +7,7 @@ on: branches: - main pull_request: + workflow_dispatch: jobs: build: @@ -93,6 +94,27 @@ jobs: - uses: actions/checkout@v1 with: submodules: true + + - 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: Run docker_build script run: ./docker_build.sh - name: Upload artifacts @@ -101,3 +123,15 @@ jobs: # Upload the dist folder. Give it a name according to the OS it was built for. name: dist-ubuntu-xenial path: dist + + - 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' }} + 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 diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000..12312c8 --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,54 @@ +# Docker image with a build toolchain and environment variables set to use +# the wasi-sdk sysroot. The SDK distribution must have first been built, +# for example using docker_build.sh + +# Extract built SDK archive to copy out the sysroot. We use an initial build +# stage to do this to make sure it is only the sysroot, not the entire SDK +# with binaries, that is included in the final image since we install those +# separately. +FROM ubuntu:22.04 as dist + +ADD dist/wasi-sdk-*.*-linux.tar.gz / + +# Move versioned folder to unversioned to using bash glob to allow +# this file to be independent of major version number. +RUN mv /wasi-sdk-* /wasi-sdk + +FROM ubuntu:22.04 + +ENV LLVM_VERSION 15 + +# Install build toolchain including clang, ld, make, autotools, ninja, and cmake +RUN apt-get update && \ + # Temporarily install to setup apt repositories + apt-get install -y curl gnupg && \ +\ + curl -sS https://apt.llvm.org/llvm-snapshot.gpg.key | gpg --dearmor > /etc/apt/trusted.gpg.d/llvm.gpg && \ + echo "deb [signed-by=/etc/apt/trusted.gpg.d/llvm.gpg] http://apt.llvm.org/jammy/ llvm-toolchain-jammy-${LLVM_VERSION} main" >> /etc/apt/sources.list.d/llvm.list && \ + echo "deb-src [signed-by=/etc/apt/trusted.gpg.d/llvm.gpg] http://apt.llvm.org/jammy/ llvm-toolchain-jammy-${LLVM_VERSION} main" >> /etc/apt/sources.list.d/llvm.list && \ +\ + apt-get update && \ + apt-get install -y clang-${LLVM_VERSION} lld-${LLVM_VERSION} cmake ninja-build make autoconf autogen automake libtool && \ + apt-get remove -y curl gnupg && \ + rm -rf /var/lib/apt/lists/* + +COPY --from=dist /wasi-sdk/share/wasi-sysroot/ /wasi-sysroot/ +# The path to the rt directory contains the LLVM patch version which is not reflected in the LLVM apt repository +# or package. To make adding the RT robust to changing patch versions without needing to duplicate the folder +# content, we symlink after extracting using a bash glob to resolve the patch version +ADD dist/libclang_rt.builtins-wasm32-wasi-*.*.tar.gz /wasi-sysroot-clang_rt +RUN ln -s /wasi-sysroot-clang_rt/lib/wasi/ $(echo /usr/lib/llvm-${LLVM_VERSION}/lib/clang/${LLVM_VERSION}.*)/lib/wasi + +ADD docker/wasi-sdk.cmake /usr/share/cmake/wasi-sdk.cmake +ENV CMAKE_TOOLCHAIN_FILE /usr/share/cmake/wasi-sdk.cmake +ADD cmake/Platform/WASI.cmake /usr/share/cmake/Modules/Platform/WASI.cmake + +ENV CC clang-${LLVM_VERSION} +ENV CXX clang++-${LLVM_VERSION} +ENV LD wasm-ld-${LLVM_VERSION} +ENV AR llvm-ar-${LLVM_VERSION} +ENV RANLIB llvm-ranlib-${LLVM_VERSION} + +ENV CFLAGS --target=wasm32-wasi --sysroot=/wasi-sysroot +ENV CXXFLAGS --target=wasm32-wasi --sysroot=/wasi-sysroot +ENV LDFLAGS --target=wasm32-wasi --sysroot=/wasi-sysroot diff --git a/docker/wasi-sdk.cmake b/docker/wasi-sdk.cmake new file mode 100644 index 0000000..b87c948 --- /dev/null +++ b/docker/wasi-sdk.cmake @@ -0,0 +1,27 @@ +# Cmake toolchain description file for the wasi-sdk docker image + +# This is arbitrary, AFAIK, for now. +cmake_minimum_required(VERSION 3.4.0) + +# To make sure it recognizes the WASI platform +list(APPEND CMAKE_MODULE_PATH /usr/share/cmake/Modules) + +set(CMAKE_SYSTEM_NAME WASI) +set(CMAKE_SYSTEM_VERSION 1) +set(CMAKE_SYSTEM_PROCESSOR wasm32) +set(triple wasm32-wasi) + +set(CMAKE_C_COMPILER /usr/bin/clang-15) +set(CMAKE_CXX_COMPILER /usr/bin/clang++-15) +set(CMAKE_AR /usr/bin/llvm-ar-15) +set(CMAKE_RANLIB /usr/bin/llvm-ranlib-15) +set(CMAKE_C_COMPILER_TARGET ${triple}) +set(CMAKE_CXX_COMPILER_TARGET ${triple}) +SET(CMAKE_SYSROOT /wasi-sysroot) + +# Don't look in the sysroot for executables to run during the build +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +# Only look in the sysroot (not in the host paths) for the rest +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)