Skip to content

Commit d0d7bc2

Browse files
speak-agentclaude
andcommitted
prepare.cppm: the primary interface holds declarations only
The primary interface still carried the former preamble's definitions, about 1,700 lines of helpers. They move into four implementation units by concern -- config.cpp (conditional merges, build flags and defines, workspace inheritance, feature requests, std-module detection), options.cpp (the MSVC guidance, the cache mode, the profile), toolchain_env.cpp (target rows, sysroots, the MSVC binding, build-program environments, the toolchain a host tool chose) and fetch.cpp (git remotes, network retries, xlings addresses and their provisioning). Exported functions keep their documented declaration, default arguments included, in prepare.cppm; the other helpers are declared in `:state`, grouped by the file that defines them, and keep their design notes beside their definitions. prepare.cppm goes from 2,414 to 777 lines: exported types, exported inline functions and declarations. An edit to a helper now recompiles its own unit and relinks, instead of changing the interface every importer depends on. Moved verbatim; the normalised resolution.json, build.ninja and emit build-database outputs of the seven golden fixtures are byte-identical to the pre-decomposition binary, and the 129 unit tests pass. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 3f802e0 commit d0d7bc2

6 files changed

Lines changed: 2176 additions & 1659 deletions

File tree

‎src/build/prepare.cppm‎

Lines changed: 22 additions & 1659 deletions
Large diffs are not rendered by default.

‎src/build/prepare/config.cpp‎

Lines changed: 865 additions & 0 deletions
Large diffs are not rendered by default.

‎src/build/prepare/fetch.cpp‎

Lines changed: 547 additions & 0 deletions
Large diffs are not rendered by default.

‎src/build/prepare/options.cpp‎

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
// options.cpp -- the invocation options prepare_build resolves: the MSVC
2+
// guidance, the build-cache mode and the profile. Declared, with their
3+
// documentation, in prepare.cppm.
4+
5+
module mcpp.build.prepare;
6+
import :state;
7+
8+
import mcpp.build.prepare_inputs;
9+
10+
import std;
11+
import mcpp.targetside;
12+
import mcpp.diag;
13+
import mcpp.build.refusal;
14+
import mcpp.xlings.address_set;
15+
import mcpp.build.version_floor;
16+
import mcpp.home;
17+
import mcpp.platform.axis;
18+
import mcpp.libs.json;
19+
import mcpp.log;
20+
import mcpp.manifest;
21+
import mcpp.source_kind;
22+
import mcpp.modgraph.glob;
23+
import mcpp.modgraph.graph;
24+
import mcpp.modgraph.scanner;
25+
import mcpp.modgraph.validate;
26+
import mcpp.toolchain.clang;
27+
import mcpp.toolchain.hostflags; // the compile-token producer the package std module reuses
28+
import mcpp.toolchain.cenv; // [c-abi] declaration → compiler configuration (design 2026-09-18)
29+
import mcpp.toolchain.cenv_probe; // [c-abi] declaration is checked, not trusted (design §3.2)
30+
import mcpp.toolchain.predefines; // the macros this engine defines: contract and emission in one module
31+
import mcpp.toolchain.cppfly;
32+
import mcpp.toolchain.detect;
33+
import mcpp.toolchain.dialect;
34+
import mcpp.toolchain.fingerprint;
35+
import mcpp.toolchain.msvc;
36+
import mcpp.toolchain.registry;
37+
import mcpp.toolchain.linkmodel;
38+
import mcpp.toolchain.gcc;
39+
// For `resolve_version_match` / `list_installed_versions`: a bare compiler
40+
// family named by the dependency graph resolves to a concrete version through
41+
// exactly the path `mcpp toolchain default <family>` uses.
42+
import mcpp.toolchain.lifecycle;
43+
import mcpp.toolchain.stdmod;
44+
import mcpp.freestanding.target; // the target sysroot layout (libdir)
45+
import mcpp.freestanding.linkline; // the ISA profile, for the std module command
46+
import mcpp.toolchain.post_install;
47+
import mcpp.toolchain.abi;
48+
import mcpp.toolchain.triple;
49+
import mcpp.build.linkage_form; // #519 — which form each dependency takes
50+
import mcpp.build.plan;
51+
import mcpp.build.schedule.policy;
52+
import mcpp.build.flags; // compute_flags — the per-role contracts (#418)
53+
import mcpp.build.distribution; // dist::Role / dist::Contract to_string
54+
import mcpp.platform.capacity; // the host fallback handed to schedule::decide
55+
import mcpp.build.graph_shape; // #407: the graph says which mode wrote it
56+
import mcpp.build.runtime_validation; // declared artifact -> identity verdict
57+
import mcpp.build.cache_key;
58+
import mcpp.pack.abi_tag; // the tag a prebuilt dependency is checked against
59+
import mcpp.pack.prebuilt; // …and the check itself
60+
import mcpp.pack.stage_tree; // where `${mcpp.stage_dir}` points, and its manifest
61+
import mcpp.build.build_program;
62+
import mcpp.build.directives; // directive table: mark / fold_private_tail
63+
import mcpp.build.tool_store; // #355 host tools: store layout + key + overrides
64+
import mcpp.build.dep_graph; // queries over the resolved edge graph
65+
import mcpp.build.provisions; // #359 build-time provisions: table + propagation
66+
import mcpp.build.resources; // #365 Windows resources: synthesise / scan / find rc
67+
import mcpp.build.backend; // BuildOptions for the tool sub-build
68+
import mcpp.build.ninja; // make_ninja_backend — driving that sub-build
69+
import mcpp.lockfile;
70+
import mcpp.config;
71+
import mcpp.xlings;
72+
import mcpp.xlings.subos_info;
73+
import mcpp.xlings.runtime_selection;
74+
import mcpp.runtime.binding;
75+
import mcpp.platform.runtime_search;
76+
import mcpp.toolchain.post_install;
77+
import mcpp.platform;
78+
import mcpp.platform.macos;
79+
import mcpp.build.runner_lookup;
80+
import mcpp.fetcher;
81+
import mcpp.fetcher.progress;
82+
import mcpp.pm.resolver;
83+
import mcpp.pm.index_spec;
84+
import mcpp.pm.index_contract;
85+
import mcpp.pm.index_route;
86+
import mcpp.pm.index_refresh;
87+
import mcpp.pm.mangle;
88+
import mcpp.pm.compat;
89+
import mcpp.pm.dep_spec;
90+
import mcpp.pm.dependency_selector;
91+
import mcpp.pm.lock_io;
92+
import mcpp.version_req;
93+
import mcpp.ui;
94+
import mcpp.log;
95+
import mcpp.wire; // Severity, for PlanNote (#699 item 2, E3)
96+
import mcpp.fallback.install_integrity;
97+
import mcpp.bmi_cache;
98+
import mcpp.project;
99+
100+
namespace mcpp::build {
101+
102+
std::string msvc_unavailable_guidance(const mcpp::toolchain::Toolchain& tc) {
103+
namespace pins = mcpp::toolchain::triple::pins;
104+
const bool haveVcTools = tc.compiler == mcpp::toolchain::CompilerId::MSVC;
105+
if (haveVcTools && mcpp::toolchain::msvc::find_msvc_tools_dir()) {
106+
return std::format(
107+
"msvc {} was detected at {}, but no Windows SDK was found —\n"
108+
" cl.exe cannot compile without the UCRT/SDK headers.\n"
109+
" Install the 'Windows 11 SDK' component via the Visual Studio\n"
110+
" Installer (it is part of the Desktop development with C++\n"
111+
" workload), then retry.",
112+
tc.version, tc.binaryPath.string());
113+
}
114+
return std::format(
115+
"this build targets the MSVC ABI, which needs Visual Studio /\n"
116+
" Build Tools (MSVC STL + Windows SDK) — neither was found.\n"
117+
"\n"
118+
" No Visual Studio? Use the self-contained MinGW-w64 toolchain\n"
119+
" (no Visual Studio required, `import std` works):\n"
120+
" mcpp toolchain default {} --target {}\n"
121+
"\n"
122+
" Have Visual Studio? Install the 'Desktop development with C++'\n"
123+
" workload — it provides the MSVC STL and the Windows SDK.",
124+
pins::kSuggestGccMingw, pins::kFirstRunWinGnuTarget);
125+
}
126+
127+
std::optional<CacheMode> parse_cache_mode(std::string_view v) {
128+
if (v == "global") return CacheMode::Global;
129+
if (v == "local") return CacheMode::Local;
130+
if (v == "off" || v == "none") return CacheMode::Off;
131+
return std::nullopt;
132+
}
133+
134+
std::string_view cache_mode_name(CacheMode m) {
135+
switch (m) {
136+
case CacheMode::Local: return "local";
137+
case CacheMode::Off: return "off";
138+
default: return "global";
139+
}
140+
}
141+
142+
CacheMode resolve_cache_mode(const mcpp::manifest::Manifest& m,
143+
std::string_view override_mode) {
144+
if (auto v = parse_cache_mode(override_mode)) return *v;
145+
if (const char* e = std::getenv("MCPP_BUILD_CACHE"); e && *e)
146+
if (auto v = parse_cache_mode(e)) return *v;
147+
if (auto v = parse_cache_mode(m.buildConfig.cacheMode)) return *v;
148+
return CacheMode::Global;
149+
}
150+
151+
std::string resolve_profile_name(const mcpp::manifest::Manifest& m,
152+
std::string_view override_name,
153+
std::string_view fallback) {
154+
if (!override_name.empty()) return std::string(override_name);
155+
if (!m.buildConfig.defaultProfile.empty()) return m.buildConfig.defaultProfile;
156+
return fallback.empty() ? std::string("dev") : std::string(fallback);
157+
}
158+
159+
std::string profile_override_from_flags(std::string_view profileOption,
160+
bool release, bool dev) {
161+
if (!profileOption.empty()) return std::string(profileOption);
162+
if (release) return "release";
163+
if (dev) return "dev";
164+
return {};
165+
}
166+
167+
} // namespace mcpp::build

‎src/build/prepare/state.cppm‎

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -538,4 +538,79 @@ std::expected<void, std::string> phase4a_graph_load(PrepareState& state);
538538
std::expected<void, std::string> phase4b_graph_worklist(PrepareState& state);
539539
std::expected<void, std::string> phase6_features_and_host_tools(PrepareState& state);
540540

541+
// ── Helpers the phases share, defined in the files named below ─────────────
542+
543+
// config.cpp: manifest conditional merges, build flags and defines, workspace inheritance, feature requests, std-module detection
544+
void warn_unknown_xpkg_keys(const mcpp::manifest::Manifest& dm,
545+
std::string_view depLabel);
546+
std::expected<void, std::string>
547+
materialize_generated_files(const std::filesystem::path& root,
548+
const mcpp::manifest::Manifest& manifest,
549+
std::vector<std::filesystem::path>* stale = nullptr);
550+
bool same_dependency_identity(const mcpp::manifest::DependencySpec& a,
551+
const mcpp::manifest::DependencySpec& b);
552+
void replace_dependencies(
553+
std::map<std::string, mcpp::manifest::DependencySpec>& into,
554+
const std::map<std::string, mcpp::manifest::DependencySpec>& from);
555+
std::vector<std::pair<std::string, std::string>>& pending_flag_words_notes();
556+
void report_flag_words_changes(const mcpp::manifest::Manifest& m);
557+
std::optional<std::string>
558+
inherit_as_workspace_member(mcpp::manifest::Manifest& member,
559+
const mcpp::manifest::Manifest& workspace,
560+
const std::filesystem::path& workspaceRoot,
561+
const std::filesystem::path& memberDir);
562+
std::optional<std::pair<mcpp::manifest::Manifest, std::filesystem::path>>
563+
workspace_listing(const std::filesystem::path& memberDir,
564+
const std::filesystem::path& bound);
565+
bool merge_layer_conditional_config(mcpp::manifest::Manifest& m,
566+
const cfgpred::Ctx& ctx);
567+
std::vector<std::string> feature_closure(const mcpp::manifest::Manifest& pm,
568+
const std::vector<std::string>& requested,
569+
bool seedDefault = true);
570+
bool is_std_module(std::string_view name);
571+
bool graph_or_targets_import_std(const mcpp::modgraph::Graph& graph,
572+
const mcpp::manifest::Manifest& manifest,
573+
const std::filesystem::path& projectRoot);
574+
575+
// toolchain_env.cpp: target rows, sysroots, the MSVC binding, build-program environments
576+
const mcpp::manifest::TargetEntry*
577+
find_target_entry(const mcpp::manifest::Manifest& m,
578+
const mcpp::toolchain::triple::Triple& t);
579+
const std::string*
580+
sysroot_override(const mcpp::manifest::Manifest& m,
581+
const mcpp::toolchain::triple::Triple& t);
582+
std::expected<void, std::string>
583+
bind_msvc_sysroot(mcpp::toolchain::Toolchain& tc,
584+
const mcpp::manifest::Manifest& m,
585+
const std::function<std::expected<mcpp::config::GlobalConfig*,
586+
std::string>()>& cfgOf);
587+
std::expected<void, std::string>
588+
check_cl_row_sysroot(const mcpp::toolchain::Toolchain& tc,
589+
const mcpp::manifest::Manifest& m);
590+
void fill_package_build_env(mcpp::build::BuildProgramEnv& e,
591+
const mcpp::manifest::Manifest& m);
592+
void fill_target_build_env(mcpp::build::BuildProgramEnv& e,
593+
const mcpp::manifest::Manifest& m,
594+
const mcpp::toolchain::Toolchain* tc,
595+
const mcpp::config::GlobalConfig* cfg);
596+
std::string min_platform_version(const mcpp::manifest::Manifest& m,
597+
const mcpp::toolchain::triple::Triple& t,
598+
const std::filesystem::path& compilerPath);
599+
600+
// fetch.cpp: git remotes, network retries, xlings addresses and their provisioning
601+
std::string git_cache_head(const std::filesystem::path& gitRoot);
602+
mcpp::platform::process::RunResult run_with_network_retry(
603+
std::string_view command,
604+
const std::function<void()>& between = {});
605+
std::vector<std::string>
606+
applicable_xlings_addresses(const mcpp::manifest::Manifest& man,
607+
const std::vector<std::string>& activeFeatures,
608+
ToolPurpose purpose, bool isRoot);
609+
std::expected<void, std::string>
610+
provision_xlings_addresses(const mcpp::config::GlobalConfig& cfg,
611+
const std::vector<std::string>& declaredDeps,
612+
const std::filesystem::path& legacyStampRoot,
613+
std::string_view label);
614+
std::string with_index_cause(std::string msg);
615+
541616
} // namespace mcpp::build

0 commit comments

Comments
 (0)