test(sysroot): the compile command forces the sysroot's libc++
GetCompileCommand is checked as text, without a compiler: the forced include directory is present for linux-gnu and linux-musl targets with a sysroot, and absent without a sysroot, for wasm32 and for mingw. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
parent
3c96d78a7d
commit
4ca8f14c70
2 changed files with 66 additions and 0 deletions
|
|
@ -131,6 +131,7 @@ extern "C" Configuration CrafterBuildProject(std::span<const std::string_view> a
|
|||
cfg.AddTest("VariantId").Dependencies({ CrafterBuildLib.get() });
|
||||
cfg.AddTest("ToolchainResolve").Dependencies({ CrafterBuildLib.get() });
|
||||
cfg.AddTest("SysrootStdModule").Dependencies({ CrafterBuildLib.get() });
|
||||
cfg.AddTest("SysrootCompileFlags").Dependencies({ CrafterBuildLib.get() });
|
||||
cfg.AddTest("VersionFlag").Dependencies({ CrafterBuildLib.get() });
|
||||
cfg.AddTest("WasiBrowserRuntime").Dependencies({ CrafterBuildLib.get() });
|
||||
cfg.AddTest("WasmVariants").Dependencies({ CrafterBuildLib.get() });
|
||||
|
|
|
|||
65
tests/SysrootCompileFlags/main.cpp
Normal file
65
tests/SysrootCompileFlags/main.cpp
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
// 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
|
||||
// (<install>/../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;
|
||||
}
|
||||
Loading…
Reference in a new issue