Skip to content

Enable opt-in isolated static-graph builds for the CLR subset - #135876

Draft
sbomer wants to merge 5 commits into
dotnet:mainfrom
sbomer:runtime-staticgraph-clr
Draft

sbomer wants to merge 5 commits into
dotnet:mainfrom
sbomer:runtime-staticgraph-clr

Conversation

@sbomer

@sbomer sbomer commented Oct 15, 2026

Copy link
Copy Markdown
Member

Summary

Enable an opt-in MSBuild static-graph build of the clr subset using /graphBuild /isolateProjects, and add a Linux x64 Debug validation job to the existing runtime CI pipeline.

The normal dynamic build remains the default. This change is limited to CLR build configuration; it does not enable static graph for the full repository or add MSBuildCache integration.

Build changes

  • Declare native-runtime producer dependencies and target mappings needed by CoreLib crossgen, NativeAOT, and AOT tools.
  • Make CLR package references and version properties available during graph evaluation rather than introducing them only during target execution.
  • Declare package and publish target protocols, and expand native-library inputs after their producer has run.
  • Disable synthetic transitive references where they interfere with the explicit graph.

The CI job uses the checkout's SDK. It restores through the normal build driver, then invokes MSBuild directly with graph building and project isolation. It requires no external checkout, machine-specific path, capture/replay, or precomputed graph data.

Validation

Validated locally on Linux x64 after merging dotnet/runtime:main at 5891955bdde:

  • ./build.sh clr+libs+host — passed.

  • With generated artifacts/bin and artifacts/obj moved aside, ran the CI-equivalent sequence below — both commands passed:

    ./build.sh -ci -s clr -c Debug --restore
    ./.dotnet/dotnet msbuild Build.proj \
      /t:Build /p:Subset=clr /p:Configuration=Debug /p:RuntimeConfiguration=Debug \
      /p:Restore=false /p:Build=true /p:Ninja=true \
      /p:TargetArchitecture=x64 /p:BuildArchitecture=x64 \
      /p:ContinuousIntegrationBuild=true /p:FeatureDynamicCodeCompiled=true \
      /graphBuild /isolateProjects /m:2 /nr:false
  • Built and ran the existing ILAssembler test suite — 2,541 passed, zero failures, errors, or skips.

  • A local dynamic/static graph comparison completed with differences, not an exact match. Remaining differences include SDK target-protocol nodes/edges and additional static-graph ILLink.Tasks framework instances, including a net472 build with separate outputs. This is not a claim of byte-for-byte output equivalence.

This is a draft for review and upstream CI validation. Azure Pipelines has not yet run on these changes; local coverage does not include all platforms/configurations or the full runtime test suite.

Note

This PR description was generated with GitHub Copilot.

sbomer and others added 4 commits October 13, 2026 20:30
…s natural location

The MoveSymbolFiles target in src/coreclr/Directory.Build.targets copied
every managed project's PDB into a single flattened $(RuntimeBinDir)PDB\
folder after each build. Besides being unnecessary busywork for the ~25
projects whose PDBs are copied there but never consumed from that location,
this consolidation caused a real bug: projects with multiple build variants
that share an assembly name (e.g. crossgen2's normal and published builds)
would race to overwrite each other's PDB in the shared folder, so the PDB
left behind in PDB\ did not necessarily match the DLL actually shipped.

The only real consumer of this folder, eng/liveBuilds.targets'
ResolveRuntimeFilesFromLocalBuild target (used when other subsets assemble
the shared framework from an already-built clr subset), only ever looked up
System.Private.CoreLib.pdb and System.Private.CoreLib.ni.pdb from it.

- System.Private.CoreLib.ni.pdb is already written directly to the PDB\
  folder by crossgen-corelib.proj, independent of MoveSymbolFiles.
- System.Private.CoreLib.pdb (the managed/IL PDB) is produced by CoreLib's
  own compile and naturally lands at $(RuntimeBinDir)IL\System.Private.CoreLib.pdb,
  identical to the copy MoveSymbolFiles produced.

This change removes the MoveSymbolFiles target and its associated item
group entirely, and updates ResolveRuntimeFilesFromLocalBuild to read the
managed CoreLib PDB directly from its natural IL\ location (mirroring the
existing DLL fallback already present in that target), removing the need
for the copy mechanism altogether.

Validated by rebuilding the clr subset (no errors, no behavior change for
consumers of the shared framework) and by directly invoking
AddRuntimeFilesToPackage on Microsoft.NETCore.App.Runtime.CoreCLR.sfxproj,
confirming System.Private.CoreLib.pdb resolves correctly from its natural
location.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 099eec3c-119a-4097-8071-6cd952af9e7c
…he clr subset

Makes the clr subset buildable with MSBuild's static graph scheduler and
project isolation enforcement (/graphBuild /isolateProjects). Static graph
mode requires every project's full set of references to be statically
determinable at evaluation time and enforces that projects only access
files/outputs they declare, so several coreclr .nuget packaging projects
and tool projects needed explicit ProjectReference items and
AddTransitiveProjectReferencesInStaticGraph=false added alongside their
existing MSBuild-task-based invocation patterns.

This is opt-in only (no change to the default dynamic build) and only
the clr subset is currently supported; other subsets will be enabled
incrementally.

Also adds a dedicated CI leg (eng/pipelines/runtime-static-graph.yml) that
builds the clr subset with /graphBuild /isolateProjects on
linux_x64_dev_innerloop, to catch regressions as this support evolves.
Restore happens via a normal dynamic build step first, since Arcade's own
toolset-bootstrap project isn't graph/isolate-safe; the actual static-graph
build then runs as a postBuildStep invoking Build.proj directly.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 099eec3c-119a-4097-8071-6cd952af9e7c
Resolve the overlapping PDB prerequisite by retaining upstream's CoreCLRArtifactsILDir path.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 099eec3c-119a-4097-8071-6cd952af9e7c
Replace the unregistered standalone pipeline with a Linux x64 Debug job in the existing runtime pipeline. Restore normally, then build the CLR subset directly with graph scheduling and project isolation.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 099eec3c-119a-4097-8071-6cd952af9e7c
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 6 pipeline(s).
10 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @dotnet/runtime-infrastructure
See info in area-owners.md if you want to be subscribed.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Cross-host tool and package consumers lack dependencies on their actual native producers, allowing missing-input races in parallel graph builds.

1 open finding
What changed in this PR

Enables opt-in isolated static-graph builds for the CLR subset while preserving dynamic builds as the default.

Changes:

  • Declares native producer dependencies and package/publish target mappings.
  • Adjusts package evaluation, version initialization, and native-library discovery for graph builds.
  • Adds Linux x64 Debug CI validation.

Review used targeted source inspection; no builds or tests were run.

File Description
src/​tools/​ilasm/​src/​ilasm/​ilasm.csproj Adds publish target mapping.
src/​coreclr/​tools/​aot/​AotCompilerCommon.props Adds native dependencies and deferred library discovery.
src/​coreclr/​nativeaot/​Directory.Build.targets Declares native producer dependency.
src/​coreclr/​crossgen-corelib.proj Declares native dependency and target mapping.
src/​coreclr/​.nuget/​versioning.targets Disables execution-time reference updates for graph builds.
src/​coreclr/​.nuget/​pkgproj.targets Adds package ordering and target protocols.
src/​coreclr/​.nuget/​Directory.Build.targets Initializes package versions locally.
src/​coreclr/​.nuget/​coreclr-packages.proj Disables synthetic transitive references.
src/​coreclr/​.nuget/​builds.targets Declares package references during evaluation.
eng/​pipelines/​runtime.yml Adds isolated graph-build validation.
Build.proj Disables synthetic transitive graph references.

🧠 Review effort: Balanced

Reuse the orchestrated cross-components project's metadata for AOT tools and host IL-tool packages, preserving native build identity and sanitizer removal. Remove package-only globals from producer references and retain RID properties when adding PackCrossComponent.

Validation: full clr+libs+host build; isolated CLR graph build; 2,541 ILAssembler tests; six cross-host graph configurations; isolated arm64-target Crossgen2 and ILCompiler publication and executable smoke checks passed. The same-architecture graph is unchanged.

Validation limitation: host IL-tool packaging is normally Windows-only. Forcing it on Linux fails to link System.Security.Cryptography.Native.OpenSsl-Static in both graph and ordinary builds. Windows package execution was not validated locally; publication with this limitation was approved.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 099eec3c-119a-4097-8071-6cd952af9e7c

@jkoritzinsky jkoritzinsky left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of adding checks for IsGraphBuild and adding specialized logic, I'd rather adjust the build to always do the "graph build compatible" path and remove incompatible infrastructure.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: No status
Status: No status

Development

Successfully merging this pull request may close these issues.

3 participants