Skip to content

Deterministic MVIDs is needed for assemblies referencing System.Private.CoreLib across different architectures #67660

Closed

Description

We're hitting an issue where the MVID of assemblies is different depending on the architecture of the runtime pack, e.g. x64 vs. arm64, for assemblies that are 100% managed code like System.Collections.dll or System.Private.Uri.dll but compile against System.Private.CoreLib.

This causes an issue for Xamarin Android and other internal teams that use the MVID to deduplicate assemblies that are the same across architectures (right now only System.Private.CoreLib.dll is actually architecture-specific).

The reason this is showing up now is because of a linker/Cecil fix (dotnet/linker#2203, dotnet/cecil#31) which fixes the PDB ID calculation which in turn affects the MVID calculation (we actually just got lucky in net6 since we run the linker against all assemblies in the libraries build which "unified" the MVID).

Since the PDB is storing the MVID of all assembly references in "Compilation Metadata References" (described in https://github.com/dotnet/runtime/blob/424a09cb81c678fb1ba1c27211b80aba2de070ad/docs/design/specs/PortablePdb-Metadata.md#CompilationMetadataReferences) we now get a different MVID on the assemblies because these projects compile directly against System.Private.CoreLib.dll whose MVID gets embedded in the PDB:
PDB

There is interest to backport the linker/Cecil fix to net6 so I discussed with @vitek-karas and we agreed the least invasive change is to simply hardcode System.Private.CoreLib.dll as the only architecture-specific assembly in Xamarin Android for net6. EDIT it turns out this plan won't work since the Mono AOT compiler verifies the MVIDs of assembly references and will error out if they don't match with the actual assembly.

For net7/net8 we'd like to come up with a "proper" fix though, some ideas:

  • Create a reference assembly for System.Private.CoreLib and compile against that one, instead of the real assembly
    • I tried using Roslyn's /refout feature but the reference assembly created by it still differs between architectures since Roslyn includes private fields like Padding.cs#L9-L16, so this'd likely need to be a real reference assembly
  • Make System.Private.CoreLib architecture-agnostic by removing all of the TARGET_64BIT and TARGET_32BIT ifdefs.
  • Tweak the (official) build so we only ever build the non-architecture-specific assemblies once and copy them into the respective runtime packs, ensuring that we only have a single version of the assemblies
    • As an extension we could split out the assemblies into another package, so they're not duplicated in the runtime packs. This would also help reducing download size.

/cc @ViktorHofer @vitek-karas @agocke @marek-safar @steveisok

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Type

No type

Projects

  • Status

    Done

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions