Skip to content

Use stable net/netframework folders for the mono SDK tasks - #132402

Merged
akoeplinger merged 2 commits into
dotnet:mainfrom
akoeplinger:remove-hardcoded-tfm
Aug 17, 2026
Merged

Use stable net/netframework folders for the mono SDK tasks#132402
akoeplinger merged 2 commits into
dotnet:mainfrom
akoeplinger:remove-hardcoded-tfm

Conversation

@akoeplinger

@akoeplinger akoeplinger commented Aug 17, 2026

Copy link
Copy Markdown
Member

Follow-up to #130782, which did the same for Microsoft.NET.Sdk.WebAssembly.Pack.Tasks.

The mono and WebAssembly SDK packages placed their task assemblies in TFM-versioned subfolders (tasks/net11.0, tasks/net472, tools/net11.0), and the Sdk.props.in/Sdk.targets.in templates hardcoded those TFMs via template tokens. Every .NET Core TFM bump then required coordinated updates across the layout producer and all of its consumers.

This emits the task build output into stable, version-independent folders (net for .NET Core, netframework for .NET Framework) by overriding OutputPath/IntermediateOutputPath, mirroring ILLink.Tasks. It covers WasmAppBuilder, WasmBuildTasks, MonoAOTCompiler, MonoTargetsTasks, LibraryBuilder, MobileBuildTasks, AppleAppBuilder, AndroidAppBuilder, HelixTestTasks and WorkloadBuildTasks.

The package layouts and the in-tree consumers (Directory.Build.props, WasmApp.LocalBuild.props, AppleBuild.LocalBuild.props) now use the same names, which also lets the hardcoded _NetCoreAppToolCurrent literals and the now-dead property forwarding in tests.ioslike.targets go away.

With no TFM tokens left, the .in templates become fully static, so they're renamed to their final names and the GenerateFileFromTemplate steps are dropped from the pkgprojs.

WorkloadBuildTasks keeps a TFM-named folder for its pinned net8.0 build, since that one is selected by the consuming project's own TFM. Its Sdk.targets now defaults to tasks/net rather than resolving tasks/$(TargetFramework), which silently produced a nonexistent path for consumers on any other TFM.

Latent issues fixed along the way

  • The netframework OutputPath overrides are now guarded on NetFrameworkToolCurrent being non-empty. In source-only builds it is empty, so the bare '$(TargetFramework)' == '$(NetFrameworkToolCurrent)' comparison was also true in the outer build of a multi-targeting project (where TargetFramework is likewise empty), appending netframework/ to the shared OutputPath. This applies to Microsoft.NET.Sdk.WebAssembly.Pack.Tasks too, which grew the same pattern in Use stable net/netframework folders for WebAssembly.Pack.Tasks #130782.
  • WasmBuildTasks.dll was packaged at tasks/ while WasmBuildTasksAssemblyPath pointed at tasks/<TFM>/. It now ships in tasks/net where the property resolves.
  • src/tests/Common/Directory.Build.targets re-derived the WasmAppBuilder and MonoTargetsTasks output paths instead of using the shared properties, so it had already drifted. It now uses them.
  • TestExclusionListTasks was removed in Remove support for issues.targets #123909 but left behind a stale project reference and two unused properties.
  • The MonoAOTCompiler.Task readme pointed at tools/<target-framework>/ rather than the tasks/ folder the package actually ships.

Validation

All 10 task projects build clean into net (+ netframework where multi-targeted), in both normal and source-only mode. All affected packages were packed and unzipped: they contain tasks/net, tasks/netframework, tools/net and tasks/net8.0 as intended, with no TFM version strings in any package path. Every *TasksAssemblyPath property was evaluated and confirmed to resolve to a file that exists on disk.

Fixes #123155

Note

This pull request was authored with the assistance of GitHub Copilot.

The mono and WebAssembly SDK packages placed their task assemblies in
TFM-versioned subfolders (tasks/net11.0, tasks/net472, tools/net11.0),
and the Sdk.props.in/Sdk.targets.in templates hardcoded those TFMs via
template tokens. Every .NET Core TFM bump then required coordinated
updates across the layout producer and all of its consumers.

Emit the task build output into stable, version-independent folders (net
for .NET Core, netframework for .NET Framework) by overriding
OutputPath/IntermediateOutputPath, mirroring ILLink.Tasks. This covers
WasmAppBuilder, WasmBuildTasks, MonoAOTCompiler, MonoTargetsTasks,
LibraryBuilder, MobileBuildTasks, AppleAppBuilder, AndroidAppBuilder,
HelixTestTasks and WorkloadBuildTasks. The package layouts and the
in-tree consumers (Directory.Build.props, WasmApp.LocalBuild.props,
AppleBuild.LocalBuild.props) now use the same net/netframework names,
which also lets the hardcoded _NetCoreAppToolCurrent literals and the
now-dead property forwarding in tests.ioslike.targets go away.

With no TFM tokens left, the .in templates become fully static, so
rename them to their final names and drop the GenerateFileFromTemplate
steps from the pkgprojs.

The netframework OutputPath overrides are guarded on
NetFrameworkToolCurrent being non-empty. In source-only builds it is
empty, so the bare '$(TargetFramework)' == '$(NetFrameworkToolCurrent)'
comparison was also true in the outer build of a multi-targeting project
(where TargetFramework is likewise empty), which appended netframework/
to the shared OutputPath and made GetFilesToPackage look in
netframework/net/. This applies to Microsoft.NET.Sdk.WebAssembly.Pack.Tasks
too, which grew the same pattern in a previous change.

WorkloadBuildTasks keeps a TFM-named folder for its pinned net8.0 build,
since that one is selected by the consuming project's own TFM. Its
Sdk.targets now defaults to tasks/net rather than resolving
tasks/$(TargetFramework), which silently produced a nonexistent path for
consumers on any other TFM.

Along the way this fixes a few latent issues:

- WasmBuildTasks.dll was packaged at tasks/ while
  WasmBuildTasksAssemblyPath pointed at tasks/<TFM>/. It now ships in
  tasks/net where the property resolves.
- src/tests/Common/Directory.Build.targets re-derived the WasmAppBuilder
  and MonoTargetsTasks output paths instead of using the shared
  properties. It now uses them so it cannot drift again.
- TestExclusionListTasks was removed in dotnet#123909 but left behind a stale
  project reference and two unused properties.
- The MonoAOTCompiler.Task readme pointed at tools/<target-framework>/
  rather than the tasks/ folder the package actually ships.

Contributes to dotnet#123155

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 50cbbd7b-5246-4157-959c-0f92990d8f73
Copilot AI lite review requested due to automatic review settings August 17, 2026 11:18
@azure-pipelines

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

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.

Pull request overview

This PR removes TFM-versioned task output folders for Mono/WebAssembly SDK task assemblies and switches to stable net / netframework (plus pinned net8.0 where required), updating both package layouts and in-tree consumers to eliminate hardcoded TFMs in paths and templates.

Changes:

  • Override OutputPath / IntermediateOutputPath for multiple task projects to emit outputs into stable net / netframework folders.
  • Update SDK props/targets, local build props, and test build targets to consume the new stable folders and remove now-unneeded TFM token templating steps.
  • Fix/align packaging and documentation paths to match the new on-disk and in-package layouts (including removing stale references like TestExclusionListTasks).

Reviewed changes

Copilot reviewed 35 out of 35 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/tests/Common/Directory.Build.targets Copy runtime dependency inputs via shared task output directory properties instead of reconstructing TFM paths.
src/tasks/WorkloadBuildTasks/WorkloadBuildTasks.csproj Emit task outputs into stable net folder while keeping a pinned net8.0 output for TFM-selected consumption.
src/tasks/WasmBuildTasks/WasmBuildTasks.csproj Emit build output into stable net folder and package it under tasks/net.
src/tasks/WasmAppBuilder/WasmAppBuilder.csproj Emit outputs into net / netframework, adjust packaged task paths, and update task loading paths.
src/tasks/tasks.proj Remove stale reference to removed TestExclusionListTasks.
src/tasks/MonoTargetsTasks/MonoTargetsTasks.csproj Emit outputs into net / netframework and package into stable task folders.
src/tasks/MonoTargetsTasks/JsonToItemsTaskFactory/README.md Update example path to use bin/.../net/ stable folder.
src/tasks/MobileBuildTasks/MobileBuildTasks.csproj Emit outputs into net / netframework and package into stable task folders.
src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks.csproj Guard netframework output path overrides and use stable net / netframework folder names.
src/tasks/LibraryBuilder/LibraryBuilder.csproj Emit outputs into net / netframework and package into stable task folders.
src/tasks/HelixTestTasks/HelixTestTasks.csproj Emit output into stable net folder for version-independent consumption.
src/tasks/AppleAppBuilder/AppleAppBuilder.csproj Emit output into stable net folder and package under tasks/net.
src/tasks/AotCompilerTask/MonoAOTCompiler.csproj Emit outputs into net / netframework and package into stable task folders.
src/tasks/AndroidAppBuilder/AndroidAppBuilder.csproj Emit output into stable net folder and package under tasks/net.
src/mono/wasm/build/WasmApp.LocalBuild.props Switch local build task output directories to stable net folder names.
src/mono/wasm/build/README.md Update documented task directory example to use stable net folder.
src/mono/nuget/Microsoft.NET.Runtime.WorkloadTesting.Internal/Sdk/Sdk.targets Default to tasks/net for task resolution, with net8.0 override for pinned TFM selection.
src/mono/nuget/Microsoft.NET.Runtime.WebAssembly.Wasi.Sdk/Sdk/Sdk.targets Resolve tasks from stable tasks/net / tasks/netframework folders.
src/mono/nuget/Microsoft.NET.Runtime.WebAssembly.Wasi.Sdk/Microsoft.NET.Runtime.WebAssembly.Wasi.Sdk.pkgproj Stop generating .targets from templates; include static Sdk.targets.
src/mono/nuget/Microsoft.NET.Runtime.WebAssembly.Sdk/Sdk/Sdk.targets Resolve tasks from stable tasks/net / tasks/netframework folders.
src/mono/nuget/Microsoft.NET.Runtime.WebAssembly.Sdk/Microsoft.NET.Runtime.WebAssembly.Sdk.pkgproj Stop generating .targets from templates; include static Sdk.targets.
src/mono/nuget/Microsoft.NET.Runtime.wasm.Sample.Mono/Microsoft.NET.Runtime.wasm.Sample.Mono.pkgproj Place sample tool files under tools/net/ stable folder.
src/mono/nuget/Microsoft.NET.Runtime.MonoTargets.Sdk/Sdk/MonoTargetsTasks.props Resolve MonoTargetsTasks from stable tasks/net / tasks/netframework folders.
src/mono/nuget/Microsoft.NET.Runtime.MonoTargets.Sdk/Microsoft.NET.Runtime.MonoTargets.Sdk.pkgproj Stop generating .props from templates; include static MonoTargetsTasks.props.
src/mono/nuget/Microsoft.NET.Runtime.MonoAOTCompiler.Task/Sdk/Sdk.props Resolve MonoAOTCompiler from stable tasks/net / tasks/netframework folders.
src/mono/nuget/Microsoft.NET.Runtime.MonoAOTCompiler.Task/README.md Update UsingTask example to use tasks/net/MonoAOTCompiler.dll.
src/mono/nuget/Microsoft.NET.Runtime.MonoAOTCompiler.Task/Microsoft.NET.Runtime.MonoAOTCompiler.Task.pkgproj Stop generating Sdk.props from templates; include static Sdk.props.
src/mono/nuget/Microsoft.NET.Runtime.LibraryBuilder.Sdk/Sdk/Sdk.targets Resolve tasks from stable tasks/net / tasks/netframework folders.
src/mono/nuget/Microsoft.NET.Runtime.LibraryBuilder.Sdk/Microsoft.NET.Runtime.LibraryBuilder.Sdk.pkgproj Stop generating .targets from templates; include static Sdk.targets.
src/mono/nuget/Microsoft.NET.Runtime.iOS.Sample.Mono/Microsoft.NET.Runtime.iOS.Sample.Mono.pkgproj Place sample tool files under tools/net/ stable folder.
src/mono/nuget/Microsoft.NET.Runtime.Android.Sample.Mono/Microsoft.NET.Runtime.Android.Sample.Mono.pkgproj Place sample tool files under tools/net/ stable folder.
src/mono/msbuild/apple/build/AppleBuild.LocalBuild.props Switch local build task output directories to stable net folder names.
src/mono/browser/build/README.md Update documented task directory example to use stable net folder.
eng/testing/tests.ioslike.targets Remove forwarding of now-unused _NetCoreAppToolCurrent property into Apple build test property set.
Directory.Build.props Switch shared task output directory properties and task assembly paths to stable net/netframework folder names and remove stale TestExclusionListTasks properties.

Comment thread src/tasks/WasmAppBuilder/WasmAppBuilder.csproj
$(TargetFramework) is now passed in as a global property by the AOT
build command instead of hardcoding the TFM in the props file, so that
.NET Core TFM bumps don't require updating it.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 50cbbd7b-5246-4157-959c-0f92990d8f73
Copilot AI review requested due to automatic review settings August 17, 2026 12:56

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.

Pull request overview

Copilot reviewed 36 out of 36 changed files in this pull request and generated no new comments.

@akoeplinger

akoeplinger commented Aug 17, 2026

Copy link
Copy Markdown
Member Author

/ba-g failure are unrelated issues

@akoeplinger
akoeplinger merged commit 45ad194 into dotnet:main Aug 17, 2026
149 of 156 checks passed
@akoeplinger

Copy link
Copy Markdown
Member Author

/backport to release/11.0-rc1

@akoeplinger
akoeplinger deleted the remove-hardcoded-tfm branch August 17, 2026 16:15
@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/11.0-rc1 (link to workflow run)

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Remove hardcoding of TFMs in wasm tests

3 participants