Skip to content

feat: declared, programmable and observable sources for toolchains, payloads and plugin tools #755

Description

@speak-agent

Motivation

A build uses three kinds of things whose source a project may want to state: the toolchain, the xlings payloads a plugin declares ([feature-xlings.<f>]), and the tools a plugin runs. Today:

  • A payload a plugin declares is provisioned before any build.mcpp runs, whether or not the build uses it. A build.mcpp that names its own tool (o.cmake = "/usr/bin/cmake") still downloads xim:cmake, and with MCPP_NO_AUTO_INSTALL=1 the build is refused before build.mcpp runs (measured on 2026.9.30.2 with a stand-in plugin; [tools.overrides] does not apply to payloads). Only manifest gates (feature, cfg, when) avoid the download.
  • A payload is installed when it is declared, not when it is used (bundletool for every Android build, appimagetool for every Linux build, emit build-database downloads).
  • The toolchain can only be a managed payload: a toolchain a developer already has (a self-built LLVM, a vendor cross toolchain) cannot be named by path, and a build program cannot configure one.
  • Output and records do not say which of these came from the ecosystem default and which a project or machine chose, so a failure cannot be attributed.

Design

Recorded in mcpp-community/mcpp-plugins .agents/docs/2026-10-01-ecosystem-build-plugin-framework-design.md (v3) and in this repository's .agents/docs with the implementing PR. In short:

  1. A source model: each toolchain, payload and plugin tool has one source of class managed, pinned, custom, program or host, with its origin (file:line, environment variable, global config). One decision record (in resolution.json) drives the output, mcpp why, machine output, the build information and the pack record.
  2. Output: a build whose sources are all managed/pinned prints exactly what it prints today. A non-default source gets one Using ... [class · origin] line; the Finished line summarises them; a failure names the source of the tool that failed. --managed-only / MCPP_MANAGED_ONLY=1 refuses any non-default source.
  3. Payload overrides: [xlings.overrides] in the root manifest (also under [target.'cfg(..)']), MCPP_XLINGS_OVERRIDE_<NS>_<NAME>, and ~/.mcpp/config.toml. An overridden payload is not provisioned; it still takes part in version unification; xpkg_dir answers the override; xpkg_program/xpkg_source are added.
  4. On-request provisioning: a payload entry may state provision = "on-request"; a build program asks with xpkg_request, the engine installs every request in one batch and re-runs only the programs that asked.
  5. Custom toolchains: [toolchain] <key> = { path = ..., prefix, sysroot, family, launcher, tools } (a normalized layout, a path is enough), MCPP_TOOLCHAIN=path:<dir>, a bootstrap key, and { configure = "build.mcpp" }: the root build program, compiled with the bootstrap toolchain, runs once in a toolchain phase before the dependency graph is resolved and states the build toolchain.
  6. Specifications and documentation of the plugin framework (SPEC build-plugins, SPEC-004, docs/20, 23, 30, 31, 50, English and Chinese).

Modules involved

modules/manifest, modules/buildmcpp, src/build/prepare/*, src/build/build_program.cppm, src/build/hostprogram.cppm, src/toolchain/*, src/ui.cppm, src/cli*, src/config.cppm, docs and specs.

Activity

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