From bc9ceb8f2456fcd8806df6deed58524e24cdb642 Mon Sep 17 00:00:00 2001 From: Jorijn van der Graaf Date: Wed, 29 Apr 2026 18:59:01 +0200 Subject: [PATCH] config from args --- implementations/Crafter.Build-Clang.cpp | 26 ++++++++++++++++++++ interfaces/Crafter.Build-Clang.cppm | 20 +++++++++++++++- project.cpp | 32 ++++--------------------- 3 files changed, 50 insertions(+), 28 deletions(-) diff --git a/implementations/Crafter.Build-Clang.cpp b/implementations/Crafter.Build-Clang.cpp index 501cc30..5642d53 100644 --- a/implementations/Crafter.Build-Clang.cpp +++ b/implementations/Crafter.Build-Clang.cpp @@ -852,6 +852,32 @@ void Crafter::EnableWasiBrowserRuntime(Configuration& cfg) { cfg.files.push_back(htmlPath); } +std::string Crafter::HostTarget() { + static const std::string cached = []() -> std::string { + CommandResult r = RunCommandChecked("clang++ -print-target-triple"); + if (r.exitCode != 0) return {}; + std::string out = std::move(r.output); + while (!out.empty() && (out.back() == '\n' || out.back() == '\r')) out.pop_back(); + return out; + }(); + return cached; +} + +void Crafter::ApplyStandardArgs(Configuration& cfg, std::span args) { + if (const char* envMarch = std::getenv("CRAFTER_BUILD_MARCH"); envMarch && *envMarch) { + cfg.march = envMarch; + } + if (const char* envMtune = std::getenv("CRAFTER_BUILD_MTUNE"); envMtune && *envMtune) { + cfg.mtune = envMtune; + } + for (std::string_view a : args) { + if (a == "--debug") cfg.debug = true; + else if (a.starts_with("--target=")) cfg.target = std::string(a.substr(std::string_view("--target=").size())); + else if (a.starts_with("--march=")) cfg.march = std::string(a.substr(std::string_view("--march=").size())); + else if (a.starts_with("--mtune=")) cfg.mtune = std::string(a.substr(std::string_view("--mtune=").size())); + } +} + static void PrintHelp(std::string_view argv0) { std::println( R"(Usage: diff --git a/interfaces/Crafter.Build-Clang.cppm b/interfaces/Crafter.Build-Clang.cppm index c43c47a..bdb49d1 100644 --- a/interfaces/Crafter.Build-Clang.cppm +++ b/interfaces/Crafter.Build-Clang.cppm @@ -87,13 +87,20 @@ export namespace Crafter { std::string output; }; + // The host target triple, detected once per process by running + // `clang++ -print-target-triple` and cached. Used as the default for + // Configuration::target so projects don't have to hardcode it for the + // no-cross-compile case. Returns "" if clang isn't on PATH or doesn't + // print a triple — those projects still need an explicit cfg.target. + CRAFTER_API std::string HostTarget(); + struct Configuration { fs::path path; std::string outputName; std::string name; std::string march = "native"; std::string mtune = "native"; - std::string target; + std::string target = HostTarget(); std::string sysroot; bool debug = false; ConfigurationType type = ConfigurationType::Executable; @@ -135,4 +142,15 @@ export namespace Crafter { // outputName is set; index.html is generated against the current // outputName so renaming the binary later requires another call. CRAFTER_API void EnableWasiBrowserRuntime(Configuration& cfg); + + // Apply the framework's standard CLI args + env vars onto cfg: + // --debug cfg.debug = true + // --target= cfg.target = + // --march= cfg.march = + // --mtune= cfg.mtune = + // $CRAFTER_BUILD_MARCH / $CRAFTER_BUILD_MTUNE seed march/mtune. + // Env applies first, then args, so CLI wins over env wins over caller's + // pre-set defaults. Project-specific flags (e.g. --shared, --timing) are + // not handled here — parse them in your own loop alongside this call. + CRAFTER_API void ApplyStandardArgs(Configuration& cfg, std::span args); } \ No newline at end of file diff --git a/project.cpp b/project.cpp index f90051b..328679a 100644 --- a/project.cpp +++ b/project.cpp @@ -4,36 +4,17 @@ namespace fs = std::filesystem; using namespace Crafter; extern "C" Configuration CrafterBuildProject(std::span args) { - bool debug = false; - std::string target = "x86_64-pc-linux-gnu"; - for (std::string_view arg : args) { - if (arg == "--debug") debug = true; - else if (arg.starts_with("--target=")) target = std::string(arg.substr(std::string_view("--target=").size())); - } - - // Honor CRAFTER_BUILD_MARCH/MTUNE so CI (which sets these for portability) - // applies them to both the self-rebuild and the mingw cross-compile — - // otherwise Configuration's "native" defaults bake in the build host's - // CPU and the published artifact's portability becomes accidental. - const char* envMarch = std::getenv("CRAFTER_BUILD_MARCH"); - const char* envMtune = std::getenv("CRAFTER_BUILD_MTUNE"); - std::string march = (envMarch && *envMarch) ? envMarch : "native"; - std::string mtune = (envMtune && *envMtune) ? envMtune : "native"; - static auto crafterBuildLib = std::make_unique(); crafterBuildLib->path = "./"; crafterBuildLib->name = "crafter.build-lib"; crafterBuildLib->outputName = "crafter-build"; - crafterBuildLib->target = target; - crafterBuildLib->march = march; - crafterBuildLib->mtune = mtune; + ApplyStandardArgs(*crafterBuildLib, args); // Windows builds (native msvc via build.cmd or cross-compiled mingw from // Linux) need a DLL + import lib + launcher exe so LoadProject can // compile project.cpp against a stable ABI boundary. Linux is monolithic. - crafterBuildLib->type = (target == "x86_64-w64-mingw32" || target == "x86_64-pc-windows-msvc") + crafterBuildLib->type = (crafterBuildLib->target == "x86_64-w64-mingw32" || crafterBuildLib->target == "x86_64-pc-windows-msvc") ? ConfigurationType::LibraryDynamic : ConfigurationType::LibraryStatic; - crafterBuildLib->debug = debug; { std::array interfaces = { "interfaces/Crafter.Build", @@ -67,7 +48,7 @@ extern "C" Configuration CrafterBuildProject(std::span a // mingw cross-build: skip the standalone executable. We only consume the // libraries, and glslang.exe pulls in libgcc_eh which needs pthread that // mingw-w64 doesn't link by default. - if (target == "x86_64-w64-mingw32") { + if (crafterBuildLib->target == "x86_64-w64-mingw32") { glslang.options.push_back("-DENABLE_GLSLANG_BINARIES=OFF"); } glslang.includeDirs = { "" }; @@ -77,18 +58,15 @@ extern "C" Configuration CrafterBuildProject(std::span a cfg.path = "./"; cfg.name = "crafter.build-exe"; cfg.outputName = "crafter-build"; - cfg.target = target; - cfg.march = march; - cfg.mtune = mtune; + ApplyStandardArgs(cfg, args); cfg.type = ConfigurationType::Executable; - cfg.debug = debug; cfg.dependencies = { crafterBuildLib.get() }; { std::array interfaces = {}; std::array implementations = { "implementations/main" }; cfg.GetInterfacesAndImplementations(interfaces, implementations); } - if (target == "x86_64-pc-linux-gnu") { + if (cfg.target == "x86_64-pc-linux-gnu") { cfg.linkFlags.push_back("-Wl,--export-dynamic"); cfg.linkFlags.push_back("-ldl"); }