feat: harden static host integration #11
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
| # SPDX-License-Identifier: AGPL-3.0-or-later | |
| # Copyright (C) 2026 Cycl0o0 | |
| name: Build | |
| on: | |
| push: | |
| pull_request: | |
| workflow_dispatch: | |
| permissions: | |
| contents: read | |
| jobs: | |
| make: | |
| name: Make and playground | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Check out source | |
| uses: actions/checkout@v7 | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: '3.13' | |
| - name: Check version consistency | |
| run: tools/check-version.sh | |
| - name: Install build dependencies | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install --yes build-essential pkg-config libsdl2-dev libgl1-mesa-dev mono-mcs | |
| - name: Build library | |
| run: make --jobs="$(nproc)" | |
| - name: Verify distributable notices | |
| run: | | |
| test -f dist/LICENSE | |
| test -f dist/LICENSES/LibUltraShip-MIT.txt | |
| test -f dist/NOTICE.md | |
| test -f dist/README.md | |
| test -f dist/CHANGELOG.md | |
| test -f dist/CONTRIBUTING.md | |
| test -f dist/CONTRIBUTORS.md | |
| test -f dist/SECURITY.md | |
| test -f dist/docs/README.md | |
| test -f dist/docs/GETTING_STARTED.md | |
| test -f dist/docs/USAGE.md | |
| test -f dist/docs/API_REFERENCE.md | |
| test -f dist/docs/UNIVERSAL_SDK.md | |
| test -f dist/docs/ENGINE_INTEGRATION.md | |
| test -f dist/docs/FIDELITY.md | |
| test -f dist/docs/ROM_COMPATIBILITY.md | |
| test -f dist/docs/DEVELOPMENT.md | |
| test -f dist/docs/RELEASING.md | |
| test -f dist/bindings/README.md | |
| test -f dist/bindings/cpp/liboot.hpp | |
| test -f dist/bindings/csharp/LibOot.cs | |
| test -f dist/bindings/csharp/README.md | |
| test -f dist/fuzz/README.md | |
| test -x dist/tools/check-install.sh | |
| test -x dist/tools/identify-rom.py | |
| test -f dist/tools/rom-profiles.json | |
| - name: Verify public headers, bindings, and ABI | |
| run: | | |
| printf '%s\n' '#include <liboot_engine.h>' \ | |
| 'int main(void) { OoTEngineInput input = OOT_ENGINE_INPUT_INIT; return input.structSize == 0u; }' \ | |
| | cc -x c -std=c11 -Wall -Wextra -Wpedantic -Werror \ | |
| -Idist/include -c -o "$RUNNER_TEMP/public-c.o" - | |
| printf '%s\n' '#include <liboot.hpp>' \ | |
| 'int main() { auto input = liboot::default_input(); return input.structSize == 0u; }' \ | |
| | c++ -x c++ -std=c++11 -Wall -Wextra -Wpedantic -Werror \ | |
| -Idist/include -c -o "$RUNNER_TEMP/public-cpp.o" - | |
| mcs -unsafe -warnaserror -target:library \ | |
| -out:"$RUNNER_TEMP/LibOot.dll" bindings/csharp/LibOot.cs | |
| mcs -unsafe -warnaserror -out:"$RUNNER_TEMP/csharp-init-test.exe" \ | |
| bindings/csharp/LibOot.cs test/csharp_init_test.cs | |
| LD_LIBRARY_PATH="$GITHUB_WORKSPACE/dist" \ | |
| mono "$RUNNER_TEMP/csharp-init-test.exe" | |
| tools/check-symbols.sh dist/liboot.so | |
| - name: Build basic example | |
| run: make --directory=examples --jobs="$(nproc)" | |
| - name: Build all tests and run the ROM-free suite | |
| run: | | |
| make test --jobs="$(nproc)" | |
| make check | |
| - name: Run ROM parser checks with sanitizers | |
| run: | | |
| cc -std=c11 -Wall -Wextra -Wpedantic -Werror \ | |
| -fsanitize=address,undefined -fno-omit-frame-pointer -Isrc \ | |
| test/rom_util_test.c src/rom_util.c \ | |
| -o "$RUNNER_TEMP/rom-util-sanitized" | |
| ASAN_OPTIONS=detect_leaks=1:halt_on_error=1 \ | |
| UBSAN_OPTIONS=halt_on_error=1 \ | |
| "$RUNNER_TEMP/rom-util-sanitized" | |
| cc -std=c11 -Wall -Wextra -Wpedantic -Werror \ | |
| -fsanitize=address,undefined -fno-omit-frame-pointer \ | |
| test/audio_overflow_test.c \ | |
| -o "$RUNNER_TEMP/audio-overflow-sanitized" | |
| ASAN_OPTIONS=detect_leaks=1:halt_on_error=1 \ | |
| UBSAN_OPTIONS=halt_on_error=1 \ | |
| "$RUNNER_TEMP/audio-overflow-sanitized" | |
| - name: Run finite parser fuzz smoke | |
| run: make fuzz-smoke | |
| - name: Build and test the complete library with sanitizers | |
| run: make sanitizers | |
| - name: Build SDL/OpenGL playground | |
| run: make --directory=test playground | |
| cmake: | |
| name: CMake ${{ matrix.os }} (${{ matrix.kind }}) | |
| runs-on: ${{ matrix.os }} | |
| # Unix jobs use the host compiler; Windows has a dedicated UCRT64 job below. | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest, ubuntu-24.04-arm, macos-latest] | |
| kind: [shared, static] | |
| env: | |
| INSTALL_PREFIX: ${{ github.workspace }}/stage/${{ matrix.kind }} | |
| steps: | |
| - name: Check out source | |
| uses: actions/checkout@v7 | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: '3.13' | |
| - name: Check version consistency | |
| shell: bash | |
| run: tools/check-version.sh | |
| - name: Install build tools (Linux) | |
| if: runner.os == 'Linux' | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install --yes cmake ninja-build pkg-config | |
| - name: Install build tools (macOS) | |
| if: runner.os == 'macOS' | |
| run: brew install ninja pkg-config | |
| - name: Configure | |
| run: >- | |
| cmake -S . -B build -G Ninja | |
| -DBUILD_SHARED_LIBS=${{ matrix.kind == 'shared' && 'ON' || 'OFF' }} | |
| -DCMAKE_BUILD_TYPE=Release | |
| -DCMAKE_INSTALL_LIBDIR=lib | |
| -DCMAKE_INSTALL_PREFIX="$INSTALL_PREFIX" | |
| - name: Build | |
| run: cmake --build build --config Release --parallel | |
| - name: Run CMake tests | |
| run: ctest --test-dir build --build-config Release --output-on-failure | |
| - name: Install | |
| run: cmake --install build --config Release | |
| - name: Verify installed package consumers | |
| shell: bash | |
| run: tools/check-install.sh "$INSTALL_PREFIX" | |
| - name: Verify multiarch and custom install directories | |
| if: matrix.os == 'ubuntu-latest' && matrix.kind == 'static' | |
| shell: bash | |
| run: | | |
| portable_prefix="$RUNNER_TEMP/liboot-portable-install" | |
| cmake -S . -B build-portable -G "Ninja Multi-Config" \ | |
| -DBUILD_SHARED_LIBS=OFF \ | |
| -DBUILD_TESTING=OFF \ | |
| -DCMAKE_INSTALL_LIBDIR=lib/x86_64-linux-gnu \ | |
| -DCMAKE_INSTALL_INCLUDEDIR=headers \ | |
| -DCMAKE_INSTALL_DATAROOTDIR=resources \ | |
| -DCMAKE_INSTALL_PREFIX="$portable_prefix" | |
| cmake --build build-portable --config Release --parallel | |
| cmake --install build-portable --config Release | |
| CMAKE_GENERATOR="Ninja Multi-Config" \ | |
| tools/check-install.sh "$portable_prefix" | |
| - name: Verify exported ABI (shared) | |
| if: matrix.kind == 'shared' | |
| shell: bash | |
| run: | | |
| case "$RUNNER_OS" in | |
| Linux) lib="$INSTALL_PREFIX/lib/liboot.so" ;; | |
| macOS) lib="$INSTALL_PREFIX/lib/liboot.dylib" ;; | |
| esac | |
| tools/check-symbols.sh "$lib" | |
| - name: Verify ELF soname (Linux shared) | |
| if: runner.os == 'Linux' && matrix.kind == 'shared' | |
| run: | | |
| test -L "$INSTALL_PREFIX/lib/liboot.so.0.8" | |
| readelf -d "$INSTALL_PREFIX/lib/liboot.so.0.8.0" \ | |
| | grep -F 'Library soname: [liboot.so.0.8]' | |
| windows: | |
| name: Windows UCRT64 (${{ matrix.kind }}) | |
| runs-on: windows-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| kind: [shared, static] | |
| env: | |
| INSTALL_SUBDIR: stage/${{ matrix.kind }} | |
| steps: | |
| - name: Check out source | |
| uses: actions/checkout@v7 | |
| - name: Set up MSYS2 UCRT64 | |
| uses: msys2/setup-msys2@v2.32.0 | |
| with: | |
| msystem: UCRT64 | |
| update: true | |
| install: diffutils | |
| pacboy: >- | |
| toolchain:p | |
| cmake:p | |
| ninja:p | |
| python:p | |
| pkgconf:p | |
| - name: Verify source contracts | |
| shell: msys2 {0} | |
| run: | | |
| tools/check-version.sh | |
| python tools/check-vendor.py | |
| python tools/check-bindings.py | |
| - name: Configure | |
| shell: msys2 {0} | |
| run: | | |
| install_prefix="$PWD/$INSTALL_SUBDIR" | |
| cmake -S . -B build -G Ninja \ | |
| -DBUILD_SHARED_LIBS=${{ matrix.kind == 'shared' && 'ON' || 'OFF' }} \ | |
| -DBUILD_TESTING=ON \ | |
| -DCMAKE_BUILD_TYPE=Release \ | |
| -DCMAKE_INSTALL_LIBDIR=lib \ | |
| -DCMAKE_INSTALL_BINDIR=bin \ | |
| -DCMAKE_INSTALL_PREFIX="$install_prefix" | |
| - name: Build and test | |
| shell: msys2 {0} | |
| run: | | |
| cmake --build build --config Release --parallel | |
| ctest --test-dir build --build-config Release --output-on-failure | |
| - name: Install and verify consumers | |
| shell: msys2 {0} | |
| run: | | |
| install_prefix="$PWD/$INSTALL_SUBDIR" | |
| cmake --install build --config Release | |
| export PATH="$install_prefix/bin:$PATH" | |
| tools/check-install.sh "$install_prefix" | |
| - name: Verify exported ABI (shared) | |
| if: matrix.kind == 'shared' | |
| shell: msys2 {0} | |
| run: | | |
| install_prefix="$PWD/$INSTALL_SUBDIR" | |
| dll="$install_prefix/bin/liboot.dll" | |
| RUNNER_OS=Windows tools/check-symbols.sh "$dll" | |
| if objdump -p "$dll" | grep -Eiq \ | |
| 'DLL Name:.*(libgcc_s|libwinpthread|libstdc\+\+)'; then | |
| echo "liboot.dll imports an unpackaged MinGW runtime DLL" >&2 | |
| exit 1 | |
| fi |