-
Notifications
You must be signed in to change notification settings - Fork 560
[One .NET] support for multiple $(RuntimeIdentifiers) #4767
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
Conversation
7521cc0
to
0d9b251
Compare
a915c1a
to
635e99f
Compare
@jonathanpeppers its green! |
635e99f
to
b25e99d
Compare
...n.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.BuildOrder.targets
Show resolved
Hide resolved
<SelfContained Condition=" '$(SelfContained)' == '' And '$(AndroidApplication)' == 'true' ">true</SelfContained> | ||
<RuntimeIdentifier Condition=" '$(RuntimeIdentifier)' == '' And '$(AndroidApplication)' == 'true' ">android.21-x86</RuntimeIdentifier> | ||
<!-- Prefer $(RuntimeIdentifiers) plural --> | ||
<RuntimeIdentifiers Condition=" '$(RuntimeIdentifier)' == '' And '$(RuntimeIdentifiers)' == '' And '$(AndroidApplication)' == 'true' ">android.21-arm;android.21-arm64</RuntimeIdentifiers> |
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.
The default $(RuntimeIdentifiers)
are arm32 & arm64? Why? Especially considering that the previous default was x86, and the "normal" Xamarin.Android default -- via xamarin/monodroid, for commercial users -- is "all the ABIs!" arm64-v8a;armeabi-v7a;x86;x86_64
.
Given that (1) we don't know what the "commercial integration" looks like, and (2) it would be Really Really Handy to be able to run the .apk
s on x86(_64?) emulators, this default seems "weird" to 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.
This is the same default we have here: https://github.com/xamarin/xamarin-android/blob/5a5580cd3cce0559da5e9d097b03d356a6630c05/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets#L234
I can put them all, if we think that makes more sense.
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.
This now defaults to android.21-arm64;android.21-x86
.
2d69d65
to
0decf45
Compare
public override bool RunTask () | ||
{ | ||
if (!string.IsNullOrEmpty (RuntimeIdentifier)) { | ||
if (RuntimeIdentifiers != null && RuntimeIdentifiers.Length > 0) { |
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.
Implicit to this is that $(RuntimeIdentifiers)
takes precedence over $(AndroidSupportedAbis)
. Is this desirable/intentional? What will be the fallout to this decision?
For example, if I have an existing App.csproj
which overrides $(AndroidSupportedAbis)
, and then I migrate to .NET 5/6 and don't touch $(RuntimeIdentifiers)
… What Happens?
Given that this PR always provides a default $(RuntimeIdentifiers)
value, what I think will happen is that we'll effectively ignore $(AndroidSupportedAbis)
, replacing the "original overridden value" with the defaults that we provide.
Is this useful or desirable? (It might be! I don't know! I am wondering if there's been any consideration here, particularly as the commit message doesn't mention this semantic.)
Meanwhile, is the opposite possible? If $(AndroidSupportedAbis)
is overridden, and $(RuntimeIdentifiers)
isn't -- though making this determination may itself be difficult! -- would it be at all possible to populate $(RuntimeIdentifiers)
based on the value of $(AndroidSupportedAbis)
?
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.
Eventually, I think that RuntimeIdentifier
and/or RuntimeIdentifiers
will be implicitly set via:
<TargetFrameworkVersion>net5.0-android</TargetFrameworkVersion>
And so, it seems like $(AndroidSupportedAbis)
would always be ignored going forward? Is it worth trying to support both?
Either way, I should document something about $(RuntimeIdentifiers)
being preferred in DotNet5.md
.
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.
If $(AndroidSupportedAbis)
will be ignored going forward, then we should consider adding a warning if the property is set at all, as having something set which doesn't do anything will be a source of confusion.
This may complicate migrating from "long-form" to "short-form" projects, i.e. it'll be a property that needs to be removed as part of the migration, but this may be for the best.
Alternatively, we would need to ensure that if $(AndroidSupportedAbis)
is set, the values within it contribute to $(RuntimeIdentifiers)
, so that when it's set, the specified ABIs will still appear in the resulting .apk
/.aab
.
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.
Since $(RuntimeIdentifiers)
is needed for Restore
to even work... I think we really should require it over $(AndroidSupportedAbis)
.
I added XA0036
if $(AndroidSupportedAbis)
is present, @brendanzagaeski you might review what I added for this, thanks.
src/Xamarin.Android.Build.Tasks/Tasks/RuntimeIdentifierToAbi.cs
Outdated
Show resolved
Hide resolved
0decf45
to
8a1d054
Compare
8a1d054
to
9e1b894
Compare
...marin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.Linker.targets
Show resolved
Hide resolved
See the Microsoft documentation on [runtime identifiers][rids] for more | ||
information. | ||
|
||
[rids]: https://docs.microsoft.com/dotnet/core/rid-catalog |
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.
Probably it was already in mind when adding this info, but this link might need to be updated if the eventual page that talks about Android RIDs ends up being elsewhere. I think what's written here is good for now. I'm mostly just thinking out loud about the future.
9e1b894
to
4cf7fec
Compare
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.
Approved on the new warning and error messages, with one last optional idea for a small change in the XA0036 message.
The generated Resources.Designer.cs
and .xlf
files are all set too.
4cf7fec
to
6fd701c
Compare
To mirror what we have for `$(AndroidSupportedAbis)` in the existing Xamarin.Android world, we need a way for .NET 6 apps to support multiple architectures. A `HelloAndroid.csproj` targeting all architectures might look like: <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>net5.0-android</TargetFramework> <RuntimeIdentifiers>android.21-x86;android.21-x64;android.21-arm;android.21-arm64</RuntimeIdentifiers> <OutputType>Exe</OutputType> </PropertyGroup> </Project> To achieve this, we can do a nested `<MSBuild/>` call: <ItemGroup> <_RIDs Include="$(RuntimeIdentifiers)" /> </ItemGroup> <MSBuild Projects="$(MSBuildProjectFile)" Targets="_ComputeFilesToPublishForRuntimeIdentifiers" Properties="RuntimeIdentifier=%(_RIDs.Identity)"> <Output TaskParameter="TargetOutputs" ItemName="ResolvedFileToPublish" /> </MSBuild> For a new target: <Target Name="_ComputeFilesToPublishForRuntimeIdentifiers" DependsOnTargets="ResolveReferences;ComputeFilesToPublish" Returns="@(ResolvedFileToPublish)"> </Target> This is equivalent to what would happen in the legacy `_ResolveAssemblies` target. The linker then outputs files to: obj\Release\net5.0\$(RuntimeIdentifier)\linked\ One problem with this, is you receive multiple BCL assemblies for each architecture: obj\Release\net5.0\android.21-arm\linked\System.Linq.dll obj\Release\net5.0\android.21-arm64\linked\System.Linq.dll obj\Release\net5.0\android.21-x86\linked\System.Linq.dll obj\Release\net5.0\android.21-x64\linked\System.Linq.dll I created a `<ProcessAssemblies/>` MSBuild task that checks the mvid of each assembly to detect duplicates. Non-duplicates will be placed in a sub-directory within the `.apk` file, such as: * `assemblies\HelloAndroid.dll` * `assemblies\System.Linq.dll` * `assemblies\arm64-v8a\System.Private.CoreLib.dll` * `assemblies\armeabi-v7a\System.Private.CoreLib.dll` * `assemblies\x86\System.Private.CoreLib.dll` * `assemblies\x86_64\System.Private.CoreLib.dll` I had to make a few build & runtime changes for these ABI sub-directories to work. Other notes: * We must pass `@(IntermediateAssembly)` from the outer build to the nested `<MSBuild/>` calls. Otherwise, the inner calls look for `obj\Release\net5.0\android.21-arm\HelloAndroid.dll` instead of `obj\Release\net5.0\HelloAndroid.dll` that actually exists. * `_ComputeFilesToPublishForRuntimeIdentifiers` was running some extra targets causing `<ResolveSdks/>` to run 5 times for 4 ABIs. I had to make changes in `BuildOrder.targets` to fix this. * `<ResolveAssemblies/>` now sets `%(IntermediateLinkerOutput)` on each assembly item. This allows .NET 6 builds to support multiple linker directories.
6fd701c
to
28d5a02
Compare
Example message should say 'warning'.
Squash-and-merge commit message:
|
To mirror what we have for
$(AndroidSupportedAbis)
in the existingXamarin.Android world, we need a way for .NET 6 apps to support
multiple architectures.
A
HelloAndroid.csproj
targeting all architectures might look like:To achieve this, we can do a nested
<MSBuild/>
call:For a new target:
This is equivalent to what would happen in the legacy
_ResolveAssemblies
target.The linker then outputs files to:
One problem with this, is you receive multiple BCL assemblies for each
architecture:
I created a
<ProcessAssemblies/>
MSBuild task that checks the mvidof each assembly to detect duplicates. Non-duplicates will be placed
in a sub-directory within the
.apk
file, such as:assemblies\HelloAndroid.dll
assemblies\System.Linq.dll
assemblies\arm64-v8a\System.Private.CoreLib.dll
assemblies\armeabi-v7a\System.Private.CoreLib.dll
assemblies\x86\System.Private.CoreLib.dll
assemblies\x86_64\System.Private.CoreLib.dll
I had to make a few build & runtime changes for these ABI
sub-directories to work.
Other notes:
@(IntermediateAssembly)
from the outer build to thenested
<MSBuild/>
calls. Otherwise, the inner calls look forobj\Release\net5.0\android.21-arm\HelloAndroid.dll
instead ofobj\Release\net5.0\HelloAndroid.dll
that actually exists._ComputeFilesToPublishForRuntimeIdentifiers
was running some extratargets causing
<ResolveSdks/>
to run 5 times for 4 ABIs. I had tomake changes in
BuildOrder.targets
to fix this.<ResolveAssemblies/>
now sets%(IntermediateLinkerOutput)
oneach assembly item. This allows .NET 6 builds to support multiple
linker directories.