-
Notifications
You must be signed in to change notification settings - Fork 556
attempt to fix dotnet/maui#17265 #8416
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
Context: dotnet/maui#17265 Reproduced the issue in a new `FixLegacyResourceDesignerStep` test. It crashes at runtime, but if you change the class libraries in the test to `net8.0`, it works fine. I first attempted to fix the problem for `Release` mode, as it seemed easier to do a "second pass" on *all assemblies* at the end of a linker step. This change starts to work: ILLink: Library2 has an assembly reference to Library1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null ILLink: Library2 has an assembly reference with a designer. ILLink: Adding reference _Microsoft.Android.Resource.Designer. ILLink: FixupAssemblyTypes Library2. ILLink: Looking for String::hello. ILLink: Fixing up System.Int32 Foo::get_Hello() ILLink: Replacing IL_0000: ldsfld System.Int32 Library1.Resource/String::hello ILLink: With IL_0000: call System.Int32 _Microsoft.Android.Resource.Designer.Resource/String::get_hello() But then fails with: System.ArgumentException: Member 'System.Int32 _Microsoft.Android.Resource.Designer.Resource/String::get_hello()' is declared in another module and needs to be imported
src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs
Outdated
Show resolved
Hide resolved
src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs
Outdated
Show resolved
Hide resolved
@dellis1972: had an alternate "brilliant idea" for how to solve this: heuristics and "manual resolution". We don't want to read all IL for all assemblies, as we believe that'll be slow. However, we already process certain assembly metadata for all assemblies, just to view the assembly references. I thus propose using
I need to try to prototype this, but for comparison consider: % monodis --memberref ~/.nuget/packages/syncfusion.maui.core/22.2.12/lib/net7.0-android30.0/Syncfusion.Maui.Core.dll
…
1341: TypeRef[472] scrollViewTheme
Resolved: [Microsoft.Maui]Microsoft.Maui.Resource/Style.scrollViewTheme
Signature: int32
If we do this in a place which already has a |
So haha we don't want to try to resolve everything, because Cecil can't resolve everything. In an intermediate version of the patch I'm cooking up, it's trying to fixup
I have no idea what This impacts like everything:
etc. Thus I'm going with the heuristic of "memberRef declaring type contains |
@dellis1972: here's my current patch. it's a mess. :-) diff --git a/external/xamarin-android-tools b/external/xamarin-android-tools
--- a/external/xamarin-android-tools
+++ b/external/xamarin-android-tools
@@ -1 +1 @@
-Subproject commit 8a971d94a3fa2f0e8f69c5cf742c6836c14be1cd
+Subproject commit 8a971d94a3fa2f0e8f69c5cf742c6836c14be1cd-dirty
diff --git a/src/Mono.Android/Xamarin.Android.Net/AndroidMessageHandler.cs b/src/Mono.Android/Xamarin.Android.Net/AndroidMessageHandler.cs
index 6804db9ce..605d5268e 100644
--- a/src/Mono.Android/Xamarin.Android.Net/AndroidMessageHandler.cs
+++ b/src/Mono.Android/Xamarin.Android.Net/AndroidMessageHandler.cs
@@ -337,6 +337,7 @@ namespace Xamarin.Android.Net
protected override void Dispose (bool disposing)
{
+ global::System.Console.WriteLine ($"# jonp: AndroidMessageHandler.Dispose ({disposing}): {new System.Diagnostics.StackTrace (true)}");
disposed = true;
base.Dispose (disposing);
diff --git a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/FixLegacyResourceDesignerStep.cs b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/FixLegacyResourceDesignerStep.cs
index 793320858..0849f5ea5 100644
--- a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/FixLegacyResourceDesignerStep.cs
+++ b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/FixLegacyResourceDesignerStep.cs
@@ -35,6 +35,7 @@ namespace MonoDroid.Tuner
protected override void EndProcess ()
{
base.EndProcess ();
+ LogMessage ($"# jonp: FixLegacyResourceDesignerStep.EndProcess");
if (designerAssembly != null) {
LogMessage ($" Setting Action on {designerAssembly.Name} to Link.");
@@ -72,6 +73,7 @@ namespace MonoDroid.Tuner
internal override bool ProcessAssemblyDesigner (AssemblyDefinition assembly, TypeDefinition designer = null)
{
+ LogMessage ($"# jonp: FixLegacyResourceDesignerStep.ProcessAssemblyDesigner: assembly={assembly?.FullName}, designer={designer?.FullName}");
if (designer is not null) {
LogMessage ($" {assembly.Name.Name} has an assembly reference with a designer.");
} else if (!FindResourceDesigner (assembly, mainApplication: false, out designer, out _)) {
@@ -86,6 +88,8 @@ namespace MonoDroid.Tuner
}
}
+ LogMessage ($"# jonp: FixLegacyResourceDesignerStep.ProcessAssemblyDesigner: fixing up? {assembly?.FullName}");
+
// This is expected for the first call, in <LinkAssembliesNoShrink/>
if (!designerLoaded)
LoadDesigner ();
diff --git a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs
index 292ac2401..c428f250e 100644
--- a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs
+++ b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs
@@ -42,6 +42,7 @@ namespace MonoDroid.Tuner {
internal bool FindResourceDesigner (AssemblyDefinition assembly, bool mainApplication, out TypeDefinition designer, out CustomAttribute designerAttribute)
{
+ LogMessage ($"# jonp: LinkDesignerBase.FindResourceDesigner: looking at assembly: {assembly.FullName}; mainApplication={mainApplication}");
string designerFullName = null;
designer = null;
designerAttribute = null;
@@ -65,6 +66,7 @@ namespace MonoDroid.Tuner {
}
}
+#if false
if (string.IsNullOrEmpty(designerFullName)) {
// Check for known designers which have been removed.
foreach (var knownDesigner in KnownDesignerAssemblies) {
@@ -76,6 +78,34 @@ namespace MonoDroid.Tuner {
}
return false;
}
+#endif
+
+ var memberRefs = assembly.MainModule.GetMemberReferences ().ToList ();
+ LogMessage ($"# jonp: LinkDesignerBase.FindResourceDesigner: looking at assembly: {assembly.FullName}; memberRefs.Count={memberRefs.Count}");
+ var memberIdx = 0;
+ foreach (var memberRef in memberRefs) {
+ memberIdx++;
+ if (!memberRef.DeclaringType?.ToString()?.Contains (".Resource/") ?? true) {
+ continue;
+ }
+ LogMessage ($"# jonp: memberRefs[{memberIdx}].Name={memberRef?.Name}; .FullName={memberRef.FullName}; .DeclaringType={memberRef.DeclaringType}");
+ var resolved = false;
+ try {
+ var def = memberRef.Resolve ();
+ resolved = def != null;
+ LogMessage ($"# jonp: memberRef '{memberRef?.Name}' resolved to: {def?.FullName} [{def != null} {def?.GetType().FullName}]");
+ }
+ catch (Exception _ex) {
+ LogMessage ($"# jonp: exception resolving memberRef {memberRef?.Name}! {_ex}");
+ resolved = false;
+ }
+ if (!resolved) {
+ LogMessage ($"# jonp: Adding _Linker.Generated.Resource to {assembly.Name.Name}");
+ designer = new TypeDefinition ("_Linker.Generated", "Resource", TypeAttributes.Public | TypeAttributes.AnsiClass);
+ designer.BaseType = new TypeDefinition ("System", "Object", TypeAttributes.Public | TypeAttributes.AnsiClass);
+ return true;
+ }
+ }
foreach (ModuleDefinition module in assembly.Modules)
{
@@ -239,6 +269,7 @@ namespace MonoDroid.Tuner {
protected override void EndProcess ()
{
+ LogMessage ($"# jonp: LinkDesignerBase.EndProcess; processedAssemblies.Count={processedAssemblies.Count}; allAssemblies.Count={allAssemblies.Count}");
// This is a "second pass" to fix assemblies with references to assemblies with a designer
if (processedAssemblies.Count > 0) {
foreach (var assembly in allAssemblies) {
@@ -249,12 +280,14 @@ namespace MonoDroid.Tuner {
if (action == AssemblyAction.Delete)
continue;
+ #if false
foreach (var processedAssembly in processedAssemblies) {
if (ProcessAssemblyDesignerSecondPass (assembly, processedAssembly) &&
(action == AssemblyAction.Skip || action == AssemblyAction.Copy)) {
Annotations.SetAction (assembly, AssemblyAction.Save);
}
}
+ #endif
}
}
}
diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.ILLink.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.ILLink.targets
index 880c3abc4..13201ec7a 100644
--- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.ILLink.targets
+++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.ILLink.targets
@@ -45,7 +45,9 @@ This file contains the .NET 5-specific targets to customize ILLink
Include="ProguardConfiguration"
Value="$(_ProguardProjectConfiguration)"
/>
+ <!--
<_TrimmerCustomData Include="AndroidKnownDesignerAssemblies" Value="@(AndroidKnownDesignerAssemblies)" />
+ -->
<!--
Used for the <ILLink CustomSteps="@(_TrimmerCustomSteps)" /> value: Most importantly, it doesn't work. I don't know why. Anyway, repro:
where The good: it appropriately detects that
So, yay, we found it. Additionally, the assemblies we want to fixup aren't "bananas": no
(Though we do want to fixup …but also this is concerning:
This weird me out, and is quite concerning. Meanwhile, previously I wrote "it doesn't work." By that I mean that while we detect that the assembly needs fixing up, it is not in fact fixed up. Which is bizarre, because |
With the addition of ever more …oh, because of: which, because we "invent" the Resource type, will never match. Consequently, |
Updated. With this New (delusions of "final" except for all the printfs) patch, diff --git a/external/xamarin-android-tools b/external/xamarin-android-tools
--- a/external/xamarin-android-tools
+++ b/external/xamarin-android-tools
@@ -1 +1 @@
-Subproject commit 8a971d94a3fa2f0e8f69c5cf742c6836c14be1cd
+Subproject commit 8a971d94a3fa2f0e8f69c5cf742c6836c14be1cd-dirty
diff --git a/src/Mono.Android/Xamarin.Android.Net/AndroidMessageHandler.cs b/src/Mono.Android/Xamarin.Android.Net/AndroidMessageHandler.cs
index 6804db9ce..605d5268e 100644
--- a/src/Mono.Android/Xamarin.Android.Net/AndroidMessageHandler.cs
+++ b/src/Mono.Android/Xamarin.Android.Net/AndroidMessageHandler.cs
@@ -337,6 +337,7 @@ namespace Xamarin.Android.Net
protected override void Dispose (bool disposing)
{
+ global::System.Console.WriteLine ($"# jonp: AndroidMessageHandler.Dispose ({disposing}): {new System.Diagnostics.StackTrace (true)}");
disposed = true;
base.Dispose (disposing);
diff --git a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/FixLegacyResourceDesignerStep.cs b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/FixLegacyResourceDesignerStep.cs
index 793320858..6078a6585 100644
--- a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/FixLegacyResourceDesignerStep.cs
+++ b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/FixLegacyResourceDesignerStep.cs
@@ -35,6 +35,7 @@ namespace MonoDroid.Tuner
protected override void EndProcess ()
{
base.EndProcess ();
+ LogMessage ($"# jonp: FixLegacyResourceDesignerStep.EndProcess");
if (designerAssembly != null) {
LogMessage ($" Setting Action on {designerAssembly.Name} to Link.");
@@ -72,6 +73,7 @@ namespace MonoDroid.Tuner
internal override bool ProcessAssemblyDesigner (AssemblyDefinition assembly, TypeDefinition designer = null)
{
+ LogMessage ($"# jonp: FixLegacyResourceDesignerStep.ProcessAssemblyDesigner: assembly={assembly?.FullName}, designer={designer?.FullName}");
if (designer is not null) {
LogMessage ($" {assembly.Name.Name} has an assembly reference with a designer.");
} else if (!FindResourceDesigner (assembly, mainApplication: false, out designer, out _)) {
@@ -86,6 +88,8 @@ namespace MonoDroid.Tuner
}
}
+ LogMessage ($"# jonp: FixLegacyResourceDesignerStep.ProcessAssemblyDesigner: fixing up? {assembly?.FullName}");
+
// This is expected for the first call, in <LinkAssembliesNoShrink/>
if (!designerLoaded)
LoadDesigner ();
@@ -145,6 +149,7 @@ namespace MonoDroid.Tuner
protected override void FixBody (MethodBody body, TypeDefinition designer)
{
+ LogMessage ($"# jonp: FixLegacyResourceDesignerStep.FixBody: body={body?.Method?.FullName}, designer={designer?.FullName}");
// replace
// IL_0068: ldsfld int32 Xamarin.Forms.Platform.Android.Resource/Layout::Toolbar
// with
@@ -156,10 +161,8 @@ namespace MonoDroid.Tuner
{
if (i.OpCode != OpCodes.Ldsfld)
continue;
- string line = i.ToString ();
- int idx = line.IndexOf (designerFullName, StringComparison.Ordinal);
- if (idx >= 0) {
- string key = line.Substring (idx + designerFullName.Length);
+ var key = GetFixupKey (i, designerFullName);
+ if (key != null) {
LogMessage ($"Looking for {key}.");
var found = lookup.TryGetValue (key, out MethodDefinition method);
if (!found) {
@@ -192,5 +195,34 @@ namespace MonoDroid.Tuner
processor.Replace(i.Key, i.Value);
}
}
+
+ string GetFixupKey (Instruction instruction, string designerFullName)
+ {
+ string line = instruction.ToString ();
+ LogMessage ($" jonp: GetFixupKey: looking at instruction: {line}");
+ int idx = line.IndexOf (designerFullName, StringComparison.Ordinal);
+ if (idx >= 0) {
+ return line.Substring (idx + designerFullName.Length);
+ }
+ LogMessage ($" jonp: GetFixupKey: instruction.Operand is {instruction.Operand?.GetType ()}");
+ if (instruction.Operand is FieldReference fieldRef &&
+ (fieldRef.DeclaringType?.ToString()?.Contains (".Resource/") ?? false)) {
+ var canResolve = false;
+ try {
+ var resolved = fieldRef.Resolve ();
+ canResolve = resolved != null;
+ } catch (Exception) {
+ }
+ if (canResolve)
+ return null;
+ var type = fieldRef.DeclaringType.FullName;
+ var s = type.LastIndexOf ('/');
+ type = type.Substring (s + 1);
+ var key = type + "::" + fieldRef.Name;
+ LogMessage ($" jonp: GetFixupKey: .Resource/ heuristic; key={key}");
+ return key;
+ }
+ return null;
+ }
}
}
diff --git a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs
index 292ac2401..cde68f7de 100644
--- a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs
+++ b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs
@@ -42,6 +42,7 @@ namespace MonoDroid.Tuner {
internal bool FindResourceDesigner (AssemblyDefinition assembly, bool mainApplication, out TypeDefinition designer, out CustomAttribute designerAttribute)
{
+ LogMessage ($"# jonp: LinkDesignerBase.FindResourceDesigner: looking at assembly: {assembly.FullName}; mainApplication={mainApplication}");
string designerFullName = null;
designer = null;
designerAttribute = null;
@@ -65,6 +66,7 @@ namespace MonoDroid.Tuner {
}
}
+#if false
if (string.IsNullOrEmpty(designerFullName)) {
// Check for known designers which have been removed.
foreach (var knownDesigner in KnownDesignerAssemblies) {
@@ -76,6 +78,34 @@ namespace MonoDroid.Tuner {
}
return false;
}
+#endif
+
+ var memberRefs = assembly.MainModule.GetMemberReferences ().ToList ();
+ LogMessage ($"# jonp: LinkDesignerBase.FindResourceDesigner: looking at assembly: {assembly.FullName}; memberRefs.Count={memberRefs.Count}");
+ var memberIdx = 0;
+ foreach (var memberRef in memberRefs) {
+ memberIdx++;
+ if (!memberRef.DeclaringType?.ToString()?.Contains (".Resource/") ?? true) {
+ continue;
+ }
+ LogMessage ($"# jonp: memberRefs[{memberIdx}].Name={memberRef?.Name}; .FullName={memberRef.FullName}; .DeclaringType={memberRef.DeclaringType}");
+ var resolved = false;
+ try {
+ var def = memberRef.Resolve ();
+ resolved = def != null;
+ LogMessage ($"# jonp: memberRef '{memberRef?.Name}' resolved to: {def?.FullName} [{def != null} {def?.GetType().FullName}]");
+ }
+ catch (Exception _ex) {
+ LogMessage ($"# jonp: exception resolving memberRef {memberRef?.Name}! {_ex}");
+ resolved = false;
+ }
+ if (!resolved) {
+ LogMessage ($"# jonp: Adding _Linker.Generated.Resource to {assembly.Name.Name}");
+ designer = new TypeDefinition ("_Linker.Generated", "Resource", TypeAttributes.Public | TypeAttributes.AnsiClass);
+ designer.BaseType = new TypeDefinition ("System", "Object", TypeAttributes.Public | TypeAttributes.AnsiClass);
+ return true;
+ }
+ }
foreach (ModuleDefinition module in assembly.Modules)
{
@@ -133,6 +163,7 @@ namespace MonoDroid.Tuner {
protected void FixType (TypeDefinition type, TypeDefinition localDesigner)
{
+ LogMessage ($"# jonp: LinkDesignerBase.FixType: type={type.FullName}; localDesigner={localDesigner.FullName}");
foreach (MethodDefinition method in type.Methods)
{
if (!method.HasBody)
@@ -200,6 +231,7 @@ namespace MonoDroid.Tuner {
protected void FixupAssemblyTypes (AssemblyDefinition assembly, TypeDefinition designer)
{
+ LogMessage ($"# jonp: LinkDesignerBase.FixupAssemblyTypes; assembly={assembly.FullName}; designer={designer.FullName}");
foreach (ModuleDefinition module in assembly.Modules)
{
foreach (TypeDefinition type in module.Types)
@@ -239,6 +271,7 @@ namespace MonoDroid.Tuner {
protected override void EndProcess ()
{
+ LogMessage ($"# jonp: LinkDesignerBase.EndProcess; processedAssemblies.Count={processedAssemblies.Count}; allAssemblies.Count={allAssemblies.Count}");
// This is a "second pass" to fix assemblies with references to assemblies with a designer
if (processedAssemblies.Count > 0) {
foreach (var assembly in allAssemblies) {
@@ -249,12 +282,14 @@ namespace MonoDroid.Tuner {
if (action == AssemblyAction.Delete)
continue;
+ #if false
foreach (var processedAssembly in processedAssemblies) {
if (ProcessAssemblyDesignerSecondPass (assembly, processedAssembly) &&
(action == AssemblyAction.Skip || action == AssemblyAction.Copy)) {
Annotations.SetAction (assembly, AssemblyAction.Save);
}
}
+ #endif
}
}
}
diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.ILLink.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.ILLink.targets
index 880c3abc4..13201ec7a 100644
--- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.ILLink.targets
+++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.ILLink.targets
@@ -45,7 +45,9 @@ This file contains the .NET 5-specific targets to customize ILLink
Include="ProguardConfiguration"
Value="$(_ProguardProjectConfiguration)"
/>
+ <!--
<_TrimmerCustomData Include="AndroidKnownDesignerAssemblies" Value="@(AndroidKnownDesignerAssemblies)" />
+ -->
<!--
Used for the <ILLink CustomSteps="@(_TrimmerCustomSteps)" /> value: |
if (!FindResourceDesigner (assembly, mainApplication: false, out TypeDefinition designer, out CustomAttribute designerAttribute)) { | ||
if (designer is not null) { | ||
LogMessage ($" {assembly.Name.Name} has an assembly reference with a designer."); | ||
} else if (!FindResourceDesigner (assembly, mainApplication: false, out designer, out _)) { |
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 hitting "perfect is the enemy of the good" territory -- so don't take this comment as a suggestion to change anything -- but I don't like the code flow here:
- It requires that
FindResourceDesigner
create a newTypeDefinition
instance, even though that instance shouldn't be used for anything, and ideally should be linked away entirely. - I suspect we could have/create a scenario in which an assembly references multiple
Resource
types, in which case returning one type -- if that type were used for anything -- would be inappropriate.
This complaint likely isn't worth addressing now, I just wanted to comment on it.
The "new fix" doesn't require us to touch as much code. I could restore much of the original code to make the diff smaller.
Draft commit message: [Xamarin.Android.Build.Tasks] Fixup indirect resource references (#8416)
Fixes: https://github.com/dotnet/maui/issues/17265
Context: dc3ccf28cdbe9f8c0a705400b83c11a85c81a980
Context: https://github.com/Zack-G-I-T/SfListView.Net8Bug/tree/ecb25af3329391858d1d64c4875ca58771e2b66c
Commit dc3ccf28 completely reworked how Android Resources work,
moving from a `$(RootNamespace).Resource` type which contained fields
(which needed to be updated at runtime across numerous assemblies)
to a "`_Microsoft.Android.Resource.Designer` reference assembly"
which contained *methods* for each Resource id.
To maintain backward compatibility, pre-.NET 8 assemblies were
rewritten so that instead of accessing fields:
ldsfld int32 $(RootNamespace).Resource/Layout::Toolbar
they became method calls:
call int32 [_Microsoft.Android.Resource.Designer]_Microsoft.Android.Resource.Designer.Resource/Layout::get_Toolbar()
Unfortunately we encountered a missing corner case: the previous
fixup logic only operated on assemblies that themselves contained a
`$(RootNamespace).Resource` type, which in turn (generally) required
that the assembly be built from a project that had
`@(AndroidResource)` items.
In dotnet/maui#17265 and Zack-G-I-T/SfListView.Net8Bug, we
encountered an assembly that:
1. Did *not* contain a `Resource` type, and
2. Used Resource ids from other assemblies, and
3. Was a .NET 7 assembly, so it and its dependencies were all using
the .NET 7 field-based Resource approach.
Setup:
* `Ako` and `Bko` are net7.0-android projects which contain an
`@(AndroidResource)`
* `RefsLibs` is a net7.0-android project which references `Ako` and
`Bko`, and uses the Resource values from them.
* `App` is a net8.0-android project which references `RefsLibs`.
"Repro" setup:
dotnet new androidlib -n Ako
# Set `$(TargetFramework)`=net7.0-android
# Add Ako/Resources/values/strings.xml with String resource ako_name
dotnet new androidlib -n Bko
# Set `$(TargetFramework)`=net7.0-android
# Add Bko/Resources/values/strings.xml with String resource bko_name
dotnet new androidlib -n RefsLibs
# Set `$(TargetFramework)`=net7.0-android
# Add ProjectReference to ..\Ako\Ako.csproj, ..\Bko\Bko.csproj
# Update `RefsLibs\Class1.cs` to use Ako.Resource.String.ako_name, Bko.Resource.String.bko_name
dotnet new android -n App
# *Remains* `$(TargetFramework)`=net8.0-android
# Add ProjectReference to ..\RefsLibs\RefsLibs.csproj
The punch:
dotnet build App/App.csproj -p:Configuration=Release
This fails to build with .NET 8 RC1:
ILLink : error IL1013: Error processing '/Users/jon/Downloads/dotnet-sdk-8.0.100-rc.1.23455.8-osx-x64/packs/Microsoft.Android.Sdk.Darwin/34.0.0-rc.1.432/targets/../PreserveLists/Mono.Android.xml'.
Fatal error in IL Linker
Unhandled exception. Mono.Linker.LinkerFatalErrorException: ILLink: error IL1013: Error processing '/Users/jon/Downloads/dotnet-sdk-8.0.100-rc.1.23455.8-osx-x64/packs/Microsoft.Android.Sdk.Darwin/34.0.0-rc.1.432/targets/../PreserveLists/Mono.Android.xml'.
---> System.ArgumentNullException: Value cannot be null. (Parameter 'key')
at System.Collections.Generic.Dictionary`2.TryInsert(TKey key, TValue value, InsertionBehavior behavior)
at System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value)
…
…/build/Microsoft.NET.ILLink.targets(87,5): error NETSDK1144: Optimizing assemblies for size failed. Optimization can be disabled by setting the PublishTrimmed property to false.
"Interestingly", it *succeeds* with .NET 8 RC2 (no build errors).
Regardless, with both .NET 8 RC1 and RC2, the app is *broken*:
% dotnet tool install --global dotnet-ilverify
% $HOME/.dotnet/tools/ilverify App/obj/Release/net8.0-android/android-arm/linked/RefsLibs.dll \
--tokens --system-module System.Private.CoreLib \
-r 'App/obj/Release/net8.0-android/android-arm/linked/*.dll'
[IL]: Error [ClassLoadGeneral]: […/App/obj/Release/net8.0-android/android-arm/linked/RefsLibs.dll : RefsLibs.Class1::.ctor()] Failed to load type 'String' from assembly 'Ako, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'
[IL]: Error [CallCtor]: […/App/obj/Release/net8.0-android/android-arm/linked/RefsLibs.dll : RefsLibs.Resource::.ctor()][offset 0x00000001] call to .ctor only allowed to initialize this pointer from within a .ctor. Try newobj.
[IL]: Error [ThisUninitReturn]: […/App/obj/Release/net8.0-android/android-arm/linked/RefsLibs.dll : RefsLibs.Resource::.ctor()][offset 0x00000006] Return from .ctor when this is uninitialized.
3 Error(s) Verifying …/App/obj/Release/net8.0-android/android-arm/linked/RefsLibs.dll
If you disassemble `RefsLibs.dll`, you find that it's using `ldsfld`,
not `call`:
% ikdasm App/obj/Release/net8.0-android/android-arm/linked/RefsLibs.dll
…
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 29 (0x1d)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldsfld int32 [Ako]Ako.Resource/String::ako_name
IL_0006: stfld int32 RefsLibs.Class1::a
IL_000b: ldarg.0
IL_000c: ldsfld int32 [Bko]Bko.Resource/String::bko_name
IL_0011: stfld int32 RefsLibs.Class1::b
IL_0016: ldarg.0
IL_0017: call instance void [System.Private.CoreLib]System.Object::.ctor()
IL_001c: ret
} // end of method Class1::.ctor
If you attempt to run the .NET 8 RC2 build, it fails at runtime:
I MonoDroid: android.runtime.JavaProxyThrowable: [System.TypeLoadException]: Arg_TypeLoadException
I MonoDroid: at App.MainActivity.OnCreate(Unknown Source:0)
I MonoDroid: at Android.App.Activity.n_OnCreate_Landroid_os_Bundle_(Unknown Source:0)
The problem is that `RefsLibs.dll` isn't being fixed up as part of
dc3ccf28, because it doesn't contain any `@(AndroidResource)` values
or an `[assembly: ResourceDesigner]` custom attribute.
`RefsLibs.dll` is "free floating", with nothing to indicate that it
needs to be updated.
Fix this scenario by updating `LinkDesignerBase` to "sanity check"
all "Resource-like" member references which cannot be resolved.
Consider:
% monodis --memberref RefsLibs/bin/Release/net7.0-android/RefsLibs.dll
…
18: TypeRef[23] ako_name
Resolved: [Ako]Ako.Resource/String.ako_name
Signature: int32
19: TypeRef[25] bko_name
Resolved: [Bko]Bko.Resource/String.bko_name
Signature: int32
These are field references. In the context of .NET 8/dc3ccf28, these
fields *will not exist*; they cannot be resolved. `LinkDesignerBase`
will check the member references table of *all* assemblies included
in the app, and if any member references contain a declaring type
which contains `.Resource/` *and* that member reference cannot be
resolved, we will assume that it is an `@(AndroidReference)` and
replace it with a `call` to the appropriate method.
With the fix in place, `ilverify` no longer reports
`Error [ClassLoadGeneral]`, and `ikdasm` shows:
% ikdasm App/obj/Release/net8.0-android/android-arm/linked/RefsLibs.dll
…
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 29 (0x1d)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call int32 [_Microsoft.Android.Resource.Designer]_Microsoft.Android.Resource.Designer.Resource/String::get_ako_name()
IL_0006: stfld int32 RefsLibs.Class1::a
IL_000b: ldarg.0
IL_000c: call int32 [_Microsoft.Android.Resource.Designer]_Microsoft.Android.Resource.Designer.Resource/String::get_bko_name()
IL_0011: stfld int32 RefsLibs.Class1::b
IL_0016: ldarg.0
IL_0017: call instance void [System.Private.CoreLib]System.Object::.ctor()
IL_001c: ret
} // end of method Class1::.ctor
Note that the .NET 7 `ldsfld` has been replaced with `call`.
Co-authored-by: Dean Ellis <[email protected]> |
src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs
Outdated
Show resolved
Hide resolved
Hi Guys - this issue is effecting me .... any ideas when this will be available to try? (or if there is a way to try it now then please let me know how :) ) |
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 looks good to me.
You can use the |
Fixes: dotnet/maui#17265 Context: dc3ccf2 Context: https://github.com/Zack-G-I-T/SfListView.Net8Bug/tree/ecb25af3329391858d1d64c4875ca58771e2b66c Commit dc3ccf2 completely reworked how Android Resources work, moving from a `$(RootNamespace).Resource` type which contained fields (which needed to be updated at runtime across numerous assemblies) to a "`_Microsoft.Android.Resource.Designer` reference assembly" which contained *methods* for each Resource id. To maintain backward compatibility, pre-.NET 8 assemblies were rewritten so that instead of accessing fields: ldsfld int32 $(RootNamespace).Resource/Layout::Toolbar they became method calls: call int32 [_Microsoft.Android.Resource.Designer]_Microsoft.Android.Resource.Designer.Resource/Layout::get_Toolbar() Unfortunately we encountered a missing corner case: the previous fixup logic only operated on assemblies that themselves contained a `$(RootNamespace).Resource` type, which in turn (generally) required that the assembly be built from a project that had `@(AndroidResource)` items. In dotnet/maui#17265 and Zack-G-I-T/SfListView.Net8Bug, we encountered an assembly that: 1. Did *not* contain a `Resource` type, and 2. Used Resource ids from other assemblies, and 3. Was a .NET 7 assembly, so it and its dependencies were all using the .NET 7 field-based Resource approach. Setup: * `Ako` and `Bko` are net7.0-android projects which contain an `@(AndroidResource)` * `RefsLibs` is a net7.0-android project which references `Ako` and `Bko`, and uses the Resource values from them. * `App` is a net8.0-android project which references `RefsLibs`. "Repro" setup: dotnet new androidlib -n Ako # Set `$(TargetFramework)`=net7.0-android # Add Ako/Resources/values/strings.xml with String resource ako_name dotnet new androidlib -n Bko # Set `$(TargetFramework)`=net7.0-android # Add Bko/Resources/values/strings.xml with String resource bko_name dotnet new androidlib -n RefsLibs # Set `$(TargetFramework)`=net7.0-android # Add ProjectReference to ..\Ako\Ako.csproj, ..\Bko\Bko.csproj # Update `RefsLibs\Class1.cs` to use Ako.Resource.String.ako_name, Bko.Resource.String.bko_name dotnet new android -n App # *Remains* `$(TargetFramework)`=net8.0-android # Add ProjectReference to ..\RefsLibs\RefsLibs.csproj The punch: dotnet build App/App.csproj -p:Configuration=Release This fails to build with .NET 8 RC1: ILLink : error IL1013: Error processing '/Users/jon/Downloads/dotnet-sdk-8.0.100-rc.1.23455.8-osx-x64/packs/Microsoft.Android.Sdk.Darwin/34.0.0-rc.1.432/targets/../PreserveLists/Mono.Android.xml'. Fatal error in IL Linker Unhandled exception. Mono.Linker.LinkerFatalErrorException: ILLink: error IL1013: Error processing '/Users/jon/Downloads/dotnet-sdk-8.0.100-rc.1.23455.8-osx-x64/packs/Microsoft.Android.Sdk.Darwin/34.0.0-rc.1.432/targets/../PreserveLists/Mono.Android.xml'. ---> System.ArgumentNullException: Value cannot be null. (Parameter 'key') at System.Collections.Generic.Dictionary`2.TryInsert(TKey key, TValue value, InsertionBehavior behavior) at System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value) … …/build/Microsoft.NET.ILLink.targets(87,5): error NETSDK1144: Optimizing assemblies for size failed. Optimization can be disabled by setting the PublishTrimmed property to false. "Interestingly", it *succeeds* with .NET 8 RC2 (no build errors). Regardless, with both .NET 8 RC1 and RC2, the app is *broken*: % dotnet tool install --global dotnet-ilverify % $HOME/.dotnet/tools/ilverify App/obj/Release/net8.0-android/android-arm/linked/RefsLibs.dll \ --tokens --system-module System.Private.CoreLib \ -r 'App/obj/Release/net8.0-android/android-arm/linked/*.dll' [IL]: Error [ClassLoadGeneral]: […/App/obj/Release/net8.0-android/android-arm/linked/RefsLibs.dll : RefsLibs.Class1::.ctor()] Failed to load type 'String' from assembly 'Ako, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' [IL]: Error [CallCtor]: […/App/obj/Release/net8.0-android/android-arm/linked/RefsLibs.dll : RefsLibs.Resource::.ctor()][offset 0x00000001] call to .ctor only allowed to initialize this pointer from within a .ctor. Try newobj. [IL]: Error [ThisUninitReturn]: […/App/obj/Release/net8.0-android/android-arm/linked/RefsLibs.dll : RefsLibs.Resource::.ctor()][offset 0x00000006] Return from .ctor when this is uninitialized. 3 Error(s) Verifying …/App/obj/Release/net8.0-android/android-arm/linked/RefsLibs.dll If you disassemble `RefsLibs.dll`, you find that it's using `ldsfld`, not `call`: % ikdasm App/obj/Release/net8.0-android/android-arm/linked/RefsLibs.dll … .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { // Code size 29 (0x1d) .maxstack 8 IL_0000: ldarg.0 IL_0001: ldsfld int32 [Ako]Ako.Resource/String::ako_name IL_0006: stfld int32 RefsLibs.Class1::a IL_000b: ldarg.0 IL_000c: ldsfld int32 [Bko]Bko.Resource/String::bko_name IL_0011: stfld int32 RefsLibs.Class1::b IL_0016: ldarg.0 IL_0017: call instance void [System.Private.CoreLib]System.Object::.ctor() IL_001c: ret } // end of method Class1::.ctor If you attempt to run the .NET 8 RC2 build, it fails at runtime: I MonoDroid: android.runtime.JavaProxyThrowable: [System.TypeLoadException]: Arg_TypeLoadException I MonoDroid: at App.MainActivity.OnCreate(Unknown Source:0) I MonoDroid: at Android.App.Activity.n_OnCreate_Landroid_os_Bundle_(Unknown Source:0) The problem is that `RefsLibs.dll` isn't being fixed up as part of dc3ccf2, because it doesn't contain any `@(AndroidResource)` values or an `[assembly: ResourceDesigner]` custom attribute. `RefsLibs.dll` is "free floating", with nothing to indicate that it needs to be updated. Fix this scenario by updating `LinkDesignerBase` to "sanity check" all "Resource-like" member references which cannot be resolved. Consider: % monodis --memberref RefsLibs/bin/Release/net7.0-android/RefsLibs.dll … 18: TypeRef[23] ako_name Resolved: [Ako]Ako.Resource/String.ako_name Signature: int32 19: TypeRef[25] bko_name Resolved: [Bko]Bko.Resource/String.bko_name Signature: int32 These are field references. In the context of .NET 8/dc3ccf28, these fields *will not exist*; they cannot be resolved. `LinkDesignerBase` will check the member references table of *all* assemblies included in the app, and if any member references contain a declaring type which contains `.Resource/` *and* that member reference cannot be resolved, we will assume that it is an `@(AndroidReference)` and replace it with a `call` to the appropriate method. With the fix in place, `ilverify` no longer reports `Error [ClassLoadGeneral]`, and `ikdasm` shows: % ikdasm App/obj/Release/net8.0-android/android-arm/linked/RefsLibs.dll … .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { // Code size 29 (0x1d) .maxstack 8 IL_0000: ldarg.0 IL_0001: call int32 [_Microsoft.Android.Resource.Designer]_Microsoft.Android.Resource.Designer.Resource/String::get_ako_name() IL_0006: stfld int32 RefsLibs.Class1::a IL_000b: ldarg.0 IL_000c: call int32 [_Microsoft.Android.Resource.Designer]_Microsoft.Android.Resource.Designer.Resource/String::get_bko_name() IL_0011: stfld int32 RefsLibs.Class1::b IL_0016: ldarg.0 IL_0017: call instance void [System.Private.CoreLib]System.Object::.ctor() IL_001c: ret } // end of method Class1::.ctor Note that the .NET 7 `ldsfld` has been replaced with `call`. Co-authored-by: Dean Ellis <[email protected]>
Fixes: dotnet/maui#17265 Context: dc3ccf2 Context: https://github.com/Zack-G-I-T/SfListView.Net8Bug/tree/ecb25af3329391858d1d64c4875ca58771e2b66c Commit dc3ccf2 completely reworked how Android Resources work, moving from a `$(RootNamespace).Resource` type which contained fields (which needed to be updated at runtime across numerous assemblies) to a "`_Microsoft.Android.Resource.Designer` reference assembly" which contained *methods* for each Resource id. To maintain backward compatibility, pre-.NET 8 assemblies were rewritten so that instead of accessing fields: ldsfld int32 $(RootNamespace).Resource/Layout::Toolbar they became method calls: call int32 [_Microsoft.Android.Resource.Designer]_Microsoft.Android.Resource.Designer.Resource/Layout::get_Toolbar() Unfortunately we encountered a missing corner case: the previous fixup logic only operated on assemblies that themselves contained a `$(RootNamespace).Resource` type, which in turn (generally) required that the assembly be built from a project that had `@(AndroidResource)` items. In dotnet/maui#17265 and Zack-G-I-T/SfListView.Net8Bug, we encountered an assembly that: 1. Did *not* contain a `Resource` type, and 2. Used Resource ids from other assemblies, and 3. Was a .NET 7 assembly, so it and its dependencies were all using the .NET 7 field-based Resource approach. Setup: * `Ako` and `Bko` are net7.0-android projects which contain an `@(AndroidResource)` * `RefsLibs` is a net7.0-android project which references `Ako` and `Bko`, and uses the Resource values from them. * `App` is a net8.0-android project which references `RefsLibs`. "Repro" setup: dotnet new androidlib -n Ako # Set `$(TargetFramework)`=net7.0-android # Add Ako/Resources/values/strings.xml with String resource ako_name dotnet new androidlib -n Bko # Set `$(TargetFramework)`=net7.0-android # Add Bko/Resources/values/strings.xml with String resource bko_name dotnet new androidlib -n RefsLibs # Set `$(TargetFramework)`=net7.0-android # Add ProjectReference to ..\Ako\Ako.csproj, ..\Bko\Bko.csproj # Update `RefsLibs\Class1.cs` to use Ako.Resource.String.ako_name, Bko.Resource.String.bko_name dotnet new android -n App # *Remains* `$(TargetFramework)`=net8.0-android # Add ProjectReference to ..\RefsLibs\RefsLibs.csproj The punch: dotnet build App/App.csproj -p:Configuration=Release This fails to build with .NET 8 RC1: ILLink : error IL1013: Error processing '/Users/jon/Downloads/dotnet-sdk-8.0.100-rc.1.23455.8-osx-x64/packs/Microsoft.Android.Sdk.Darwin/34.0.0-rc.1.432/targets/../PreserveLists/Mono.Android.xml'. Fatal error in IL Linker Unhandled exception. Mono.Linker.LinkerFatalErrorException: ILLink: error IL1013: Error processing '/Users/jon/Downloads/dotnet-sdk-8.0.100-rc.1.23455.8-osx-x64/packs/Microsoft.Android.Sdk.Darwin/34.0.0-rc.1.432/targets/../PreserveLists/Mono.Android.xml'. ---> System.ArgumentNullException: Value cannot be null. (Parameter 'key') at System.Collections.Generic.Dictionary`2.TryInsert(TKey key, TValue value, InsertionBehavior behavior) at System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value) … …/build/Microsoft.NET.ILLink.targets(87,5): error NETSDK1144: Optimizing assemblies for size failed. Optimization can be disabled by setting the PublishTrimmed property to false. "Interestingly", it *succeeds* with .NET 8 RC2 (no build errors). Regardless, with both .NET 8 RC1 and RC2, the app is *broken*: % dotnet tool install --global dotnet-ilverify % $HOME/.dotnet/tools/ilverify App/obj/Release/net8.0-android/android-arm/linked/RefsLibs.dll \ --tokens --system-module System.Private.CoreLib \ -r 'App/obj/Release/net8.0-android/android-arm/linked/*.dll' [IL]: Error [ClassLoadGeneral]: […/App/obj/Release/net8.0-android/android-arm/linked/RefsLibs.dll : RefsLibs.Class1::.ctor()] Failed to load type 'String' from assembly 'Ako, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' [IL]: Error [CallCtor]: […/App/obj/Release/net8.0-android/android-arm/linked/RefsLibs.dll : RefsLibs.Resource::.ctor()][offset 0x00000001] call to .ctor only allowed to initialize this pointer from within a .ctor. Try newobj. [IL]: Error [ThisUninitReturn]: […/App/obj/Release/net8.0-android/android-arm/linked/RefsLibs.dll : RefsLibs.Resource::.ctor()][offset 0x00000006] Return from .ctor when this is uninitialized. 3 Error(s) Verifying …/App/obj/Release/net8.0-android/android-arm/linked/RefsLibs.dll If you disassemble `RefsLibs.dll`, you find that it's using `ldsfld`, not `call`: % ikdasm App/obj/Release/net8.0-android/android-arm/linked/RefsLibs.dll … .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { // Code size 29 (0x1d) .maxstack 8 IL_0000: ldarg.0 IL_0001: ldsfld int32 [Ako]Ako.Resource/String::ako_name IL_0006: stfld int32 RefsLibs.Class1::a IL_000b: ldarg.0 IL_000c: ldsfld int32 [Bko]Bko.Resource/String::bko_name IL_0011: stfld int32 RefsLibs.Class1::b IL_0016: ldarg.0 IL_0017: call instance void [System.Private.CoreLib]System.Object::.ctor() IL_001c: ret } // end of method Class1::.ctor If you attempt to run the .NET 8 RC2 build, it fails at runtime: I MonoDroid: android.runtime.JavaProxyThrowable: [System.TypeLoadException]: Arg_TypeLoadException I MonoDroid: at App.MainActivity.OnCreate(Unknown Source:0) I MonoDroid: at Android.App.Activity.n_OnCreate_Landroid_os_Bundle_(Unknown Source:0) The problem is that `RefsLibs.dll` isn't being fixed up as part of dc3ccf2, because it doesn't contain any `@(AndroidResource)` values or an `[assembly: ResourceDesigner]` custom attribute. `RefsLibs.dll` is "free floating", with nothing to indicate that it needs to be updated. Fix this scenario by updating `LinkDesignerBase` to "sanity check" all "Resource-like" member references which cannot be resolved. Consider: % monodis --memberref RefsLibs/bin/Release/net7.0-android/RefsLibs.dll … 18: TypeRef[23] ako_name Resolved: [Ako]Ako.Resource/String.ako_name Signature: int32 19: TypeRef[25] bko_name Resolved: [Bko]Bko.Resource/String.bko_name Signature: int32 These are field references. In the context of .NET 8/dc3ccf28, these fields *will not exist*; they cannot be resolved. `LinkDesignerBase` will check the member references table of *all* assemblies included in the app, and if any member references contain a declaring type which contains `.Resource/` *and* that member reference cannot be resolved, we will assume that it is an `@(AndroidReference)` and replace it with a `call` to the appropriate method. With the fix in place, `ilverify` no longer reports `Error [ClassLoadGeneral]`, and `ikdasm` shows: % ikdasm App/obj/Release/net8.0-android/android-arm/linked/RefsLibs.dll … .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { // Code size 29 (0x1d) .maxstack 8 IL_0000: ldarg.0 IL_0001: call int32 [_Microsoft.Android.Resource.Designer]_Microsoft.Android.Resource.Designer.Resource/String::get_ako_name() IL_0006: stfld int32 RefsLibs.Class1::a IL_000b: ldarg.0 IL_000c: call int32 [_Microsoft.Android.Resource.Designer]_Microsoft.Android.Resource.Designer.Resource/String::get_bko_name() IL_0011: stfld int32 RefsLibs.Class1::b IL_0016: ldarg.0 IL_0017: call instance void [System.Private.CoreLib]System.Object::.ctor() IL_001c: ret } // end of method Class1::.ctor Note that the .NET 7 `ldsfld` has been replaced with `call`. Co-authored-by: Dean Ellis <[email protected]>
* main: [Mono.Android] Generate API docs with "full" verbosity (dotnet#8435) [profiled-aot] update profile for .NET 8 GA (dotnet#8428) Bump to xamarin/Java.Interop/main@3c83179 (dotnet#8429) [Xamarin.Android.Build.Tasks] Small refactoring to `AddKeepAlives` method (dotnet#8423) [Xamarin.Android.Build.Tasks] Fixup indirect resource references (dotnet#8416)
Context: dotnet/maui#17265
fixes dotnet/maui#17265
Reproduced the issue in a new
FixLegacyResourceDesignerStep
test. It crashes at runtime, but if you change the class libraries in the test tonet8.0
, it works fine.I first attempted to fix the problem for
Release
mode, as it seemed easier to do a "second pass" on all assemblies at the end of a linker step.This change starts to work:
But then fails with: