name: CI on: push: branches: [ master, dev, ci_testing, experiments ] pull_request: branches: [ master, dev ] workflow_dispatch: env: LLVM_RELEASE_VERSION: 21.x LLVM_RELEASE_VERSION_LINUX_MUSL: 20 LLVM_RELEASE_VERSION_OPENBSD: 20 LLVM_RELEASE_VERSION_NETBSD: 19 LLVM_DEV_VERSION: 22 # CACHE_INVALIDATION_SEED: '%Y-%m-%d' # Daily CACHE_INVALIDATION_SEED: '%G-%V' # Weekly jobs: build-msvc: runs-on: windows-latest timeout-minutes: 30 strategy: fail-fast: false matrix: build_type: [ Release, Debug ] defaults: run: shell: cmd steps: - uses: actions/checkout@v6 - uses: actions/cache@v5 with: path: build/_deps key: ${{ runner.os }}-llvm-${{ env.LLVM_RELEASE_VERSION }}-${{ matrix.build_type }}-${{ hashFiles('CMakeLists.txt', '.github/workflows/main.yml') }} # set up the environment for Ninja - uses: ilammy/msvc-dev-cmd@v1 with: arch: x64 - name: CMake Build run: | cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DC3_FETCH_LLVM=ON cmake --build build --config ${{ matrix.build_type }} # We remove the GNU link tool so C3C picks up the MSVC link.exe - name: Remove GNU Link shell: bash run: rm -f /usr/bin/link - name: Run Unified Tests shell: bash run: ./scripts/tools/ci_tests.sh "./build/c3c.exe" - name: Cache MSVC SDK id: cache-msvc-sdk uses: actions/cache@v5 with: path: msvc_sdk key: msvc-sdk-${{ runner.os }}-${{ hashFiles('msvc_build_libraries.py') }} - if: steps.cache-msvc-sdk.outputs.cache-hit != 'true' run: py msvc_build_libraries.py --accept-license - name: Bundle (Windows) shell: bash run: ./scripts/tools/package_build.sh "./build/c3c.exe" "c3-windows-${{ matrix.build_type }}" "zip" - uses: actions/upload-artifact@v6 with: name: c3-windows-${{ matrix.build_type }} path: c3-windows-${{ matrix.build_type }}.zip build-msys2-mingw: runs-on: windows-latest timeout-minutes: 30 strategy: fail-fast: false matrix: build_type: [Debug] defaults: run: shell: msys2 {0} steps: - uses: actions/checkout@v6 - uses: msys2/setup-msys2@v2 with: msystem: MINGW64 update: false cache: true install: git binutils mingw-w64-x86_64-clang mingw-w64-x86_64-ninja mingw-w64-x86_64-cmake mingw-w64-x86_64-toolchain mingw-w64-x86_64-python mingw-w64-x86_64-llvm mingw-w64-x86_64-llvm-libs - name: Install LLD run: | echo "Server = https://mirror.msys2.org/mingw/mingw64" > /etc/pacman.d/mirrorlist.mingw64 for i in 1 2; do \ pacman -Sy --noconfirm --needed \ mingw-w64-x86_64-llvm \ mingw-w64-x86_64-llvm-libs \ mingw-w64-x86_64-lld \ mingw-w64-x86_64-clang && break || sleep 5; \ done - name: CMake Build run: | cmake -B build -G Ninja -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DCMAKE_LINKER=lld -DC3_LINK_DYNAMIC=OFF -DLLVM_DIR=/mingw64/lib/cmake/llvm -DC3_LLD_DIR=/mingw64/lib/ cmake --build build - name: Run Unified Tests run: ./scripts/tools/ci_tests.sh "./build/c3c" build-msys2-clang: runs-on: windows-latest timeout-minutes: 30 strategy: fail-fast: false matrix: build_type: [Debug] defaults: run: shell: msys2 {0} steps: - uses: actions/checkout@v6 - uses: msys2/setup-msys2@v2 with: msystem: CLANG64 update: false cache: true install: git binutils mingw-w64-clang-x86_64-cmake mingw-w64-clang-x86_64-toolchain mingw-w64-clang-x86_64-python - name: CMake Build run: | cmake -B build -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} cmake --build build - name: Run Unified Tests run: ./scripts/tools/ci_tests.sh "./build/c3c" build-linux: runs-on: ubuntu-latest strategy: fail-fast: false matrix: build_type: [Release, Debug] steps: - uses: actions/checkout@v6 - name: Get current date context id: date run: echo "date=$(date +'${{ env.CACHE_INVALIDATION_SEED }}')" >> $GITHUB_OUTPUT - name: Cache APT archives uses: actions/cache@v5 with: path: apt-cache key: apt-cache-${{ runner.os }}-${{ steps.date.outputs.date }} - run: | mkdir -p apt-cache/partial for i in 1 2 3; do sudo apt-get update && break || sleep 2; done for i in 1 2 3; do sudo apt-get install -y -o dir::cache::archives="$(pwd)/apt-cache" --fix-missing zlib1g zlib1g-dev python3 ninja-build curl libcurl4-openssl-dev && break || sleep 2; done sudo chown -R $USER:$USER apt-cache - name: CMake Build run: | cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=${{matrix.build_type}} -DC3_FETCH_LLVM=ON cmake --build build - name: Run Unified Tests run: ./scripts/tools/ci_tests.sh "./build/c3c" - name: Embedded/QEMU Tests run: | sudo apt-get install -y opensbi qemu-system-misc u-boot-qemu gcc-riscv64-unknown-elf cd resources/examples/embedded/riscv-qemu make C3C_PATH=../../../../build/ run - name: Bundle & Upload (Linux) run: | bash ./scripts/tools/package_build.sh "./build/c3c" "c3-linux-${{matrix.build_type}}" "tar" - uses: actions/upload-artifact@v6 with: name: c3-linux-${{matrix.build_type}} path: c3-linux-${{matrix.build_type}}.tar.gz build-linux-alpine: runs-on: ubuntu-latest container: image: alpine:3.23 strategy: fail-fast: false matrix: build_type: [Release, Debug] steps: - uses: actions/checkout@v6 - name: Get current date context id: date run: echo "date=$(date +'${{ env.CACHE_INVALIDATION_SEED }}')" >> $GITHUB_OUTPUT #https://wiki.alpinelinux.org/wiki/Local_APK_cache - name: Prepare real apk cache directory + symlink run: | mkdir -p /var/cache/apk ln -sf /var/cache/apk /etc/apk/cache - name: Cache APK downloaded packages (daily) uses: actions/cache@v5 with: path: /var/cache/apk key: apk-pkgs-${{ runner.os }}-alpine-3.23-${{ steps.date.outputs.date }} restore-keys: | apk-pkgs-${{ runner.os }}-alpine-3.23- - name: Install dependencies run: | V=${{env.LLVM_RELEASE_VERSION_LINUX_MUSL}} for i in 1 2 3; do apk update && break || sleep 2; done for i in 1 2 3; do \ apk add \ build-base bash git cmake ninja python3 linux-headers \ tar zstd \ zlib-dev curl-dev libffi-dev \ llvm${V}-dev \ llvm${V}-static \ llvm${V}-gtest \ clang${V}-dev \ clang${V}-static \ lld${V}-dev \ lld${V}-libs && break || sleep 2; \ done - name: CMake Build run: | cmake -B build -G Ninja \ -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} \ -DC3_FETCH_LLVM=OFF \ -DLLVM_ENABLE_LIBXML2=OFF \ -DC3_LINK_DYNAMIC=ON cmake --build build - name: Run Unified Tests run: ./scripts/tools/ci_tests.sh "./build/c3c" - name: Bundle & Upload (Alpine) run: bash ./scripts/tools/package_build.sh "./build/c3c" "c3-linux-musl-${{ matrix.build_type }}" "tar" - uses: actions/upload-artifact@v6 with: name: c3-linux-musl-${{ matrix.build_type }} path: c3-linux-musl-${{ matrix.build_type }}.tar.gz build-mac: runs-on: macos-latest strategy: fail-fast: false matrix: build_type: [Release, Debug] steps: - uses: actions/checkout@v6 - name: CMake Build run: | cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DC3_FETCH_LLVM=ON cmake --build build - name: Run Unified Tests run: ./scripts/tools/ci_tests.sh "./build/c3c" - name: Build Lib (Mac) run: | cd resources/testproject ../../build/c3c build hello_world_lib -vv --trust=full - name: Bundle & Upload (Mac) run: bash ./scripts/tools/package_build.sh "./build/c3c" "c3-macos-${{matrix.build_type}}" "zip" - uses: actions/upload-artifact@v6 with: name: c3-macos-${{matrix.build_type}} path: c3-macos-${{matrix.build_type}}.zip build-openbsd: runs-on: ubuntu-latest strategy: fail-fast: false matrix: build_type: [Debug] version: ['7.8'] steps: - uses: actions/checkout@v6 - name: Build, Test and Package in OpenBSD uses: cross-platform-actions/action@master with: operating_system: openbsd version: ${{ matrix.version }} cpu_count: 4 memory: 6G run: | # Install dependencies for i in 1 2 3; do sudo pkg_add ninja cmake llvm%${{ env.LLVM_RELEASE_VERSION_OPENBSD }} bash && break || sleep 5 done export MALLOC_OPTIONS=j # Setup RAM Disk sudo mkdir -p /mnt/ram sudo mount_mfs -s $((2 * 1024 * 1024 * 2)) swap /mnt/ram sudo chown -R $(id -u):$(id -g) /mnt/ram export TMPDIR=/mnt/ram # Copy source to RAM disk and switch to it cp -rp . /mnt/ram/ cd /mnt/ram # Build cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} cmake --build build # Run Unified Tests chmod +x scripts/tools/ci_tests.sh ulimit -d $(ulimit -Hd) || true ./scripts/tools/ci_tests.sh "./build/c3c" # Package chmod +x scripts/tools/package_build.sh ./scripts/tools/package_build.sh "./build/c3c" "c3-openbsd-${{matrix.build_type}}" "tar" # Move results back to workspace for GitHub rsync/upload mkdir -p "$GITHUB_WORKSPACE"/build cp build/c3c "$GITHUB_WORKSPACE"/build/ cp *.tar.gz "$GITHUB_WORKSPACE"/ - uses: actions/upload-artifact@v6 with: name: c3-openbsd-${{matrix.build_type}} path: c3-openbsd-${{matrix.build_type}}.tar.gz build-netbsd: runs-on: ubuntu-latest strategy: fail-fast: false matrix: build_type: [Debug] version: ['10.1'] steps: - uses: actions/checkout@v6 - name: Build, Test and Package in NetBSD uses: cross-platform-actions/action@master with: operating_system: netbsd version: ${{ matrix.version }} cpu_count: 4 memory: 6G run: | # Install dependencies export PATH="/usr/pkg/sbin:/usr/pkg/bin:$PATH" export PKG_PATH="https://ftp.netbsd.org/pub/pkgsrc/packages/NetBSD/$(uname -m)/$(uname -r)/All/" # Ensure pkgin is available and updated sudo /usr/sbin/pkg_add -U pkgin || true for i in 1 2 3; do sudo pkgin -y update && \ sudo pkgin -y install cmake gcc14 ninja-build bash \ 'llvm>=${{ env.LLVM_RELEASE_VERSION_NETBSD }}' \ 'clang>=${{ env.LLVM_RELEASE_VERSION_NETBSD }}' \ 'lld>=${{ env.LLVM_RELEASE_VERSION_NETBSD }}' && break || sleep 5 done export CC=clang export CXX=clang++ # Setup RAM Disk sudo mkdir -p /mnt/ram sudo mount_tmpfs -s 2G tmpfs /mnt/ram sudo chown -R $(id -u):$(id -g) /mnt/ram export TMPDIR=/mnt/ram # Copy source to RAM disk and switch to it cp -rp . /mnt/ram/ cd /mnt/ram # Build cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} cmake --build build # Run Unified Tests chmod +x scripts/tools/ci_tests.sh ./scripts/tools/ci_tests.sh "./build/c3c" # Package chmod +x scripts/tools/package_build.sh ./scripts/tools/package_build.sh "./build/c3c" "c3-netbsd-${{matrix.build_type}}" "tar" # Move results back to workspace for GitHub rsync/upload mkdir -p "$GITHUB_WORKSPACE"/build cp build/c3c "$GITHUB_WORKSPACE"/build/ cp *.tar.gz "$GITHUB_WORKSPACE"/ - uses: actions/upload-artifact@v6 with: name: c3-netbsd-${{matrix.build_type}} path: c3-netbsd-${{matrix.build_type}}.tar.gz build-with-docker: name: LLVM ${{ matrix.llvm_version }} Compatibility runs-on: ubuntu-latest strategy: fail-fast: false matrix: llvm_version: [17, 18, 19, 20] steps: - uses: actions/checkout@v6 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Build and cache Docker image uses: docker/build-push-action@v6 with: context: ./docker build-args: | LLVM_VERSION=${{ matrix.llvm_version }} UBUNTU_VERSION=22.04 CMAKE_VERSION=3.20.0 tags: c3c-builder:latest outputs: type=docker,dest=/tmp/c3c-builder.tar cache-from: type=gha,scope=build-with-docker-${{ matrix.llvm_version }} cache-to: type=gha,mode=max,scope=build-with-docker-${{ matrix.llvm_version }} env: DOCKER_BUILD_SUMMARY: false - name: Load Docker image run: docker load -i /tmp/c3c-builder.tar - name: Build C3 in Docker run: | rm -rf build bin mkdir -p build bin chmod -R 777 build bin docker run --rm \ -v "$(pwd):/home/c3c/source" \ -w /home/c3c/source \ c3c-builder:latest \ bash -c "git config --global --add safe.directory /home/c3c/source && \ cmake -S . -B build \ -G Ninja \ -DCMAKE_BUILD_TYPE=Debug \ -DCMAKE_C_COMPILER=clang-${{ matrix.llvm_version }} \ -DCMAKE_CXX_COMPILER=clang++-${{ matrix.llvm_version }} \ -DCMAKE_LINKER=lld-${{ matrix.llvm_version }} \ -DCMAKE_OBJCOPY=llvm-objcopy-${{ matrix.llvm_version }} \ -DCMAKE_STRIP=llvm-strip-${{ matrix.llvm_version }} \ -DCMAKE_DLLTOOL=llvm-dlltool-${{ matrix.llvm_version }} \ -DC3_LLVM_VERSION=auto && \ cmake --build build && \ cp -r build/c3c build/lib bin" - name: Run Unified Tests run: | docker run --rm \ -u 0 \ -v "$(pwd):/home/c3c/source" \ -w /home/c3c/source \ c3c-builder \ bash -c "./scripts/tools/ci_tests.sh ./bin/c3c" build-nix: runs-on: ubuntu-22.04 strategy: fail-fast: false matrix: build_type: [ Debug ] nixpkgs: [ Lock, Latest ] steps: - uses: actions/checkout@v6 - uses: cachix/install-nix-action@v31 with: github_access_token: ${{ secrets.GITHUB_TOKEN }} - name: Update flake if: matrix.nixpkgs == 'Latest' run: nix flake update - name: CMake build and run Unified Tests run: | CHECK_NAME=".#c3c-checks" if [[ ${{ matrix.build_type }} = "Debug" ]]; then CHECK_NAME=".#c3c-debug-checks"; fi nix build -L "$CHECK_NAME" build-android: strategy: fail-fast: false matrix: build_type: [ Release, Debug ] architecture: [ aarch64, x86_64 ] include: - architecture: aarch64 runner: ubuntu-24.04-arm - architecture: x86_64 runner: ubuntu-24.04 runs-on: ${{matrix.runner}} container: image: termux/termux-docker:${{matrix.architecture}} volumes: - /tmp/node20:/__e/node20 - /tmp/node24:/__e/node24 env: TERMUX_MAIN_PACKAGE_FORMAT: debian ANDROID_ROOT: /system ANDROID_DATA: /data PREFIX: /data/data/com.termux/files/usr HOME: /data/data/com.termux/files/home PATH: /data/data/com.termux/files/usr/bin TMPDIR: /data/data/com.termux/files/usr/tmp LANG: en_US.UTF-8 TZ: UTC steps: - name: prepare termux run: | ln -sf ${PREFIX}/etc/termux/mirrors/default ${PREFIX}/etc/termux/chosen_mirrors for i in 1 2; do /entrypoint.sh pkg update && break || sleep 5; done /entrypoint.sh bash -c "yes | pkg upgrade -y" chmod -R o+x ${PREFIX}/bin for i in 1 2; do /entrypoint.sh pkg install -y nodejs-lts tar git && break || sleep 5; done # Symlink Termux node to where GHA expects it mkdir -p /__e/node20/bin /__e/node24/bin || true ln -sf ${PREFIX}/bin/node /__e/node20/bin/node || true ln -sf ${PREFIX}/bin/node /__e/node24/bin/node || true - name: Get current date context id: date run: echo "date=$(date +'${{ env.CACHE_INVALIDATION_SEED }}')" >> $GITHUB_OUTPUT - name: Cache Termux packages uses: actions/cache@v5 with: path: /data/data/com.termux/cache/apt/archives/ key: termux-cache-${{ matrix.architecture }}-${{ steps.date.outputs.date }} - uses: actions/checkout@v6 - name: fix permissions after checkout run: chown -R 1000:1000 . - name: setup run: | for i in 1 2; do \ /entrypoint.sh pkg install -y llvm binutils libgc build-essential cmake git libedit zlib clang make mlir llvm-tools libpolly python libllvm-static && break || sleep 10; \ done - name: build run: | cmake -Bbuild -DCMAKE_BUILD_TYPE=${{matrix.build_type}} cmake --build build - name: Run Unified Tests if: matrix.build_type == 'Debug' run: ./scripts/tools/ci_tests.sh "./build/c3c" "android" - name: bundle_output run: | chmod +x ./scripts/tools/package_build.sh ./scripts/tools/package_build.sh "./build/c3c" "c3-android-${{matrix.architecture}}-${{matrix.build_type}}" "tar" - name: upload artifacts uses: actions/upload-artifact@v4 with: name: c3-android-${{matrix.architecture}}-${{matrix.build_type}} path: c3-android-${{matrix.architecture}}-${{matrix.build_type}}.tar.gz release: runs-on: ubuntu-22.04 needs: [build-msvc, build-linux, build-mac, build-linux-alpine, build-openbsd, build-netbsd, build-android] if: github.ref == 'refs/heads/master' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: - uses: actions/checkout@v6 - uses: actions/download-artifact@v4 - name: Prepare Assets run: | # --- Release Assets --- mv c3-windows-Release/c3-windows-Release.zip c3-windows.zip mv c3-macos-Release/c3-macos-Release.zip c3-macos.zip mv c3-linux-Release/c3-linux-Release.tar.gz c3-linux.tar.gz mv c3-linux-musl-Release/c3-linux-musl-Release.tar.gz c3-linux-musl.tar.gz mv c3-openbsd-Release/c3-openbsd-Release.tar.gz c3-openbsd.tar.gz || true mv c3-netbsd-Release/c3-netbsd-Release.tar.gz c3-netbsd.tar.gz || true mv c3-android-aarch64-Release/c3-android-aarch64-Release.tar.gz c3-android-aarch64.tar.gz mv c3-android-x86_64-Release/c3-android-x86_64-Release.tar.gz c3-android-x86_64.tar.gz # --- Debug Assets --- mv c3-windows-Debug/c3-windows-Debug.zip c3-windows-debug.zip mv c3-macos-Debug/c3-macos-Debug.zip c3-macos-debug.zip mv c3-linux-Debug/c3-linux-Debug.tar.gz c3-linux-debug.tar.gz mv c3-linux-musl-Debug/c3-linux-musl-Debug.tar.gz c3-linux-musl-debug.tar.gz mv c3-openbsd-Debug/c3-openbsd-Debug.tar.gz c3-openbsd-debug.tar.gz || true mv c3-netbsd-Debug/c3-netbsd-Debug.tar.gz c3-netbsd-debug.tar.gz || true mv c3-android-aarch64-Debug/c3-android-aarch64-Debug.tar.gz c3-android-aarch64-debug.tar.gz mv c3-android-x86_64-Debug/c3-android-x86_64-Debug.tar.gz c3-android-x86_64-debug.tar.gz - run: gh release delete latest-prerelease-tag --cleanup-tag -y || true - run: echo "RELEASE_NAME=latest-prerelease-$(date +'%Y%m%d-%H%M')" >> $GITHUB_ENV - uses: softprops/action-gh-release@v2 with: tag_name: latest-prerelease-tag name: ${{ env.RELEASE_NAME }} prerelease: true files: | c3-windows.zip c3-macos.zip c3-linux.tar.gz c3-linux-musl.tar.gz c3-openbsd.tar.gz c3-netbsd.tar.gz c3-android-aarch64.tar.gz c3-android-x86_64.tar.gz # --- Debug Artifacts --- c3-windows-debug.zip c3-macos-debug.zip c3-linux-debug.tar.gz c3-linux-musl-debug.tar.gz c3-openbsd-debug.tar.gz c3-netbsd-debug.tar.gz c3-android-aarch64-debug.tar.gz c3-android-x86_64-debug.tar.gz