question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[question] supporting multiple $(RuntimeIdentifiers) in Xamarin

See original GitHub issue

This might also need changes in dotnet/runtime, but I’ll file here since it is mostly build related.

In https://github.com/xamarin/xamarin-android/pull/4767, I have an implementation that would enable:

<RuntimeIdentifiers>android.21-arm;android.21-arm64;android.21-x86;android.21-x64</RuntimeIdentifiers>

And you could build the project via:

> dotnet build HelloAndroid.csproj -p:Configuration=Release

This produces an Android HelloAndroid.apk file with contents such as:

assemblies\HelloAndroid.dll
assemblies\armeabi-v7a\System.Private.CoreLib.dll
assemblies\arm64-v8a\System.Private.CoreLib.dll
assemblies\x86\System.Private.CoreLib.dll
assemblies\x86_64\System.Private.CoreLib.dll
lib\armeabi-v7a\libmonosgen-2.0.so
lib\arm64-v8a\libmonosgen-2.0.so
lib\x86\libmonosgen-2.0.so
lib\x86_64\libmonosgen-2.0.so

You can install and run this .apk file on Android devices/emulators of any of the 4 architectures.

What I actually had to do to make this work, brings up several questions.

Is the mechanism I’m using to process multiple $(RuntimeIdentifier) the right idea?

At a high level, after Build we do something like:

<ItemGroup>
  <_RIDs Include="$(RuntimeIdentifiers)" />
</ItemGroup>
<MSBuild
    Projects="$(MSBuildProjectFile)"
    Targets="_ComputeFilesToPublishForRuntimeIdentifiers"
    Properties="RuntimeIdentifier=%(_RIDs.Identity)">
  <Output TaskParameter="TargetOutputs" ItemName="ResolvedFileToPublish" />
</MSBuild>

Against a new target we define:

<Target Name="_ComputeFilesToPublishForRuntimeIdentifiers"
    DependsOnTargets="ResolveReferences;ComputeFilesToPublish"
    Returns="@(ResolvedFileToPublish)">
</Target>

So in the example above with 4 architectures:

  1. Build occurs. Microsoft.Android.Sdk defaults $(AppendRuntimeIdentifierToOutputPath) to false. We only need a single HelloAndroid.dll and HelloAndroid.apk file.
  2. The <MSBuild/> task call runs for each RID.
  3. ILLink will run 4 times (once per RID). We get linker output into 4 distinct directories such as $(IntermediateOutputPath)$(RuntimeIdentifier)\linked\.
  4. --deterministic is passed to ILLink, so almost all of the BCL assemblies are duplicate across architectures.
  5. We have an MSBuild task that uses System.Reflection.Metadata to read the mvid of all assemblies. Any duplicates are removed, architecture-specific assemblies go in a sub-directory as described above.

Is this the right idea, in general? Is there a change in dotnet/sdk that could simplify this?

If we should deduplicate .NET assemblies, should the assemblies be identical across all runtime packs?

In a Debug build (or ILLink disabled), the deduplication does not work. The BCL assemblies in the runtime pack for each architecture are different. This results in a ~130MB .apk file.

But if I compare them:

$ monodis packages/microsoft.netcore.app.runtime.android-arm/5.0.0-preview.6.20264.1/runtimes/android-arm/lib/net5.0/System.IO.dll --module
Module Table (1..1)
1: System.IO.dll 1 {1D745C86-CC08-41A8-ABA5-F221F7BAD20D}
$ monodis packages/microsoft.netcore.app.runtime.android-arm64/5.0.0-preview.6.20264.1/runtimes/android-arm64/lib/net5.0/System.IO.dll --module
Module Table (1..1)
1: System.IO.dll 1 {B582D0AC-1AE7-4E41-8DF0-6938725B4ADB}

It looks like only the mvid differs, and none of the IL differs. Is this intentional or are these packages built with /p:Deterministic=false?

If a fix is needed for the runtime packs, I think this would be in dotnet/runtime.

/cc @dsplaisted @marek-safar @steveisok

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:7 (7 by maintainers)

github_iconTop GitHub Comments

1reaction
marek-safarcommented, Jun 10, 2020

@jonathanpeppers I think we don’t have the deterministic option enabled for illinker process libraries during runtime pack build step and that’s what is causing the different outputs.

0reactions
marek-safarcommented, Jun 11, 2020

@jonathanpeppers I think it should be we cannot enable it as it exposes Cecil bug we didn’t resolve yet

Read more comments on GitHub >

github_iconTop Results From Across the Web

Relationship between PlatformTarget and ...
One thing to be noted is when you have more than one RID like those in the sample above, you have to run...
Read more >
RuntimeIdentifiers error when multiple identifiers
Hi,. I'm facing the following error when I have more than one rutimeidentifier: The project 'XXXXXXXXX' ran into a problem during the last ......
Read more >
Chapter 11. Multiple frameworks and runtimes - .NET Core in ...
NET Core SDK support multiple frameworks and runtimes? The .NET Core SDK supports ... NET Framework, Xamarin Forms, and Universal Windows Applications.
Read more >
Questions - Microsoft Q&A
Hi, I am migrating xamarin forms project to .net maui.as part of migration i am changing the iOS .csproj. I have changed the...
Read more >
Multi-Targeting and Porting a .NET Library to .NET Core 2.0
I've been holding off porting any of my full frameworks to .NET Core. With the latest .NET Core 2.0 and .NET Standard 2.0...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found