Skip to content

Commit

Permalink
add Linux/ARM64 cross-compilation support
Browse files Browse the repository at this point in the history
Currently, the Makefile assumes the LLVM toolchain it builds can be executed
natively to build `wasi-libc` etc., which isn't true when cross-compiling for
another platform, but we can work around that by:

1. Building the native LLVM toolchain and using it to build everything else, as usual
2. Deleting that LLVM build and rebuilding (and reinstalling) it with `LLVM_CMAKE_FLAGS` set to cross compile
3. Rebuilding and reinstalling a cross-compiled `wasm-component-ld`
4. Building deb and tar files from the above

Note that we now label the tarfiles `linux-amd64` and `linux-arm64`,
respectively for clarity.

The whole approach is a bit hacky, but GitHub is planning to roll out ARM64
runner support for open source projects later this year, at which point we can
start building natively, so I don't think we need to invest a lot of effort into
this.

I've run CI in my fork and verified the artifact produced there works on my
Ubuntu 24.04 ARM64 machine (Asahi Linux on an Apple M2 Pro).

Fixes WebAssembly#236
Fixes WebAssembly#347

Signed-off-by: Joel Dice <joel.dice@fermyon.com>
  • Loading branch information
dicej committed Jun 10, 2024
1 parent 68df37e commit 946b725
Show file tree
Hide file tree
Showing 8 changed files with 53 additions and 16 deletions.
18 changes: 17 additions & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ jobs:
run: sudo apt install ccache ninja-build
if: matrix.os == 'ubuntu-latest'
- name: Build
run: NINJA_FLAGS=-v make package LLVM_CMAKE_FLAGS=-DLLVM_CCACHE_BUILD=ON
run: NINJA_FLAGS=-v make package LLVM_CMAKE_FLAGS=-DLLVM_CCACHE_BUILD=ON DEB_ARCH=amd64 TAR_MACHINE=linux-amd64
shell: bash
- name: Run the testsuite
run: NINJA_FLAGS=-v make check RUNTIME=wasmtime
Expand Down Expand Up @@ -168,6 +168,22 @@ jobs:
- name: Run docker_build script
run: ./docker_build.sh

- name: Cross-compile for ARM64
# Hacktastic cross-compilation step: build and install an ARM64 LLVM,
# reusing everything else we built using the native toolchain. Once
# GitHub provides ARM64 runners to open source projects (planned for
# second half of 2024) we'll be able to build natively and avoid this
# step.
run: |
docker run --rm \
--user $(id -u):$(id -g) \
-v "$PWD":/workspace:Z \
-v ~/.ccache:/home/builder/.ccache:Z \
--tmpfs /tmp:exec \
wasi-sdk-builder:latest \
bash cross_build_arm64.sh
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
Expand Down
5 changes: 4 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ RUN apt-get update \
python3 \
git \
ninja-build \
gcc-aarch64-linux-gnu \
g++-aarch64-linux-gnu \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*

Expand All @@ -31,7 +33,8 @@ ENV PATH /opt/cmake/bin:$PATH
ENV RUSTUP_HOME=/rust/rustup CARGO_HOME=/rust/cargo PATH=$PATH:/rust/cargo/bin
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | \
sh -s -- -y --profile=minimal && \
chmod -R a+w /rust
chmod -R a+w /rust && \
rustup target add aarch64-unknown-linux-gnu

RUN groupadd -g ${GID} builder && \
useradd --create-home --uid ${UID} --gid ${GID} builder
Expand Down
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -283,8 +283,8 @@ package: build/package.BUILT

build/package.BUILT: build strip
mkdir -p dist
./deb_from_installation.sh $(shell pwd)/dist "$(VERSION)" "$(BUILD_PREFIX)"
./tar_from_installation.sh "$(shell pwd)/dist" "$(VERSION)" "$(BUILD_PREFIX)"
./deb_from_installation.sh $(shell pwd)/dist "$(VERSION)" "$(BUILD_PREFIX)" "$(DEB_ARCH)"
./tar_from_installation.sh "$(shell pwd)/dist" "$(VERSION)" "$(BUILD_PREFIX)" "$(TAR_MACHINE)"
touch build/package.BUILT

.PHONY: default clean build strip package check
9 changes: 9 additions & 0 deletions cross_build_arm64.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/bin/sh
set -ex

rm -r build/llvm build/llvm.BUILT
NINJA_FLAGS=-v make strip LLVM_CMAKE_FLAGS="-DLLVM_CCACHE_BUILD=ON -DCMAKE_C_COMPILER=aarch64-linux-gnu-gcc -DCMAKE_CXX_COMPILER=aarch64-linux-gnu-g++ -DCMAKE_CROSSCOMPILING=True -DCMAKE_CXX_FLAGS=-march=armv8-a -DCMAKE_SYSTEM_PROCESSOR=arm64 -DCMAKE_SYSTEM_NAME=Linux -DLLVM_HOST_TRIPLE=aarch64-linux-gnu"
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc cargo install wasm-component-ld@0.5.0 --root "$(pwd)/build/install/opt/wasi-sdk" --target aarch64-unknown-linux-gnu
mkdir -p dist
./deb_from_installation.sh "$(pwd)/dist" "$(./version.py)" "$(pwd)/build/install/opt/wasi-sdk" "arm64"
./tar_from_installation.sh "$(pwd)/dist" "$(./version.py)" "$(pwd)/build/install/opt/wasi-sdk" "linux-arm64"
8 changes: 6 additions & 2 deletions deb_from_installation.sh
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,17 @@ else
INSTALL_DIR=/opt/wasi-sdk
fi

if [ -n "$4" ]; then
ARCH="$4"
else
ARCH=$(dpkg --print-architecture)
fi

if [ ! -d $INSTALL_DIR ] ; then
echo "Directory $INSTALL_DIR doesn't exist. Nothing to copy from."
exit 1
fi

ARCH=$(dpkg --print-architecture)

rm -rf build/pkg
mkdir -p build/pkg/opt
mkdir -p build/pkg/DEBIAN
Expand Down
2 changes: 1 addition & 1 deletion docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
# separately.
FROM ubuntu:22.04 as dist

ADD dist/wasi-sdk-*.*-linux.tar.gz /
ADD dist/wasi-sdk-*.*-linux-amd64.tar.gz /
ADD dist/libclang_rt.builtins-wasm32-wasi-*.*.tar.gz /wasi-sysroot-clang_rt

# Move versioned folder to unversioned to using bash glob to allow
Expand Down
3 changes: 2 additions & 1 deletion docker_build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ docker build \

echo "Building the package in docker image"
mkdir -p ~/.ccache
arch=$(dpkg --print-architecture)
docker run --rm \
--user $(id -u):$(id -g) \
-v "$PWD":/workspace:Z \
-v ~/.ccache:/home/builder/.ccache:Z \
-e NINJA_FLAGS=-v \
--tmpfs /tmp:exec \
wasi-sdk-builder:latest \
make package LLVM_CMAKE_FLAGS=-DLLVM_CCACHE_BUILD=ON
make package LLVM_CMAKE_FLAGS=-DLLVM_CCACHE_BUILD=ON DEB_ARCH=$arch TAR_MACHINE=linux-$arch
20 changes: 12 additions & 8 deletions tar_from_installation.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,18 @@ else
INSTALL_DIR=/opt/wasi-sdk
fi

case "$(uname -s)" in
Linux*) MACHINE=linux;;
Darwin*) MACHINE=macos;;
CYGWIN*) MACHINE=cygwin;;
MINGW*) MACHINE=mingw;;
MSYS*) MACHINE=msys;; #MSYS_NT-10.0-19043
*) MACHINE="UNKNOWN"
esac
if [ -n "$4" ]; then
MACHINE="$4"
else
case "$(uname -s)" in
Linux*) MACHINE=linux;;
Darwin*) MACHINE=macos;;
CYGWIN*) MACHINE=cygwin;;
MINGW*) MACHINE=mingw;;
MSYS*) MACHINE=msys;; #MSYS_NT-10.0-19043
*) MACHINE="UNKNOWN"
esac
fi

if [ ! -d $INSTALL_DIR ] ; then
echo "Directory $INSTALL_DIR doesn't exist. Nothing to copy from."
Expand Down

0 comments on commit 946b725

Please sign in to comment.