| Filename | Latest commit message | Latest commit date |
|---|---|---|
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> |
||
| .. | ||
| mylib | ||
| tests | ||
| project.cpp | ||
| README.md | ||
tests
Tests are declared in project.cpp via cfg.AddTest(name). One line per
test; deps and other options chain off the returned builder.
cd examples/tests
crafter-build test
Layout:
mylib/MyMath.cppm # the library being tested
project.cpp # declares the library and its tests
tests/Smoke/main.cpp # zero-config test
tests/UnitMyMath/main.cpp # test that links MyMath
project.cpp does:
cfg.AddTest("Smoke"); // exit 0 = pass
cfg.AddTest("UnitMyMath").Dependencies({ &cfg }); // imports MyMath
AddTest(name) defaults the source to tests/<name>/main.cpp (resolved at
the project root) and the target/march/mtune to the parent project's. The
builder methods overlay overrides:
.Target(triple)/.March(...)/.Mtune(...)/.Sysroot(path).Define(name, value)/.Debug().Timeout(seconds).Args(vec)— runtime args.Requires("tool:foo")/.Requires("file:/path")/.Requires("env:VAR").Dependencies({ &otherCfg, ... }).Path(p)— rebase the test's source-resolution path.LinkFlag(s)/.CompileFlag(s)
Test conventions
- Exit code
0= pass, anything nonzero = fail,77= skipped (autoconf convention). Usestd::exit(77)for runtime skips like "tool not on PATH". - Each test runs in its own subprocess; a segfault doesn't take down the runner.
- Default timeout is 60 s (
crafter-build test --timeout=Noverrides). - Filter by name:
crafter-build test 'Unit*'. List without running:crafter-build test --list.
Linking the parent project
UnitMyMath depends on the library via .Dependencies({ &cfg }) — the
test imports MyMath and the build engine links cfg's output into the
test exe.
Cross-target test runs
AddTest inherits the parent project's target; for per-test cross-arch
runs, override via the builder:
cfg.AddTest("CrossArchAarch64")
.Target("aarch64-linux-gnu")
.Sysroot("/opt/aarch64-rootfs")
.Requires("tool:qemu-aarch64");
crafter-build test sweeps every distinct target declared across the
project's tests plus the host triple, so cross-arch tests run by default.
--target=<triple> restricts the run to that target.
--runner=<spec> overrides the per-target runner for one invocation.
Useful specs: local, cmd:<command> (e.g. cmd:wine, cmd:qemu-aarch64).
Persistent override via env: CRAFTER_BUILD_RUNNER_<normalized_target>=<spec>.
SIMD march fan-out
For libraries with per-march SIMD codegen (e.g. Crafter.Math), use
AddMarchVariants to produce one Test per tier sharing the same source
and interface set:
constexpr MarchTier tiers[] = {
{"sapphirerapids", "native"},
{"x86-64-v4", "generic"},
{"x86-64-v3", "generic"},
};
cfg.AddMarchVariants("Vector", libInterfaces, tiers);
Each tier becomes a Test named Vector-<march>, with the library's
interfaces rebuilt under that tier's -march/-mtune (so codegen actually
varies). Per-arch gating is just an if (target.starts_with("x86_64"))
guard around the call — no special toml syntax.