dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
15.34k stars 4.74k forks source link

Regression: 'dotnet msbuild' publish fails with 'PublishAot' unless 'SelfContained' is also set #109154

Closed Sergio0694 closed 3 weeks ago

Sergio0694 commented 3 weeks ago

Description

As of .NET 9, neither 'dotnet msbuild' nor Desktop MSBuild can publish with Native AOT anymore unless SelfContained is also set. This is especially impactful for WinUI 3 and UWP on .NET 9 apps. Eg. the default templates for WinUI 3 are also broken because of this, when on .NET 9.

Reproduction Steps

Expected behavior

Should publish just fine.

Actual behavior

Image

"D:.nuget\packages\microsoft.net.illink.tasks\9.0.0-rc.2.24473.5\build\Microsoft.NET.ILLink.targets(207,5): error NETSDK1102: Optimizing assemblies for size is not supported for the selected publish configuration. Please ensure that you are publishing a self-contained app."

Regression?

Yes. Works fine on .NET 8.

Known Workarounds

Manually set SelfContained as well.

Configuration

dotnet-policy-service[bot] commented 3 weeks ago

Tagging subscribers to this area: @agocke, @MichalStrehovsky, @jkotas See info in area-owners.md if you want to be subscribed.

MichalStrehovsky commented 3 weeks ago

This was intentional. See #95496 and the discussion on it. It never actually worked without SelfContained=true, but you may not have ran into the bug. SDK needs to know this is a SelfContained publish and PublishAot and PublishTrimmed are always SelfContained.

The fix is to put SelfContained=true in the csproj (or just run dotnet publish that sets it automatically).

Sergio0694 commented 3 weeks ago

"just run dotnet publish that sets it automatically"

Right, but my question was why can we not do the same in .targets that MSBuild can also see, so it's automatic in either case? 😅

MichalStrehovsky commented 3 weeks ago

"just run dotnet publish that sets it automatically"

Right, but my question was why can we not do the same in .targets that MSBuild can also see, so it's automatic in either case? 😅

We only want Publish to be SelfContained, not Build. Doing a SelfContained build just does lots of extra work to copy and collect all the files. Build runs in inner loop so if we can keep inner loop faster, we should.

(My advice to put SelfContained in the project file is going to slow down your inner loop, but there's not much else we can do. You should ideally use dotnet publish, not dotnet build /t:Publish.)

Sergio0694 commented 3 weeks ago

The problem is that dotnet publish just does not work at all for MSIX. You have to use MSBuild. I suppose we can just leave SelfContained= true in the .pubxml files so that it's only going to get picked up when doing an actual publish, and that way you can still just keep PublishAot=true in the .csproj to get the analyzers and the CoreCLR AOT emulation mode 🤔

Thank you for confirming though!

"We only want Publish to be SelfContained, not Build."

I'm still not entirely sure I get why can the SDK not automatically set that only when you're actually publishing 😅

MichalStrehovsky commented 3 weeks ago

I'm still not entirely sure I get why can the SDK not automatically set that only when you're actually publishing 😅

It does that, but msbuild /t:Publish is not "actually publishing". dotnet publish is.

MSBuild doesn't know about publish, it's just a target.

Internally, publish is implemented by dotnet publish setting the undocumented _IsPublishing property to true and executing the Publish target. So msbuild /t:Publish /p:_IsPublishing=true would also work, but you're setting an undocumented property...

Sergio0694 commented 3 weeks ago

Ooh gotcha, I see. Thank you for sharing the additional context! 🙂