// SPDX-License-Identifier: LGPL-3.0-only // SPDX-FileCopyrightText: Copyright (C) 2026 Catcrafts® import std; import Crafter.Build; namespace fs = std::filesystem; using namespace Crafter; // clang's driver ranks the host toolchain's own libc++ headers // (/../include/c++/v1) above --sysroot. A unit that only does // `import std;` never notices, because the std module is precompiled with the // sysroot's headers forced. A unit that includes a standard header textually // (vendored C++ in a dependency, say) got the host's libc++ configured for the // host's libc: against a musl sysroot every such unit died with "unknown rune // table for this platform", and against a glibc sysroot it compiled against // the wrong release without a word. // // GetCompileCommand therefore has to point every sysroot compile at the // sysroot's copy. It must not do so where there is no sysroot, for wasm (which // has its own sysroot handling) or for mingw (libstdc++, no libc++ at all). // The command is checked as text: no compiler runs. namespace { std::int32_t Failures = 0; void Check(bool cond, std::string_view msg) { if (!cond) { std::println(std::cerr, "FAIL: {}", msg); ++Failures; } } std::string CommandFor(std::string_view target, std::string_view sysroot) { Configuration cfg; cfg.path = "/tmp/crafter-build-sysroot-compile-flags"; cfg.name = "flags"; cfg.outputName = "flags"; cfg.target = std::string(target); cfg.march = "generic"; cfg.mtune = "generic"; cfg.type = ConfigurationType::Executable; cfg.sysroot = std::string(sysroot); return GetCompileCommand(cfg).command; } } int main() { const std::string sysroot = "/opt/crafter-build-test-sysroot"; const std::string forced = std::format("-nostdinc++ -isystem {}/usr/include/c++/v1", sysroot); for (std::string_view target : {"aarch64-alpine-linux-musl", "aarch64-unknown-linux-gnu", "x86_64-pc-linux-gnu"}) { const std::string command = CommandFor(target, sysroot); Check(command.contains(std::format("--sysroot={}", sysroot)), std::format("{}: the sysroot is passed", target)); Check(command.contains(forced), std::format("{}: the sysroot's libc++ headers are forced", target)); } Check(!CommandFor("x86_64-pc-linux-gnu", "").contains("/usr/include/c++/v1 -Wno-unused-command-line-argument"), "no sysroot: nothing is forced"); Check(!CommandFor("wasm32-wasip1", sysroot).contains(forced), "wasm: left to its own sysroot handling"); Check(!CommandFor("x86_64-w64-mingw32", sysroot).contains(forced), "mingw: libstdc++ target, libc++ headers are not forced"); if (Failures > 0) { std::println(std::cerr, "{} assertions failed", Failures); return 1; } return 0; }