Merge pull request #3124 from GaijinEntertainment/bbatkin/jit-paralle… #1176
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: build | |
| on: | |
| push: | |
| branches: [master] | |
| pull_request: | |
| workflow_dispatch: | |
| defaults: | |
| run: | |
| shell: bash | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| ########################################################### | |
| pre_job: | |
| ########################################################### | |
| # continue-on-error: true # Uncomment once integration is finished | |
| runs-on: ubuntu-latest-fat | |
| # Map a step output to a job output | |
| outputs: | |
| should_skip: ${{ steps.skip_check.outputs.should_skip }} | |
| steps: | |
| - id: skip_check | |
| uses: fkirc/skip-duplicate-actions@v5 | |
| with: | |
| # All of these options are optional, so you can remove them if you are happy with the defaults | |
| concurrent_skipping: 'same_content' | |
| do_not_skip: '["pull_request", "workflow_dispatch", "release"]' | |
| - name: Cache LLVM | |
| uses: actions/cache@v3 | |
| id: llvm-cache | |
| with: | |
| # Cache LLVM.dll, to make CI faster. | |
| path: build/_deps/das_llvm_shared_lib-src | |
| key: ${{ runner.os }}-${{ hashFiles('modules/dasLLVM/CMakeLists.txt') }} | |
| ########################################################### | |
| build: | |
| ########################################################### | |
| needs: pre_job | |
| if: needs.pre_job.outputs.should_skip != 'true' | |
| runs-on: ${{ matrix.runner }} | |
| # actions: write needed for `gh cache delete` in the sccache refresh step. | |
| permissions: | |
| contents: read | |
| actions: write | |
| env: | |
| das_dll_build: 'NO' | |
| das_llvm_disabled: 'OFF' | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| target: [linux, linux_arm, darwin15, darwin26, windows] | |
| architecture: [32, 64, arm64] | |
| cmake_preset: [ Debug, Release ] | |
| sanitizers: [none] | |
| include: | |
| - target: linux | |
| release_target: linux | |
| release_arch: x86_64 | |
| runner: ubuntu-latest-fat | |
| archive_ext: tar.gz | |
| sanitizers: none | |
| # Sanitizer matrix — Linux + Release + full tests (dastest + test_aot | |
| # + ctest). Release keeps walltime in budget; the previous Debug+ASAN | |
| # was prohibitive for production CI. See issue #2530. | |
| - target: linux | |
| architecture: 64 | |
| runner: ubuntu-latest-fat | |
| cmake_preset: Release | |
| sanitizers: asan | |
| build_name: linux_asan | |
| build_system: cmake | |
| cmake_generator: Ninja | |
| - target: linux | |
| architecture: 64 | |
| runner: ubuntu-latest-fat | |
| cmake_preset: Release | |
| sanitizers: tsan | |
| build_name: linux_tsan | |
| build_system: cmake | |
| cmake_generator: Ninja | |
| - target: linux | |
| architecture: 64 | |
| runner: ubuntu-latest-fat | |
| cmake_preset: Release | |
| sanitizers: ubsan | |
| build_name: linux_ubsan | |
| build_system: cmake | |
| cmake_generator: Ninja | |
| - target: linux_arm | |
| release_target: linux | |
| release_arch: arm64 | |
| runner: ubuntu-24.04-arm-fat | |
| archive_ext: tar.gz | |
| - target: darwin15 | |
| architecture: arm64 | |
| release_target: darwin15 | |
| release_arch: arm64 | |
| runner: macos-15-xlarge # Apple Silicon arm64, M2 | |
| architecture_string: arm64 | |
| archive_ext: tar.gz | |
| - target: darwin26 | |
| release_target: darwin26 | |
| release_arch: arm64 | |
| runner: macos-26-xlarge # Apple Silicon arm64, M2 | |
| architecture_string: arm64 | |
| archive_ext: tar.gz | |
| - target: windows | |
| runner: windows-latest-fat | |
| archive_ext: zip | |
| - target: windows | |
| build_system: cmake | |
| cmake_generator: Ninja | |
| - target: darwin15 | |
| build_system: cmake | |
| cmake_generator: Ninja | |
| - target: darwin26 | |
| build_system: cmake | |
| cmake_generator: Ninja | |
| - target: linux | |
| build_system: cmake | |
| cmake_generator: Ninja | |
| - target: linux_arm | |
| build_system: cmake | |
| cmake_generator: Ninja | |
| - target: windows | |
| release_target: windows | |
| release_arch: x86 | |
| architecture: 32 | |
| architecture_string: Win32 | |
| - target: windows | |
| release_target: windows | |
| release_arch: x86_64 | |
| architecture: 64 | |
| architecture_string: x64 | |
| # RelWithDebInfo only on Windows x64 | |
| # jit_disabled: skip the JIT prewarm + JIT test sweep here. JIT on | |
| # win64-MSVC stays covered by the Release cell below and by the full | |
| # clang JIT sweep in build_windows_mingw — running it on all three | |
| # win64 presets just triples the slowest jobs in the matrix. | |
| - target: windows | |
| architecture: 64 | |
| cmake_preset: RelWithDebInfo | |
| sanitizers: none | |
| runner: windows-latest-fat | |
| archive_ext: zip | |
| build_system: cmake | |
| cmake_generator: Ninja | |
| release_target: windows | |
| release_arch: x86_64 | |
| architecture_string: x64 | |
| jit_disabled: 'ON' | |
| # Debug win64 also skips JIT (same rationale as RelWithDebInfo above). | |
| - target: windows | |
| architecture: 64 | |
| cmake_preset: Debug | |
| jit_disabled: 'ON' | |
| exclude: | |
| # macOS Intel (darwin15 x86_64) has no prebuilt LLVM.dll (the | |
| # llvm-release workflow doesn't build one) and Apple no longer makes | |
| # new Intel macOS runners worth gating on. Drop entirely. | |
| - target: darwin15 | |
| architecture: 64 | |
| - target: darwin15 | |
| architecture: 32 | |
| - target: darwin26 | |
| architecture: 32 | |
| - target: darwin26 | |
| architecture: 64 | |
| - target: linux | |
| architecture: 32 | |
| - target: linux | |
| architecture: arm64 | |
| - target: linux_arm | |
| architecture: 32 | |
| - target: linux_arm | |
| architecture: arm64 # todo | |
| - target: windows | |
| architecture: arm64 # todo https://github.com/actions/partner-runner-images/tree/main?tab=readme-ov-file#available-images | |
| steps: | |
| - name: "SCM Checkout" | |
| uses: actions/checkout@v4 | |
| - name: "Exclude workspace from Windows Defender" | |
| if: runner.os == 'Windows' | |
| shell: pwsh | |
| continue-on-error: true | |
| # Real-time Defender scans every .obj/.exe/.dll the build writes and every | |
| # test process/DLL load; excluding the workspace cuts Windows CI wall-time. | |
| # continue-on-error: a managed-Defender runner must not fail the job. | |
| run: | | |
| Add-MpPreference -ExclusionPath "${{ github.workspace }}" | |
| Add-MpPreference -ExclusionProcess "daslang.exe" | |
| Add-MpPreference -ExclusionProcess "test_aot.exe" | |
| - name: "Install CMake and Ninja" | |
| uses: lukka/get-cmake@latest | |
| - if: runner.os == 'Windows' | |
| uses: ilammy/setup-nasm@v1 # need nasm for openssl | |
| - name: "Set up MSVC environment (Windows)" | |
| if: runner.os == 'Windows' | |
| # cl.exe on PATH so the bash build step drives Ninja with MSVC. arch | |
| # follows the matrix (x86 for the 32-bit job). MUST run BEFORE the vcpkg | |
| # openssl step: msvc-dev-cmd's vcvars sets VCPKG_ROOT to the VS-bundled | |
| # vcpkg, so the openssl step has to write our VCPKG_ROOT last. | |
| uses: ilammy/msvc-dev-cmd@v1 | |
| with: | |
| arch: ${{ matrix.architecture == 32 && 'x86' || 'x64' }} | |
| - name: "Cache vcpkg + openssl" | |
| if: runner.os == 'Windows' | |
| uses: actions/cache@v4 | |
| with: | |
| # Whole vcpkg/ dir: bootstrapped vcpkg.exe + installed/<triplet>/openssl. | |
| # On hit, install step skips clone + bootstrap + openssl build. | |
| path: vcpkg | |
| key: vcpkg-${{ matrix.architecture == 32 && 'x86' || 'x64' }}-windows-v1 | |
| - name: "Install openssl windows" | |
| if: runner.os == 'Windows' | |
| run: | | |
| if [ ! -x vcpkg/vcpkg.exe ] && [ ! -x vcpkg/vcpkg ]; then | |
| git clone https://github.com/microsoft/vcpkg && ./vcpkg/bootstrap-vcpkg.sh | |
| fi | |
| ./vcpkg/vcpkg install openssl:${{ matrix.architecture == 32 && 'x86' || 'x64' }}-windows --binarycaching | |
| echo "VCPKG_ROOT=$(pwd)/vcpkg" >> $GITHUB_ENV | |
| echo "CMAKE_TOOLCHAIN_FILE=$(pwd)/vcpkg/scripts/buildsystems/vcpkg.cmake" >> $GITHUB_ENV | |
| - name: "Install: Required Dev Packages" | |
| run: | | |
| set -eux | |
| case "${{ matrix.target }}${{ matrix.architecture }}" in | |
| darwin15arm64|darwin26arm64) | |
| brew install bison | |
| echo 'export PATH="/usr/local/opt/bison/bin:$PATH"' >> ~/.bash_profile | |
| export LDFLAGS="-L/usr/local/opt/bison/lib" | |
| ;; | |
| darwin1564|darwin2664) | |
| brew install bison | |
| echo 'export PATH="/opt/homebrew/opt/bison/bin:$PATH"' >> ~/.bash_profile | |
| export LDFLAGS="-L/opt/homebrew/opt/bison/lib" | |
| ;; | |
| esac | |
| case "${{ matrix.target }}${{ matrix.architecture }}" in | |
| linux64) | |
| echo "MARCH=64" >> $GITHUB_ENV | |
| sudo apt-get update -y | |
| sudo apt-get install --no-install-recommends -y \ | |
| libatomic-ops-dev \ | |
| libglu1-mesa-dev \ | |
| freeglut3-dev \ | |
| mesa-common-dev \ | |
| libglfw3-dev \ | |
| libfreetype6-dev \ | |
| libudev-dev \ | |
| libopenal-dev \ | |
| libvorbis-dev \ | |
| libflac-dev \ | |
| libclang-dev \ | |
| libx11-dev \ | |
| libxrandr-dev \ | |
| libxcursor-dev \ | |
| libxinerama-dev \ | |
| libxi-dev | |
| ;; | |
| esac | |
| # sccache with LOCAL-DISK backend, wrapped in ONE actions/cache entry per | |
| # matrix config. The GHA backend writes one cache item per TU (~40k items, | |
| # quota fragmentation, ~74% concurrent-write failures); local disk keeps | |
| # all objects in $SCCACHE_DIR and we persist it as a single tarball. | |
| # Windows is on Ninja now (honors CMAKE_*_COMPILER_LAUNCHER); its MSVC | |
| # compiles are cacheable because daslang builds with /Z7 (CMakeCommon.txt) — | |
| # debug info embedded in the .obj. sccache refuses to cache /Zi (separate | |
| # shared PDB) output. | |
| - uses: mozilla-actions/sccache-action@v0.0.10 | |
| - run: | | |
| echo "SCCACHE_DIR=${{ runner.temp }}/sccache" >> $GITHUB_ENV | |
| echo "SCCACHE_GHA_ENABLED=false" >> $GITHUB_ENV | |
| # Non-Windows: export the launcher via env (also wraps the GLFW/libhv | |
| # ExternalProject sub-builds — harmless on gcc/clang). Windows must NOT | |
| # export it: CMake seeds CMAKE_<LANG>_COMPILER_LAUNCHER from the env | |
| # into the sub-cmakes, where sccache + MSVC /Zi (those sub-builds keep | |
| # /Zi) + parallel Ninja collide on the shared glfw.pdb (C1041). Windows | |
| # instead passes the launcher as -D on the MAIN configure only (Build | |
| # step), scoping sccache to daslang's own /Z7 TUs. | |
| if [ "$RUNNER_OS" != "Windows" ]; then | |
| echo "CMAKE_C_COMPILER_LAUNCHER=sccache" >> $GITHUB_ENV | |
| echo "CMAKE_CXX_COMPILER_LAUNCHER=sccache" >> $GITHUB_ENV | |
| fi | |
| # Stable per-config key, one fixed slot. Restore always; on master, | |
| # delete + re-save the same key after Build so the slot is overwritten | |
| # with fresh objects (GHA caches are immutable — plain save under an | |
| # existing key is a no-op, so we delete first). PRs read-only. Bounded | |
| # footprint: N configs × one tarball, no run_id pileup. | |
| - name: "Restore sccache objects" | |
| uses: actions/cache/restore@v4 | |
| with: | |
| path: ${{ runner.temp }}/sccache | |
| key: sccache-${{ matrix.target }}-${{ matrix.architecture }}-${{ matrix.cmake_preset }}-${{ matrix.sanitizers }} | |
| - name: "Override das_llvm_disabled for win32" | |
| if: matrix.target == 'windows' && matrix.architecture == 32 | |
| shell: bash | |
| run: echo "das_llvm_disabled=ON" >> $GITHUB_ENV | |
| - name: "Build: Daslang" | |
| run: | | |
| set -eux | |
| mkdir build | |
| case "${{ matrix.build_system }}" in | |
| cmake) | |
| case "${{ matrix.target }}${{ matrix.architecture }}" in | |
| linux64) | |
| CC=clang CXX=clang++ cmake --no-warn-unused-cli -B./build -DCMAKE_BUILD_TYPE:STRING=${{ matrix.cmake_preset }} -G \ | |
| "${{ matrix.cmake_generator }}" -DDAS_USE_SANITIZER=${{ matrix.sanitizers }} -DDAS_LLVM_DISABLED=${{ env.das_llvm_disabled }} | |
| cd build | |
| ninja | |
| ;; | |
| windows32) | |
| export PATH="/c/Strawberry/perl/bin:$PATH" # prepend Strawberry perl to path, so openssl will use it. | |
| # Launcher passed as -D here (not env) so it scopes to daslang's | |
| # own targets and does NOT leak into the GLFW/libhv sub-builds. | |
| # daslang's MSVC debug info is /Z7 (CMakeCommon.txt) so sccache | |
| # can cache it. | |
| cmake --no-warn-unused-cli -B./build -G "${{ matrix.cmake_generator }}" -DCMAKE_BUILD_TYPE:STRING=${{ matrix.cmake_preset }} -DCMAKE_C_COMPILER_LAUNCHER=sccache -DCMAKE_CXX_COMPILER_LAUNCHER=sccache -DCMAKE_TOOLCHAIN_FILE="$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake" | |
| cmake --build ./build --config ${{ matrix.cmake_preset }} --parallel | |
| ;; | |
| windows64) | |
| export PATH="/c/Strawberry/perl/bin:$PATH" # prepend Strawberry perl to path, so openssl will use it. | |
| # Launcher passed as -D here (not env) so it scopes to daslang's | |
| # own targets and does NOT leak into the GLFW/libhv sub-builds. | |
| # daslang's MSVC debug info is /Z7 (CMakeCommon.txt) so sccache | |
| # can cache it. | |
| cmake --no-warn-unused-cli -B./build -G "${{ matrix.cmake_generator }}" -DCMAKE_BUILD_TYPE:STRING=${{ matrix.cmake_preset }} -DCMAKE_C_COMPILER_LAUNCHER=sccache -DCMAKE_CXX_COMPILER_LAUNCHER=sccache -DDAS_LLVM_DISABLED=${{ env.das_llvm_disabled }} -DCMAKE_TOOLCHAIN_FILE="$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake" | |
| cmake --build ./build --config ${{ matrix.cmake_preset }} --parallel | |
| ;; | |
| linux_arm*) | |
| CC=clang CXX=clang++ cmake --no-warn-unused-cli -B./build -DCMAKE_BUILD_TYPE:STRING=${{ matrix.cmake_preset }} -DDAS_GLFW_DISABLED=ON -DDAS_HV_DISABLED=OFF -DDAS_SQLITE_DISABLED=OFF -DDAS_LLVM_DISABLED=${{ env.das_llvm_disabled }} -G \ | |
| "${{ matrix.cmake_generator }}" | |
| cd build | |
| ninja | |
| ;; | |
| *) | |
| CC=clang CXX=clang++ cmake --no-warn-unused-cli -B./build -DCMAKE_OSX_ARCHITECTURES="${{ matrix.architecture_string }}" -DCMAKE_BUILD_TYPE:STRING=${{ matrix.cmake_preset }} -DDAS_LLVM_DISABLED=${{ env.das_llvm_disabled }} -G "${{ matrix.cmake_generator }}" | |
| cd build | |
| ninja | |
| ;; | |
| esac | |
| ;; | |
| esac | |
| - name: "Refresh sccache slot" | |
| if: github.ref == 'refs/heads/master' | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| SCKEY: sccache-${{ matrix.target }}-${{ matrix.architecture }}-${{ matrix.cmake_preset }}-${{ matrix.sanitizers }} | |
| run: gh cache delete "$SCKEY" -R ${{ github.repository }} || true | |
| - name: "Save sccache objects" | |
| if: github.ref == 'refs/heads/master' | |
| uses: actions/cache/save@v4 | |
| with: | |
| path: ${{ runner.temp }}/sccache | |
| key: sccache-${{ matrix.target }}-${{ matrix.architecture }}-${{ matrix.cmake_preset }}-${{ matrix.sanitizers }} | |
| - name: "Prewarm JIT cache" | |
| if: env.das_llvm_disabled != 'ON' && matrix.jit_disabled != 'ON' | |
| run: | | |
| set -eux | |
| cmake --build ./build --config ${{ matrix.cmake_preset }} --target jit_cache_all_tests | |
| - name: "Test" | |
| run: | | |
| set -eux | |
| # When daslang is sanitizer-instrumented, its JIT-emitted .dll cache | |
| # link cmd needs -fsanitize=<kind> to pull the sanitizer runtime | |
| # (otherwise unresolved __ubsan_*/__asan_*/__tsan_* symbols in lib.so). | |
| JIT_LINKER_STRING="" | |
| case "${{ matrix.sanitizers }}" in | |
| ubsan) JIT_LINKER_STRING="--jit-linker-string=-fsanitize=undefined" ;; | |
| asan) JIT_LINKER_STRING="--jit-linker-string=-fsanitize=address" ;; | |
| tsan) JIT_LINKER_STRING="--jit-linker-string=-fsanitize=thread" ;; | |
| esac | |
| # daslang built with clang on sanitizer matrix — JIT-emitted .dll | |
| # must link with the same compiler (incompatible asan/tsan runtimes | |
| # otherwise). c++ default = g++ on Ubuntu, mismatches. | |
| JIT_PATH_TO_LINKER="" | |
| if [ "${{ matrix.sanitizers }}" != "none" ] && [ -n "${{ matrix.sanitizers }}" ]; then | |
| JIT_PATH_TO_LINKER="--jit-path-to-linker=clang++" | |
| fi | |
| # Match JIT codegen opt level to build type: Debug → -O0 (fast codegen), | |
| # Release/RelWithDebInfo → -O3. | |
| case "${{ matrix.cmake_preset }}" in | |
| Debug) JIT_OPT="--jit-opt-level=0" ;; | |
| *) JIT_OPT="--jit-opt-level=3" ;; | |
| esac | |
| case "${{ matrix.target }}${{ matrix.architecture }}" in | |
| linux64) | |
| cd bin | |
| # LSan suppressions: format_error (fmt::throw_format_error allocates | |
| # std::runtime_error whose internal string is reported as leaked | |
| # because the exception object isn't always destroyed); uriParseSingleUriA | |
| # / uriMakeOwner (Uri handle bound to daslang without auto-finalize — | |
| # tracked separately, real fix is in the binding). | |
| printf 'leak:format_error\nleak:uriParseSingleUriA\nleak:uriMakeOwner\n' > suppressions.txt | |
| export LSAN_OPTIONS="suppressions=$(pwd)/suppressions.txt" | |
| # Sanitizer matrix: only run language tests under JIT (full test | |
| # suite under asan/tsan/ubsan adds ~10m wall-clock without proportionate | |
| # coverage value). Non-sanitizer keeps the full sweep. | |
| if [ "${{ matrix.sanitizers }}" != "none" ]; then | |
| TEST_DIR=_dasroot_/tests/language | |
| else | |
| TEST_DIR=_dasroot_/tests | |
| fi | |
| # Use more time to pass UBSAN and disable leaks in JIT mode because we exit using exit(), and do not call destructors. | |
| [ "${{ env.das_llvm_disabled }}" = "ON" ] || ASAN_OPTIONS=detect_leaks=0 ./daslang _dasroot_/dastest/dastest.das -jit -- $JIT_LINKER_STRING $JIT_PATH_TO_LINKER $JIT_OPT --color --failures-only --timeout 900 --test $TEST_DIR || ASAN_OPTIONS=detect_leaks=0 ./daslang _dasroot_/dastest/dastest.das -jit -- $JIT_LINKER_STRING $JIT_PATH_TO_LINKER $JIT_OPT --color --failures-only --isolated-mode --timeout 3600 --test $TEST_DIR | |
| # Interpreter sweep: non-sanitizer only. | |
| if [ "${{ matrix.sanitizers }}" = "none" ]; then | |
| ./daslang _dasroot_/dastest/dastest.das -- --color --failures-only --timeout 900 --test _dasroot_/tests || ./daslang _dasroot_/dastest/dastest.das -- --color --failures-only --isolated-mode --timeout 3600 --test _dasroot_/tests | |
| fi | |
| ;; | |
| windows32) | |
| cd bin | |
| ./daslang _dasroot_/dastest/dastest.das -- --color --failures-only --timeout 900 --test _dasroot_/tests || ./daslang _dasroot_/dastest/dastest.das -- --color --failures-only --isolated-mode --timeout 3600 --test _dasroot_/tests | |
| ;; | |
| windows*) | |
| cd bin | |
| [ "${{ env.das_llvm_disabled }}" = "ON" ] || [ "${{ matrix.jit_disabled }}" = "ON" ] || ./daslang _dasroot_/dastest/dastest.das -jit -- $JIT_LINKER_STRING $JIT_PATH_TO_LINKER $JIT_OPT --timeout 900 --color --failures-only --test _dasroot_/tests || ./daslang _dasroot_/dastest/dastest.das -jit -- $JIT_LINKER_STRING $JIT_PATH_TO_LINKER $JIT_OPT --color --failures-only --isolated-mode --timeout 3600 --test _dasroot_/tests | |
| ./daslang _dasroot_/dastest/dastest.das -- --color --failures-only --timeout 900 --test _dasroot_/tests || ./daslang _dasroot_/dastest/dastest.das -- --color --failures-only --isolated-mode --timeout 3600 --test _dasroot_/tests | |
| ;; | |
| linux_arm64) | |
| cd bin | |
| # Skip JIT tests on the Debug cmake preset — LLVM ARM64 SelectionDAG | |
| # hangs reproducibly mid-suite under Debug (different test each run, | |
| # ~20 min in). Tracked separately. Release of the same matrix still | |
| # runs JIT — keep --failures-only off there so PASS lines print and | |
| # name the test running just before the hang if it reoccurs (see | |
| # RC2 release run #25572466058). | |
| [ "${{ env.das_llvm_disabled }}" = "ON" ] || [ "${{ matrix.cmake_preset }}" = "Debug" ] || ./daslang _dasroot_/dastest/dastest.das -jit -- $JIT_LINKER_STRING $JIT_PATH_TO_LINKER $JIT_OPT --color --timeout 900 --test _dasroot_/tests || ./daslang _dasroot_/dastest/dastest.das -jit -- $JIT_LINKER_STRING $JIT_PATH_TO_LINKER $JIT_OPT --color --failures-only --isolated-mode --timeout 3600 --test _dasroot_/tests | |
| ./daslang _dasroot_/dastest/dastest.das -- --color --failures-only --timeout 900 --test _dasroot_/tests || ./daslang _dasroot_/dastest/dastest.das -- --color --failures-only --isolated-mode --timeout 3600 --test _dasroot_/tests | |
| ;; | |
| *) | |
| cd bin | |
| [ "${{ env.das_llvm_disabled }}" = "ON" ] || ./daslang _dasroot_/dastest/dastest.das -jit -- $JIT_LINKER_STRING $JIT_PATH_TO_LINKER $JIT_OPT --color --failures-only --timeout 900 --test _dasroot_/tests || ./daslang _dasroot_/dastest/dastest.das -jit -- $JIT_LINKER_STRING $JIT_PATH_TO_LINKER $JIT_OPT --color --failures-only --isolated-mode --timeout 3600 --test _dasroot_/tests | |
| ./daslang _dasroot_/dastest/dastest.das -- --color --failures-only --timeout 900 --test _dasroot_/tests || ./daslang _dasroot_/dastest/dastest.das -- --color --failures-only --isolated-mode --timeout 3600 --test _dasroot_/tests | |
| ;; | |
| esac | |
| - name: "Small C++ Tests" | |
| run: | | |
| set -eux | |
| # Suppress LSan false-positives from format_error and JIT-mode exit() paths; | |
| # see "Test" step above for the same suppressions. | |
| printf 'leak:format_error\nleak:uriParseSingleUriA\nleak:uriMakeOwner\n' > build/suppressions.txt | |
| export LSAN_OPTIONS="suppressions=$(pwd)/build/suppressions.txt" | |
| cd build | |
| case "${{ matrix.target }}${{ matrix.architecture }}" in | |
| windows*) | |
| ctest --build-config "${{ matrix.cmake_preset }}" -L small --output-on-failure | |
| ;; | |
| *) | |
| ctest -L small --output-on-failure | |
| ;; | |
| esac | |
| - name: "Slow Release Tests" | |
| if: matrix.cmake_preset == 'Release' | |
| run: | | |
| set -eux | |
| case "${{ matrix.target }}${{ matrix.architecture }}" in | |
| windows32) | |
| echo "Skipping AOT tests on 32-bit Windows" | |
| ;; | |
| windows*) | |
| cd bin | |
| ./test_aot -use-aot _dasroot_/dastest/dastest.das -- --use-aot --color --failures-only --timeout 900 --test _dasroot_/tests | |
| ;; | |
| *) | |
| cd bin | |
| # Same suppressions as the "Test" step — sanitizer matrix entries | |
| # need them here too. | |
| printf 'leak:format_error\nleak:uriParseSingleUriA\nleak:uriMakeOwner\n' > suppressions.txt | |
| export LSAN_OPTIONS="suppressions=$(pwd)/suppressions.txt" | |
| ./test_aot -use-aot _dasroot_/dastest/dastest.das -- --use-aot --color --failures-only --timeout 900 --test _dasroot_/tests | |
| ;; | |
| esac | |
| ########################################################### | |
| bundle_smoke: | |
| ########################################################### | |
| # Catches release-bundle install-rule regressions at PR time on the | |
| # platform that produces 95% of such bugs (Linux x86_64). Mirrors the | |
| # release.yml linux64 build path: same module flags via ci/release_modules.txt, | |
| # same install layout (cmake --install --prefix ./daslang_bundle), same | |
| # ci/smoke_test_bundle.sh that release.yml runs. Full-matrix smoke is | |
| # still gated at release-cut time in release.yml. | |
| ########################################################### | |
| needs: pre_job | |
| if: needs.pre_job.outputs.should_skip != 'true' | |
| runs-on: ubuntu-latest-fat | |
| steps: | |
| - name: "SCM Checkout" | |
| uses: actions/checkout@v4 | |
| - name: "Install CMake and Ninja" | |
| uses: lukka/get-cmake@latest | |
| - name: "Install: Required Dev Packages" | |
| run: | | |
| set -eux | |
| sudo apt-get update -y | |
| sudo apt-get install --no-install-recommends -y \ | |
| libatomic-ops-dev \ | |
| libglu1-mesa-dev \ | |
| freeglut3-dev \ | |
| mesa-common-dev \ | |
| libglfw3-dev \ | |
| libfreetype6-dev \ | |
| libudev-dev \ | |
| libopenal-dev \ | |
| libvorbis-dev \ | |
| libflac-dev \ | |
| libx11-dev \ | |
| libxrandr-dev \ | |
| libxcursor-dev \ | |
| libxinerama-dev \ | |
| libxi-dev | |
| - name: "Build: Daslang with release modules" | |
| run: | | |
| set -eux | |
| mkdir build | |
| ACTIVE_MODULES=$(cat ci/release_modules.txt | grep -v "^#" | cut -d':' -f2 | sed 's|^|-D|' | xargs) | |
| CC=clang CXX=clang++ cmake --no-warn-unused-cli -B./build -DCMAKE_BUILD_TYPE:STRING=Release \ | |
| -G Ninja $ACTIVE_MODULES | |
| cmake --build ./build --config Release --parallel | |
| - name: "Install bundle" | |
| run: | | |
| set -eux | |
| mkdir daslang_bundle | |
| cmake --install ./build --prefix ./daslang_bundle --config Release --strip | |
| - name: "Smoke-test installed bundle" | |
| run: bash ci/smoke_test_bundle.sh ./daslang_bundle | |
| ########################################################### | |
| build_windows_mingw: | |
| ########################################################### | |
| # Catches clang-mingw64 toolchain regressions at PR time. The mingw path | |
| # diverges from MSVC in src/hal/debug_break.cpp, src/hal/project_specific_crash_handler.cpp, | |
| # and src/builtin/module_jit.cpp (PR #2838). Without this job, a Windows-touching | |
| # change that compiles under MSVC but breaks mingw would only surface when a | |
| # maintainer rebuilds locally. Same runner pool as the MSVC matrix | |
| # (windows-latest-fat), separate top-level job so mingw churn doesn't risk | |
| # the much-larger MSVC entries. | |
| # | |
| # dasClangBind is enabled here — find_package(Clang 22.1) matches msys2's | |
| # libclang 22.1.x and POST_BUILD copies the libclang+libLLVM+libc++ chain | |
| # next to daslang.exe so the .shared_module dlopen resolves at runtime. | |
| ########################################################### | |
| needs: pre_job | |
| if: needs.pre_job.outputs.should_skip != 'true' | |
| runs-on: windows-latest-fat | |
| defaults: | |
| run: | |
| shell: msys2 {0} | |
| steps: | |
| - name: "SCM Checkout" | |
| uses: actions/checkout@v4 | |
| - name: "Install MSYS2 + clang-mingw64 toolchain" | |
| uses: msys2/setup-msys2@v2 | |
| with: | |
| msystem: CLANG64 | |
| update: true | |
| cache: true | |
| install: >- | |
| mingw-w64-clang-x86_64-toolchain | |
| mingw-w64-clang-x86_64-cmake | |
| mingw-w64-clang-x86_64-ninja | |
| mingw-w64-clang-x86_64-openssl | |
| mingw-w64-clang-x86_64-glfw | |
| bison | |
| git | |
| - name: "Build: Daslang (clang-mingw64)" | |
| run: | | |
| set -eux | |
| mkdir -p build-mingw | |
| cmake --no-warn-unused-cli -B./build-mingw -G Ninja \ | |
| -DCMAKE_BUILD_TYPE=Release \ | |
| -DCMAKE_C_COMPILER=clang \ | |
| -DCMAKE_CXX_COMPILER=clang++ \ | |
| -DDAS_CLANG_BIND_DISABLED=OFF \ | |
| -DDAS_LLVM_DISABLED=OFF | |
| cmake --build ./build-mingw --parallel | |
| - name: "Test: interpreter sweep" | |
| run: | | |
| set -eux | |
| cd bin | |
| ./daslang _dasroot_/dastest/dastest.das -- --color --failures-only --timeout 900 --test _dasroot_/tests \ | |
| || ./daslang _dasroot_/dastest/dastest.das -- --color --failures-only --isolated-mode --timeout 3600 --test _dasroot_/tests | |
| - name: "Test: JIT sweep" | |
| run: | | |
| set -eux | |
| cd bin | |
| ./daslang _dasroot_/dastest/dastest.das -jit -- --color --failures-only --timeout 900 --test _dasroot_/tests \ | |
| || ./daslang _dasroot_/dastest/dastest.das -jit -- --color --failures-only --isolated-mode --timeout 3600 --test _dasroot_/tests | |
| - name: "Small C++ Tests" | |
| run: | | |
| set -eux | |
| cd build-mingw | |
| ctest -L small --output-on-failure | |
| - name: "Slow Release Tests (AOT)" | |
| run: | | |
| set -eux | |
| cd bin | |
| ./test_aot -use-aot _dasroot_/dastest/dastest.das -- --use-aot --color --failures-only --timeout 900 --test _dasroot_/tests | |
| # bind_clangbind self-binder lives here (not on linux extended_checks) | |
| # because dasClangBind on linux pulls libclang.so → libLLVM-22.so.1, | |
| # which collides with dasLLVM in the same process (shared pass | |
| # registry, double-init breaks JIT). msys2 clang64 ships libclang as | |
| # a separate SO chain, and the mingw worker doesn't exercise JIT-uses- | |
| # dasClangBind paths, so they coexist cleanly. | |
| # | |
| # TODO: bind_llvm.das self-binder doesn't run on mingw — libclang as | |
| # library doesn't find <cstddef> via msys2's libcxx auto-detection. | |
| # Needs explicit -resource-dir / -isystem injection. Tracked as a | |
| # follow-up; we lose master's previous bind_llvm.das CI coverage in | |
| # the meantime. | |
| - name: "Run self-binder (bind_clangbind.das)" | |
| run: | | |
| set -eux | |
| CLANG_INCLUDE="$(cygpath -w "${MSYSTEM_PREFIX}/include")" | |
| ./bin/daslang.exe modules/dasClangBind/bind/bind_clangbind.das -- --clang_path "${CLANG_INCLUDE}/" | |
| git diff --exit-code -- modules/dasClangBind/src/ \ | |
| || (echo "ERROR: dasClangBind generated files are out of date. Run './bin/daslang modules/dasClangBind/bind/bind_clangbind.das -- --clang_path <libclang-include-path>' locally and commit the result." && exit 1) | |
| - name: "Run cbind const-gen regression test" | |
| # Exercises collectActiveDefines (preprocessor-active constant generation); | |
| # main returns non-zero on failure. Lives on the mingw worker because that | |
| # is where libclang/cbind is available (same reason as the self-binder). | |
| run: ./bin/daslang.exe modules/dasClangBind/tests/test_const_preproc.das | |
| build_windows_clangcl: | |
| ########################################################### | |
| # Catches clang-cl (Visual Studio "ClangCL" toolset) build regressions. clang-cl | |
| # sets CMake's MSVC=TRUE but uses clang's resource headers, and the toolset puts | |
| # that resource include dir on INCLUDE. dasHV builds OpenSSL from source with plain | |
| # cl, which rejects clang's #include_next <stdint.h> (C1021) — modules/dasHV/ | |
| # scrub_clang_include.cmake strips the clang dir from INCLUDE so cl falls back to | |
| # MSVC's stdint.h. Without this job that fix — and clang-cl buildability generally — | |
| # could silently rot. Same runner pool as the MSVC matrix; separate top-level job. | |
| ########################################################### | |
| needs: pre_job | |
| if: needs.pre_job.outputs.should_skip != 'true' | |
| runs-on: windows-latest-fat | |
| steps: | |
| - name: "SCM Checkout" | |
| uses: actions/checkout@v4 | |
| - name: "Exclude workspace from Defender" | |
| shell: pwsh | |
| continue-on-error: true | |
| run: | | |
| Add-MpPreference -ExclusionPath "${{ github.workspace }}" | |
| Add-MpPreference -ExclusionProcess "daslang.exe" | |
| Add-MpPreference -ExclusionProcess "test_aot.exe" | |
| - name: "Install nasm (OpenSSL asm)" | |
| uses: ilammy/setup-nasm@v1 | |
| # dasHV builds OpenSSL from source here (the path the scrub fix targets), and | |
| # nmake is serial — ~7 min. Cache the install so only the first run (or a dasHV | |
| # CMakeLists change) pays it; on a hit find_package(OpenSSL) finds it and the | |
| # from-source ExternalProject is skipped. (sccache — the matrix's compiler cache | |
| # — is not usable here: the VS generator, required for the ClangCL toolset, does | |
| # not support CMAKE_CXX_COMPILER_LAUNCHER.) | |
| - name: "Cache OpenSSL (clang-cl from-source build)" | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| build-clangcl/openssl/include | |
| build-clangcl/openssl/lib | |
| build-clangcl/openssl/bin | |
| key: openssl-clangcl-${{ runner.os }}-${{ hashFiles('modules/dasHV/CMakeLists.txt') }} | |
| - name: "Build: Daslang (clang-cl / VS ClangCL toolset)" | |
| shell: pwsh | |
| run: | | |
| cmake -B build-clangcl -G "Visual Studio 17 2022" -A x64 -T ClangCL -DCMAKE_BUILD_TYPE=Release | |
| if ($LASTEXITCODE -ne 0) { exit 1 } | |
| cmake --build build-clangcl --config Release --parallel | |
| if ($LASTEXITCODE -ne 0) { exit 1 } | |
| - name: "Test: interpreter sweep" | |
| shell: pwsh | |
| run: | | |
| bin\Release\daslang.exe dastest\dastest.das -- --color --failures-only --timeout 900 --test tests | |
| if ($LASTEXITCODE -ne 0) { exit 1 } | |
| - name: "Test: AOT sweep" | |
| shell: pwsh | |
| run: | | |
| cmake --build build-clangcl --config Release --target test_aot --parallel | |
| if ($LASTEXITCODE -ne 0) { exit 1 } | |
| bin\Release\test_aot.exe -use-aot dastest\dastest.das -- --use-aot --color --failures-only --timeout 900 --test tests | |
| if ($LASTEXITCODE -ne 0) { exit 1 } | |
| - name: "Small C++ tests" | |
| shell: pwsh | |
| run: | | |
| cd build-clangcl | |
| ctest --build-config Release -L small --output-on-failure | |
| if ($LASTEXITCODE -ne 0) { exit 1 } | |