-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathdetect.cppm
More file actions
113 lines (91 loc) · 4.21 KB
/
detect.cppm
File metadata and controls
113 lines (91 loc) · 4.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
// mcpp.toolchain.detect - compiler discovery facade.
export module mcpp.toolchain.detect;
export import mcpp.toolchain.model;
export import mcpp.toolchain.probe;
import std;
import mcpp.toolchain.clang;
import mcpp.toolchain.gcc;
import mcpp.xlings;
export namespace mcpp::toolchain {
// Detect toolchain. If explicit_compiler is given, use that binary path
// directly. Otherwise fall back to $CXX, then PATH g++.
std::expected<Toolchain, DetectError>
detect(const std::filesystem::path& explicit_compiler = {});
// Compatibility helper for older call sites/tests: GCC std module lookup now
// lives in the GCC provider.
std::optional<std::filesystem::path> find_std_module_source(
const std::filesystem::path& cxx_binary, std::string_view version);
} // namespace mcpp::toolchain
namespace mcpp::toolchain {
std::optional<std::filesystem::path> find_std_module_source(
const std::filesystem::path& cxx_binary, std::string_view version) {
return mcpp::toolchain::gcc::find_std_module_source(cxx_binary, version);
}
std::expected<Toolchain, DetectError>
detect(const std::filesystem::path& explicit_compiler) {
auto bin_r = probe_compiler_binary(explicit_compiler);
if (!bin_r) return std::unexpected(bin_r.error());
Toolchain tc;
tc.binaryPath = *bin_r;
tc.compilerRuntimeDirs = discover_compiler_runtime_dirs(tc.binaryPath);
auto envPrefix = compiler_env_prefix(tc);
auto ver_r = run_capture(std::format("{}{} --version 2>&1",
envPrefix,
mcpp::xlings::shq(tc.binaryPath.string())));
if (!ver_r) return std::unexpected(ver_r.error());
const auto& vstr = *ver_r;
tc.driverIdent = normalize_driver_output(vstr);
auto head = first_line_of(vstr);
auto headLower = lower_copy(head);
auto fullLower = lower_copy(vstr);
if (mcpp::toolchain::clang::matches_version_output(headLower, fullLower)) {
tc.compiler = CompilerId::Clang;
tc.version = extract_version(head.empty()
? std::string_view(vstr)
: std::string_view(head));
} else if (mcpp::toolchain::gcc::matches_version_output(headLower)) {
tc.compiler = CompilerId::GCC;
tc.version = mcpp::toolchain::gcc::parse_version(head);
} else {
return std::unexpected(DetectError{
std::format("unrecognized compiler output:\n{}", vstr)});
}
if (auto triple = probe_target_triple(tc.binaryPath, envPrefix)) {
tc.targetTriple = *triple;
}
#if defined(_WIN32)
// On Windows, Clang targeting MSVC auto-detects the MSVC version at
// compile time and bakes it into the module AST. The -dumpmachine triple
// doesn't include this version, so fingerprints don't change when MSVC
// patches (e.g. 19.44.35226 → 35227), causing stale BMI cache hits.
// Query the effective triple which includes the actual MSVC version.
if (tc.compiler == CompilerId::Clang
&& is_msvc_target(tc)) {
auto vr = run_capture(std::format(
"{}{} -print-effective-triple 2>NUL",
envPrefix,
mcpp::xlings::shq(tc.binaryPath.string())));
if (vr) {
auto effective = trim_line(*vr);
if (!effective.empty() && effective != tc.targetTriple)
tc.driverIdent += "\neffective-triple: " + effective;
}
}
#endif
if (tc.compiler == CompilerId::GCC) {
mcpp::toolchain::gcc::enrich_toolchain(tc);
} else if (tc.compiler == CompilerId::Clang) {
mcpp::toolchain::clang::enrich_toolchain(tc, envPrefix);
}
tc.sysroot = probe_sysroot(tc.binaryPath, envPrefix);
// Probe fine-grained payload paths from sibling xpkgs (glibc, linux-headers).
// When available, flags are assembled from these paths instead of --sysroot.
tc.payloadPaths = probe_payload_paths(tc.binaryPath);
// For GCC: ensure the probed sysroot has complete headers by symlinking
// missing content (linux kernel headers, glibc) from payload xpkgs.
// This makes mcpp self-sufficient — not dependent on xlings subos init.
if (tc.payloadPaths && !tc.sysroot.empty())
ensure_sysroot_complete(tc.sysroot, *tc.payloadPaths);
return tc;
}
} // namespace mcpp::toolchain