Every clang++, clang and llvm-ar the tool spawned was a bare name on PATH, the std module source was /usr/share/libc++/v1/std.cppm, the WASI sysroot /usr/share/wasi-sysroot and the mingw headers /usr/x86_64-w64-mingw32, spelled out at eighteen call sites. A toolchain installed anywhere else, which is what the Flatpak ships under /app, had no way in. Crafter.Build:Toolchain resolves all of it once per process: CRAFTER_BUILD_LLVM_DIR, else a clang++ installed beside crafter-build (<prefix>/bin, found through the same walk GetCrafterBuildHome does), else PATH. What sits beside the compiler is used when present: its libclang.so, its clang-c headers, its std module source, its WASI sysroot. An explicit prefix without a clang++ is an error rather than a fallback, for the same reason CRAFTER_BUILD_LIBCLANG was already exclusive. CRAFTER_BUILD_LIBCXX_DIR points at a libc++ install other than the compiler's own, and CRAFTER_MINGW_DIR now does what its help line always claimed: it is passed as --sysroot for the mingw target. Binaries linked by a toolchain outside /usr get an rpath to its lib dir, since its libc++.so.1 is not on the loader's default path. HostTarget() is the resolved clang's -print-target-triple. A clang built without a vendor reports x86_64-unknown-linux-gnu where Arch's reports x86_64-pc-linux-gnu, so target equality that decides whether a test runs locally and which targets a bare `test` sweeps goes through SameTarget, which ignores the vendor field. The strings themselves are never rewritten: clang rejects a PCM whose triple differs from the importing unit's. The examples and README stop hardcoding the host triple; the default is already the host. `crafter-build --version` prints the version baked in at build time (CRAFTER_BUILD_VERSION, else `git describe`, else 0.0.0-dev), the compiler and the host triple, and is answered before any argument is forwarded to project.cpp. The version is a define on the library, so each version is its own library variant and relinks the executable and tests once per commit. build.sh gains a shebang and `set -eu`, honours CRAFTER_BUILD_LLVM_DIR and CRAFTER_BUILD_VERSION, skips the glslang clone when it is already there, and writes a fresh archive instead of appending to one that may hold members from an older layout. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
126 lines
5.5 KiB
Shell
Executable file
126 lines
5.5 KiB
Shell
Executable file
#!/bin/sh
|
|
#SPDX-License-Identifier: LGPL-3.0-only
|
|
#SPDX-FileCopyrightText: Copyright (C) 2026 Catcrafts®
|
|
|
|
# Bootstrap: compile crafter-build by hand, without crafter-build. The
|
|
# self-host build through project.cpp follows (`./bin/crafter-build`).
|
|
set -eu
|
|
|
|
# The toolchain. CRAFTER_BUILD_LLVM_DIR names an LLVM prefix (the Flatpak
|
|
# sets /app); otherwise the tools come from PATH. The same rule the built
|
|
# binary applies at run time (Crafter.Build:Toolchain).
|
|
if [ -n "${CRAFTER_BUILD_LLVM_DIR:-}" ]; then
|
|
CXX="$CRAFTER_BUILD_LLVM_DIR/bin/clang++"
|
|
CC="$CRAFTER_BUILD_LLVM_DIR/bin/clang"
|
|
AR="$CRAFTER_BUILD_LLVM_DIR/bin/llvm-ar"
|
|
LLVM_CONFIG="$CRAFTER_BUILD_LLVM_DIR/bin/llvm-config"
|
|
# A prefix other than the system one keeps its libc++ off the loader's
|
|
# default path; the rpath is what lets the binary start.
|
|
if [ "$CRAFTER_BUILD_LLVM_DIR" != /usr ]; then
|
|
RPATH_FLAG="-Wl,-rpath,$CRAFTER_BUILD_LLVM_DIR/lib"
|
|
else
|
|
RPATH_FLAG=""
|
|
fi
|
|
if [ -f "$CRAFTER_BUILD_LLVM_DIR/share/libc++/v1/std.cppm" ]; then
|
|
STD_CPPM="$CRAFTER_BUILD_LLVM_DIR/share/libc++/v1/std.cppm"
|
|
else
|
|
STD_CPPM=/usr/share/libc++/v1/std.cppm
|
|
fi
|
|
else
|
|
CXX=clang++
|
|
CC=clang
|
|
AR=llvm-ar
|
|
LLVM_CONFIG=llvm-config
|
|
RPATH_FLAG=""
|
|
STD_CPPM=/usr/share/libc++/v1/std.cppm
|
|
fi
|
|
|
|
# The version baked into the binary: the environment (CI sets it from the
|
|
# tag), else the nearest tag, else a development marker. `latest` is the
|
|
# rolling CI tag and never a version.
|
|
VERSION="${CRAFTER_BUILD_VERSION:-$(git describe --tags --always --dirty --exclude=latest 2>/dev/null || echo 0.0.0-dev)}"
|
|
|
|
mkdir -p build bin lib share/crafter-build share/crafter-build/wasi-runtime
|
|
|
|
cp wasi-runtime/runtime.js share/crafter-build/wasi-runtime/
|
|
cp wasi-runtime/index.html.in share/crafter-build/wasi-runtime/
|
|
|
|
# Partition order is the import order: every unit is listed before the
|
|
# units that import it, and the umbrella last.
|
|
PARTITIONS="Toolchain Shader Platform Interface Implementation External Clang Test Lint Progress Asset"
|
|
|
|
cp interfaces/Crafter.Build.cppm share/crafter-build/
|
|
for p in $PARTITIONS; do
|
|
cp "interfaces/Crafter.Build-$p.cppm" share/crafter-build/
|
|
done
|
|
|
|
if [ ! -d build/glslang/.git ]; then
|
|
git clone --depth 1 https://github.com/KhronosGroup/glslang.git build/glslang
|
|
fi
|
|
|
|
current_dir=$(pwd)
|
|
|
|
cd build/glslang
|
|
cmake -B build \
|
|
-DCMAKE_C_COMPILER="$CC" \
|
|
-DCMAKE_CXX_COMPILER="$CXX" \
|
|
-DCMAKE_CXX_FLAGS="-stdlib=libc++" \
|
|
-DCMAKE_EXE_LINKER_FLAGS="-stdlib=libc++ $RPATH_FLAG" \
|
|
-DCMAKE_SHARED_LINKER_FLAGS="-stdlib=libc++ $RPATH_FLAG" \
|
|
-DCMAKE_BUILD_TYPE=Release \
|
|
-DCMAKE_ARCHIVE_OUTPUT_DIRECTORY="$current_dir/build" \
|
|
-DCMAKE_LIBRARY_OUTPUT_DIRECTORY="$current_dir/build" \
|
|
-DENABLE_OPT=OFF
|
|
cmake --build build --config Release
|
|
cd ../../
|
|
|
|
MARCH="${CRAFTER_BUILD_MARCH:-native}"
|
|
MTUNE="${CRAFTER_BUILD_MTUNE:-native}"
|
|
# The bootstrap targets the toolchain's own triple: x86_64-pc-linux-gnu on
|
|
# glibc distros, x86_64-unknown-linux-gnu for the bundled LLVM,
|
|
# x86_64-alpine-linux-musl on Alpine. Override with CRAFTER_BUILD_TARGET.
|
|
TARGET="${CRAFTER_BUILD_TARGET:-$("$CXX" -print-target-triple)}"
|
|
TARGET_DEFINE="CRAFTER_BUILD_CONFIGURATION_TARGET_$(printf '%s' "$TARGET" | tr - _)"
|
|
|
|
# Crafter.Build-Lint includes libclang's clang-c/Index.h. glibc distros keep
|
|
# it in /usr/include; other prefixes keep it under their own include dir, so
|
|
# ask llvm-config and add the dir when it is not already on the default path
|
|
# (never add /usr/include itself: that breaks libc++'s #include_next).
|
|
LLVM_INCDIR="$("$LLVM_CONFIG" --includedir 2>/dev/null || true)"
|
|
case "$LLVM_INCDIR" in ""|/usr/include) LLVM_INCFLAG="" ;; *) LLVM_INCFLAG="-I$LLVM_INCDIR" ;; esac
|
|
|
|
common_options="--target=$TARGET -stdlib=libc++ -I./build/glslang $LLVM_INCFLAG -std=c++26 -O3 -march=$MARCH -mtune=$MTUNE -fprebuilt-module-path=./build -D $TARGET_DEFINE -D CRAFTER_BUILD_CONFIGURATION_TYPE_EXECUTABLE -D CRAFTER_BUILD_VERSION=\"$VERSION\" -c"
|
|
|
|
"$CXX" --target="$TARGET" -std=c++26 -stdlib=libc++ -O3 -march="$MARCH" -mtune="$MTUNE" -Wno-reserved-identifier -Wno-reserved-module-identifier --precompile "$STD_CPPM" -o ./build/std.pcm
|
|
|
|
# Asset partition: bootstrap compiles it WITHOUT CRAFTER_BUILD_HAS_ASSET so
|
|
# CompressAsset takes the stub branch and the impl unit doesn't try to
|
|
# `import Crafter.Asset` (no Crafter.Asset PCM exists at this stage — the
|
|
# self-host pass that follows wires in the real dep).
|
|
OBJECTS=""
|
|
for p in $PARTITIONS; do
|
|
"$CXX" $common_options -fmodule-output "interfaces/Crafter.Build-$p.cppm" -o "./build/Crafter.Build-$p.o"
|
|
OBJECTS="$OBJECTS ./build/Crafter.Build-$p.o"
|
|
done
|
|
"$CXX" $common_options -fmodule-output interfaces/Crafter.Build.cppm -o ./build/Crafter.Build.o
|
|
OBJECTS="$OBJECTS ./build/Crafter.Build.o"
|
|
|
|
for p in $PARTITIONS; do
|
|
"$CXX" $common_options "./implementations/Crafter.Build-$p.cpp" -o "./build/Crafter.Build-${p}_impl.o"
|
|
OBJECTS="$OBJECTS ./build/Crafter.Build-${p}_impl.o"
|
|
done
|
|
"$CXX" $common_options ./implementations/main.cpp -o ./build/main.o
|
|
|
|
# A fresh archive each time: `ar rcs` into an existing one keeps members a
|
|
# previous layout left behind.
|
|
rm -f ./lib/libcrafter-build.a
|
|
"$AR" rcs ./lib/libcrafter-build.a $OBJECTS
|
|
|
|
"$CXX" --target="$TARGET" -std=c++26 -stdlib=libc++ -O3 -march="$MARCH" -mtune="$MTUNE" -fuse-ld=lld \
|
|
-Wl,--export-dynamic $RPATH_FLAG \
|
|
-L./build \
|
|
$OBJECTS \
|
|
./build/main.o \
|
|
-lSPIRV -lGenericCodeGen -lglslang -lOSDependent -lMachineIndependent -lglslang-default-resource-limits \
|
|
-ldl \
|
|
-o ./bin/crafter-build
|