Commit 03018e0
[Xamarin.Android.Build.Tasks] Fixup indirect resource references (#8416)
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]>1 parent 2b0761b commit 03018e0
File tree
3 files changed
+113
-5
lines changed- src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner
- tests/MSBuildDeviceIntegration/Tests
3 files changed
+113
-5
lines changedLines changed: 29 additions & 5 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
139 | 139 | | |
140 | 140 | | |
141 | 141 | | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
142 | 168 | | |
143 | 169 | | |
144 | 170 | | |
| |||
152 | 178 | | |
153 | 179 | | |
154 | 180 | | |
155 | | - | |
156 | | - | |
157 | | - | |
158 | | - | |
| 181 | + | |
| 182 | + | |
159 | 183 | | |
160 | 184 | | |
161 | 185 | | |
162 | 186 | | |
163 | 187 | | |
164 | 188 | | |
165 | 189 | | |
166 | | - | |
| 190 | + | |
167 | 191 | | |
168 | 192 | | |
169 | 193 | | |
| |||
Lines changed: 31 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
60 | 60 | | |
61 | 61 | | |
62 | 62 | | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
63 | 94 | | |
64 | 95 | | |
65 | 96 | | |
| |||
Lines changed: 53 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1115 | 1115 | | |
1116 | 1116 | | |
1117 | 1117 | | |
| 1118 | + | |
| 1119 | + | |
| 1120 | + | |
| 1121 | + | |
| 1122 | + | |
| 1123 | + | |
| 1124 | + | |
| 1125 | + | |
| 1126 | + | |
| 1127 | + | |
| 1128 | + | |
| 1129 | + | |
| 1130 | + | |
| 1131 | + | |
| 1132 | + | |
| 1133 | + | |
| 1134 | + | |
| 1135 | + | |
| 1136 | + | |
| 1137 | + | |
| 1138 | + | |
| 1139 | + | |
| 1140 | + | |
| 1141 | + | |
| 1142 | + | |
| 1143 | + | |
| 1144 | + | |
| 1145 | + | |
| 1146 | + | |
| 1147 | + | |
| 1148 | + | |
| 1149 | + | |
| 1150 | + | |
| 1151 | + | |
| 1152 | + | |
| 1153 | + | |
| 1154 | + | |
| 1155 | + | |
| 1156 | + | |
| 1157 | + | |
| 1158 | + | |
| 1159 | + | |
| 1160 | + | |
| 1161 | + | |
| 1162 | + | |
| 1163 | + | |
| 1164 | + | |
| 1165 | + | |
| 1166 | + | |
| 1167 | + | |
| 1168 | + | |
| 1169 | + | |
| 1170 | + | |
1118 | 1171 | | |
1119 | 1172 | | |
0 commit comments