-
Notifications
You must be signed in to change notification settings - Fork 516
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix default link mode for NativeAOT #18530
Conversation
/azp run |
Azure Pipelines successfully started running 1 pipeline(s). |
💻 [CI Build] Windows Integration Tests passed 💻✅ All Windows Integration Tests passed. Pipeline on Agent |
💻 [PR Build] Tests on macOS M1 - Mac Big Sur (11.5) passed 💻✅ All tests on macOS M1 - Mac Big Sur (11.5) passed. Pipeline on Agent |
📚 [PR Build] Artifacts 📚Packages generatedView packagesPipeline on Agent |
💻 [PR Build] Tests on macOS M1 - Mac Ventura (13.0) passed 💻✅ All tests on macOS M1 - Mac Ventura (13.0) passed. Pipeline on Agent |
✅ API diff for current PR / commitNET (empty diffs)
✅ API diff vs stable.NET (No breaking changes)ℹ️ Generator diffGenerator Diff: vsdrops (html) vsdrops (raw diff) gist (raw diff) - Please review changes) Pipeline on Agent |
🚀 [CI Build] Test results 🚀Test results✅ All tests passed on VSTS: simulator tests. 🎉 All 92 tests passed 🎉 Tests counts
Pipeline on Agent |
@@ -1583,7 +1583,7 @@ | |||
<_DefaultLinkMode>TrimMode</_DefaultLinkMode> | |||
</PropertyGroup> | |||
<PropertyGroup Condition="'$(TrimMode)' == ''"> | |||
<_DefaultLinkMode Condition="'$(_UseNativeAot)' != 'true'">Full</_DefaultLinkMode> <!-- Linking is always on for all assemblies when using NativeAOT - this is because we need to modify all assemblies in the linker for them to be compatible with NativeAOT --> | |||
<_DefaultLinkMode Condition="'$(_UseNativeAot)' == 'true'">Full</_DefaultLinkMode> <!-- Linking is always on for all assemblies when using NativeAOT - this is because we need to modify all assemblies in the linker for them to be compatible with NativeAOT --> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that the comment does not match how _DefaultLinkMode
is set, but I think there is more to this and that the introduced change only works because we explicitly pass:
<IlcArg Include="--defaultrooting" /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Without this fix _DefaultLinkMode
is not set. Then you get to the _ComputeLinkMode
target here:
xamarin-macios/msbuild/Xamarin.Shared/Xamarin.Shared.targets
Lines 2263 to 2271 in 05502d1
<Target Name="_ComputeLinkMode" DependsOnTargets="$(_ComputeLinkModeDependsOn)"> | |
<PropertyGroup> | |
<_LinkMode Condition="'$(_LinkMode)' == '' And '$(_PlatformName)' == 'macOS'">$(LinkMode)</_LinkMode> | |
<_LinkMode Condition="'$(_LinkMode)' == '' And '$(_PlatformName)' != 'macOS'">$(MtouchLink)</_LinkMode> | |
<_LinkMode Condition="'$(_LinkMode)' == ''">$(_DefaultLinkMode)</_LinkMode> <!-- Let the .NET targets chime in --> | |
<_LinkMode Condition="'$(_LinkMode)' == '' And '$(_PlatformName)' == 'macOS'">None</_LinkMode> <!-- Linking is off by default for macOS apps --> | |
<_LinkMode Condition="'$(_LinkMode)' == '' And '$(_PlatformName)' != 'macOS'">SdkOnly</_LinkMode> <!-- Default linking is SdkOnly for iOS/tvOS/watchOS apps --> | |
</PropertyGroup> | |
</Target> |
On iOS-like platform you end up in the SdkOnly
code path which translates to partial
TrimMode iirc and somehow ends up doing mostly the right thing. On macOS, however, you get the None
mode in the fallback. This results in copy
TrimMode which does no linking at all and then passes all the assemblies as --root:<assembly name>
to ILCompiler. That in turns results in compilation of the whole world, and in Debug version of ILC it asserts on trying to compile Array<T>
. That's definitely wrong.
This is all irrespective of --defaultrooting
which is already filed as issue #18482.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What I meant is (considering just iOS):
- if
_DefaultLinkMode=Full
->_LinkMode
will becomeFull
- if
_LinkMode=Full
->TrimMode
will becomefull
<TrimMode Condition="'$(_LinkMode)' == 'Full'">full</TrimMode> - if
TrimMode=full
-> ILC will not use--defaultrooting
https://github.com/dotnet/runtime/blob/f25bc7b5b859935192e4eddc5b71efe71a60a4de/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets#L270 - If
--defaultrooting
is not passed to ILC -> ILC will start trimming (which will break the app)
So I just wanted to draw the attention that the above change only works in the current setup, as we are explicitly passing --defaultrooting
to ILC
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Additionally, this means that for iOS/tvOS/watchOS (in case of NativeAOT) the default linking mode becomes Full
which is not how ILLink is configured in the noNativeAOT mode for these platforms: https://github.com/xamarin/xamarin-macios/pull/18530/files#diff-2e24f1b6f44df7580244d00f106fa1a9e2257536fbca9d7bbdc74571549324a9R1591
This could start breaking the apps with NativeAOT that work normally in noNativeAOT mode, as the change enables ILLink to trim more than what is the current default mode.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, what do you propose the default to be?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just think that we should not change ILLink default trimming modes just because NativeAOT compilation later fails.
Also, just in case it's not clear, this is currently changing the default ONLY when PublishAot=true
AND you are running dotnet publish
...
Maybe the right fix would be to "intercept" the build and set the right properties for NativeAOT, after ILLink has finished its work and before ILC compilation starts.
... so the end effect is not really any different than this. It doesn't matter whether ILLink trims it first, or NativeAOT trims it later. In the end you still need the trimming to take place.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, just in case it's not clear, this is currently changing the default ONLY when PublishAot=true AND you are running dotnet publish...
Thanks, I did understand this exactly as you explained, but again I just want to emphasise that with this change we will start trimming the user code which was not marked with IsTrimmable=true
(at least in case of iOS-like platforms) and the reasons for potential regressions that this could bring will not be necessarily related to the fact that we are using NativeAOT as a deployment toolchain-runtime, but rather to the fact that we started trimming something that was never trimmed before - meaning it is not something NativeAOT trimmer/compiler brought in, but how we configured the whole toolchain
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't have a problem setting a different default as long as some default is set and it's not None
(which is the underlying problem for me).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I, however, feel that defaulting to partial
(current default for iOS-like platforms without this PR) is weird when .NET 7+ default for other platforms is full
and it's documented that you can change it, and how.
That said, either partial
(SdkOnly
) or full
would work to solve the macOS issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I, however, feel that defaulting to partial (current default for iOS-like platforms without this PR) is weird when .NET 7+ default for other platforms is full and it's documented that you can change it, and how.
That is something that should be checked with @rolfbjarne
As for the NativeAOT story regarding macOS, I believe something like:
<_DefaultLinkMode Condition="'$(_UseNativeAot)' == 'true' And '$(_PlatformName)' == 'macOS'">Full</_DefaultLinkMode>
<_DefaultLinkMode Condition="'$(_UseNativeAot)' == 'true' And '$(_PlatformName)' != 'macOS'">SdkOnly</_DefaultLinkMode>
and
<IlcArg Condition="''$(_PlatformName)' != 'macOS'" Include="--defaultrooting" />
should be tested, as in the current set up NativeAOT trimming is disabled, due to:
- ILLink removing
IsTrimmable
attributes from assemblies - NativeAOT operating in
--defaultrooting
mode
Alternative to #18530, see #18530 (comment) Contributes to #18482
Superceded by #18560 |
No description provided.