Commit c765c8c
* docs(design): a UI framework on Android, iOS and Web, and the plan that lands it (#622)
* wasm32-emscripten names its launcher .js and carries the .wasm as a link output (#622 A5)
- artifact_naming grows an `emscripten` row (triple.cppm): exeSuffix ".js",
lib prefix/ext as ELF's, sharedLibExt empty with the shared-unsupported
marker set. Independent of host naming (Linux/Windows both answer ".js"),
and a "none" OS still falls back to the host answer unchanged.
- LinkIntentFlavor gains Wasm, rendered exactly as Elf (-L, -l); the switch
in flags.cppm has no default arm.
- ninja_backend.cppm declares bin/<name>.wasm as an implicit output of the
same link edge that writes bin/<name>.js, for every Binary/TestBinary link
unit on a Wasm-object-format triple.
- prepare.cppm refuses `kind = "shared"` on a Wasm triple by name, before any
toolchain is resolved (same site/reasoning as the Apple SDK check it sits
beside), naming -sSIDE_MODULE as the unrendered mechanism.
- stage_tree.cppm adds emscripten_stem_family(): the launcher is the
executable, the family is every other <name>.<anything> the link also
wrote, read from the directory rather than a fixed extension list.
pack.cppm gains a wasm packaging path (Plan::targetIsWasm, run_wasm) that
stages the launcher plus the whole stem family, with no dependency-closure
step (an ordinary Emscripten link is one static image).
Verified end to end on this machine's installed emsdk@6.0.9 payload:
`mcpp build/run/pack --target wasm32-emscripten` names bin/app.js +
bin/app.wasm, runs and prints its marker (fixture declares its own
`[target.wasm32-emscripten] runner = ["node"]`), and stages both files under
`--format dir` and `--format tar` with both listed in .stage-manifest. The
`shared` refusal is reached with MCPP_NO_AUTO_INSTALL=1 (no network).
Tests: tests/unit/test_artifact_naming.cpp (new emscripten/none-OS cases),
tests/unit/test_pack_stage_tree.cpp (emscripten_stem_family, positive and
negative), tests/e2e/650_wasm_row_names_its_launcher.sh.
* an application is a kind, and its link form is the row's (#622 A3)
- modules/manifest/src/types.cppm: `Target::Kind` gains `Application`;
`Target::is_program()` answers "is this a program" ({Binary, Application})
so every "is this the program" call site stops asking `kind == Binary`.
- modules/manifest/src/toml.cppm: `kind = "app"` parses; the refusal for an
unrecognized kind lists all four; `main` is required for `app` as for
`bin`; `windows_subsystem`/`windows_entry` accept `is_program()`, not
`Binary` alone; target inference from a bare `src/main.cpp` stays `Binary`
on purpose (a platform fact an author states, never a default guessed).
- modules/manifest/src/xpkg.cppm: a Form B descriptor's target can be `app`.
- modules/toolchain-model/src/triple.cppm: `ApplicationForm` and
`application_form(const Triple&)`, beside `artifact_naming` -- `env ==
"android"` answers `SharedObject`, every other row answers `Executable`.
A manifest carries no predicate for this; the row alone decides.
- src/build/plan.cppm: the link-unit builder maps `Application` to a shared
link when `application_form(targetTriple)` is `SharedObject` and to an
ordinary executable link otherwise; `target_output` grows an
`asSharedObject` parameter so the Android row's `app` links as
`lib<name>.so`; the entry-`main` census and the entry-synthesis gate widen
from `is_program()` so an Android `app`'s `main` still compiles as a
translation unit of the shared library.
- src/build/prepare.cppm: a virtual workspace's default member picks a
program (`is_program()`); the host-tool provisioning site stays literally
`Binary` on purpose -- a build-time tool is exec'd directly and must be
the row's executable form, not whatever an `app` resolves to.
- modules/buildmcpp/src/directives.cppm: `windows-subsystem`/`windows-entry`
directives reach a program (`is_program()`), not only `Binary`.
- src/pack/route.cppm: `"app"` joins the kind-name table; an `Application`
is a program route on every row, exactly as `Binary` is.
- src/build/execute.cppm: `mcpp run` of an `app` whose row form is a shared
library, with no `--format`, is refused by name rather than falling into
the generic "no binary target" message, which would blame the user for a
target that does exist.
- tests/unit/{test_manifest,test_artifact_naming,test_build_directives}.cpp:
parsing, the four-kind refusal, `is_program()`'s exact membership,
`windows_subsystem`/`entry` acceptance, `application_form` per row.
- tests/e2e/652_an_application_is_a_kind.sh (`# requires: elf gcc`): the
host build, `mcpp run`, `mcpp pack`, and the older engine's three-kind
refusal (verified by hand against mcpp 2026.9.12.2, recorded in the
header rather than run).
- tests/e2e/652b_an_application_on_android_is_a_shared_library.sh
(`# requires: android-ndk`, new capability registered in run_all.sh): the
Android row links `lib<name>.so` and no executable, `bin` is unaffected,
and `mcpp run` without `--format` is refused with the exact sentence.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* build programs deploy what they generated, and read the platform floor (#622 A4, A11)
Two build-program surfaces, protocol 11:
- `mcpp::deploy(from, to)` places a file the program produced or selected
beside the artifact at a path relative to the executable -- the build-
program form of `[runtime] deploy` (#615). `from` may be an action's own
absolute declared output, which the manifest key can never name because it
refuses an absolute path. Wire: `mcpp:deploy=<from>\t<to>` (tab-separated,
because an absolute Windows `from` contains `:`). `to` obeys
`deploy_path_problem`, checked before `apply` on both the run path and the
cache-hit path.
- `mcpp::min_platform_version()` / `MCPP_TARGET_MIN_PLATFORM_VERSION` hands a
build program the same platform floor the compiler's `--target` flag and
the fingerprint slot already resolve: `14.0` on macOS, `18.0` on iOS, an
API level on Android, empty elsewhere. `dist-apple` and `dist-apk` read
this instead of restating the value, where it was measured drifting
(`dist/apple.cppm:140-143`).
The deploy directive surfaced a pre-existing gap in the root package's
directive-tail mirror (prepare.cppm): `packages[0]` is snapshotted from the
root manifest BEFORE the root's own build.mcpp runs, so `apply()`'s later
mutations reach `*m` but not `packages[0].manifest` -- the object
`resolve_runtime_contract` (plan.cppm) actually reads. The existing mirror
already repairs this for sources/cflags/cxxflags/includeDirs/ldflags; this
change adds `runtimeConfig.linkIntent.deploy` to that list. Without it a
directive-sourced deploy entry landed in `*m` and produced no copy edge.
Docs are T7's. The two surfaces this task adds: `mcpp::deploy(from, to)` and
`mcpp::min_platform_version()` / `MCPP_TARGET_MIN_PLATFORM_VERSION`.
* frameworks is per target, and platforms names the rows that exist (#622 A2, A7)
* exceptions is the second abi member, and a requirement can sit on the target axis (#622 A1, A6)
* mcpp run --format hands the distributable to the runner (#622 A10)
`mcpp run --format <name>` is `mcpp pack --format <name>` -- the two
prepares, the build, the staging, the provider's action -- followed by
the ordinary run, with the artifact the pack pipeline reported as the
operand. Runner resolution is unchanged (project runner, then a
dependency's, then the payload descriptor's); `--format` with
`--no-runner` is refused, and an unknown format is refused by the pack
pipeline's own message naming the available set.
`build_and_pack` now returns `PackOutcome{rc, artifacts}` instead of a
bare exit code, so the artifact(s) it reported travel to the caller
instead of only being printed; `mcpp pack` itself only ever needed the
exit code (cmd_publish.cppm). The runner-resolution + exec tail of
`build_run_target` is factored into `run_artifact_via_runner`, shared
between the ordinary link-output run and the `--format` run.
Second half of #622 A3: the pack pipeline's program-target selection
asks `Target::is_program()` rather than `LinkUnit::Binary` alone, so an
`app` whose row links it as a shared object (Android) is still found as
the program target; `make_plan`/`Plan` carry that fact
(`programIsSharedObject`), and `pack::run` stages such a file under
`lib/`, as the closure stages any shared object, without attempting a
dependency closure walk on an object this host cannot execute at all.
Tests: new tests/e2e/656_run_hands_the_distributable_to_the_runner.sh;
tests/e2e/652b_an_application_on_android_is_a_shared_library.sh
extended with the pack + MCPP_TARGET_MIN_PLATFORM_VERSION assertions.
* docs(design): the sandbox verification script for #622
* docs: the keys, the row and the directive of #622
* chore: bump version to 2026.9.12.3
* a build program under a target row's pin resolves the host's compiler, not the row's (#622)
* changelog: the build program's host compiler under a row's pin
* e2e 67: the platform vocabulary is asserted on the warning's absence, not on --strict
* the dlopen-surface check counts an application on a library-form row as a program (#622 A3)
---------
Co-authored-by: speak-agent <248744407+speak-agent@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
1 parent 85df514 commit c765c8c
58 files changed
Lines changed: 5635 additions & 318 deletions
File tree
- .agents/docs
- docs
- zh
- modules
- buildmcpp/src
- manifest/src
- toolchain-model/src
- versioning/src
- src
- build
- cli
- pack
- tests
- e2e
- unit
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 1001 additions & 0 deletions
Large diffs are not rendered by default.
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
18 | 18 | | |
19 | 19 | | |
20 | 20 | | |
21 | | - | |
| 21 | + | |
22 | 22 | | |
23 | 23 | | |
24 | 24 | | |
| |||
47 | 47 | | |
48 | 48 | | |
49 | 49 | | |
| 50 | + | |
| 51 | + | |
50 | 52 | | |
51 | 53 | | |
52 | 54 | | |
| |||
61 | 63 | | |
62 | 64 | | |
63 | 65 | | |
| 66 | + | |
| 67 | + | |
64 | 68 | | |
65 | 69 | | |
66 | 70 | | |
| |||
0 commit comments