fix: key the std module's directory on everything it is compiled with

StdPcmDir named the directory by target, march and toolchain, then
grew a case per target for the rest: the wasm flags, and with the first
fix for #43 the mingw prefix. Every other flag BuildStdPcm passes went
unkeyed, so configurations that differed only there took turns
rebuilding one std PCM in place, under the PCMs built against it: a
project with -mtune=generic against project.cpp's -mtune=native on every
run, or two sysroots for one target. And the mingw prefix was keyed only
when there was one, so a build without a prefix landed in the directory
an older release had filled with a CRAFTER_MINGW_DIR=/usr build, and
relinked its objects.

StdPcmFlags is now the one source of the flags BuildStdPcm compiles
with, and StdPcmKey names the directory by target, march and toolchain
followed by a hash of those flags and, for the mingw target, of the
prefix behind its --sysroot. VariantId hashes StdPcmKey in place of the
mingw prefix: units do not notice a std module that moved directories,
so a build has to move with it. Every std PCM directory and build
directory moves once, as after a compiler update; the old ones stay
until `clean` and the cache is cleared by hand.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Jorijn van der Graaf 2026-10-31 22:58:44 +01:00
commit 5d25495621
Signed by: jorijnvdgraaf
GPG key ID: 2937E59CDCC1BCFB
4 changed files with 114 additions and 65 deletions

View file

@ -178,6 +178,46 @@ int main() {
Check(mingw.VariantId(hostUsr) != mingw.VariantId(optMingw), "two mingw prefixes are two variants");
Configuration host = MakeBase();
Check(host.VariantId(discovered) == host.VariantId(hostUsr), "the mingw prefix leaves other targets' variants alone");
// The std module's directory is keyed the same way, and so is a
// prefix given whole against one reached through a view.
Check(StdPcmKey(mingw, discovered) != StdPcmKey(mingw, hostUsr), "a mingw prefix moves the mingw std module");
Check(StdPcmKey(mingw, hostUsr) != StdPcmKey(mingw, optMingw), "two mingw prefixes are two std modules");
Toolchain hostUsrWhole = hostUsr;
hostUsrWhole.mingwPrefixIsSystem = !hostUsr.mingwPrefixIsSystem;
Check(StdPcmKey(mingw, hostUsr) != StdPcmKey(mingw, hostUsrWhole), "a prefix given whole and one shown through a view are two std modules");
Check(mingw.VariantId(hostUsr) != mingw.VariantId(hostUsrWhole), "and two variants, through the std module");
Check(StdPcmKey(host, discovered) == StdPcmKey(host, hostUsr), "the mingw prefix leaves other targets' std modules alone");
}
{
// Everything the std module is compiled with keys its directory, not
// only target and march. -mtune was left out, so a project built
// with -mtune=generic shared one std PCM with project.cpp's
// -mtune=native, and the two rebuilt it in turn on every run, under
// every module built against it; two sysroots did the same.
Toolchain tc;
tc.clangxx = "/app/bin/clang++";
tc.clangVersion = "clang version 23.1.2";
Configuration native = MakeBase();
Configuration generic = MakeBase();
generic.mtune = "generic";
Check(StdPcmKey(native, tc) != StdPcmKey(generic, tc), "-mtune keys the std module");
Configuration sysrootA = MakeBase();
sysrootA.sysroot = "/opt/sysroot-a";
Configuration sysrootB = MakeBase();
sysrootB.sysroot = "/opt/sysroot-b";
Check(StdPcmKey(sysrootA, tc) != StdPcmKey(sysrootB, tc) && StdPcmKey(sysrootA, tc) != StdPcmKey(native, tc), "the sysroot keys the std module");
Configuration wasm = MakeBase();
wasm.target = "wasm32-wasip1";
wasm.sysroot = "/opt/wasi-sysroot";
Configuration relaxed = MakeBase();
relaxed.target = wasm.target;
relaxed.sysroot = wasm.sysroot;
relaxed.wasmVariantFlags = {"-mrelaxed-simd"};
Check(StdPcmKey(wasm, tc) != StdPcmKey(relaxed, tc), "a wasm variant pass's flags key the std module");
Check(StdPcmKey(native, tc) == StdPcmKey(MakeBase(), tc), "one configuration, one std module");
Check(StdPcmKey(native, tc).starts_with(std::format("{}-{}-{}-", native.target, native.march, tc.Key())), std::format("the directory still says target, march and toolchain (got '{}')", StdPcmKey(native, tc)));
Check(native.VariantId(tc) != generic.VariantId(tc) && sysrootA.VariantId(tc) != sysrootB.VariantId(tc), "a build moves with its std module");
}
if (Failures > 0) {