From e906f797da2cd0b1776dd1b420f9b04d3cd24baf Mon Sep 17 00:00:00 2001 From: Jorijn van der Graaf Date: Fri, 2 Oct 2026 21:58:44 +0200 Subject: [PATCH] fix: wire the HouseRules test only when this is the top-level project crafter-build loads this project file as a `#pragma crafter dependency` of its own project.cpp. The HouseRules test pulls crafter-build in via GitProject so it can run the linter in-process, which from inside crafter-build means loading crafter-build's project.cpp a second time, which loads this file a second time, and the cycle guard throws. Every crafter-build invocation that loads its project.cpp has failed since the test was wired. Guard the test with IsTopLevelProject(), which crafter-build exposes for exactly this: it is false while a project file runs as somebody else's dependency. Consumers never needed the test; only `crafter-build test` run in this repository does. Co-Authored-By: Claude Fable 5.1 --- project.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/project.cpp b/project.cpp index 6515374..8403d20 100644 --- a/project.cpp +++ b/project.cpp @@ -29,8 +29,11 @@ extern "C" Configuration CrafterBuildProject(std::span a // The rule test compiles the module as its own interface and links // crafter-build to run the linter in-process: from git by default, or // the sibling checkout with `crafter-build test --local`. Host only, - // like the rules themselves. - if (cfg.target == "x86_64-pc-linux-gnu") { + // like the rules themselves, and only when this is the project being + // built: crafter-build itself loads this file as a dependency, and the + // test's GitProject would then load crafter-build's project file again + // and recurse into the cycle guard. + if (IsTopLevelProject() && cfg.target == "x86_64-pc-linux-gnu") { Configuration* build = useLocal ? LocalProject({ .projectFile = "../Crafter.Build/project.cpp", .args = depArgs }) : GitProject({ .source = { .url = "https://forgejo.catcrafts.net/Catcrafts/Crafter.Build.git" }, .args = depArgs });