-
Couldn't load subscription status.
- Fork 561
Description
Android framework version
net10.0-android (Preview)
Affected platform version
.NET 10
Description
This is just a tracking issue for fully enabling R2R builds ie with marshalled methods enabled.
This should be similar to how Mono AOT tasks are run.
Investigation
SDK limitations
There are several limitations with running ReadyToRun build tasks in the same fashion as Mono AOT compiler tasks:
- ReadyToRun compilation requires publishing i.e.,
dotnet publishwhich is different from how Android SDK handles AOT compilation with Mono especially with universal apps enabling AOT compilation for all supported abis/rids as part of regular build iedotnet build. However, ReadyToRun and NativeAOT deployments are designed to be publish-only deployments and setting the properties which enable themPublishAot=truePublishReadyToRun=truedo not have any effect if the app is built withdotnet build. This is true on both desktop and iOS, triggering NativeAOT builds only happens with dotnet publish , dotnet build uses "regular" default runtimes/builds -> on desktop: CoreCLR is used, on iOS: Mono is used. For reference here is how it is handled in iOS SDK: https://github.com/dotnet/macios/blob/d936f060894801df6350b7f3fb1a42e02d74ced4/dotnet/targets/Xamarin.Shared.Sdk.props#L39 - When publishing with ReadyToRun enabled SDK required RID to be specified early on in the SDK, throwing with:
dotnet/sdk/10.0.100-preview.4.25180.3/Sdks/Microsoft.NET.Sdk/targets/Microsoft.NET.RuntimeIdentifierInference.targets(219,5): error NETSDK1191: A runtime identifier for the property 'PublishReadyToRun' couldn't be inferred. Specify a rid explicitly
Tentative list of possible approaches is provided below:
Approach 1
In the first Android SDK inner build (that runs ILLink), ReadyToRun targets must not run if we want to have postprocessing of assemblies as Mono.Cecil cannot modify mixed-mode assemblies. Disabling ReadyToRun targets can be accomplished by explicitly passing PublishReadyToRun=false as an additional property which would overwrite globally set PublishReadyToRun value. For example:
<PropertyGroup>
<!-- for some reason previous approach disabbles mono from running its AOT tasks.. --> <_PublishReadyToRunForInnerBuild Condition="'$(PublishReadyToRun)' == 'true'">PublishReadyToRun=false</_PublishReadyToRunForInnerBuild> </PropertyGroup>
</PropertyGroup>
<ItemGroup>
<_ProjectToBuild Include="$(MSBuildProjectFile)" AdditionalProperties="RuntimeIdentifier=%(_RIDs.Identity);$(_AdditionalProperties);$(_PublishReadyToRunForInnerBuild)" />
</ItemGroup>
<MSBuild Condition=" '$(DesignTimeBuild)' != 'true' " Projects="@(_ProjectToBuild)" BuildInParallel="$(_AndroidBuildRuntimeIdentifiersInParallel)" Targets="_ComputeFilesToPublishForRuntimeIdentifiers">
<Output TaskParameter="TargetOutputs" ItemName="ResolvedFileToPublish" />
</MSBuild>
Furthermore, ReadyToRun targets could run in a separate inner build which happens after _GenerateJavaStubs, similarly to Mono AOT compilation with the following changes, if it runs in the second inner build:
- We need to accommodate all required properties/items being properly resolved and set, like resolving crossgen packages, etc
- after it runs we need to rerun the majority of
_ResolveAssemblieswhich populates internally used MSBuild items and their metadata, since R2R targets are generating new assemblies. This needs to be handled with care as the targets running after AOT compilation rely on the fact internal MSBuild items are configured correctly.
For reference, here is a workaround which does not use the inner build for R2R compiler, but makes it work with marshalled methods generation: ivanpovazan/android@772de8e...36491ac
Approach 2
Move _GenerateJavaStubs into the first inner build, just after ILLink and before R2R MSBuild targets. This is probably more involved work considering dependencies of _GenerateJavaStubs but should be much more straight-forward in regard to running R2R targets at the right time of the build.
Final note
Once a solution is implemented marshal method generation should be reenabled with R2R builds:
android/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
Lines 345 to 347 in db84b3d
| <AndroidEnableMarshalMethods Condition=" '$(AndroidEnableMarshalMethods)' == '' and '$(_AndroidRuntime)' != 'NativeAOT' and '$(PublishReadyToRun)' != 'true' ">True</AndroidEnableMarshalMethods> | |
| <!-- NOTE: temporarily disable for NativeAOT for now, to get build passing --> | |
| <AndroidEnableMarshalMethods Condition=" '$(AndroidEnableMarshalMethods)' == '' and ('$(_AndroidRuntime)' == 'NativeAOT' or '$(PublishReadyToRun)' == 'true') ">False</AndroidEnableMarshalMethods> |