diff --git a/.github/workflows/llvm-project-epoch-one.yml b/.github/workflows/llvm-project-epoch-one.yml index 5de49d3..2917a59 100644 --- a/.github/workflows/llvm-project-epoch-one.yml +++ b/.github/workflows/llvm-project-epoch-one.yml @@ -24,7 +24,13 @@ jobs: with: context: ./llvm-project file: ./llvm-project/Dockerfile.epoch1 + load: true platforms: linux/amd64 - push: ${{ github.repository_owner == 'ClangBuiltLinux' && github.event_name != 'pull_request' && github.ref_name == 'main' }} tags: | ghcr.io/clangbuiltlinux/llvm-project:stage2 + - name: Test statically linked clang + run: bash ci/test-clang.sh + - name: Push image to ghcr.io + if: ${{ github.repository_owner == 'ClangBuiltLinux' && github.event_name != 'pull_request' && github.ref_name == 'main' }} + run: | + docker push ghcr.io/clangbuiltlinux/llvm-project:stage2 diff --git a/.github/workflows/llvm-project-epoch-two.yml b/.github/workflows/llvm-project-epoch-two.yml index b2dd52b..20163dc 100644 --- a/.github/workflows/llvm-project-epoch-two.yml +++ b/.github/workflows/llvm-project-epoch-two.yml @@ -24,7 +24,13 @@ jobs: with: context: ./llvm-project file: ./llvm-project/Dockerfile.epoch2 + load: true platforms: linux/amd64 - push: ${{ github.repository_owner == 'ClangBuiltLinux' && github.event_name != 'pull_request' && github.ref_name == 'main' }} tags: | ghcr.io/clangbuiltlinux/llvm-project:stage2 + - name: Test statically linked clang + run: bash ci/test-clang.sh + - name: Push image to ghcr.io + if: ${{ github.repository_owner == 'ClangBuiltLinux' && github.event_name != 'pull_request' && github.ref_name == 'main' }} + run: | + docker push ghcr.io/clangbuiltlinux/llvm-project:stage2 diff --git a/ci/test-clang-docker.sh b/ci/test-clang-docker.sh new file mode 100755 index 0000000..d975ae1 --- /dev/null +++ b/ci/test-clang-docker.sh @@ -0,0 +1,70 @@ +#!/usr/bin/env bash + +set -eu + +if [[ ! -d /repo ]]; then + echo "[-] This script needs to be run within Docker! Use test-clang.sh instead." + exit 1 +fi + +CC=/repo/toolchain/bin/clang +CXX=/repo/toolchain/bin/clang++ +hello_c=/repo/llvm-project/hello.c +hello_cpp=/repo/llvm-project/hello.cpp +hello_exe=/tmp/hello +host_arch=$(uname -m) + +# Print clang information, which makes sure it can run +echo "[+] Testing 'clang --version'" +"$CC" --version + +case "$(source /usr/lib/os-release; echo "$ID")" in + arch) + musl_cc_flags=(--sysroot=/usr/lib/musl) + + echo "[+] Updating OS and installing musl" + pacman -Syyu --noconfirm musl + ;; + + fedora) + musl_cc_flags=( + -B /usr/"$host_arch"-linux-musl/lib64 # Scrt1.o, crti.o, crtn.o + -I /usr/"$host_arch"-linux-musl/include # stdio.h + -L /usr/"$host_arch"-linux-musl/lib64 # -lc + ) + + echo "[+] Updating OS" + dnf update -qy + + echo "[+] Installing musl" + dnf install -qy \ + musl-devel \ + musl-libc \ + musl-libc-static + ;; +esac + +######## +# MUSL # +######## + +echo "[+] Testing dynamically linking hello.c against musl" +"$CC" "${musl_cc_flags[@]}" -o "$hello_exe" "$hello_c" +"$hello_exe" + +echo "[+] Testing statically linking hello.c against musl" +"$CC" "${musl_cc_flags[@]}" -static -o "$hello_exe" "$hello_c" +"$hello_exe" + +echo "[+] Testing dynamically linking hello.cpp against musl ('--rpath')" +# --rpath to avoid having to pull in libc++ and libunwind from distribution +"$CXX" "${musl_cc_flags[@]}" -Wl,--rpath=/repo/toolchain/lib/"$host_arch"-alpine-linux-musl -o "$hello_exe" "$hello_cpp" +"$hello_exe" + +echo "[+] Testing dynamically linking hello.cpp against musl ('LD_LIBRARY_PATH')" +"$CXX" "${musl_cc_flags[@]}" -o "$hello_exe" "$hello_cpp" +LD_LIBRARY_PATH=/lib:/repo/toolchain/lib/"$host_arch"-alpine-linux-musl "$hello_exe" + +echo "[+] Testing statically linking hello.cpp against musl" +"$CXX" "${musl_cc_flags[@]}" -static -lc++abi -o "$hello_exe" "$hello_cpp" +"$hello_exe" diff --git a/ci/test-clang.sh b/ci/test-clang.sh new file mode 100755 index 0000000..354717c --- /dev/null +++ b/ci/test-clang.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env bash + +set -eu + +trap 'rm -fr "$toolchain"' EXIT + +# Set up workspace +rootdir=${GITHUB_WORKSPACE:-$(dirname "$(dirname "$(realpath "$0")")")} +toolchain=$rootdir/toolchain + +# Pull toolchain out of container +echo "[+] Downloading toolchain from container" +docker create --name llvm-project ghcr.io/clangbuiltlinux/llvm-project:stage2 +mkdir "$toolchain" +docker cp llvm-project:/usr/local/bin "$toolchain" +docker cp llvm-project:/usr/local/include "$toolchain" +docker cp llvm-project:/usr/local/lib "$toolchain" +echo "[+] Cleaning up container" +docker rm llvm-project + +# Test toolchain in Docker images so that the environment is consistent, +# regardless of runners. +docker_images=( + docker.io/fedora:latest +) +# Arch Linux is an x86_64-only distribution +[[ $(uname -m) = "x86_64" ]] && docker_images+=(docker.io/archlinux:latest) +for docker_image in "${docker_images[@]}"; do + echo "[+] Updating '$docker_image'" + docker pull "$docker_image" + echo "[+] Testing clang in '$docker_image' container" + docker run \ + --rm \ + --volume "$rootdir":/repo:ro \ + "$docker_image" \ + bash /repo/ci/test-clang-docker.sh +done