-
Notifications
You must be signed in to change notification settings - Fork 533
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
Update to new linker custom steps API #5748
Conversation
/azp run |
Commenter does not have sufficient privileges for PR 5748 in repo xamarin/xamarin-android |
@jonathanpeppers could you help me trigger a ci run for this change? |
/azp run |
Azure Pipelines successfully started running 1 pipeline(s). |
Looks like Will just try again. |
/azp run |
Azure Pipelines successfully started running 1 pipeline(s). |
83e9029
to
336b7ce
Compare
/azp run |
Azure Pipelines successfully started running 1 pipeline(s). |
Getting failures like:
@jonathanpeppers is there a way I could get permissions to trigger the pipelines myself? |
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 manually tested the changes here with the projects in dotnet/net6-mobile-samples.
@sbomer I think the couple CI failures here we can ignore. The test phases all look good.
@dellis1972 or @jonpryor care to review?
Thanks @jonathanpeppers! |
76b2718
to
dac30f3
Compare
/azp run |
Azure Pipelines successfully started running 1 pipeline(s). |
src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/FixAbstractMethodsStep.cs
Outdated
Show resolved
Hide resolved
src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/FixAbstractMethodsStep.cs
Outdated
Show resolved
Hide resolved
{ | ||
AssemblyAction action = Annotations.HasAction (assembly) ? Annotations.GetAction (assembly) : AssemblyAction.Skip; | ||
if (action == AssemblyAction.Skip || action == AssemblyAction.Copy || action == AssemblyAction.Delete) | ||
Annotations.SetAction (assembly, AssemblyAction.Save); |
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.
Do we really want to do this? I don't think we should change copy action to save not alone skip action to save.
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 full context on how we can get into this situation - it looks to me like it was intended to inject methods into non-SDK assemblies which may be copy. I could get rid of skip/delete, but I'm trying to minimize functional changes here.
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.
It'd be fine to fix this in follow-up PR but I think this needs to be addressed because we changed the meaning of "copy" action in net6. It also does not make much sense to be to update code in deleted assembly.
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 got rid of the skip/delete cases because those don't make any sense to me. If anyone can provide more context on the copy case I'd be happy to address it in a follow-up.
src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/FixAbstractMethodsStep.cs
Show resolved
Hide resolved
...marin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.ILLink.targets
Outdated
Show resolved
Hide resolved
/azp run |
Azure Pipelines successfully started running 1 pipeline(s). |
Current state of unit test affairs:
I've restarted MSBuild Legacy - Windows-2 and MSBuild One .NET - Windows-3 suites, as thy previously because they couldn't download test infrastructure. |
src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/AddKeepAlivesStep.cs
Outdated
Show resolved
Hide resolved
src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/FixAbstractMethodsStep.cs
Show resolved
Hide resolved
src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/FixAbstractMethodsStep.cs
Show resolved
Hide resolved
- Use "IMetadataResolver cache" fields
Proposed commit message: Context: https://github.com/mono/linker/issues/1953
Context: https://github.com/mono/linker/pull/1774
Context: https://github.com/mono/linker/pull/1774#issuecomment-783563526
Context: https://github.com/mono/linker/pull/1979
Context: https://github.com/mono/linker/pull/2019
Context: https://github.com/mono/linker/pull/2045
Context: https://github.com/xamarin/java.interop/commit/2573dc8c84fd4eb68e75bcae73912c26f4942356
Context: https://github.com/xamarin/xamarin-android/pull/5870
Context: https://github.com/xamarin/xamarin-android/pull/5878
Update the custom linker steps to use the new `IMarkHandler` API
which runs logic during "MarkStep".
(See [this list][0] of pipeline steps for additional context.)
As part of this, I've removed the workaround that loads all referenced
assemblies up-front and simplified some of the linker MSBuild targets.
Some of the `MonoDroid.Tuner` steps were duplicated and changed to
implement the new `IMarkHandler` interface, to avoid touching the
`MonoDroid.Tuner` code.
In my analysis of the custom steps, most of them "just work" if we
call them only for marked members, because they ultimately either:
- Just call `AddPreserved*()` to conditionally keep members of types
(which with the new API will just happen when the type is marked)
- In the case of `FixAbstractMethodsStep()`, inject missing interface
implementations which will only be kept if they are marked for some
other reason.
Most of the steps have been updated in a straightforward way based on
the above.
The exceptions are:
- `AddKeepAlivesStep` needs to run on all code that survived
linking, and can run as a normal step.
- `ApplyPreserveAttribute`: this step globally marks members with
`PreserveAttribute`.
- The step is only active for non-SDK link assemblies. Usually we
root non-SDK assemblies, but it will be a problem if linking all
assemblies.
- For now, I updated it to use the new custom step API on assembly
mark -- so it will scan for the attribute in all marked
assemblies -- but we should investigate whether this is good
enough.
- This can't be migrated to use `IMarkHandler` because it needs
to scan code for attributes, including unmarked code.
- `PreserveExportedTypes`: similar to the above, this globally marks
members with `Export*Attribute`. It's used for java interop in
cases where the java methods aren't referenced statically, like
from xml, or for special serialization methods.
- It's only active for non-SDK assemblies, so like above it will
be a problem only if linking all assemblies.
- Like above, I've made it scan marked assemblies.
- `PreserveApplications`: globally scans for `ApplicationAttribute`
on types/assemblies, and sets the `TypePreserve` annotation for
any types referenced by the attribute.
- This step technically does a global scan, but it's likely to work
on "mark type"/"mark assembly", as `ApplicationAttribute` is only
used on types/assembies that are already kept.
- I've updated it to use the new `IMarkHandler` API.
Additionally, as per xamarin/java.interop@2573dc8c, stop using
`TypeDefinitionCache` everywhere and instead use `IMetadataResolver`
to support caching `TypeDefinition`s across shared steps.
For .NET 6, `LinkContextMetadataResolver` implements the
`IMetadataResolver` interface in terms of `LinkContext`.
TODO: Replace `LinkContextMetadataResolver` with `IMetadataResolver`
implemented directly on `LinkContext` in mono/linker#2045.
TODO: Get rid of all reflection in `SetupStep` with the fix for shared
state in mono/linker#2019.
[0]: https://github.com/mono/linker/blob/main/src/linker/Linker/Driver.cs#L714-L730 |
@jonpryor thank you! I would remove the TODO - that work was done in this PR (I updated the original PR description to reflect this). Could you also add:
(Feel free to adjust wording or formatting) |
Actually, looks like the merge from main brought in the update from dotnet/linker#2045 which is a breaking change so I'll need to address that here. |
LinkContext now directly implements IMetadataResolver.
Indeed, commit da536fc bumped our .NET 6 build, which includes a mono/linker bump, which includes dotnet/linker#2045…. Explains why my changes before the merge also failed to build, while this PR was otherwise green yesterday… |
@jonpryor I addressed the remaining TODOs in the latest changes (they can be removed from the proposed commit message). |
This will allow extension methods that take an `IMetadataResolver` like in dotnet/java-interop#842 to use the LinkContext Resolve cache. Context: dotnet/android#5748 (comment) The Resolve cache added in dotnet/linker#1979 requires calling `Resolve*Definition` methods directly on `LinkContext`, which means that any extension methods that do resolution logic need to take a `LinkContext`. This doesn't work well with the layering in xamarin-android, where java.interop uses a resolution cache with cecil, but doesn't depend on the linker. Instead it uses a custom `TypeResolutionCache` for extension methods like `GetBaseDefinition`: https://github.com/xamarin/java.interop/blob/main/src/Java.Interop.Tools.Cecil/Java.Interop.Tools.Cecil/MethodDefinitionRocks.cs#L16 These extension methods are also used from xamarin-android, but there's a desire to use the `LinkContext` cache in this case. @jonpryor had the idea to change the extension methods to use cecil's `IMetadataResolver`, which can be implemented by `TypeDefinitionCache` and by `LinkContext`. Java.interop will continue using their `TypeDefinitionCache`, and xamarin-android will use `LinkContext`. One limitation of this approach is that `LinkContext.TryResolve*Definition` (renamed to just `TryResolve` for consistency) methods aren't usable from the extension methods. Commit migrated from dotnet/linker@aaf4880
This updates the custom steps to use the new API which runs logic on mark (dotnet/linker#1774). As part of this, I've removed the workaround that loads all referenced assemblies up-front and simplified some of the linker msbuild targets. Some of the MonoDroid.Tuner steps were duplicated and changed to implement the new IMarkHandler interface, to avoid touching the MonoDroid.Tuner code.
@radekdoulik PTAL - in particular I would appreciate your opinion on whether the below assumptions are reasonable. Please also add anyone else who you think should review the change.
Notes from dotnet/linker#1774 (comment):
In my analysis of the custom steps, most of them "just work" if we call them only for marked members, because they ultimately either:
Most of the steps have been updated in a straightforward way based on the above.
The exceptions are:
edit: per conversation with @jonathanpeppers the plan is to
move all of the steps (including the exceptions I mentioned above) to use the new custom steps API, and get rid of the workaround that loads references up-front, even if there is a small chance that they will miss PreserveAttribute and similar in assemblies which are unused (never marked by the linker).(done in this PR)