Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
486935bce8 |
|||
|
03728fd4a7 |
|||
|
995a40e7dd |
|||
|
b5a366d060 |
5 changed files with 54 additions and 7 deletions
|
|
@ -110,7 +110,7 @@ Beyond the rules:
|
|||
- There is no host-platform preprocessor split: the host is Linux. Target differences (mingw, wasm) branch on `cfg.target` strings at runtime, in the library as well as in `project.cpp` and tests.
|
||||
- A build step fails when its command exits nonzero, never because it printed. Use `RunBuildCommand` or `RunCommandChecked`; warnings go to `Progress::Diagnostic`.
|
||||
- Every output path goes through `Configuration::BinDir()`, `BuildDir()` and `PcmDir()`. Hand-rolled `path / "bin" / ...` clobbered variants before; do not add new ones.
|
||||
- Anything that changes what gets compiled or bundled belongs in `VariantId()`. It already hashes type, debug, sysroot, defines, compile flags, wasm variant flags and uninterpreted project args.
|
||||
- Anything that changes what gets compiled or bundled belongs in `VariantId()`. It already hashes type, debug, sysroot, defines, compile flags, wasm variant flags, uninterpreted project args and the toolchain (`Toolchain::Key()`).
|
||||
|
||||
## Design rules
|
||||
|
||||
|
|
@ -170,4 +170,4 @@ To release: add a `<release>` to `packaging/flatpak/net.catcrafts.CrafterBuild.m
|
|||
- The bootstrap binary is compiled without `CRAFTER_BUILD_HAS_ASSET`, so `cfg.assets` only works in the self-hosted binary. Changing asset extensions means updating two maps in `Crafter.Build-Clang.cpp`: `assetOutput` and the transitive copy loop.
|
||||
- A warning is printed only when its unit actually recompiles. A build with nothing to do is silent, which is not evidence that a warning is gone.
|
||||
- A std module source only compiles against the headers of its own libc++ release, and a sysroot does not always ship one (Alpine). The Flatpak therefore carries the sources of the release next to the bundled one under `share/crafter-build/libc++-modules/<major>/`, one `libcxx-<major>-modules` manifest module each. When the bundled LLVM is bumped, keep the release it leaves behind as such a module: sysroots on the stable distro stay on it for months. The native loop has no such directory; stage one by hand under `share/crafter-build/` to test against a foreign sysroot.
|
||||
- `VariantId()` names the output directory, so CI globs `bin/crafter.build-exe-<target>-<march>-*/` rather than predicting the hash.
|
||||
- `VariantId()` names the output directory, so CI globs `bin/crafter.build-exe-<target>-<march>-*/` rather than predicting the hash. The hash includes the compiler, so after a toolchain update the previous variant's directories stay in `bin/` and `build/` until `clean`, and such a glob matches both.
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ extern "C" Configuration CrafterBuildProject(std::span<const std::string_view> a
|
|||
}
|
||||
```
|
||||
|
||||
Run `crafter-build` in that directory; outputs land at `bin/myapp-<target>-<march>/myapp` and intermediates at `build/myapp-<target>-<march>/`. Add `-r` to run the produced executable straight after a successful build.
|
||||
Run `crafter-build` in that directory; outputs land at `bin/myapp-<target>-<march>-<mtune>-<hash>/myapp` and intermediates at `build/myapp-<target>-<march>-<mtune>-<hash>/`. The hash covers everything that changes what is compiled (build type, defines, flags, sysroot, the compiler itself), so two such builds never share a directory. After a compiler update, a new crafter-build release included, the first build starts a fresh directory and recompiles; `crafter-build clean` removes the ones left behind. Add `-r` to run the produced executable straight after a successful build.
|
||||
|
||||
## Dependencies
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import :Shader;
|
|||
import :Interface;
|
||||
import :Implementation;
|
||||
import :External;
|
||||
import :Toolchain;
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
export namespace Crafter {
|
||||
|
|
@ -488,10 +489,21 @@ 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) 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 {
|
||||
// (type, debug, sysroot, defines, compileFlags, 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()); }
|
||||
// The variant under an explicit toolchain; VariantId() is this for
|
||||
// the running one. The compiler is compile state like any flag: a
|
||||
// PCM can only be read by the clang release that wrote it, and
|
||||
// staleness is decided by mtimes, which a compiler update does not
|
||||
// touch. Before the toolchain was hashed, a project built with clang
|
||||
// 22 kept its PCMs when crafter-build moved to clang 23, and the
|
||||
// first edit afterwards failed with "module file ... uses an older
|
||||
// format that is no longer supported" until the project was cleaned.
|
||||
// Keyed here, an update starts an empty directory and rebuilds; the
|
||||
// old one stays until `crafter-build clean`.
|
||||
std::string VariantId(const Toolchain& toolchain) const {
|
||||
std::string compileKey;
|
||||
compileKey += std::to_string(static_cast<std::int32_t>(type));
|
||||
compileKey += '|';
|
||||
|
|
@ -521,6 +533,8 @@ export namespace Crafter {
|
|||
compileKey += "|A:";
|
||||
compileKey += a;
|
||||
}
|
||||
compileKey += "|T:";
|
||||
compileKey += toolchain.Key();
|
||||
std::size_t configHash = std::hash<std::string>{}(compileKey);
|
||||
return std::format("{}-{}-{}-{}-{:08x}", name, target, march, mtune, configHash);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,12 @@
|
|||
</provides>
|
||||
<content_rating type="oars-1.1"/>
|
||||
<releases>
|
||||
<release version="2.1.0" date="2026-10-03">
|
||||
<description>
|
||||
<p>The bundled toolchain is now LLVM 23.1.2. Build outputs are kept per compiler, so the first build after updating recompiles each project into a fresh directory and nothing has to be cleaned by hand.</p>
|
||||
<p>Cross builds pick the std module source that matches the sysroot's libc++ release. The source for libc++ 22 ships beside the bundled 23 for sysroots that carry libc++ without one, such as Alpine, and a sysroot nothing matches fails with one line naming both releases. crafter-build --version prints the libc++ release in use.</p>
|
||||
</description>
|
||||
</release>
|
||||
<release version="2.0.0" date="2026-10-03">
|
||||
<description>
|
||||
<p>First release distributed as a Flatpak, with a bundled LLVM 22 toolchain and WASI sysroot. Windows host support is removed; crafter-build gains --version and resolves its compiler from one place.</p>
|
||||
|
|
|
|||
|
|
@ -133,6 +133,33 @@ int main() {
|
|||
Check(a.BuildDir() != b.BuildDir(), "different VariantId yields different BuildDir");
|
||||
Check(a.BinDir() != b.BinDir(), "different VariantId yields different BinDir");
|
||||
}
|
||||
{
|
||||
// The compiler is compile state as much as any flag: a PCM can only
|
||||
// be read by the clang release that wrote it, and nothing in a
|
||||
// project's sources changes when the compiler does. With the
|
||||
// toolchain left out of the id, a project built with clang 22 kept
|
||||
// its PCMs after crafter-build moved to clang 23; the build after
|
||||
// the update found nothing stale, and the first edit failed with
|
||||
// "module file ... uses an older format that is no longer supported"
|
||||
// until the project was cleaned by hand.
|
||||
Configuration cfg = MakeBase();
|
||||
Toolchain older;
|
||||
older.clangxx = "/app/bin/clang++";
|
||||
older.clangVersion = "clang version 22.1.8";
|
||||
Toolchain newer = older;
|
||||
newer.clangVersion = "clang version 23.1.2";
|
||||
Check(cfg.VariantId(older) != cfg.VariantId(newer), "a compiler update at the same path perturbs VariantId");
|
||||
Check(cfg.VariantId(older) == cfg.VariantId(older), "VariantId under one toolchain is deterministic");
|
||||
|
||||
// Two installs of one release are still two toolchains: their
|
||||
// libc++ need not be the same build.
|
||||
Toolchain elsewhere = older;
|
||||
elsewhere.clangxx = "/usr/bin/clang++";
|
||||
Check(cfg.VariantId(older) != cfg.VariantId(elsewhere), "the same release installed elsewhere perturbs VariantId");
|
||||
|
||||
Check(cfg.VariantId() == cfg.VariantId(GetToolchain()), "VariantId() is the variant under the running toolchain");
|
||||
Check(cfg.BuildDir().filename() == cfg.VariantId(GetToolchain()), "BuildDir is named for the running toolchain's variant");
|
||||
}
|
||||
|
||||
if (Failures > 0) {
|
||||
std::println(std::cerr, "{} assertions failed", Failures);
|
||||
|
|
|
|||
Loading…
Reference in a new issue