feat: msbuildProperties — evaluation-time MSBuild properties - #3
Conversation
Conditional, codegen-only ProjectReferences (ReferenceOutputAssembly=false, gated on a property like SkipApiClientGen) put build-ordering edges into the inferred graph that a production/Docker build never compiles, over-attributing affected projects — and platform-dependently when the condition involves globs. A workspace-level msbuildProperties map is applied to every dependency/ task-inference evaluation as -p:NAME=VALUE, so the graph matches how the code actually deploys. Properties ride on EvalEnv, so the batched traversal and every per-project fallback see identical values (command-line global properties propagate through the traversal's MSBuild task). They are folded into the eval-cache digest: a conditional PackageReference gated on such a property evaluates differently, so a cached package set from one configuration is never served under another. Inferred task commands deliberately do not pass them — evaluation-time only.
- Apply cargo fmt. `cargo fmt --all --check` is a CI gate and was failing on config.rs and msbuild.rs, which would have turned main red on merge. - Document the setting in the README, the one place every other setting is listed, and state the two boundaries the implementation already has: the properties need to match how the code is really built (inferred builds pass --no-dependencies, so moon is the only thing ordering dependencies, and dropping an edge drops that ordering), and they reach evaluation but not `dotnet restore`, so a package gated on one can be hashed without being restored. - Add two integration tests that assert the properties reach MSBuild and change the result, rather than only that they render into -p: arguments: one for the inferred graph, one for the evaluated package set, which is the case that justifies folding them into the eval-cache digest. Both reuse the existing matrix/cond fixture, whose gated reference is keyed on a property the project sets itself, so they also pin the global-property-wins semantics the feature depends on. - Use the imported BTreeMap instead of the inline std path.
|
Thanks, this is well put together. The design fits the architecture, and folding the properties into the eval-cache digest is the part that would have been easy to miss. I pushed 45f72bf to your branch rather than sending small stuff back and forth. Three things in it. rustfmt. README. The settings table is the one place every other setting is listed, so it now has a row, plus a short "Evaluation properties" section with the motivating example. Integration coverage. Your three tests cover arg rendering, the schema and the digest, which are the mechanical parts, but nothing asserted that the properties reach MSBuild and change the result. Added two that do, both on the existing
One thing worth passing on, because it briefly had me chasing a bug that did not exist: the sandbox resolves the wasm through On the two boundaries, I documented them rather than changing anything, since scoping to evaluation looks right for a first cut:
Both are in the README and the setting's doc comment now. CI is green on all four jobs, including ubuntu and macOS, which had never run on this branch (fork PRs need approval, I approved it). Left |
Closes #1.
Adds a workspace-level
msbuildPropertiesmap (string → string) applied to every MSBuild evaluation behind dependency and task inference, as-p:NAME=VALUE:Why: conditional, codegen-only
ProjectReferences (ReferenceOutputAssembly=false, gated on a property likeSkipApiClientGen) put build-ordering edges into the inferred graph that a production/Docker build never compiles — over-attributing affected projects, and platform-dependently when the condition involves globs. Evaluating with the same properties the deployment build uses makes the graph match how the code actually ships. See #1 for the full case.How:
EvalEnvcarries the properties;with_eval_envrenders them via a new puremsbuild_property_argshelper. That covers both the batched traversal and every per-project fallback in one place — command-line global properties propagate through the traversal's<MSBuild>task into child projects, so batch and per-project evaluation see identical values.PackageReferencegated on such a property evaluates differently, so a cached package set from one configuration is never served under the other. Read and write keys stay symmetric —hash_task_contentsnow parses the toolchain config before the cache read.moon runbuilds stay exactly what the project defines.parse_manifestcarries no toolchain config (same pre-existing limitation asdotnetRoot); comment extended.Tests: schema/deserialization (camelCase key),
-p:rendering incl. deterministic ordering, eval-cache invalidation on property add/change. Full suite green locally (112 passed, wasm target builds).Validated end-to-end against our 177-project workspace: with
msbuildProperties: {SkipApiClientGen: 'true'}the gateway over-attribution disappears and our fan-out regression suite passes. This is the port of the feature we run in production via the internal fork (innovadis-devdotnet_toolchain v0.2.0), adapted to this repo's batched-evaluation architecture.