Crafter.Build/tests
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Jorijn van der Graaf f77d913171
fix(external): fetch and build each clone once per build pass
`crafter-build test` builds a project's tests side by side, and a
project whose tests each copy its externalDependencies hands every one
of them the same unpinned dependency. Each test's Build() pulled the
shared clone. Before the clone had a lock, those pulls ran at the same
time and broke its .git/FETCH_HEAD, which failed every test of
Crafter.Graphics (issue #34). Since 653dd0b they wait for each other,
but every one is still a network round trip: 26 tests cost 26 pulls of
each dependency, one after another, and for a CMake dependency as many
configure checks and builds.

depResults already records one build pass, keyed by the PcmDir of every
dependency configuration built in it. An external dependency now goes
in the same map, keyed by the directory its build leaves
(ExternalBuildDir: the clone, or for CMake its build directory). The
first configuration that needs it fetches and builds it; the others
wait for that and take its outcome. Keying on the build directory
rather than the clone keeps a CMake declaration from taking the outcome
of a header-only declaration of the same clone, which only fetched it.
A fresh depResults is a fresh pass, so the next build still pulls, and
every caller of Build() gets this: RunTests, a plain build, and the
pragma dependencies LoadProject builds.

To make that possible BuildExternal is split. BuildExternal is now the
shared work, lock, fetch, configure and build, and returns the error.
ExternalOutputs computes what one declaration compiles and links with,
because two declarations of one clone can differ in includeDirs,
libDirs and libs; ExternalBuildResult loses its error field. The work
no longer stops between steps when the configuration that started it
is cancelled: others may be waiting on it, and a run cut short would
leave them a clone nobody fetched. A dependency configuration's Build()
already runs to completion for the same reason.

The promise and future the dependency threads used to build or wait for
a configuration are now one helper, OncePerPass, which both kinds use.
An exception thrown in BuildExternal used to escape its thread into
std::terminate; it is now a build error, as for a dependency.

With eight tests that share a local dependency, a test run fetched it
eight times before this and fetches it once now (SharedExternalFetch,
next commit).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 02:09:24 +01:00
..
CleanProject test(cli): a word after format is a glob, not the clean verb 2026-10-20 19:08:26 +02:00
CompilerWarning refactor: drop Windows host support 2026-10-02 22:03:34 +02:00
ConcurrentCacheRace linting 2026-07-23 01:24:42 +02:00
ConcurrentDependencyReset linting 2026-07-23 01:24:42 +02:00
ConcurrentExternalFetch fix: rebuild and relink on what changed, submodules at their revisions, and mingw found where it is 2026-10-20 20:20:29 +02:00
DependencyLink linting 2026-07-23 01:24:42 +02:00
ExternalArtifactTime fix(external): fetch and build each clone once per build pass 2026-10-31 02:09:24 +01:00
GitSubmodules fix: rebuild and relink on what changed, submodules at their revisions, and mingw found where it is 2026-10-20 20:20:29 +02:00
HelloWorld linting 2026-07-23 01:24:42 +02:00
HostCacheSourceStamp test(host-cache): changed declarations recompile project.so 2026-10-06 16:50:41 +02:00
HostCacheToolchainKey fix: key PCM and project.so freshness on content, not installed mtimes 2026-10-02 23:18:09 +02:00
IncrementalHeaderChange test: header-change incrementality across every compile path 2026-07-31 11:11:49 +00:00
IncrementalInterfaceChange fix: re-resolve module imports before checking staleness 2026-07-30 17:12:24 +00:00
LinkFlagsChange fix: rebuild and relink on what changed, submodules at their revisions, and mingw found where it is 2026-10-20 20:20:29 +02:00
Lint feat(lint): const-local and constexpr-constant rules 2026-07-31 00:50:48 +02:00
MingwMissing fix: rebuild and relink on what changed, submodules at their revisions, and mingw found where it is 2026-10-20 20:20:29 +02:00
ModuleInterface linting 2026-07-23 01:24:42 +02:00
ProjectDependency fix: let a project file ask whether it is the top-level project 2026-10-02 22:02:40 +02:00
RunSingleTestExit linting 2026-07-23 01:24:42 +02:00
Script fix(script): a script that throws anything at all exits 1 2026-10-20 19:08:26 +02:00
ShaderCompile fix: rebuild and relink on what changed, submodules at their revisions, and mingw found where it is 2026-10-20 20:20:29 +02:00
ShaderIncludeChange fix: rebuild and relink on what changed, submodules at their revisions, and mingw found where it is 2026-10-20 20:20:29 +02:00
ShaderVariantBuild test(shader): variants through the Shader API and through Build() 2026-10-06 16:50:41 +02:00
StandardArgs fix: key the host PCM cache on source content, add clean, hash project args 2026-07-30 17:43:09 +00:00
StaticLib linting 2026-07-23 01:24:42 +02:00
SysrootCompileFlags test(sysroot): the compile command forces the sysroot's libc++ 2026-10-06 16:50:41 +02:00
SysrootStdModule test(sysroot): cover the std module source choice for a sysroot build 2026-10-03 16:37:00 +02:00
TestRunnerSpec feat(toolchain): resolve the compiler in one place 2026-10-02 22:26:31 +02:00
ToolchainResolve fix: rebuild and relink on what changed, submodules at their revisions, and mingw found where it is 2026-10-20 20:20:29 +02:00
TransitiveInterfaceChange test change 2026-08-05 05:49:42 +02:00
VariantId test(incremental): a compiler update perturbs VariantId 2026-10-03 20:09:22 +02:00
VersionFlag feat(toolchain): resolve the compiler in one place 2026-10-02 22:26:31 +02:00
WasiBrowserRuntime linting 2026-07-23 01:24:42 +02:00
WasmHelloRuns feat(packaging): ship crafter-build as a Flatpak with its own toolchain 2026-10-02 23:18:10 +02:00
WasmVariants linting 2026-07-23 01:24:42 +02:00