Skip to content

Commit 01cd739

Browse files
committed
Refactor toolchain providers
1 parent 805255b commit 01cd739

12 files changed

Lines changed: 1024 additions & 667 deletions

File tree

src/build/flags.cppm

Lines changed: 9 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export module mcpp.build.flags;
1111
import std;
1212
import mcpp.build.plan;
1313
import mcpp.toolchain.detect;
14-
import mcpp.xlings;
14+
import mcpp.toolchain.registry;
1515

1616
export namespace mcpp::build {
1717

@@ -37,30 +37,8 @@ namespace mcpp::build {
3737

3838
namespace {
3939

40-
std::filesystem::path derive_c_compiler(const std::filesystem::path& cxxPath) {
41-
auto stem = cxxPath.stem().string();
42-
auto parent = cxxPath.parent_path();
43-
auto ext = cxxPath.extension();
44-
45-
// g++ → gcc, clang++ → clang, x86_64-linux-musl-g++ → x86_64-linux-musl-gcc
46-
std::string cc_stem;
47-
if (stem.ends_with("++")) {
48-
cc_stem = stem.substr(0, stem.size() - 2);
49-
// g++ → gcc; x86_64-linux-musl-g++ → x86_64-linux-musl-gcc;
50-
// clang++ → clang.
51-
if (cc_stem == "g" || cc_stem.ends_with("-g"))
52-
cc_stem += "cc"; // g → gcc
53-
// else clang++ → clang (already correct after stripping ++)
54-
} else {
55-
cc_stem = stem; // fallback: same as cxx
56-
}
57-
return parent / (cc_stem + ext.string());
58-
}
59-
6040
std::filesystem::path staged_std_bmi_path(const BuildPlan& plan) {
61-
if (plan.toolchain.compiler == mcpp::toolchain::CompilerId::Clang)
62-
return plan.outputDir / "pcm.cache" / "std.pcm";
63-
return plan.outputDir / "gcm.cache" / "std.gcm";
41+
return mcpp::toolchain::staged_std_bmi_path(plan.toolchain, plan.outputDir);
6442
}
6543

6644
// Escape a path for embedding in ninja rule strings.
@@ -81,7 +59,7 @@ std::string escape_path(const std::filesystem::path& p) {
8159
CompileFlags compute_flags(const BuildPlan& plan) {
8260
CompileFlags f;
8361
f.cxxBinary = plan.toolchain.binaryPath;
84-
f.ccBinary = derive_c_compiler(plan.toolchain.binaryPath);
62+
f.ccBinary = mcpp::toolchain::derive_c_compiler(plan.toolchain);
8563
f.toolEnv = mcpp::toolchain::compiler_env_prefix(plan.toolchain);
8664

8765
// PIC?
@@ -109,14 +87,13 @@ CompileFlags compute_flags(const BuildPlan& plan) {
10987
}
11088

11189
// Binutils -B flag
112-
bool isMuslTc = plan.toolchain.targetTriple.find("-musl") != std::string::npos;
113-
bool isClang = plan.toolchain.compiler == mcpp::toolchain::CompilerId::Clang;
90+
bool isMuslTc = mcpp::toolchain::is_musl_target(plan.toolchain);
91+
bool isClang = mcpp::toolchain::is_clang(plan.toolchain);
11492
std::filesystem::path binutilsBin;
11593
if (!isMuslTc && !isClang) {
116-
if (auto ar = mcpp::xlings::paths::find_sibling_binary(
117-
plan.toolchain.binaryPath, "binutils", "bin/ar")) {
118-
binutilsBin = ar->parent_path(); // bin/ar → bin/
119-
}
94+
auto ar = mcpp::toolchain::archive_tool(plan.toolchain);
95+
if (!ar.empty())
96+
binutilsBin = ar.parent_path();
12097
}
12198
std::string b_flag;
12299
if (!binutilsBin.empty()) {
@@ -125,17 +102,7 @@ CompileFlags compute_flags(const BuildPlan& plan) {
125102
}
126103

127104
// AR binary
128-
if (isClang) {
129-
auto llvmAr = plan.toolchain.binaryPath.parent_path() / "llvm-ar";
130-
if (std::filesystem::exists(llvmAr))
131-
f.arBinary = llvmAr;
132-
} else if (!binutilsBin.empty()) {
133-
f.arBinary = binutilsBin / "ar";
134-
} else if (isMuslTc) {
135-
auto muslAr = plan.toolchain.binaryPath.parent_path() / "x86_64-linux-musl-ar";
136-
if (std::filesystem::exists(muslAr))
137-
f.arBinary = muslAr;
138-
}
105+
f.arBinary = mcpp::toolchain::archive_tool(plan.toolchain);
139106

140107
// Opt level (musl ICE workaround)
141108
std::string opt_flag = isMuslTc ? " -Og" : " -O2";

src/build/ninja_backend.cppm

Lines changed: 3 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import mcpp.build.flags;
2424
import mcpp.build.compile_commands;
2525
import mcpp.dyndep;
2626
import mcpp.toolchain.detect;
27+
import mcpp.toolchain.registry;
2728
import mcpp.xlings;
2829

2930
export namespace mcpp::build {
@@ -118,39 +119,6 @@ std::filesystem::path mcpp_exe_path() {
118119
return "mcpp"; // fall back to PATH lookup
119120
}
120121

121-
// Derive a sibling C compiler from a C++ compiler binary path. Used so .c
122-
// sources can be compiled by the actual C frontend (cc1), not g++ which
123-
// rejects implicit `void*` conversions and `restrict` etc.
124-
// .../bin/g++ → .../bin/gcc
125-
// .../bin/x86_64-linux-musl-g++ → .../bin/x86_64-linux-musl-gcc
126-
// .../bin/clang++ → .../bin/clang
127-
// .../bin/c++ → .../bin/cc
128-
// If no sibling exists, return "gcc" so PATH lookup is the final fallback
129-
// (this also keeps unit tests that don't touch a real toolchain happy).
130-
std::filesystem::path derive_c_compiler(const std::filesystem::path& cxx) {
131-
auto fname = cxx.filename().string();
132-
auto try_replace = [&](std::string_view from,
133-
std::string_view to) -> std::optional<std::filesystem::path> {
134-
auto pos = fname.rfind(from);
135-
if (pos == std::string::npos)
136-
return std::nullopt;
137-
std::string repl = fname;
138-
repl.replace(pos, from.size(), to);
139-
auto p = cxx.parent_path() / repl;
140-
std::error_code ec;
141-
if (std::filesystem::exists(p, ec))
142-
return p;
143-
return std::nullopt;
144-
};
145-
if (auto p = try_replace("clang++", "clang"))
146-
return *p;
147-
if (auto p = try_replace("g++", "gcc"))
148-
return *p;
149-
if (auto p = try_replace("c++", "cc"))
150-
return *p;
151-
return "gcc";
152-
}
153-
154122
bool is_c_source(const std::filesystem::path& src) {
155123
return src.extension() == ".c";
156124
}
@@ -159,7 +127,7 @@ bool is_c_source(const std::filesystem::path& src) {
159127

160128
std::string emit_ninja_string(const BuildPlan& plan) {
161129
bool dyndep = dyndep_mode_enabled()
162-
&& plan.toolchain.compiler == mcpp::toolchain::CompilerId::GCC;
130+
&& mcpp::toolchain::is_gcc(plan.toolchain);
163131
std::string out;
164132
auto append = [&](std::string s) { out += std::move(s); };
165133

@@ -278,9 +246,7 @@ std::string emit_ninja_string(const BuildPlan& plan) {
278246
}
279247

280248
// Stage prebuilt std artifacts into the compiler-specific BMI cache.
281-
auto std_bmi_dst = plan.toolchain.compiler == mcpp::toolchain::CompilerId::Clang
282-
? std::filesystem::path("pcm.cache") / "std.pcm"
283-
: std::filesystem::path("gcm.cache") / "std.gcm";
249+
auto std_bmi_dst = mcpp::toolchain::staged_std_bmi_path(plan.toolchain, {});
284250
auto std_o_dst = std::filesystem::path("obj") / "std.o";
285251

286252
bool has_std_artifacts = !plan.stdBmiPath.empty() && !plan.stdObjectPath.empty();

0 commit comments

Comments
 (0)