feat(flatpak): ship the SPIRV-Tools programs

Crafter.Graphics' PushConstantRewrite and UIFusedShader tests require
tool:spirv-val, and the Sdk has no spirv-val, so inside the Flatpak they
are skipped. The spirv-tools module the validation layer needs built
only the libraries, and removed them afterwards.

It now builds the programs as well, spirv-val, spirv-opt, spirv-dis and
the rest, which link SPIRV-Tools statically, and ships them. The
headers, the static libraries, the CMake and pkg-config files and
libSPIRV-Tools-shared.so, which nothing here links, are still removed,
and a post-install step runs spirv-val --version.
This commit is contained in:
Jorijn van der Graaf 2026-11-01 22:28:08 +01:00
commit 40dcb18a1e
Signed by: jorijnvdgraaf
GPG key ID: 2937E59CDCC1BCFB
3 changed files with 21 additions and 8 deletions

View file

@ -197,7 +197,7 @@ Local builds are two scripts in `project.cpp`. Run them with the native binary:
- The bootstrap binary is compiled without `CRAFTER_BUILD_HAS_ASSET`, so `cfg.assets` only works in the self-hosted binary. Changing asset extensions means updating two maps in `Crafter.Build-Clang.cpp`: `assetOutput` and the transitive copy loop. - The bootstrap binary is compiled without `CRAFTER_BUILD_HAS_ASSET`, so `cfg.assets` only works in the self-hosted binary. Changing asset extensions means updating two maps in `Crafter.Build-Clang.cpp`: `assetOutput` and the transitive copy loop.
- A warning is printed only when its unit actually recompiles. A build with nothing to do is silent, which is not evidence that a warning is gone. - A warning is printed only when its unit actually recompiles. A build with nothing to do is silent, which is not evidence that a warning is gone.
- A std module source only compiles against the headers of its own libc++ release, and a sysroot does not always ship one (Alpine). The Flatpak therefore carries the sources of the release next to the bundled one under `share/crafter-build/libc++-modules/<major>/`, one `libcxx-<major>-modules` manifest module each. When the bundled LLVM is bumped, keep the release it leaves behind as such a module: sysroots on the stable distro stay on it for months. The native loop has no such directory; stage one by hand under `share/crafter-build/` to test against a foreign sysroot. - A std module source only compiles against the headers of its own libc++ release, and a sysroot does not always ship one (Alpine). The Flatpak therefore carries the sources of the release next to the bundled one under `share/crafter-build/libc++-modules/<major>/`, one `libcxx-<major>-modules` manifest module each. When the bundled LLVM is bumped, keep the release it leaves behind as such a module: sysroots on the stable distro stay on it for months. The native loop has no such directory; stage one by hand under `share/crafter-build/` to test against a foreign sysroot.
- The Flatpak carries the debugging tools for what it builds, because those programs run in its sandbox: lldb is a project of the `llvm` module, with `LLDB_ENABLE_PYTHON`, `LIBEDIT`, `CURSES`, `LIBXML2` and `LZMA` set ON so that a missing dependency fails the configure step (SWIG through Python, which needs it), and the `swig` and `libedit` modules come before it. The Khronos validation layer is the `vulkan-validation-layers` module plus four build-only modules before it, all after the LLVM and WASI modules, so that bumping them reuses the cached LLVM and WASI builds. The layer follows the Sdk's Vulkan loader: when `runtime-version` moves to a runtime with a newer loader, move the layer to the Vulkan SDK release of that loader and take the other four revisions from that release's `scripts/known_good.json`. - The Flatpak carries the debugging tools for what it builds, because those programs run in its sandbox: lldb is a project of the `llvm` module, with `LLDB_ENABLE_PYTHON`, `LIBEDIT`, `CURSES`, `LIBXML2` and `LZMA` set ON so that a missing dependency fails the configure step (SWIG through Python, which needs it), and the `swig` and `libedit` modules come before it. The Khronos validation layer is the `vulkan-validation-layers` module plus four modules before it, build-only except for SPIRV-Tools' programs (`spirv-val` and the rest), all after the LLVM and WASI modules, so that bumping them reuses the cached LLVM and WASI builds. The layer follows the Sdk's Vulkan loader: when `runtime-version` moves to a runtime with a newer loader, move the layer to the Vulkan SDK release of that loader and take the other four revisions from that release's `scripts/known_good.json`.
- The wasm compile flags live in one place, `WasmBaselineFlags` in `Crafter.Build-Clang.cppm`: the std module and every unit have to agree on them, and `VariantId()` and the std PCM directory hash them, so a change rebuilds instead of mixing old and new BMIs. They enable C++ exceptions, so the link takes the exception-enabled libc++ and libunwind from the sysroot's `lib/<triple>/eh/` (wasi-sdk 33 and later). The Flatpak's sysroot has them and a distro's may not; where they are missing the wasm tests skip, so run those through the Flatpak. A browser page checks the engine with the `WasmBaselineProbes` named in `variants.json`. - The wasm compile flags live in one place, `WasmBaselineFlags` in `Crafter.Build-Clang.cppm`: the std module and every unit have to agree on them, and `VariantId()` and the std PCM directory hash them, so a change rebuilds instead of mixing old and new BMIs. They enable C++ exceptions, so the link takes the exception-enabled libc++ and libunwind from the sysroot's `lib/<triple>/eh/` (wasi-sdk 33 and later). The Flatpak's sysroot has them and a distro's may not; where they are missing the wasm tests skip, so run those through the Flatpak. A browser page checks the engine with the `WasmBaselineProbes` named in `variants.json`.
- `WasiBrowserRuntimeExit` runs `wasi-runtime/runtime.js` under node and skips where there is none. The Flatpak has no node, so CI never runs it: after touching `runtime.js`, run the suite in the native loop with node on `PATH`. - `WasiBrowserRuntimeExit` runs `wasi-runtime/runtime.js` under node and skips where there is none. The Flatpak has no node, so CI never runs it: after touching `runtime.js`, run the suite in the native loop with node on `PATH`.
- `VariantId()` names the output directory, so CI globs `bin/crafter.build-exe-<target>-<march>-*/` rather than predicting the hash. The hash includes the compiler, so after a toolchain update the previous variant's directories stay in `bin/` and `build/` until `clean`, and such a glob matches both. - `VariantId()` names the output directory, so CI globs `bin/crafter.build-exe-<target>-<march>-*/` rather than predicting the hash. The hash includes the compiler, so after a toolchain update the previous variant's directories stay in `bin/` and `build/` until `clean`, and such a glob matches both.

View file

@ -368,7 +368,7 @@ Things to know:
## Debugging ## Debugging
Programs that `-r` and the test runner start run inside the Flatpak's sandbox, and so do the tools to debug them: lldb, with `lldb-server`, `lldb-dap` and `lldb-mcp`, from the same LLVM build as the compiler; `gdb`, `gdbserver`, `valgrind` and `strace` from the Freedesktop Sdk; and the Khronos Vulkan validation layer. A default build is optimised (`-O3`, and ThinLTO except for wasm) and carries no debug information: set `cfg.debug = true` for a program you want to debug, which compiles its C++ units with `-g` and links it without LTO; its C and CUDA sources (`cfg.cFiles`, `cfg.cuda`) stay at `-O3` without debug information. A `project.cpp` that calls `ApplyStandardArgs` sets it from the `--debug` argument, as in `crafter-build --debug -r`. Start the tools with `--command`: Programs that `-r` and the test runner start run inside the Flatpak's sandbox, and so do the tools to debug them: lldb, with `lldb-server`, `lldb-dap` and `lldb-mcp`, from the same LLVM build as the compiler; `gdb`, `gdbserver`, `valgrind` and `strace` from the Freedesktop Sdk; the Khronos Vulkan validation layer; and the SPIRV-Tools programs (`spirv-val`, `spirv-opt`, `spirv-dis`, ...). A default build is optimised (`-O3`, and ThinLTO except for wasm) and carries no debug information: set `cfg.debug = true` for a program you want to debug, which compiles its C++ units with `-g` and links it without LTO; its C and CUDA sources (`cfg.cFiles`, `cfg.cuda`) stay at `-O3` without debug information. A `project.cpp` that calls `ApplyStandardArgs` sets it from the `--debug` argument, as in `crafter-build --debug -r`. Start the tools with `--command`:
```bash ```bash
flatpak run --die-with-parent --command=lldb net.catcrafts.CrafterBuild ./bin/myapp-<variant>/myapp flatpak run --die-with-parent --command=lldb net.catcrafts.CrafterBuild ./bin/myapp-<variant>/myapp

View file

@ -11,8 +11,9 @@
# #
# Programs that `-r` and the test runner start run in this sandbox, so the # Programs that `-r` and the test runner start run in this sandbox, so the
# tools to debug them live here too: lldb (above), the Sdk's gdb, valgrind # tools to debug them live here too: lldb (above), the Sdk's gdb, valgrind
# and strace, and the Khronos Vulkan validation layers, GPU-assisted # and strace, the Khronos Vulkan validation layers, GPU-assisted validation
# validation included, which neither the Sdk nor its GL extensions carry. # included, which neither the Sdk nor its GL extensions carry, and the
# SPIRV-Tools programs such as spirv-val.
app-id: net.catcrafts.CrafterBuild app-id: net.catcrafts.CrafterBuild
runtime: org.freedesktop.Sdk runtime: org.freedesktop.Sdk
runtime-version: '26.08' runtime-version: '26.08'
@ -270,7 +271,7 @@ modules:
# move the layers to the SDK release of that loader and take the other # move the layers to the SDK release of that loader and take the other
# four revisions from its known_good.json again. The four are built into # four revisions from its known_good.json again. The four are built into
# /app at those revisions rather than taken from the Sdk, whose versions # /app at those revisions rather than taken from the Sdk, whose versions
# follow the runtime, and none of them ships. # follow the runtime, and of them only SPIRV-Tools' programs ship.
- name: vulkan-headers - name: vulkan-headers
buildsystem: cmake-ninja buildsystem: cmake-ninja
builddir: true builddir: true
@ -308,20 +309,32 @@ modules:
- name: spirv-tools - name: spirv-tools
# The optimizer GPU-assisted validation instruments shaders with, linked # The optimizer GPU-assisted validation instruments shaders with, linked
# into the layer statically. # into the layer statically, and SPIRV-Tools' programs (spirv-val,
# spirv-opt, spirv-dis and the rest), which ship: a program or test that
# checks its SPIR-V with spirv-val, as Crafter.Graphics' do, finds it in
# the sandbox. The libraries and headers stay build-only.
buildsystem: cmake-ninja buildsystem: cmake-ninja
builddir: true builddir: true
build-options: build-options:
no-debuginfo: true no-debuginfo: true
strip: true
config-opts: config-opts:
- -DCMAKE_BUILD_TYPE=Release - -DCMAKE_BUILD_TYPE=Release
# The installed SPIRV-Headers: its include/ holds the grammar files # The installed SPIRV-Headers: its include/ holds the grammar files
# SPIRV-Tools generates its tables from, as the source tree does. # SPIRV-Tools generates its tables from, as the source tree does.
- -DSPIRV-Headers_SOURCE_DIR=/app - -DSPIRV-Headers_SOURCE_DIR=/app
- -DSPIRV_SKIP_EXECUTABLES=ON - -DSPIRV_SKIP_TESTS=ON
- -DSPIRV_WERROR=OFF - -DSPIRV_WERROR=OFF
cleanup: cleanup:
- '*' - /include/spirv-tools
- /lib/libSPIRV-Tools*.a
# Always built besides the static libraries, and linked by nothing
# here: the programs and the layer take SPIRV-Tools statically.
- /lib/libSPIRV-Tools-shared.so
- /lib/cmake/SPIRV-Tools*
- /lib/pkgconfig/SPIRV-Tools*
post-install:
- spirv-val --version
sources: sources:
- type: archive - type: archive
url: https://github.com/KhronosGroup/SPIRV-Tools/archive/b707790a898e44038547df54580022fc1cf89c3d.tar.gz url: https://github.com/KhronosGroup/SPIRV-Tools/archive/b707790a898e44038547df54580022fc1cf89c3d.tar.gz