Skip to content

mcpp emit build-database, program probes as argument vectors, and xlings 2026.9.14.1 (2026.9.15.1, #636) - #639

Merged
Sunrisepeak merged 16 commits into
mainfrom
ci/634-close-and-bootstrap-pin
Sep 14, 2026
Merged

Sunrisepeak merged 16 commits into
mainfrom
ci/634-close-and-bootstrap-pin

Conversation

@Sunrisepeak

@Sunrisepeak Sunrisepeak commented Sep 14, 2026

Copy link
Copy Markdown
Member

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 that mcpp build --configure-only computes 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-commands prints compile_commands.json entries instead.
  • --format json wraps the document in the mcpp.build-database envelope.
  • The document is S1 level 2:
    • one set per package, plus <package>:test and mcpp:std;
    • visible-sets lists every other set;
    • roles come from the scanner's declaration form;
    • arguments come from the same record the compile database is rendered from;
    • baseline-arguments is the longest prefix shared within a set, and local-arguments is each unit's remainder;
    • private is false;
    • config-files lists what the driver reads without being named on the command line.
  • SPEC-005 (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:

  • The BuildOverrides::work_dir leaks are fixed.
  • describe_std_module describes the std module without compiling it. The std cache identity does not change.
  • One UnitInvocation record feeds both databases.
  • The scanner records ModuleDeclaration.
  • plan_only planning reads mcpp.lock from the project and never writes it back, and writes no link-only input: the GCC -dumpspecs probe for mcpp-clean-link.specs is skipped. An independent review of this PR found that call.
  • A target entry source that no sources glob matched is now read by the scanner (scan_entry_file). Before, it was read from line-leading import alone, 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."

A (via the pin). kXlingsVersion, and every pin check_version_pins.sh names, 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), and xlings self doctor --fix repairs 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 test passes locally (Linux), including the new tests:
    • BuildDatabase.*
    • CaptureStdout.*
    • XlingsVersionPin.ProbeReadsStandardOutputThroughTheLauncher
    • Scanner.DeclarationFormIsRecordedAsRead
    • Scanner.AnEntrySourceIsReadByTheScanner
    • Scanner.AnEntrySourceTheScannerRefusesKeepsItsImports
    • CompileCommandsEmit.UnitInvocationsAreTheCompileDatabaseArguments
    • WireGolden.NullDataIsOmitted
  • e2e 687, the argument-vector probe, passes. Its discriminating leg ran green on Windows CI.
  • e2e 688, the build database, passes on Linux, macOS and Windows. It checks:
    • the envelope;
    • no writes, with a configure-only control leg;
    • validation against the vendored S1 schema;
    • roles and sets;
    • the std unit;
    • compile-commands parity;
    • usage errors;
    • watch and fingerprint;
    • the baseline/local decomposition, private and config-files;
    • the discovered test's imports;
    • no object, BMI or link specs in the work directory, and a cold std cache that stays cold while --configure-only in the same home compiles std (the control).
  • 60 further e2e tests that exercise mcpp test and entry mains pass locally.
  • lsp-mcpp's S1 semantic and mcpp-contract checks (specs/tools/validate.py) pass on three databases: a GCC project, an LLVM project, and the lsp-mcpp repository (11 sets, package-provided std).
  • lsp-mcpp's conformance runner passes against this mcpp instead of its mock:
    • mcpp-emit: 12/12
    • mcpp-emit-package-std: 13/13
    • a real-manifest watch scenario: 10/10 (edit reloads; a broken manifest leaves the model stale with MCPP_BUILD_DATABASE_PLAN_FAILED; the repair makes it fresh)
  • Docs structure and style, modules wiring, narrow conversions and version pins checks pass.
  • CI on Linux, macOS and Windows at the head commit.

…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.
@Sunrisepeak Sunrisepeak changed the title ci: workspace mcpp bootstrap pin -> 2026.9.14.3; the #634 records are closed mcpp emit build-database, program probes as argument vectors, and the latest xlings (#636) Sep 14, 2026
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
@Sunrisepeak Sunrisepeak changed the title mcpp emit build-database, program probes as argument vectors, and the latest xlings (#636) mcpp emit build-database, program probes as argument vectors, and xlings 2026.9.14.1 (2026.9.15.1, #636) Sep 14, 2026
@Sunrisepeak
Sunrisepeak merged commit 87d4ff0 into main Sep 14, 2026
41 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants