Repository navigation
prepare: split the longest phase functions into sub-steps #722
Copy link
Copy link
Closed
Description
Activity
Done in 2026.9.28.1 (#727). The long phase functions of
src/build/prepare/are split into sub-steps along the sections their own banners name, by the #719 method. Statements are moved, not reordered or rewritten. Where several steps of one phase share locals, those locals live in a phase-local context struct.- Scope. The seven functions this issue named are split, together with the three others over about 400 lines that the measurement found:
phase0,phase3andphase11. So are the six sub-steps and closures that were still over 400 after the first pass, among themphase2_define_toolchain_resolver(1,006 lines) and theloadVersionDepclosure. - Where the code now lives.
plan.cppwould have exceeded the 2,500-line file gate after the merge. The records half of P13, which writesmcpp.lockandresolution.json, moved torecords.cpp. - The size check.
.github/tools/check_function_sizes.shruns clang-tidy'sreadability-function-sizeover the compile database of an LLVM build. It reported 10 functions over 400 lines at the base and reports none now. - Why the check is not in CI. The only CI job that builds mcpp with clang has never completed that build, and it reports success anyway; CI: the LLVM toolchain job reports success while mcpp's self-build with llvm@20.1.7 fails #729 records this and the check's wiring. Until then the check runs by hand after
mcpp build --toolchain llvm@22.1.8.
Readings on the final tree:
resolution.json,build.ninjaand theemit build-databaseoutput of seven fixtures are byte-identical to the pre-split binary. The fixtures are: a single package, a workspace, a git dependency, a host tool, a build program, a musl cross target, andemit.- AddressSanitizer with
detect_stack_use_after_return=1reports nothing over those fixtures and a 20-script prepare-heavy e2e subset. - The unit suite passes, 132 of 132.
- PR 2026.9.28.1: eight reports (#717, #718, #720, #722-#726), one download progress, and an index floor that is a tip #727's CI is green apart from the two xcode-27 jobs that fail on
maintoo (ci-macos xcode-27: ld64.lld cannot parse arm64e.x1 in either available SDK (upstream, tracked) #669).
- Scope. The seven functions this issue named are split, together with the three others over about 400 lines that the measurement found:
Metadata
Metadata
Assignees
Labels
No labels
Observation
mcpp 2026.9.27.1 (#719) decomposes
src/build/prepare.cppm:prepare_buildbecomes eleven phase functions over an explicitPrepareState, in implementation units of at most 2,500 lines each. The file boundaries are architectural; several phases are still single functions of about two thousand lines:phase13_finishsrc/build/prepare/plan.cppphase4b_graph_worklistgraph.cppphase6_features_and_host_toolsfeatures.cppphase9_target_sidetarget_side.cppphase4a_graph_loadgraph_load.cppphase1_toolchain_spec_and_axestoolchain.cppphase2_define_toolchain_resolvertoolchain.cppEach still keeps many locals of its own and defines closures that later steps of the same phase call, so a step inside a phase can be read, tested or changed only through the whole phase.
Proposal
Split each of these along the sections its own banners already name, the way the decomposition split
prepare_build:phase13_finish: prebuilt dependencies, link forms,make_plan, the runtime binding, assembly units, Windows resources, the global dependency cache,mcpp.lock,resolution.json, the empty-link check;phase4b_graph_worklist: the worklist step for one item, identity adoption, the cycle check;phase6_features_and_host_tools: feature activation, capability and ABI accumulation, host-tool provisioning, the dependencies' build programs;phase9_target_side: capability binding, target-side resolution, link forms.Each sub-step is a function over
PrepareState&(or over a phase-local struct passed by reference), extracted verbatim; the checks the decomposition used apply unchanged: the golden fixtures byte-identical, the unit tests, the e2e suite, AddressSanitizer withdetect_stack_use_after_return=1for closures that outlive their step, and no new interface unit inmcpp.build.prepare's import chain (#721).Acceptance
src/build/prepare/longer than about 400 lines, and the length gate extended to functions.tests/unit/test_prepare_helpers.cpp.