feat(targets): per-target entry-scoped flags + required_features; test --profile (#131)#132
Merged
Merged
Conversation
…t --profile; 0.0.55 (#131) Resolve issue #131 without violating the compile-once model. Configuration that must reach shared code stays at the package/feature boundary; a target only carries flags private to its own exclusive entry. - [targets.<name>]: new `defines` / `cxxflags` / `cflags`, applied ONLY to that target's exclusive entry source (its `main`) — never to shared module/impl objects (compile-once). Fits flags that affect just a binary's own entry (e.g. a per-test contract evaluation semantic). - [targets.<name>]: new `required_features` gate — a target is emitted only when all listed features are active; otherwise silently skipped. Pure build-selection, runs before the modgraph so gated-out targets cost nothing. - Unsupported keys under [targets.<name>] now warn (error under --strict) and point at workspace / features / profile, instead of being dropped silently (the historic footgun behind #131). - `mcpp test` now accepts --profile / --features / --strict, so the code-under-test plus test binaries build under the chosen whole-build mode (sanitizers, contract semantics, ...). - docs/05-mcpp-toml.md (+ zh): document the new keys and a "where build configuration goes" decision guide. Design: .agents/docs/2026-06-18-... Tests: tests/unit/test_manifest.cpp covers parsing + unsupported-key warning + std-flag guard; e2e 57 (per-target flags, shared source stays neutral), 58 (required_features gate), 59 (mcpp test --profile reaches code-under-test).
…xxflag on own entry) Mirrors the issue's `[targets.test_contracts] cxxflags=[...]` shape: a single bin target whose per-target codegen flag must affect only its own `main`, not shared code. Uses -fno-exceptions (preprocessor-observable via __EXCEPTIONS) as a portable stand-in for -fcontract-evaluation-semantic=observe, which needs a contracts-enabled toolchain not guaranteed across the Linux/macOS/Windows CI matrix. Checks: reaches the entry, does NOT leak to a shared unit, appears on the target's main edge in build.ninja, and the binary builds + runs.
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.
Resolves #131 — per-target
cxxflagsoverride — but by the book, without breaking mcpp's compile-once model.Approach
A source maps to one object (and one BMI for modules), shared by every target, so a shared source cannot be compiled two ways in one build. Configuration that must reach shared code therefore stays at the package/feature boundary; a target only carries flags private to its own exclusive entry. Design rationale in
.agents/docs/2026-06-18-per-target-build-config-design.md.What's in
[targets.<name>]→defines/cxxflags/cflags— applied only to that target's exclusive entry source (itsmain), never to shared module/impl objects. Fits flags that affect just a binary's (or test's) own entry — e.g. a per-test contract evaluation semantic where the entry exercises the violation.[targets.<name>]→required_features— a target is emitted only when all listed features are active; otherwise silently skipped. Pure build-selection; runs before the modgraph so gated-out targets cost nothing.[targets.<name>]now warn (error under--strict) and point at workspace / features / profile — instead of being dropped silently (the historic footgun behind this issue).mcpp testaccepts--profile/--features/--strict— so the code-under-test plus the test binaries build under the chosen whole-build mode (sanitizers, contract semantics, ...).docs/05-mcpp-toml.md(+docs/zh): the new keys + a "where build configuration goes" decision guide.Not in scope (deliberately)
General per-target flags over the shared compile pool / variant partitioning — high cost (BMI×variant, infectious along the import graph) and the need is already served by workspace members + features + profiles.
Tests
tests/unit/test_manifest.cpp: per-target key parsing, unsupported-key warning,-std=guard.tests/e2e/57_per_target_flags.sh: two bin targets, each its own-D; a shared source stays neutral.tests/e2e/58_required_features_gate.sh:--features Xbuilds only the matching target.tests/e2e/59_test_profile_features.sh:mcpp test --profile observereaches the code-under-test.Local:
mcpp buildself-host OK;mcpp test18/18; new e2e 57/58/59 + multi-target/workspace/static/shared/package-flags regression set all pass.Version bumped to 0.0.55; CHANGELOG updated.