feat(tooling): Debug::Use says whether it added the library
A consumer adds its debug-only sources, the ones that import Crafter.Debug, under the same condition Use adds the library. Testing its own flag is not that condition: a build with the flag for a target other than native Linux gets neither the library nor the define, and its debug-only sources would then fail to import Crafter.Debug. Use now returns whether it added them, and the README shows the pattern. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
5d34df7afb
commit
6da3b274a6
2 changed files with 19 additions and 12 deletions
10
README.md
10
README.md
|
|
@ -56,15 +56,17 @@ extern "C" Configuration CrafterBuildProject(std::span<const std::string_view> a
|
||||||
if (arg != "--debug-api") depArgs.emplace_back(arg);
|
if (arg != "--debug-api") depArgs.emplace_back(arg);
|
||||||
}
|
}
|
||||||
// ...give depArgs to every other dependency too...
|
// ...give depArgs to every other dependency too...
|
||||||
Debug::Use(cfg, { .enabled = opts.Has("--debug-api"), .flag = "--debug-api",
|
const bool debugApi = Debug::Use(cfg, { .enabled = opts.Has("--debug-api"), .flag = "--debug-api",
|
||||||
.define = "MYAPP_DEBUG_API", .args = depArgs });
|
.define = "MYAPP_DEBUG_API", .args = depArgs });
|
||||||
// ...
|
// ...your sources, plus the debug-only ones when debugApi...
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
**What `Use` does with the flag:**
|
**What `Use` does with the flag:**
|
||||||
- **Flag on, native Linux target:** it adds the define and the library, from the checkout the pragma names, and writes `build/crafter-debug`.
|
- **Flag on, native Linux target:** it adds the define and the library, from the checkout the pragma names, writes `build/crafter-debug`, and returns true.
|
||||||
- **Otherwise:** it adds nothing, and release builds never link Crafter.Debug. Until a debug build has run, `build/crafter-debug` is a stub that says to build one.
|
- **Otherwise:** it adds nothing and returns false, and release builds never link Crafter.Debug. Until a debug build has run, `build/crafter-debug` is a stub that says to build one.
|
||||||
|
|
||||||
|
Add your debug-only sources when `Use` returns true, not when the flag is on: a non-Linux target with the flag gets neither the library nor the define.
|
||||||
|
|
||||||
A dependency that two paths in the build graph share must get the **same arg list on both**. Otherwise crafter-build refuses the graph with "module … built twice". Build one `depArgs` and give it to every dependency, as above.
|
A dependency that two paths in the build graph share must get the **same arg list on both**. Otherwise crafter-build refuses the graph with "module … built twice". Build one `depArgs` and give it to every dependency, as above.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,9 @@
|
||||||
// #pragma crafter dependency "https://forgejo.catcrafts.net/Catcrafts/Crafter.Debug.git" project "tooling/project.cpp"
|
// #pragma crafter dependency "https://forgejo.catcrafts.net/Catcrafts/Crafter.Debug.git" project "tooling/project.cpp"
|
||||||
// import Crafter.Debug.Build;
|
// import Crafter.Debug.Build;
|
||||||
// ...
|
// ...
|
||||||
// Debug::Use(cfg, { .enabled = opts.Has("--debug-api"), .flag = "--debug-api",
|
// const bool debugApi = Debug::Use(cfg, { .enabled = opts.Has("--debug-api"), .flag = "--debug-api",
|
||||||
// .define = "MYAPP_DEBUG_API", .args = depArgs });
|
// .define = "MYAPP_DEBUG_API", .args = depArgs });
|
||||||
|
// if (debugApi) { /* add the debug-only sources */ }
|
||||||
//
|
//
|
||||||
// crafter-build builds this module for the host and links it into the
|
// crafter-build builds this module for the host and links it into the
|
||||||
// consumer's project.so, the way Crafter.LintRules gets in, so Use runs each
|
// consumer's project.so, the way Crafter.LintRules gets in, so Use runs each
|
||||||
|
|
@ -164,9 +165,12 @@ export namespace Crafter::Debug {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Adds Crafter.Debug to `cfg` when options.enabled, and writes the
|
// Adds Crafter.Debug to `cfg` when options.enabled, and writes the
|
||||||
// launcher; see the comment at the top. `at` defaults to the call site,
|
// launcher; see the comment at the top. Returns whether it added the
|
||||||
// which is how Use finds the consumer's directory.
|
// library and the define, which is when the consumer adds its debug-only
|
||||||
void Use(Configuration& cfg, const UseOptions& options, std::source_location at = std::source_location::current()) {
|
// sources: not for every build with the flag, since a target other than
|
||||||
|
// native Linux gets neither. `at` defaults to the call site, which is how
|
||||||
|
// Use finds the consumer's directory.
|
||||||
|
bool Use(Configuration& cfg, const UseOptions& options, std::source_location at = std::source_location::current()) {
|
||||||
const fs::path launcher = fs::path(at.file_name()).parent_path() / "build" / "crafter-debug";
|
const fs::path launcher = fs::path(at.file_name()).parent_path() / "build" / "crafter-debug";
|
||||||
// Only for the project crafter-build was pointed at: a consumer loaded
|
// Only for the project crafter-build was pointed at: a consumer loaded
|
||||||
// as someone else's dependency has no agent driving it from its own
|
// as someone else's dependency has no agent driving it from its own
|
||||||
|
|
@ -174,17 +178,18 @@ export namespace Crafter::Debug {
|
||||||
const bool topLevel = IsTopLevelProject();
|
const bool topLevel = IsTopLevelProject();
|
||||||
if (!options.enabled || !NativeLinux(cfg.target)) {
|
if (!options.enabled || !NativeLinux(cfg.target)) {
|
||||||
if (topLevel && !fs::exists(launcher)) WriteIfChanged(launcher, StubText(options.flag));
|
if (topLevel && !fs::exists(launcher)) WriteIfChanged(launcher, StubText(options.flag));
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
Configuration* library = LocalProject({ .projectFile = Checkout() / "project.cpp", .args = options.args });
|
Configuration* library = LocalProject({ .projectFile = Checkout() / "project.cpp", .args = options.args });
|
||||||
cfg.dependencies.push_back(library);
|
cfg.dependencies.push_back(library);
|
||||||
if (!options.define.empty()) cfg.defines.push_back({ options.define, "" });
|
if (!options.define.empty()) cfg.defines.push_back({ options.define, "" });
|
||||||
if (!topLevel) return;
|
if (!topLevel) return true;
|
||||||
const auto client = std::ranges::find(library->dependencies, std::string_view("crafter.debug-cli"),
|
const auto client = std::ranges::find(library->dependencies, std::string_view("crafter.debug-cli"),
|
||||||
[](const Configuration* dependency) { return std::string_view(dependency->name); });
|
[](const Configuration* dependency) { return std::string_view(dependency->name); });
|
||||||
if (client == library->dependencies.end()) {
|
if (client == library->dependencies.end()) {
|
||||||
throw std::runtime_error(std::format("Crafter.Debug: {} declares no crafter.debug-cli client", (Checkout() / "project.cpp").string()));
|
throw std::runtime_error(std::format("Crafter.Debug: {} declares no crafter.debug-cli client", (Checkout() / "project.cpp").string()));
|
||||||
}
|
}
|
||||||
WriteIfChanged(launcher, LauncherText((*client)->BinDir() / (*client)->outputName, CurrentSandbox(), options.flag));
|
WriteIfChanged(launcher, LauncherText((*client)->BinDir() / (*client)->outputName, CurrentSandbox(), options.flag));
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue