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:
parent
06b61e84f9
commit
5d25495621
4 changed files with 114 additions and 65 deletions
|
|
@ -392,6 +392,15 @@ export namespace Crafter {
|
|||
};
|
||||
|
||||
struct Configuration;
|
||||
// The name StdPcmDir gives the directory of this configuration's std
|
||||
// module under `toolchain`: target, march and the toolchain's key, which
|
||||
// say what it is, then a hash of everything else it is compiled with,
|
||||
// each flag BuildStdPcm passes (StdPcmFlags) and for the mingw target the
|
||||
// prefix behind its --sysroot. Two configurations that would compile the
|
||||
// std module differently never share a directory, so neither rebuilds it
|
||||
// under the PCMs the other compiled against it. Declared ahead of
|
||||
// Configuration, whose VariantId keys on it.
|
||||
std::string StdPcmKey(const Configuration& config, const Toolchain& toolchain);
|
||||
|
||||
// What a Script's callback is handed when `crafter-build run <name>`
|
||||
// starts it.
|
||||
|
|
@ -580,7 +589,8 @@ export namespace Crafter {
|
|||
void AddAstLintRule(std::string name, std::function<void(LintContext&)> check);
|
||||
// Suffix that uniquely identifies this Configuration's compile state.
|
||||
// target+march+mtune are spelled out for readability; the rest
|
||||
// (type, debug, sysroot, defines, compileFlags, the toolchain)
|
||||
// (type, debug, sysroot, defines, compileFlags, the std module, the
|
||||
// toolchain)
|
||||
// collapse into a short hash so two Configurations sharing a path but
|
||||
// with different compile state can't clobber each other's outputs.
|
||||
std::string VariantId() const { return VariantId(GetToolchain()); }
|
||||
|
|
@ -628,17 +638,15 @@ export namespace Crafter {
|
|||
compileKey += "|B:";
|
||||
compileKey += WasmBaselineFlags;
|
||||
}
|
||||
// The mingw-w64 prefix decides what the mingw target compiles
|
||||
// against, and until issue #43 clang got it as the sysroot
|
||||
// itself, which put the host's own headers on the include path.
|
||||
// Unkeyed, the release that fixed it kept the objects compiled
|
||||
// against glibc's headers: the build after the update only
|
||||
// relinked them, and failed to link as before. No prefix keeps
|
||||
// the id as it was, since clang's own discovery has not changed.
|
||||
if (target == "x86_64-w64-mingw32" && !toolchain.mingwPrefix.empty()) {
|
||||
compileKey += "|M:";
|
||||
compileKey += toolchain.mingwPrefix.string();
|
||||
}
|
||||
// The std module the units import. Its PCMs and objects record
|
||||
// it by path, and units do not notice it moving: when the mingw
|
||||
// prefix stopped being clang's sysroot as is (issue #43), the
|
||||
// std module was rebuilt and the objects compiled against the
|
||||
// host's glibc headers were only relinked, failing as before. A
|
||||
// std module that moves directories, because anything it is
|
||||
// compiled with changed, moves the build with it.
|
||||
compileKey += "|S:";
|
||||
compileKey += StdPcmKey(*this, toolchain);
|
||||
// Sorted by ApplyStandardArgs, so flag order on the command line
|
||||
// doesn't split the cache.
|
||||
for (const std::string& a : projectArgs) {
|
||||
|
|
@ -673,10 +681,9 @@ export namespace Crafter {
|
|||
std::vector<std::string> requires_;
|
||||
};
|
||||
|
||||
// Directory holding the std module PCM for this Configuration. Keyed on
|
||||
// target+march because a BMI is only loadable by a TU with matching target
|
||||
// features, and suffixed with the wasm flags (WasmBaselineFlags, then the
|
||||
// variant's) for the same reason.
|
||||
// Directory holding the std module PCM for this Configuration,
|
||||
// GetCacheDir() / StdPcmKey(config, GetToolchain()): a BMI is only
|
||||
// loadable by a unit compiled the way it was.
|
||||
fs::path StdPcmDir(const Configuration& config);
|
||||
|
||||
// Where Build leaves this Configuration's linked artifact: the executable
|
||||
|
|
@ -805,4 +812,9 @@ namespace Crafter {
|
|||
// compile command and of the std module's, which have to agree flag for
|
||||
// flag.
|
||||
std::string WasmCompileFlags(const Configuration& config);
|
||||
// The flags BuildStdPcm compiles the std module with, after the base
|
||||
// command and before the source, each with a leading space. StdPcmKey
|
||||
// hashes the same string, so the command and the directory it writes to
|
||||
// cannot disagree about what decides the BMI.
|
||||
std::string StdPcmFlags(const Configuration& config);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue