Skip to content

prepare: split the longest phase functions into sub-steps #722

Description

@speak-agent

Observation

mcpp 2026.9.27.1 (#719) decomposes src/build/prepare.cppm: prepare_build becomes eleven phase functions over an explicit PrepareState, 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:

Phase function File Lines
phase13_finish src/build/prepare/plan.cpp 2,293
phase4b_graph_worklist graph.cpp 2,245
phase6_features_and_host_tools features.cpp 1,953
phase9_target_side target_side.cpp 1,869
phase4a_graph_load graph_load.cpp 1,060
phase1_toolchain_spec_and_axes toolchain.cpp 1,029
phase2_define_toolchain_resolver toolchain.cpp 1,007

Each 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 with detect_stack_use_after_return=1 for closures that outlive their step, and no new interface unit in mcpp.build.prepare's import chain (#721).

Acceptance

  • No function under src/build/prepare/ longer than about 400 lines, and the length gate extended to functions.
  • The pure pieces that fall out of the split gain unit tests alongside tests/unit/test_prepare_helpers.cpp.

Activity

  1. added a commit that references this issue on Sep 27, 2026
  2. speak-agent commented on Sep 27, 2026

    @speak-agent
    MemberAuthor

    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, phase3 and phase11. So are the six sub-steps and closures that were still over 400 after the first pass, among them phase2_define_toolchain_resolver (1,006 lines) and the loadVersionDep closure.
    • Where the code now lives. plan.cpp would have exceeded the 2,500-line file gate after the merge. The records half of P13, which writes mcpp.lock and resolution.json, moved to records.cpp.
    • The size check. .github/tools/check_function_sizes.sh runs clang-tidy's readability-function-size over 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:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions