### Auto build Box64 and release its binary with Github Action name: Build and Release Box64 permissions: actions: 'write' on: workflow_dispatch: release: push: paths: - "**/*.c" - "**/*.h" - "**/*.S" - "**/*.py" - "CMakeLists.txt" - "**/*.yml" pull_request: types: [assigned, opened, synchronize, reopened] paths: - "**/*.c" - "**/*.h" - "**/*.S" - "**/*.py" - "CMakeLists.txt" - "**/*.yml" defaults: run: # needed on container images which could default to sh shell: bash jobs: build: strategy: fail-fast: false matrix: platform: [X64, RISCV, RK3588, ARM64, ANDROID, TERMUX, LARCH64, ANDROID_GLIBC, WOW64, ARM64-GCC-8] type: [Release, Trace, StaticBuild, Box32] os: [ubuntu-latest, ubuntu-22.04-arm] exclude: - platform: ANDROID type: StaticBuild - platform: TERMUX type: StaticBuild - platform: X64 type: StaticBuild - platform: ANDROID type: Box32 - platform: TERMUX type: Box32 - platform: X64 os: ubuntu-22.04-arm - platform: RISCV os: ubuntu-22.04-arm - platform: RK3588 os: ubuntu-latest - platform: ARM64 os: ubuntu-latest - platform: ANDROID os: ubuntu-22.04-arm - platform: TERMUX os: ubuntu-22.04-arm - platform: LARCH64 os: ubuntu-22.04-arm - platform: ANDROID_GLIBC os: ubuntu-latest - platform: WOW64 os: ubuntu-latest - platform: WOW64 type: Trace - platform: WOW64 type: StaticBuild - platform: WOW64 type: Box32 - platform: ARM64-GCC-8 os: ubuntu-latest - platform: ARM64-GCC-8 type: Trace - platform: ARM64-GCC-8 type: StaticBuild - platform: ANDROID type: Trace - platform: TERMUX type: Trace - platform: LARCH64 type: Trace include: - platform: ARM64-GCC-8 image: arm64v8/ubuntu:18.04 runs-on: ${{ matrix.os }} container: image: ${{ matrix.image || '' }} steps: - name: "Checkout Box64 Repository" if: ${{ matrix.platform != 'ARM64-GCC-8' }} uses: actions/checkout@v4 - name: "Checkout Box64 Repository (No NodeJS)" if: ${{ matrix.platform == 'ARM64-GCC-8' }} uses: taiki-e/checkout-action@v1 - name: Get all the unique changed directory names id: changed-files-dir-names if: ${{ matrix.platform != 'ARM64-GCC-8' }} uses: tj-actions/changed-files@ed68ef82c095e0d48ec87eccea555d944a631a4c # v46 with: dir_names: "true" - name: Early exit other jobs if this is a ARM64-only change id: early-exit-arm64 env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} if: steps.changed-files-dir-names.outputs.all_modified_files == 'src/dynarec/arm64' continue-on-error: true run: | if [[ ${{ matrix.platform }} != 'RISCV' && ${{ matrix.platform }} != 'LARCH64' && ${{ matrix.platform }} != 'X64' ]]; then exit 1 fi - name: Early exit other jobs if this is a LA64-only change id: early-exit-la64 env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} if: steps.changed-files-dir-names.outputs.all_modified_files == 'src/dynarec/la64' continue-on-error: true run: | if [[ ${{ matrix.platform }} == 'LARCH64' ]]; then exit 1 fi - name: Early exit other jobs if this is a RV64-only change id: early-exit-rv64 env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} if: steps.changed-files-dir-names.outputs.all_modified_files == 'src/dynarec/rv64' continue-on-error: true run: | if [[ ${{ matrix.platform }} == 'RISCV' ]]; then exit 1 fi - name: Do not early exit otherwise id: early-exit-never env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} DIRS: ${{ steps.changed-files-dir-names.outputs.all_modified_files }} if: env.DIRS != 'src/dynarec/arm64' && env.DIRS != 'src/dynarec/la64' && env.DIRS != 'src/dynarec/rv64' continue-on-error: true run: exit 1 - name: Merge early exit conditions id: early-exit if: steps.early-exit-arm64.outcome == 'failure' || steps.early-exit-la64.outcome == 'failure' || steps.early-exit-rv64.outcome == 'failure' || steps.early-exit-never.outcome == 'failure' continue-on-error: true run: exit 1 # Use `steps.early-exit.outcome == 'failure'` to check whether the current step should be processed. - name: "Environment preparation" if: steps.early-exit.outcome == 'failure' run: | if [[ ${{ matrix.platform }} == 'ARM64-GCC-8' ]]; then apt-get update apt install -y sudo else sudo apt-get update zydis_package=libzydis-dev fi if [[ ${{ matrix.platform }} != 'X64' && ${{ matrix.platform }} != 'RISCV' && ${{ matrix.platform }} != 'LARCH64' ]]; then sudo apt-get -y install git cmake make python3 patchelf $zydis_package if [[ ${{ matrix.platform }} == 'ANDROID' || ${{ matrix.platform }} == 'TERMUX' ]]; then sudo apt-get -y install p7zip wget -q https://dl.google.com/android/repository/android-ndk-r26b-linux.zip unzip -qq android-ndk-r26b-linux.zip echo "BOX64_COMPILER=$PWD/android-ndk-r26b/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android31-clang" >> $GITHUB_ENV echo "BOX64_PLATFORM_MARCRO=-DANDROID=1 -DARM_DYNAREC=1 -DBAD_SIGNAL=1" >> $GITHUB_ENV git clone https://github.com/termux/termux-docker.git sudo cp -rf termux-docker/system/arm /system sudo chown -R $(whoami):$(whoami) /system sudo chmod 755 -R /system elif [[ ${{ matrix.platform }} == 'ANDROID_GLIBC' ]]; then sudo apt-get -y install git gcc-aarch64-linux-gnu echo "BOX64_PLATFORM_MARCRO=-DARM64=1 -DWINLATOR_GLIBC=1 -DARM_DYNAREC=1 -DBAD_SIGNAL=1" >> $GITHUB_ENV echo "BOX64_COMPILER=aarch64-linux-gnu-gcc" >> $GITHUB_ENV elif [[ ${{ matrix.platform }} == 'WOW64' ]]; then sudo apt-get -y install git gcc-aarch64-linux-gnu echo "BOX64_PLATFORM_MARCRO=-DWOW64=1 -DARM_DYNAREC=1" >> $GITHUB_ENV echo "BOX64_COMPILER=aarch64-linux-gnu-gcc" >> $GITHUB_ENV export LLVM_MINGW_VERSION=20250430 wget -q https://github.com/mstorsjo/llvm-mingw/releases/download/${LLVM_MINGW_VERSION}/llvm-mingw-${LLVM_MINGW_VERSION}-ucrt-ubuntu-22.04-aarch64.tar.xz tar -xf llvm-mingw-${LLVM_MINGW_VERSION}-ucrt-ubuntu-22.04-aarch64.tar.xz echo "MINGW_COMPILER_PATH=$PWD/llvm-mingw-${LLVM_MINGW_VERSION}-ucrt-ubuntu-22.04-aarch64/bin" >> $GITHUB_ENV elif [[ ${{ matrix.platform }} == 'ARM64-GCC-8' ]]; then # some of these dependencies may be unnecessary to explicitly install depending on the image sudo apt-get -y install git software-properties-common lsb-release \ wget curl build-essential autoconf automake \ pkg-config ca-certificates \ python3 make gettext zstd \ gcc-8 g++-8 sudo add-apt-repository ppa:theofficialgman/cmake-bionic -y sudo apt update sudo apt install -y cmake echo "BOX64_PLATFORM_MARCRO=-DARM64=1" >> $GITHUB_ENV echo "BOX64_COMPILER=aarch64-linux-gnu-gcc-8" >> $GITHUB_ENV else sudo apt-get -y install git gcc-aarch64-linux-gnu echo "BOX64_PLATFORM_MARCRO=-D${{ matrix.platform }}=1" >> $GITHUB_ENV echo "BOX64_COMPILER=aarch64-linux-gnu-gcc" >> $GITHUB_ENV fi if [[ ${{ matrix.platform }} == 'TERMUX' ]]; then wget https://packages.termux.dev/apt/termux-main/pool/main/liba/libandroid-sysv-semaphore/libandroid-sysv-semaphore_0.1-1_aarch64.deb 7z x libandroid-sysv-semaphore_0.1-1_aarch64.deb tar -xf data.tar.xz sudo cp -rf data / sudo chmod 755 -R /data sudo chown -R $(whoami):$(whoami) /data echo "CFLAGS=-L/data/data/com.termux/files/usr/lib" >> $GITHUB_ENV echo "IS_TERMUX=1" >> $GITHUB_ENV echo "QEMU_SET_ENV=LD_LIBRARY_PATH=/data/data/com.termux/files/usr/lib" >> $GITHUB_ENV else echo "IS_TERMUX=0" >> $GITHUB_ENV fi else if [[ ${{ matrix.platform }} == 'X64' ]]; then echo "BOX64_PLATFORM_MARCRO=-DLD80BITS=1 -DNOALIGN=1" >> $GITHUB_ENV echo "BOX64_COMPILER=gcc" >> $GITHUB_ENV sudo apt-get -y install git cmake make python3 libzydis-dev elif [[ ${{ matrix.platform }} == 'RISCV' ]]; then echo BOX64_PLATFORM_MARCRO="-DRV64=ON" >> $GITHUB_ENV echo "BOX64_COMPILER=riscv64-linux-gnu-gcc-14" >> $GITHUB_ENV sudo apt-get -y install git gcc-14-riscv64-linux-gnu cmake make python3 ninja-build libglib2.0-dev libzydis-dev elif [[ ${{ matrix.platform }} == 'LARCH64' ]]; then sudo mkdir /usr/local/larch wget -O- -q https://github.com/loongson/build-tools/releases/download/2025.02.21/x86_64-cross-tools-loongarch64-binutils_2.44-gcc_14.2.0-glibc_2.41.tar.xz | sudo tar -C /usr/local/larch --strip-components=1 --xz -xf - sudo ln -sf /usr/local/larch/target /usr/loongarch64-linux-gnu sudo cp -r /usr/local/larch/loongarch64-unknown-linux-gnu/lib/* /usr/loongarch64-linux-gnu/lib64/ for i in objdump objcopy strip; do sudo ln -sf /usr/local/larch/bin/loongarch64-unknown-linux-gnu-$i /usr/bin/loongarch64-linux-gnu-$i done echo '/usr/local/larch/bin/loongarch64-unknown-linux-gnu-gcc -L/usr/local/larch/loongarch64-unknown-linux-gnu "$@"' | sudo tee /usr/bin/loongarch64-linux-gnu-gcc echo '/usr/local/larch/bin/loongarch64-unknown-linux-gnu-g++ -L/usr/local/larch/loongarch64-unknown-linux-gnu "$@"' | sudo tee /usr/bin/loongarch64-linux-gnu-g++ sudo chmod 755 /usr/bin/loongarch64-linux-gnu-{gcc,g++} echo BOX64_PLATFORM_MARCRO="-DLARCH64=ON" >> $GITHUB_ENV echo "BOX64_COMPILER=loongarch64-linux-gnu-gcc" >> $GITHUB_ENV sudo apt-get -y install git cmake make python3 libzydis-dev else echo BOX64_PLATFORM_MARCRO="-DARM_DYNAREC=ON" >> $GITHUB_ENV echo "BOX64_COMPILER=aarch64-linux-gnu-gcc" >> $GITHUB_ENV sudo apt-get -y install git gcc-aarch64-linux-gnu cmake make python3 libzydis-dev fi fi if [[ ${{ matrix.type }} == 'Release' ]]; then echo BOX64_BUILD_TYPE=Release >> $GITHUB_ENV echo BOX64_HAVE_TRACE=0 >> $GITHUB_ENV echo BOX64_STATICBUILD=0 >> $GITHUB_ENV echo BOX64_BOX32=0 >> $GITHUB_ENV elif [[ ${{ matrix.type }} == 'StaticBuild' ]]; then echo BOX64_BUILD_TYPE=Release >> $GITHUB_ENV echo BOX64_HAVE_TRACE=0 >> $GITHUB_ENV echo BOX64_STATICBUILD=1 >> $GITHUB_ENV echo BOX64_BOX32=0 >> $GITHUB_ENV elif [[ ${{ matrix.type }} == 'Box32' ]]; then echo BOX64_BUILD_TYPE=Release >> $GITHUB_ENV echo BOX64_HAVE_TRACE=0 >> $GITHUB_ENV echo BOX64_STATICBUILD=0 >> $GITHUB_ENV echo BOX64_BOX32=1 >> $GITHUB_ENV else echo BOX64_BUILD_TYPE=RelWithDebInfo >> $GITHUB_ENV echo BOX64_HAVE_TRACE=1 >> $GITHUB_ENV echo BOX64_STATICBUILD=0 >> $GITHUB_ENV echo BOX64_BOX32=0 >> $GITHUB_ENV fi if [[ ${{ matrix.os }} == 'ubuntu-22.04-arm' ]]; then echo "BOX64_ZYDIS3=1" >> $GITHUB_ENV else echo "BOX64_ZYDIS3=0" >> $GITHUB_ENV fi - name: "Get XuanTie QEMU Cache Key" if: matrix.platform == 'RISCV' && steps.early-exit.outcome == 'failure' id: get-xuantie-qemu-cache-key run: | echo "key=f2dfdd13014d51f957c7172acc2e791cb42dc400" >> $GITHUB_OUTPUT - name: "Cache XuanTie QEMU" if: matrix.platform == 'RISCV' && steps.early-exit.outcome == 'failure' id: cache-xuantie-qemu uses: actions/cache@v3 with: path: ${{ github.workspace }}/xuantie_qemu_install key: ${{ runner.os }}-${{ steps.get-xuantie-qemu-cache-key.outputs.key }}-xuantie-qemu - name: "Checkout XuanTie QEMU" if: matrix.platform == 'RISCV' && steps.cache-xuantie-qemu.outputs.cache-hit != 'true' && steps.early-exit.outcome == 'failure' uses: actions/checkout@v3 with: repository: revyos/qemu path: xuantie_qemu ref: f2dfdd13014d51f957c7172acc2e791cb42dc400 - name: "Build XuanTie QEMU for XTheadVector" if: matrix.platform == 'RISCV' && steps.cache-xuantie-qemu.outputs.cache-hit != 'true' && steps.early-exit.outcome == 'failure' run: | cd xuantie_qemu ./configure --prefix=$GITHUB_WORKSPACE/xuantie_qemu_install --target-list=riscv64-linux-user --disable-system make -j$(nproc) make install - name: "Display Build info" if: steps.early-exit.outcome == 'failure' run: | echo "CMake Platform Macro: ${{ env.BOX64_PLATFORM_MARCRO }}" echo "CMake C Compiler: ${{ env.BOX64_COMPILER }}" echo "Build type: ${{ env.BOX64_BUILD_TYPE }}" echo "Trace Enabled: ${{ env.BOX64_HAVE_TRACE }}" echo "StaticBuild Enabled: ${{ env.BOX64_STATICBUILD }}" echo "Box32 Enabled: ${{ env.BOX64_BOX32 }}" - name: "Build Box64" if: steps.early-exit.outcome == 'failure' run: | export PATH=$PATH:${{ env.MINGW_COMPILER_PATH }} mkdir build cd build cmake .. -DCMAKE_C_COMPILER=${{ env.BOX64_COMPILER }}\ -DTERMUX=${{ env.IS_TERMUX }}\ ${{ env.BOX64_PLATFORM_MARCRO }}\ -DCMAKE_BUILD_TYPE=${{ env.BOX64_BUILD_TYPE }}\ -DHAVE_TRACE=${{ env.BOX64_HAVE_TRACE }}\ -DZYDIS3=${{ env.BOX64_ZYDIS3 }}\ -DSTATICBUILD=${{ env.BOX64_STATICBUILD }}\ -DBOX32=${{ env.BOX64_BOX32 }}\ -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON\ -DCI=${{ matrix.platform != 'ANDROID' }} make -j$(nproc) VERBOSE=1 - name: "Test Box64" if: steps.early-exit.outcome == 'failure' run: | if [[ ${{ matrix.platform }} != 'X64' ]]; then mkdir qemu10 wget -O- -q https://archive.archlinux.org/packages/q/qemu-user-static/qemu-user-static-10.0.0-7-x86_64.pkg.tar.zst | tar -I zstd -C qemu10 -xf - sudo cp qemu10/usr/bin/* /usr/bin/ fi cd build export CTEST_OPTIONS="-j$(nproc) --timeout 300 --output-on-failure --repeat until-pass:20" if [[ ${{ matrix.platform }} == 'RISCV' ]]; then export INTERPRETER=qemu-riscv64-static export QEMU_LD_PREFIX=/usr/riscv64-linux-gnu/ if [[ ${{ env.BOX64_BOX32 }} == '1' ]]; then export BOX32_PERSONA32BITS=1 # hack to disable personality setting fi ctest $CTEST_OPTIONS QEMU_CPU=rv64,v=false BOX64_DYNAREC=0 ctest $CTEST_OPTIONS QEMU_CPU=rv64,v=false,zba=true,zbb=true,zbc=true,zbs=true ctest $CTEST_OPTIONS QEMU_CPU=rv64,v=true,vlen=128,vext_spec=v1.0 ctest $CTEST_OPTIONS QEMU_CPU=rv64,v=true,vlen=256,vext_spec=v1.0 ctest $CTEST_OPTIONS QEMU_CPU=thead-c906 ctest $CTEST_OPTIONS BOX64_DYNAREC_TEST=1 ctest $CTEST_OPTIONS -E nocosim BOX64_DYNAREC_TEST=1 QEMU_CPU=rv64,v=false,zba=true,zbb=true,zbc=true,zbs=true ctest $CTEST_OPTIONS -E nocosim BOX64_DYNAREC_TEST=1 QEMU_CPU=rv64,v=true,vlen=128,vext_spec=v1.0 ctest $CTEST_OPTIONS -E nocosim BOX64_DYNAREC_TEST=1 QEMU_CPU=rv64,v=true,vlen=256,vext_spec=v1.0 ctest $CTEST_OPTIONS -E nocosim BOX64_DYNAREC_TEST=1 QEMU_CPU=thead-c906 ctest $CTEST_OPTIONS -E nocosim export INTERPRETER=$GITHUB_WORKSPACE/xuantie_qemu_install/bin/qemu-riscv64 QEMU_CPU=c910v ctest $CTEST_OPTIONS BOX64_DYNAREC_TEST=1 QEMU_CPU=c910v ctest $CTEST_OPTIONS -E nocosim elif [[ ${{ matrix.platform }} == 'LARCH64' ]]; then export INTERPRETER=qemu-loongarch64-static export QEMU_LD_PREFIX=/usr/loongarch64-linux-gnu/ if [[ ${{ env.BOX64_BOX32 }} == '1' ]]; then export BOX32_PERSONA32BITS=1 # hack to disable personality setting fi ctest $CTEST_OPTIONS -E nocosim BOX64_DYNAREC_LA64NOEXT=1 ctest $CTEST_OPTIONS -E nocosim BOX64_DYNAREC=0 ctest $CTEST_OPTIONS -E nocosim BOX64_DYNAREC_TEST=1 ctest $CTEST_OPTIONS -E nocosim BOX64_DYNAREC_TEST=1 BOX64_DYNAREC_LA64NOEXT=1 ctest $CTEST_OPTIONS -E nocosim elif [[ ${{ matrix.platform }} == 'ANDROID' ]]; then export INTERPRETER=qemu-aarch64-static export QEMU_LD_PREFIX=/system/lib64 BOX64_DYNAREC=0 ctest $CTEST_OPTIONS ctest $CTEST_OPTIONS elif [[ ${{ matrix.platform }} == 'TERMUX' ]]; then export INTERPRETER=qemu-aarch64-static export QEMU_SET_ENV=LD_LIBRARY_PATH=/data/data/com.termux/files/usr/lib export QEMU_LD_PREFIX=/system/lib64:/data/data/com.termux/files/usr/lib BOX64_DYNAREC=0 ctest $CTEST_OPTIONS ctest $CTEST_OPTIONS elif [[ ${{matrix.type}} == 'Box32' ]]; then ctest $CTEST_OPTIONS else ctest -j$(nproc) fi - name: "Get short Git commit" id: git-info if: steps.early-exit.outcome == 'failure' run: echo "SHORT_COMMIT=$(git rev-parse --short HEAD)" >> $GITHUB_ENV - name: "Get Box64 Version" if: steps.early-exit.outcome == 'failure' run: echo "BOX64_VERSION=$(cat src/box64version.h | grep BOX64_MAJOR | cut -d " " -f 3).$(cat src/box64version.h | grep BOX64_MINOR | cut -d " " -f 3).$(cat src/box64version.h | grep BOX64_REVISION | cut -d " " -f 3)" >> $GITHUB_ENV - name: "Packaging WCP file for Winlator" if: matrix.platform == 'ANDROID_GLIBC' && matrix.type != 'StaticBuild' && steps.early-exit.outcome == 'failure' run: | cd build cat < profile.json { "type": "Box64", "versionName": "latest-${SHORT_COMMIT}", "versionCode": 1, "description": "Box64-latest-${SHORT_COMMIT}. Built from [https://github.com/ptitSeb/box64].", "files": [ { "source": "box64", "target": "\${localbin}/box64" } ] } EOF patchelf --set-interpreter /data/data/com.winlator/files/imagefs/usr/lib/ld-linux-aarch64.so.1 ./box64 tar --zstd -cf box64-latest.wcp box64 profile.json - name: "Package Rat File for MiceWine" if: matrix.platform == 'ANDROID' && matrix.type != 'StaticBuild' && steps.early-exit.outcome == 'failure' run: | cd build mkdir -p files/usr/bin cp box64 files/usr/bin echo "name=Box64 (CI Build)" > pkg-header echo "category=Box64" >> pkg-header echo "version=${BOX64_VERSION}-${SHORT_COMMIT}" >> pkg-header echo "architecture=aarch64" >> pkg-header echo "vkDriverLib=" >> pkg-header 7z -tzip -mx=5 a box64-latest.rat files pkg-header - name: "Upload WCP file" if: matrix.platform == 'ANDROID_GLIBC' && matrix.type == 'Release' && steps.early-exit.outcome == 'failure' uses: actions/upload-artifact@v4 with: name: box64-latest-${{ matrix.type }}-wcp path: build/box64-latest.wcp - name: "Upload Rat File" if: matrix.platform == 'ANDROID' && matrix.type == 'Release' && steps.early-exit.outcome == 'failure' uses: actions/upload-artifact@v4 with: name: box64-MiceWine-${{ matrix.type }} path: build/box64-latest.rat - name: "Upload WowBox64 file" if: matrix.platform == 'WOW64' && matrix.type == 'Release' && steps.early-exit.outcome == 'failure' uses: actions/upload-artifact@v4 with: name: wowbox64-${{ matrix.type }} path: build/wowbox64-prefix/src/wowbox64-build/wowbox64.dll