mcpp emit build-database, program probes as argument vectors, and xlings 2026.9.14.1 (2026.9.15.1, #636) - #639
Merged
Merged
Conversation
…634 ledger closed Version group 2 moves to 2026.9.14.3, released from 9b6a118 and named `latest` by the published xim index artifact `xim-index-ed04041`. The #634 implementation plan and the triage record are marked landed. The ledger closes every row with a reading (E1-E24 in mcpp#637, E25 in mcpp#638, P1-P9 in mcpp-plugins#24, I1 in mcpplibs/mcpp-index#426, R1-R4, V1-V4), and §9 records what landed, the sandbox readings on 2026.9.14.2, 2026.9.14.3 and the 2026.9.14.1 control, the ecosystem review, and two observations this work did not change.
…ay to the latest xlings The record of the analysis, the plan and its self-review: xlings stages a hookless package from the shared download directory; a POSIX redirect in the vendored-xlings probe reaches cmd.exe on Windows; and mcpp emits an S1 build database from the plan without writing into the project.
…in/sh string The vendored-xlings version probe ran `<xlings> --version 2>/dev/null` as a command string. On Windows every command string reaches cmd.exe, which cannot open /dev/null: it printed "The system cannot find the path specified." in every command after the first, did not run xlings, and returned an empty version, so a Windows home never replaced a vendored xlings older than the pin. mcpp.platform.process gains capture_stdout: the program runs directly, its standard output is captured, its standard error is discarded and its standard input is empty; on Windows the redirect names cmd.exe's own null device. The xlings probe and the four other program probes that carried POSIX grammar on a path Windows reaches use it: the clean link specs, the libstdc++ fallback probe, the freestanding size report and the publish digest. Tests: capture_stdout unit tests (stdout only, exit code, empty stdin, environment, empty output for a missing program, the Windows command line); a version-probe unit test that runs a .bat through the real launcher on Windows; e2e 687 (no path error on the second command; an older vendored binary is replaced).
…itten into nothing (#636) `mcpp emit build-database` plans as `mcpp build --configure-only` plans, with the same selectors, and prints the plan as an S1 build database (C++ Build Database: IDE Profile 0.2.0, a profile of WG21 P2977R2) without writing into the project. `--spec compile-commands` prints compile_commands.json entries instead; `--format json` wraps the document in the mcpp.build-database envelope; `-o <file>` writes it atomically. docs/specs/build-database.md (SPEC-005) states the rules. The document is S1 level 2: one set per package plus <package>:test and mcpp:std; visible-sets lists every other set, because the engine resolves imports over one module graph; each unit's arguments come from the record the compile database renders; ide.role is the declaration form the scanner read. Five engine changes make the no-write planning exact: - BuildOverrides::work_dir had two writes that ignored it (the multi-version mangling stage, and the root package's generated_files, which are now compared rather than written under plan_only); - the std module is described without being compiled (describe_std_module, the derivation ensure_built builds from); - the std units' commands are recovered from the commands mcpp runs, so the std cache identity does not change; - compile_commands and the build database render one UnitInvocation record; - the scanner records the module declaration form (ModuleDeclaration). mcpp.lock is read from the project and never written back; a difference is the warning MCPP_LOCK_WOULD_CHANGE. Planning narration goes to stderr through a descriptor-level redirect. A failure envelope omits data. Tests: BuildDatabase.* unit tests drive the real gcc and clang std command builders; Scanner.DeclarationFormIsRecordedAsRead; CompileCommandsEmit.UnitInvocationsAreTheCompileDatabaseArguments; WireGolden.NullDataIsOmitted; e2e 688 validates the output against the vendored S1 schema and uses --configure-only as the control leg for the no-write criterion.
A store package's build program may declare inputs, and they were listed in `watch`; its files are fixed by the version its manifest and lock name, so only an editable package's declared inputs are inputs that can change. Found by running the command over lsp-mcpp, whose openkal-musl dependency declares its own mcpp.toml.
Drives msvc::std_module_build_commands and std_compat_build_commands, the command shape a Windows host with msvc@system runs (cd /d, a quoted cl.exe, /ifcOutput, /Fo:, 2>&1), through recover_invocation.
A \x1f separator followed by `f`, `c` or `a` (`\x1ffeatures`, `\x1fcap`, `\x1faccel`) is one longer hex escape; clang refuses it as out of range and every clang host failed to build the branch. GCC accepted it, which is why the Linux build did not see it. The sandbox verification script for the release is added alongside.
A target's entry source that no `sources` glob matched (a discovered test, a `main` outside the globs) had its imports read from line-leading `import` alone, in make_plan and again in the standard library check before planning. An import inside a comment or a raw string was therefore planned as one. Validating the lsp-mcpp repository's own build database against S1 found it: its scanner test was planned as importing three modules no source provides. scan_entry_file reads such a file with scan_file. The scanner's refusals (an import inside `#if`, a header unit, an extension without a role) were never applied on this path and are not applied now: a file it refuses yields the line-leading imports of its code, comments and raw strings removed, with the declaration form Unknown. Both readers now call it, so they cannot disagree about `import std`. Refs #636
The S1 SHOULD fields the lsp-mcpp validator reads, with values the plan determines: - `baseline-arguments` and `local-arguments`. A unit's arguments are its driver, the set's baseline, its local arguments and its own trailing `-c <source> -o <object>`, whose operands name the unit's source and object from its work directory. The baseline is the longest prefix every unit of the set shares; a prefix keeps argument order, which decides include search and macro definitions. - `private` is false: every module is visible to every set. - `config-files` lists what the driver reads without being named: the clang `<driver>.cfg` of resolve_clang_driver unless the units pass `--no-default-config`, and GCC's `lib/gcc/<triple>/<version>/specs` (or the major version) beside the driver. e2e 688 gains J (the decomposition, private, config-files) and K (the discovered test's imports inside a comment and a raw string are not `requires`); its F mapping compares paths with one separator, and the fixture's main.cpp is well-formed. SPEC-005 R3.2a, R3.6, R3.8 and R3.9a state the rules. Refs #636
The macOS runner's inherited configuration names its ~/.xlings shim as the xlings binary, so nothing was vendored and the precondition failed before either criterion ran. The home now uses its own configuration, whose binary is the vendored one. Refs #636
mcpp.toml and MCPP_VERSION move together; the bootstrap pin stays at the released 2026.9.14.3. The changelog names the release on the three entries that land in it, and records the S1 fields and the entry-source scan. Refs #636
kXlingsVersion and every pin check_version_pins.sh names move to the xlings release in which a package without an install hook receives its own archive (openxlings/xlings#596). The constant's comment records it as the third reason for the floor. Refs #636
What landed in each repository, the five findings made while implementing, and the measurements taken so far, including lsp-mcpp's validator and its conformance runner against this mcpp. Refs #636
… project Section D reads a clean store first, then requires the finding's label and the seeded lock file's name, and after --fix requires the reinstalled payload: no seeded file and */mcpp.toml present. Section C2 emits the build database of section B's project: the dependency's set, no watched store path, the S1 SHOULD fields, and an unchanged tree with target/ present. Sections that need python3 say so when it is missing. Refs #636
prepare_build ran `g++ -dumpspecs` to write mcpp-clean-link.specs under plan_only. The file is read only by the link line, so the planning pass neither needs it nor should run the driver for it, and the compile arguments are the same without it (e2e 688 F still compares them with configure-only's). Found by an independent review of #639. e2e 688 criterion L measures what SPEC-005 R2.2 states: the fresh work directory holds the resolution record and no object, BMI or link specs, and a home whose build cache is empty stays without objects or BMIs while its document lists the std unit. Its control leg runs configure-only on a copy in the same home and sees the std module compiled. R2.2 now says what is true: nothing is compiled, and the toolchain is still queried as for `mcpp build`. Refs #636
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This one pull request carries every mcpp change in the design record
.agents/docs/2026-09-14-636-build-database-and-the-latest-xlings.md(analysis, plan, self-review). It releases as 2026.9.15.1.C.
mcpp emit build-database(#636). The command prints the plan thatmcpp build --configure-onlycomputes as an S1 build database and writes nothing into the project. S1 is "C++ Build Database: IDE Profile" 0.2.0, a profile of WG21 P2977R2.--spec compile-commandsprintscompile_commands.jsonentries instead.--format jsonwraps the document in themcpp.build-databaseenvelope.<package>:testandmcpp:std;visible-setslists every other set;baseline-argumentsis the longest prefix shared within a set, andlocal-argumentsis each unit's remainder;privateis false;config-fileslists what the driver reads without being named on the command line.docs/specs/build-database.md) states the rules. docs/50 and docs/01, with their translations, document the command.The command depends on these engine changes:
BuildOverrides::work_dirleaks are fixed.describe_std_moduledescribes the std module without compiling it. The std cache identity does not change.UnitInvocationrecord feeds both databases.ModuleDeclaration.plan_onlyplanning readsmcpp.lockfrom the project and never writes it back, and writes no link-only input: the GCC-dumpspecsprobe formcpp-clean-link.specsis skipped. An independent review of this PR found that call.sourcesglob matched is now read by the scanner (scan_entry_file). Before, it was read from line-leadingimportalone, so an import inside a comment or a raw string was planned as a real import. Validating lsp-mcpp's own database against S1 found this.B. Windows no longer prints "The system cannot find the path specified."
<xlings> --version 2>/dev/nullthrough cmd.exe, which cannot open/dev/null.mcpp build|test的时候提示The system cannot find the path specified.openxlings/xlings#543).capture_stdoutnow runs a program probe as an argument vector, and five probes use it.A (via the pin).
kXlingsVersion, and every pincheck_version_pins.shnames, move to xlings 2026.9.14.1. In that release a package without an install hook receives its own archive instead of the shared download directory (openxlings/xlings#596), andxlings self doctor --fixrepairs a swept store.Also carried: the #634 ledger closure and the bootstrap pin commit this branch started with.
Refs #636, openxlings/xlings#543.
Test plan
mcpp testpasses locally (Linux), including the new tests:BuildDatabase.*CaptureStdout.*XlingsVersionPin.ProbeReadsStandardOutputThroughTheLauncherScanner.DeclarationFormIsRecordedAsReadScanner.AnEntrySourceIsReadByTheScannerScanner.AnEntrySourceTheScannerRefusesKeepsItsImportsCompileCommandsEmit.UnitInvocationsAreTheCompileDatabaseArgumentsWireGolden.NullDataIsOmittedprivateandconfig-files;--configure-onlyin the same home compiles std (the control).mcpp testand entry mains pass locally.specs/tools/validate.py) pass on three databases: a GCC project, an LLVM project, and the lsp-mcpp repository (11 sets, package-provided std).mcpp-emit: 12/12mcpp-emit-package-std: 13/13MCPP_BUILD_DATABASE_PLAN_FAILED; the repair makes it fresh)