# SPDX-License-Identifier: LGPL-3.0-only # SPDX-FileCopyrightText: Copyright (C) 2026 Catcrafts® # # crafter-build as a Flatpak. The runtime is the Freedesktop *Sdk*, not the # Platform: a build tool needs glibc's headers and crt objects, gcc's # libgcc_s, cmake, ninja, make, git and python at run time. Everything # compiler-shaped is ours and lives under /app: clang, lld, libclang, libc++, # compiler-rt (native and wasm32), lldb and the WASI sysroot, all built from # one LLVM source tree so the modules crafter-build builds and the compiler # that consumes them can never drift apart. # # 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 # and strace, the Khronos Vulkan validation layers, GPU-assisted validation # included, which neither the Sdk nor its GL extensions carry, and the # SPIRV-Tools programs such as spirv-val. app-id: net.catcrafts.CrafterBuild runtime: org.freedesktop.Sdk runtime-version: '26.08' sdk: org.freedesktop.Sdk command: crafter-build finish-args: # git dependencies, and the local web server `-r` starts for browser builds - --share=network - --socket=ssh-auth # projects live anywhere; user sysroots too - --filesystem=host # so `-r` can launch what it built, games included - --share=ipc - --socket=wayland - --socket=fallback-x11 - --socket=pulseaudio - --device=all # lldb, and gdb and friends from the Sdk - --allow=devel - --env=PATH=/app/bin:/usr/bin cleanup: - /share/man - /share/doc modules: - name: swig # Generates lldb's Python bindings while the llvm module builds; nothing # of it ships. cleanup: - '*' sources: - type: archive url: https://downloads.sourceforge.net/project/swig/swig/swig-4.4.1/swig-4.4.1.tar.gz sha256: 40162a706c56f7592d08fd52ef5511cb7ac191f3593cf07306a0a554c6281fcf - name: libedit # Line editing, history and completion at lldb's prompt. The Sdk has the # ncurses it needs but not libedit itself; liblldb links the shared # library, so that ships and the rest goes. config-opts: - --disable-static cleanup: - /include - /lib/pkgconfig - /lib/*.la sources: - type: archive url: https://thrysoee.dk/editline/libedit-20260512-3.1.tar.gz sha256: 432d5e7ea8b0116dd39f2eca7bc11d0eed77faa6b77ea526ace89907c23ea4a0 - name: llvm buildsystem: cmake-ninja builddir: true subdir: llvm build-options: # flatpak-builder's default CFLAGS carry -g. For all of LLVM that is a # 30 GB build tree and a multi-gigabyte .Debug extension, so build # without debug info, strip, and skip the split. The hardening flags # from the defaults stay. no-debuginfo: true strip: true cflags: -O2 -pipe -fexceptions -fasynchronous-unwind-tables -fstack-protector-strong -fstack-clash-protection -fcf-protection cflags-override: true cxxflags: -O2 -pipe -fexceptions -fasynchronous-unwind-tables -fstack-protector-strong -fstack-clash-protection -fcf-protection cxxflags-override: true config-opts: - -DCMAKE_BUILD_TYPE=Release - -DLLVM_ENABLE_ASSERTIONS=OFF - -DLLVM_ENABLE_PROJECTS=clang;lld;lldb - -DLLVM_ENABLE_RUNTIMES=compiler-rt;libcxx;libcxxabi;libunwind # lldb with Python scripting (its bindings generated by the swig module # above, against the Sdk's Python), libedit (the module above), curses, # libxml2 and lzma, each set ON rather than left to the default of "if # found", so a dependency gone missing fails the configure step instead # of shipping an lldb without it. lldb-server, lldb-dap and lldb-mcp # come with it. - -DLLDB_ENABLE_PYTHON=ON - -DLLDB_ENABLE_LIBEDIT=ON - -DLLDB_ENABLE_CURSES=ON - -DLLDB_ENABLE_LIBXML2=ON - -DLLDB_ENABLE_LZMA=ON - -DLLDB_ENABLE_LUA=OFF - -DLLVM_TARGETS_TO_BUILD=X86;AArch64;WebAssembly # Classic layout: libc++ in lib/ and include/c++/v1, not under a # per-target subdirectory, the same shape as a distro install. # crafter-build adds -L and an rpath for /lib itself, since # clang searches only its per-target directory and the system paths. - -DLLVM_ENABLE_PER_TARGET_RUNTIME_DIR=OFF # One shared LLVM and one shared clang library instead of a statically # linked copy per tool: a fraction of the install size. - -DLLVM_BUILD_LLVM_DYLIB=ON - -DLLVM_LINK_LLVM_DYLIB=ON - -DCLANG_LINK_CLANG_DYLIB=ON - -DCLANG_DEFAULT_CXX_STDLIB=libc++ - -DCLANG_DEFAULT_LINKER=lld - -DLIBCXX_INSTALL_MODULES=ON - -DLLVM_INCLUDE_TESTS=OFF - -DLLVM_INCLUDE_EXAMPLES=OFF - -DLLVM_INCLUDE_DOCS=OFF - -DLLVM_INCLUDE_BENCHMARKS=OFF - -DLLVM_INSTALL_UTILS=OFF - -DCLANG_INCLUDE_TESTS=OFF - -DCOMPILER_RT_INCLUDE_TESTS=OFF # The Sdk links with binutils' ld; two libLLVM-sized links at a time # fit the CX53's memory with room to spare. - -DLLVM_PARALLEL_LINK_JOBS=2 cleanup: - /include/llvm - /include/llvm-c - /include/clang - /include/clang-tidy - /include/lld - /include/lldb - /lib/cmake - /lib/*.a - /share/opt-viewer - /share/scan-build - /share/scan-view - /bin/clang-check - /bin/clang-extdef-mapping - /bin/clang-import-test - /bin/clang-linker-wrapper - /bin/clang-nvlink-wrapper - /bin/clang-offload-bundler - /bin/clang-offload-packager - /bin/clang-refactor - /bin/clang-rename - /bin/clang-repl - /bin/clang-sycl-linker - /bin/diagtool - /bin/git-clang-format - /bin/hmaptool - /bin/llvm-exegesis - /bin/scan-build* - /bin/scan-view sources: - type: archive url: https://github.com/llvm/llvm-project/releases/download/llvmorg-23.1.2/llvm-project-23.1.2.src.tar.xz sha256: c98bbef08a2b4c2613cd50e9aa9ae7b69b1fe6c16b2c40373bc0ab6116fdf78a - name: wasi-sysroot # wasi-sdk's sysroot-only mode, driven by the clang built above: # wasi-libc, compiler-rt builtins (installed into our clang's resource # dir, where the wasm32 driver looks for them) and libc++ for wasip1 and # wasip1-threads. The llvm-project tree is the same release as above so # the wasm libc++ matches the native one. buildsystem: cmake-ninja builddir: true build-options: no-debuginfo: true # flatpak-builder's default CFLAGS/LDFLAGS are x86-64 hardening flags # (-fcf-protection, -z relro) that the nested wasm32 builds inherit # through the environment and clang rejects for that target. cflags: "" cflags-override: true cxxflags: "" cxxflags-override: true ldflags: "" ldflags-override: true strip: true config-opts: - -DCMAKE_TOOLCHAIN_FILE=/run/build/wasi-sysroot/wasi-host-toolchain.cmake - -DWASI_SDK_BUILD_TOOLCHAIN=OFF - -DWASI_SDK_INSTALL_TO_CLANG_RESOURCE_DIR=ON - -DWASI_SDK_TARGETS=wasm32-wasip1;wasm32-wasip1-threads - -DWASI_SDK_INCLUDE_TESTS=OFF # crafter-build compiles every wasm unit with C++ exceptions and links # the libc++ and libunwind built with them, from lib//eh. The # default is DUAL only when the driving clang is 23 or newer and OFF # below that; said outright, an LLVM downgrade cannot quietly ship a # sysroot that no wasm build links against. - -DWASI_SDK_EXCEPTIONS=DUAL - -DCMAKE_INSTALL_PREFIX=/app post-install: # wasi-sdk installs into /share/wasi-sysroot; crafter-build # looks there (Crafter.Build:Toolchain), so nothing to move. - test -f /app/share/wasi-sysroot/share/libc++/v1/std.cppm # The wasm tests skip when these are missing, as on a distro sysroot, # so the Flatpak checks for them itself: without them its CI would # pass while every wasm build failed. - test -f /app/share/wasi-sysroot/lib/wasm32-wasip1/eh/libunwind.a - test -f /app/share/wasi-sysroot/lib/wasm32-wasip1-threads/eh/libunwind.a sources: - type: git url: https://github.com/WebAssembly/wasi-sdk.git tag: wasi-sdk-34 disable-submodules: true # The compiler-rt sub-build gets the C target but not the ASM target, so # its two wasm/*.S stubs come out as host objects when the driving clang # does not default to wasm32. Reported upstream; drop once wasi-sdk has it. - type: patch path: wasi-sdk-asm-target.patch - type: git url: https://github.com/WebAssembly/wasi-libc.git commit: 2e6fb9d8ee0cdf9e431fbcabe8af3115de000a13 dest: src/wasi-libc # A git checkout, where the llvm module above unpacks the release # tarball of the same tag: wasi-sdk treats src/llvm-project as the # submodule it is upstream. It patches the tree with `git apply` before # building libc++, and records `git rev-parse HEAD` in the sysroot's # VERSION file. Unpacked from a tarball the directory is a plain # subdirectory of the wasi-sdk checkout, where git treats the patched # paths as outside the current directory, skips every one of them and # exits 0. LLVM 22 happened to build without the patches; LLVM 23's # libc++ does not compile for WASI without one of them. - type: git url: https://github.com/llvm/llvm-project.git tag: llvmorg-23.1.2 commit: 85ac560262434c9ccfc0c183ec22d4138ed647fb dest: src/llvm-project - type: file path: wasi-host-toolchain.cmake - name: wasmtime # The runner for wasm32-wasi tests and `-r` on a non-browser wasm build. buildsystem: simple build-commands: - install -Dm755 wasmtime /app/bin/wasmtime sources: - type: archive url: https://github.com/bytecodealliance/wasmtime/releases/download/v49.0.2/wasmtime-v49.0.2-x86_64-linux.tar.xz sha256: a4d6e9e3a5a60f527cf7793d674c48930c80c2e8977995b8a275cad3254b9322 - name: libcxx-22-modules # The std module source of the libc++ release before the bundled one, for # cross sysroots that carry that libc++ without it: Alpine packages the # headers and the library but not share/libc++/v1, and a module source # only compiles against the headers of its own release. crafter-build # picks /std.cppm here by the sysroot's _LIBCPP_VERSION # (SysrootStdModule in Crafter.Build:Toolchain). Add a module like this # one per release worth supporting; the bundled clang has to be able to # compile that release's headers. buildsystem: simple build-commands: # Configure only. The cxx-modules component is std.cppm as configure # generates it plus the .inc files straight from the source tree, so # nothing is compiled, and libc++'s own install rule stays the one # place that knows what a module source install consists of. - cmake -S runtimes -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=/app/bin/clang -DCMAKE_CXX_COMPILER=/app/bin/clang++ "-DLLVM_ENABLE_RUNTIMES=libcxx;libcxxabi" -DLIBCXXABI_USE_LLVM_UNWINDER=OFF -DLIBCXX_INSTALL_MODULES=ON # Staged, not installed to /app: the component also writes # lib/libc++.modules.json, which would replace the bundled libc++'s. - cmake --install build --component cxx-modules --prefix "$PWD/stage" - grep -q "_LIBCPP_VERSION 22" libcxx/include/__config - mkdir -p /app/share/crafter-build/libc++-modules - cp -r stage/share/libc++/v1 /app/share/crafter-build/libc++-modules/22 sources: - type: archive url: https://github.com/llvm/llvm-project/releases/download/llvmorg-22.1.8/llvm-project-22.1.8.src.tar.xz sha256: 922f1817a0df7b1489272d18134ee0087a8b068828f87ac63b9861b1a9965888 # The Khronos validation layers and the four modules they are built from, # after llvm, so that bumping them reuses the cached LLVM build. All five # are pinned to the Vulkan SDK release of the Sdk's own Vulkan loader and # headers (1.4.357), at the dependency revisions that release's # scripts/known_good.json names. When the runtime moves to a newer loader, # 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 # /app at those revisions rather than taken from the Sdk, whose versions # follow the runtime, and of them only SPIRV-Tools' programs ship. - name: vulkan-headers buildsystem: cmake-ninja builddir: true cleanup: - '*' sources: - type: archive url: https://github.com/KhronosGroup/Vulkan-Headers/archive/refs/tags/v1.4.357.tar.gz sha256: 7dc0dbcf1d49dd3d7da3761c251c6097dfbaac475321a4a8a99269d3d5abecdc - name: vulkan-utility-libraries buildsystem: cmake-ninja builddir: true config-opts: - -DCMAKE_BUILD_TYPE=Release # CMake searches its install prefix after /usr, where the Sdk has # Vulkan headers of its own. - -DCMAKE_PREFIX_PATH=/app cleanup: - '*' sources: - type: archive url: https://github.com/KhronosGroup/Vulkan-Utility-Libraries/archive/refs/tags/v1.4.357.tar.gz sha256: e8688013cdc67dad26f15dcece91fa6b80ad595d551fceb56397fc4795efd00a - name: spirv-headers buildsystem: cmake-ninja builddir: true cleanup: - '*' sources: - type: archive url: https://github.com/KhronosGroup/SPIRV-Headers/archive/29981f65241605e08b0ede4cfeb999fe3b723c6a.tar.gz sha256: 232899f1ad4104fb5bc377b94596c7621575eee62ad9a9e8f929b63a7dd8a7ad - name: spirv-tools # The optimizer GPU-assisted validation instruments shaders with, linked # 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 builddir: true build-options: no-debuginfo: true strip: true config-opts: - -DCMAKE_BUILD_TYPE=Release # The installed SPIRV-Headers: its include/ holds the grammar files # SPIRV-Tools generates its tables from, as the source tree does. - -DSPIRV-Headers_SOURCE_DIR=/app - -DSPIRV_SKIP_TESTS=ON - -DSPIRV_WERROR=OFF 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: - type: archive url: https://github.com/KhronosGroup/SPIRV-Tools/archive/b707790a898e44038547df54580022fc1cf89c3d.tar.gz sha256: 05d8af89737bde57571c48dbd36714c9f520a69623e14de72c3be6b600e277d6 - name: vulkan-validation-layers # VK_LAYER_KHRONOS_validation. The loader finds its manifest under # /app/share/vulkan/explicit_layer.d through XDG_DATA_DIRS, and the # manifest names the library without a path, which the sandbox's loader # finds in /app/lib. GPU-AV is a setting of this layer, not a layer of # its own (VK_KHRONOS_VALIDATION_GPUAV_ENABLE=1, or the layer settings). buildsystem: cmake-ninja builddir: true build-options: no-debuginfo: true strip: true config-opts: - -DCMAKE_BUILD_TYPE=Release - -DCMAKE_PREFIX_PATH=/app # ON by default: it clones every dependency with update_deps.py, which # the build sandbox has no network for, instead of using the four # modules above. - -DUPDATE_DEPS=OFF - -DBUILD_TESTS=OFF - -DBUILD_WERROR=OFF post-install: - test -f /app/share/vulkan/explicit_layer.d/VkLayer_khronos_validation.json - test -f /app/lib/libVkLayer_khronos_validation.so sources: - type: archive url: https://github.com/KhronosGroup/Vulkan-ValidationLayers/archive/refs/tags/vulkan-sdk-1.4.357.0.tar.gz sha256: 73180b11992a3554e97ebc18e6bf2b45ff9790ded9d87fc526c7bab865d1303f - name: crafter-build buildsystem: simple build-options: # The self-host build fetches Crafter.Math, Crafter.Asset, # Crafter.LintRules and glslang from git; they are unpinned on purpose # (sibling repos tracking their default branch, see AGENTS.template.md). build-args: - --share=network # On this module, not at the top of the manifest: top-level build # options are part of every module's cache key, and the version changes # with every commit, which made flatpak-builder rebuild LLVM each run. env: CRAFTER_BUILD_LLVM_DIR: /app # The shipped binary runs on any x86_64 from the last decade; user # projects still build with -march=native by default. CRAFTER_BUILD_MARCH: x86-64-v2 CRAFTER_BUILD_MTUNE: generic # CI replaces this with the version; a local build is a development # build. CRAFTER_BUILD_VERSION: 0.0.0-dev build-commands: # Bootstrap by hand, then let the result build itself: only the # self-hosted binary has asset support and ThinLTO. - ./build.sh - ./bin/crafter-build - CRAFTER_BUILD_HOME=$PWD/share/crafter-build ./bin/crafter-build test - install -Dm755 bin/crafter.build-exe-*/crafter-build /app/bin/crafter-build - install -Dm644 bin/crafter.build-lib-*/libcrafter-build.a /app/lib/libcrafter-build.a - mkdir -p /app/share && cp -r share/crafter-build /app/share/ - install -Dm644 LICENSE LICENSE.GPL -t /app/share/licenses/net.catcrafts.CrafterBuild/ - install -Dm644 packaging/flatpak/net.catcrafts.CrafterBuild.metainfo.xml -t /app/share/metainfo/ sources: - type: dir path: ../.. skip: - .git - bin - build - lib/libcrafter-build.a - share/crafter-build