Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
93e59b5
0.19.0: one resolver for where a member's tool comes from, payloads i…
speak-agent Oct 1, 2026
1fc2c37
docs: the plan records what was built, and the two portability findin…
speak-agent Oct 1, 2026
e042567
ci: the release every job fetches is its own variable, so a change ca…
speak-agent Oct 1, 2026
5d92352
testing: a case sees only the payloads it states, and one CI criterio…
speak-agent Oct 1, 2026
e67e6db
testing: the environment array is reached the way each platform offer…
speak-agent Oct 1, 2026
a694d16
docs: the plan record carries the lab result and the ecosystem-level …
speak-agent Oct 1, 2026
11cf1cf
docs: two usage examples name the current version, and dist-apk says …
speak-agent Oct 1, 2026
e48c481
rules-sycl: the compiler and the root its libraries sit under are two…
speak-agent Oct 1, 2026
358841d
docs: the plan record carries the sycl finding and why the local roun…
speak-agent Oct 1, 2026
789a0bb
docs: the toolchain builders listed are the ones the module has
speak-agent Oct 1, 2026
8a7d604
tool: a stated program path resolves whichever executable suffix the …
speak-agent Oct 1, 2026
be3dfbd
manifest: the test kit's comment sits above the test kit again
speak-agent Oct 1, 2026
10a8662
docs: the plan record carries the linker and executable-suffix findings
speak-agent Oct 1, 2026
87c7f9d
docs: the plan record carries the framework lab's results and the mea…
speak-agent Oct 1, 2026
141f416
docs: the plan record carries the toolchain lab's before-and-after re…
speak-agent Oct 1, 2026
5eb083b
rules-qt: warn() walks the message by index, because gcc 16 refuses t…
speak-agent Oct 1, 2026
40a5d21
docs: the plan record carries the gcc 16 inlining finding
speak-agent Oct 1, 2026
e00da73
ci: the bootstrap pin is the released 2026.10.1.3, which is this coll…
speak-agent Oct 1, 2026
eb29dc5
Merge main: the qrc resource-input fix (#42) lands before this release
speak-agent Oct 1, 2026
bbf0f50
docs: a project that names its own Qt SDK states where the payload co…
speak-agent Oct 1, 2026
14ff15c
docs: where a tool comes from, as scenarios for authors, designers an…
speak-agent Oct 1, 2026
96b856b
docs: the plan record carries the reference page and why it exists
speak-agent Oct 1, 2026
1911600
docs: the final self-review, with the readings this delivery actually…
speak-agent Oct 1, 2026
7d22dc0
docs: the four ways a build program names its own tool, compiled befo…
speak-agent Oct 1, 2026
d1a3cf5
docs: replacing the default tool from build.mcpp is its own chapter
speak-agent Oct 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
314 changes: 314 additions & 0 deletions .agents/docs/2026-10-01-ecosystem-build-plugin-framework-plan.md

Large diffs are not rendered by default.

92 changes: 91 additions & 1 deletion .github/scripts/check-deps-and-qt.sh
Original file line number Diff line number Diff line change
Expand Up @@ -576,7 +576,97 @@ vcpkg_make_port() {
echo "ok: a make-based port builds with the managed toolset first on the kept PATH"
}

# 0.19.0 (mcpp#755): a tool the build program names is used, and the payload the
# member declares `provision = "on-request"` is NOT asked for.
#
# THE CRITERION IS THE ENGINE'S OWN RECORD, NOT THE STORE. A runner may already
# hold `xim:cmake` -- every other case here installs it -- so "nothing was
# downloaded" cannot be read from the store, and a clean `MCPP_HOME` would cost
# a download per case. `resolution.json` states what each payload's source was
# and whether this build asked for it, which is the decision itself. The pair is
# the criterion: the same project asks for the payload when nothing names a
# tool, and does not when the build program names one.
tool_sources() {
cd "$ROOT/tests/cmake-consumer"
local cmake; cmake=$(command -v cmake || true)
[ -n "$cmake" ] || { echo "SKIP: no cmake on this host to name"; return 0; }

# `considered` of the payload entry, and the class of each subject.
record() {
python3 - <<'PYEOF'
import glob, json, sys
paths = glob.glob("target/*/*/resolution.json")
if not paths:
print("NO-RECORD"); raise SystemExit(0)
doc = json.load(open(sorted(paths)[0]))
for d in doc.get("sources", []):
print(d["subject"], d["class"], "|", "; ".join(d.get("considered", [])), sep="\t")
PYEOF
}

cp build.mcpp build.mcpp.bak
restore() { mv -f build.mcpp.bak build.mcpp 2>/dev/null || true; }
trap restore EXIT

# The control: nothing names a tool, so the member asks for the payload.
rm -rf target
NO_COLOR=1 "$MCPP" build >/dev/null 2>&1 || fail "the control build failed"
record | grep -q "payload:xim:cmake.*installed on request" \
|| fail "the control did not ask for xim:cmake: $(record)"

# The build program names the host's cmake, through the member's option.
python3 - "$cmake" <<'PYEOF'
import pathlib, sys
p = pathlib.Path("build.mcpp")
t = p.read_text()
marker = " o.shared = true;"
assert marker in t, t
p.write_text(t.replace(marker, marker + '\n o.cmake = "%s";' % sys.argv[1].replace("\\", "/"), 1))
PYEOF
rm -rf target
local out
out=$(MCPP_NO_AUTO_INSTALL=1 NO_COLOR=1 "$MCPP" build 2>&1) \
|| fail "a named cmake still needed the payload: $out"
case "$out" in
*"Using cmake (mcpp.deps.cmake)"*"[program · build.mcpp:"*) ;;
*) fail "the build did not report the tool's source: $out" ;;
esac
case "$out" in
*"program: cmake (mcpp.deps.cmake)"*) ;;
*) fail "the Finished line did not summarise the source: $out" ;;
esac
record | grep -q "payload:xim:cmake.*not requested by this build" \
|| fail "the payload was asked for although the program named a cmake: $(record)"
MCPP_NO_AUTO_INSTALL=1 "$MCPP" run | grep -q '^cmake-consumer: greet says 42$' \
|| fail "the program built with the named cmake does not run"

# The same statement as an engine override, with the payload untouched.
restore
rm -rf target
out=$(MCPP_XLINGS_OVERRIDE_XIM_CMAKE="$cmake" MCPP_NO_AUTO_INSTALL=1 NO_COLOR=1 "$MCPP" build 2>&1) \
|| fail "an override still needed the payload: $out"
case "$out" in
*"Using xim:cmake"*"[custom · env MCPP_XLINGS_OVERRIDE_XIM_CMAKE]"*) ;;
*) fail "the build did not report the override: $out" ;;
esac
record | grep -q "payload:xim:cmake.*custom.*overridden" \
|| fail "the record does not state the override: $(record)"

# `--managed-only` refuses the same build, naming the payload.
rm -rf target
out=$(MCPP_XLINGS_OVERRIDE_XIM_CMAKE="$cmake" MCPP_NO_AUTO_INSTALL=1 NO_COLOR=1 \
"$MCPP" build --managed-only 2>&1 || true)
case "$out" in
*managed-only*xim:cmake*) ;;
*) fail "--managed-only did not refuse the override: $out" ;;
esac
trap - EXIT
rm -rf target
echo "OK: a named tool is used, the payload is not asked for, and both are reported"
}

case "${1:-}" in
tool-sources) tool_sources ;;
vcpkg-consumer) vcpkg_consumer ;;
vcpkg-libcxx) vcpkg_libcxx ;;
archive-consumer) archive_consumer ;;
Expand All @@ -592,5 +682,5 @@ case "${1:-}" in
vcpkg-managed) vcpkg_managed ;;
vcpkg-msbuild-refused) vcpkg_msbuild_refused ;;
vcpkg-make-port) vcpkg_make_port ;;
*) echo "usage: $0 vcpkg-consumer|vcpkg-libcxx|archive-consumer|vcpkg-workspace|cmake-consumer|cmake-cache|qt-consumer|qt-widgets-consumer|qt-sdk-consumer|qt-import-only|plugin-logic|vcpkg-crt|vcpkg-managed|vcpkg-msbuild-refused|vcpkg-make-port"; exit 2 ;;
*) echo "usage: $0 vcpkg-consumer|vcpkg-libcxx|archive-consumer|vcpkg-workspace|cmake-consumer|cmake-cache|qt-consumer|qt-widgets-consumer|qt-sdk-consumer|qt-import-only|plugin-logic|tool-sources|vcpkg-crt|vcpkg-managed|vcpkg-msbuild-refused|vcpkg-make-port"; exit 2 ;;
esac
66 changes: 50 additions & 16 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ on:
workflow_dispatch:
inputs:
mcpp_source_ref:
description: "A branch or tag of mcpp-community/mcpp to build and run in place of the release MCPP_VERSION names"
description: "A branch or tag of mcpp-community/mcpp to build and run in place of the release MCPP_BOOTSTRAP names"
required: false
default: ""

Expand Down Expand Up @@ -60,7 +60,25 @@ env:
# 2026.9.28.3 IS WHAT 0.17.0 NEEDS, and the package floor states it: the
# build information `mcpp.plugins.toolset` reads, `mcpp::report`, and one
# placement edge for many files (mcpp#734).
MCPP_VERSION: 2026.9.28.3
#
# 2026.10.1.3 IS WHAT 0.19.0 NEEDS (mcpp#755): protocol 15 states where each
# tool and payload comes from -- `xpkg_source`, `xpkg_program`,
# `xpkg_request`, `mcpp::decision`, `mcpp::toolchain`, `mcpp::phase` -- and
# it is the release that honours the `provision = "on-request"` entries this
# collection now declares, so a consumer that names its own tool downloads
# nothing. An older engine refuses the manifest at the package floor.
MCPP_VERSION: 2026.10.1.3
# THE RELEASE EVERY JOB FETCHES, WHICH IS NOT ALWAYS THE ONE UNDER TEST.
#
# `MCPP_VERSION` states the engine this collection needs -- the package floor
# (`[package] mcpp`) is the same statement -- and a release of it may not exist
# yet: 0.19.0 was written against mcpp#755 and pinned 2026.10.1.3 before that
# release was published. Every fetch therefore names this variable instead, and
# the dispatch input `mcpp_source_ref` builds the engine under review with it.
#
# It moves to `MCPP_VERSION` once that release exists, so the ordinary path
# runs the engine this collection states.
MCPP_BOOTSTRAP: 2026.10.1.3
# AN ENGINE BUILT FROM SOURCE, WHEN A DISPATCH NAMES ONE.
#
# Empty on every push and pull request, so the steps run the release above.
Expand Down Expand Up @@ -107,16 +125,16 @@ jobs:
uses: actions/cache@v4
with:
path: ~/.mcpp
key: mcpp-sandbox-v2-${{ runner.os }}-${{ runner.arch }}-${{ env.MCPP_VERSION }}-${{ hashFiles('tests/*/mcpp.toml') }}
key: mcpp-sandbox-v2-${{ runner.os }}-${{ runner.arch }}-${{ env.MCPP_BOOTSTRAP }}-${{ hashFiles('tests/*/mcpp.toml') }}
restore-keys: |
mcpp-sandbox-v2-${{ runner.os }}-${{ runner.arch }}-${{ env.MCPP_VERSION }}-
mcpp-sandbox-v2-${{ runner.os }}-${{ runner.arch }}-${{ env.MCPP_BOOTSTRAP }}-

- name: Fetch the released mcpp
run: |
curl -L -fsS --retry 3 --retry-all-errors -o mcpp.tar.gz \
"https://github.com/mcpp-community/mcpp/releases/download/v${MCPP_VERSION}/mcpp-${MCPP_VERSION}-linux-x86_64.tar.gz"
"https://github.com/mcpp-community/mcpp/releases/download/v${MCPP_BOOTSTRAP}/mcpp-${MCPP_BOOTSTRAP}-linux-x86_64.tar.gz"
tar -xzf mcpp.tar.gz
MCPP="$PWD/mcpp-${MCPP_VERSION}-linux-x86_64/bin/mcpp"
MCPP="$PWD/mcpp-${MCPP_BOOTSTRAP}-linux-x86_64/bin/mcpp"
"$MCPP" --version
# THE BUNDLED xlings, NAMED EXPLICITLY BECAUSE `MCPP_HOME` IS PINNED.
#
Expand All @@ -126,7 +144,7 @@ jobs:
# with `xlings binary not found` -- measured. The override is needed
# only for that first call: mcpp copies the binary into the pinned
# home and answers from there afterwards.
export MCPP_VENDORED_XLINGS="$PWD/mcpp-${MCPP_VERSION}-linux-x86_64/registry/bin/xlings"
export MCPP_VENDORED_XLINGS="$PWD/mcpp-${MCPP_BOOTSTRAP}-linux-x86_64/registry/bin/xlings"
"$MCPP" self config --mirror GLOBAL
echo "MCPP=$MCPP" >> "$GITHUB_ENV"
echo "MCPP_VENDORED_XLINGS=$MCPP_VENDORED_XLINGS" >> "$GITHUB_ENV"
Expand Down Expand Up @@ -728,7 +746,11 @@ jobs:
grep -v '^[[:space:]]*#' mcpp.toml | grep -n 'host-module'
exit 1
fi
"$MCPP" build | tee build.log
# `2>&1`, BECAUSE THE LINE THIS ASSERTS ON IS NARRATION. mcpp writes
# every status line to standard error from 2026.10.1.1 (the output
# streams design), so a step that captures stdout alone reads an empty
# log and reports that the rule did not run while it did.
"$MCPP" build 2>&1 | tee build.log
grep -q 'Rules mcpp.rules.spirv' build.log \
|| { echo "FAIL: the build did not report which rule it ran"; exit 1; }
"$MCPP" run | tee run.log
Expand Down Expand Up @@ -1690,6 +1712,12 @@ jobs:
- name: deps-cmake builds a CMake subproject as an action and links it
run: bash .github/scripts/check-deps-and-qt.sh cmake-consumer

# 0.19.0 (mcpp#755): a tool the build program names is used and the
# payload is not asked for; an override says the same and is reported;
# `--managed-only` refuses both.
- name: a tool the build program names is used, and its payload is not asked for
run: bash .github/scripts/check-deps-and-qt.sh tool-sources

# 0.18.0: an installation is kept under a key with no path of the
# machine, and taken by a build without target/, by a checkout at another
# path; an edit, other CFLAGS and an installation that names its own
Expand Down Expand Up @@ -1783,20 +1811,20 @@ jobs:
uses: actions/cache@v4
with:
path: ~/.mcpp
key: mcpp-sandbox-v2-${{ runner.os }}-${{ runner.arch }}-${{ env.MCPP_VERSION }}-${{ hashFiles('tests/spirv-consumer/mcpp.toml') }}
key: mcpp-sandbox-v2-${{ runner.os }}-${{ runner.arch }}-${{ env.MCPP_BOOTSTRAP }}-${{ hashFiles('tests/spirv-consumer/mcpp.toml') }}
restore-keys: |
mcpp-sandbox-v2-${{ runner.os }}-${{ runner.arch }}-${{ env.MCPP_VERSION }}-
mcpp-sandbox-v2-${{ runner.os }}-${{ runner.arch }}-${{ env.MCPP_BOOTSTRAP }}-

- name: Fetch the released mcpp
run: |
set -e
curl -L -fsS --retry 3 --retry-all-errors -o mcpp.pkg \
"https://github.com/mcpp-community/mcpp/releases/download/v${MCPP_VERSION}/mcpp-${MCPP_VERSION}-${{ matrix.asset }}"
"https://github.com/mcpp-community/mcpp/releases/download/v${MCPP_BOOTSTRAP}/mcpp-${MCPP_BOOTSTRAP}-${{ matrix.asset }}"
case "${{ matrix.asset }}" in
*.zip) unzip -q mcpp.pkg ;;
*) tar -xzf mcpp.pkg ;;
esac
dir="mcpp-${MCPP_VERSION}-${{ matrix.dir-suffix }}"
dir="mcpp-${MCPP_BOOTSTRAP}-${{ matrix.dir-suffix }}"
MCPP="$PWD/$dir/bin/mcpp"
"$MCPP" --version
# The bundled xlings, named explicitly because MCPP_HOME is pinned
Expand Down Expand Up @@ -2388,6 +2416,12 @@ jobs:
- name: deps-cmake builds a CMake subproject as an action and links it
run: bash .github/scripts/check-deps-and-qt.sh cmake-consumer

# 0.19.0 (mcpp#755): a tool the build program names is used and the
# payload is not asked for; an override says the same and is reported;
# `--managed-only` refuses both.
- name: a tool the build program names is used, and its payload is not asked for
run: bash .github/scripts/check-deps-and-qt.sh tool-sources

# 0.18.0: an installation is kept under a key with no path of the
# machine, and taken by a build without target/, by a checkout at another
# path; an edit, other CFLAGS and an installation that names its own
Expand Down Expand Up @@ -2454,20 +2488,20 @@ jobs:
uses: actions/cache@v4
with:
path: ~/.mcpp
key: mcpp-sandbox-v2-${{ runner.os }}-${{ runner.arch }}-${{ env.MCPP_VERSION }}-${{ hashFiles('tests/vcpkg-consumer/mcpp.toml') }}
key: mcpp-sandbox-v2-${{ runner.os }}-${{ runner.arch }}-${{ env.MCPP_BOOTSTRAP }}-${{ hashFiles('tests/vcpkg-consumer/mcpp.toml') }}
restore-keys: |
mcpp-sandbox-v2-${{ runner.os }}-${{ runner.arch }}-${{ env.MCPP_VERSION }}-
mcpp-sandbox-v2-${{ runner.os }}-${{ runner.arch }}-${{ env.MCPP_BOOTSTRAP }}-

- name: Fetch the released mcpp
run: |
set -e
curl -L -fsS --retry 3 --retry-all-errors -o mcpp.pkg \
"https://github.com/mcpp-community/mcpp/releases/download/v${MCPP_VERSION}/mcpp-${MCPP_VERSION}-windows-x86_64.zip"
"https://github.com/mcpp-community/mcpp/releases/download/v${MCPP_BOOTSTRAP}/mcpp-${MCPP_BOOTSTRAP}-windows-x86_64.zip"
case "windows-x86_64.zip" in
*.zip) unzip -q mcpp.pkg ;;
*) tar -xzf mcpp.pkg ;;
esac
dir="mcpp-${MCPP_VERSION}-windows-x86_64"
dir="mcpp-${MCPP_BOOTSTRAP}-windows-x86_64"
MCPP="$PWD/$dir/bin/mcpp"
"$MCPP" --version
# The bundled xlings, named explicitly because MCPP_HOME is pinned
Expand Down
Loading
Loading