[Mono.Android] Compile RuntimeFeature into a single assembly to avoid conflict warnings#11669
Conversation
`Microsoft.Android.Runtime.RuntimeFeature` was compiled into both
`Mono.Android.Runtime.dll` and `Mono.Android.dll`. Because `Mono.Android`
references `Mono.Android.Runtime` (which exposes its internals to
`Mono.Android` via `InternalsVisibleTo`), building `Mono.Android.dll`
emitted 58 `CS0436` warnings:
warning CS0436: The type 'RuntimeFeature' in
'src/Mono.Android/Microsoft.Android.Runtime/RuntimeFeature.cs' conflicts
with the imported type 'RuntimeFeature' in 'Mono.Android.Runtime'.
Compile `RuntimeFeature.cs` only into `Mono.Android.Runtime.dll` (the
lower-level assembly that already owns it) and let the other assemblies use
it through `InternalsVisibleTo`:
* Remove the duplicate `<Compile Include="...RuntimeFeature.cs" />` from
`Mono.Android.csproj`.
* Grant `Mono.Android.Runtime` internals to
`Microsoft.Android.Runtime.NativeAOT` and `Mono.Android.NET-Tests`, which
previously accessed `RuntimeFeature` through `Mono.Android.dll`.
* Once `RuntimeFeature` is only imported (no longer source-compiled) into
`Mono.Android`, the unqualified name `RuntimeFeature` becomes ambiguous
with `System.Runtime.CompilerServices.RuntimeFeature`. Add
`using RuntimeFeature = Microsoft.Android.Runtime.RuntimeFeature;` to the
three affected files, matching the alias already used in `JNIEnvInit.cs`.
`Microsoft.Android.Runtime.RuntimeFeature` is now defined in exactly one
assembly (`Mono.Android.Runtime.dll`), and the 58 `CS0436` warnings are gone.
This is a focused subset of #11625 that addresses only the `RuntimeFeature`
duplication, without that PR's class rename or unrelated warning cleanups.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR removes the duplicate compilation of Microsoft.Android.Runtime.RuntimeFeature into Mono.Android.dll, ensuring it is defined only in Mono.Android.Runtime.dll to eliminate CS0436 type-conflict warnings and avoid CS0104 ambiguity with System.Runtime.CompilerServices.RuntimeFeature.
Changes:
- Stop compiling
Microsoft.Android.Runtime/RuntimeFeature.csintoMono.Android.dll(leaving it only inMono.Android.Runtime.dll). - Add
InternalsVisibleToentries inMono.Android.RuntimeforMicrosoft.Android.Runtime.NativeAOTandMono.Android.NET-Tests. - Disambiguate
RuntimeFeatureusage viausing RuntimeFeature = Microsoft.Android.Runtime.RuntimeFeature;in the affected source files.
Show a summary per file
| File | Description |
|---|---|
| src/Mono.Android/Mono.Android.csproj | Removes duplicate Compile entry for RuntimeFeature.cs to prevent cross-assembly type conflicts. |
| src/Mono.Android/Java.Interop/TypeManager.cs | Adds RuntimeFeature type alias to avoid CS0104 ambiguity. |
| src/Mono.Android/Android.Runtime/JNIEnv.cs | Adds RuntimeFeature type alias to avoid CS0104 ambiguity (while still using BCL RuntimeFeature fully-qualified). |
| src/Mono.Android/Android.Runtime/AndroidRuntime.cs | Adds RuntimeFeature type alias to avoid CS0104 ambiguity. |
| src/Mono.Android.Runtime/Properties/AssemblyInfo.cs.in | Grants internals access to NativeAOT and test assemblies now that RuntimeFeature is owned by Mono.Android.Runtime. |
Copilot's findings
- Files reviewed: 5/5 changed files
- Comments generated: 0
|
@copilot we definitely changed something that affects the numbers of warnings and how our tests filter them. For example, this test is now failing: I want to |
…adjust warning totals Co-authored-by: simonrozsival <374616+simonrozsival@users.noreply.github.com>
…HasTrimmerWarnings Co-authored-by: simonrozsival <374616+simonrozsival@users.noreply.github.com>
Addressed in commits Changes made:
Validation:
|
|
@copilot now fix the underlying issues:
|
…nt CI output Co-authored-by: simonrozsival <374616+simonrozsival@users.noreply.github.com>
... Fixed in I pulled the current AZDO build logs for build
This covers the MonoVM failure you pasted plus the corresponding CoreCLR failures seen in the same CI logs. |
Moving RuntimeFeature into Mono.Android.Runtime made the IsNativeAotRuntime guard in JNIEnvInit.Initialize a cross-assembly feature switch, so ILLink no longer eliminates Initialize under NativeAOT. Initialize is force-preserved by the ILLink descriptor and contains a [LibraryImport] to xamarin_app_init, which becomes a direct native reference (xa-internal-api is a DirectPInvoke). That symbol is only defined by the MonoVM/CoreCLR marshal methods native code, which is never generated for NativeAOT, so the link failed with XA3007 "undefined symbol: xamarin_app_init". Emit a no-op xamarin_app_init definition into the NativeAOT jni-init assembler source so the linker can resolve the reference. Initialize is never invoked under NativeAOT (InitializeNativeAotRuntime is used instead), so the no-op is safe. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…timefeature-single-assembly
Enable ILLink to process Mono.Android.Runtime.dll so RuntimeFeature feature switches can be folded when referenced from Mono.Android during partial trimming. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Update BuildHasTrimmerWarnings counts after marking Mono.Android.Runtime trimmable removes the extra CoreCLR warning. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Mono.Android.Runtime is now trimmable, so RuntimeFeature switches can fold the unreachable JNIEnvInit.Initialize body for NativeAOT and the jni-init assembler no longer needs to emit a no-op xamarin_app_init definition. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Keep the RuntimeFeature single-assembly PR focused by moving the BuildHasTrimmerWarnings diagnostics change to a separate PR and dropping the leftover LlvmIrGeneratorTests using change. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
| [assembly: AssemblyTitle ("Mono.Android.Runtime.dll")] | ||
| [assembly: AssemblyProduct (".NET for Android")] | ||
| [assembly: AssemblyCompany ("Microsoft Corporation")] | ||
| [assembly: AssemblyMetadata ("IsTrimmable", "True")] |
There was a problem hiding this comment.
Should we actually set the IsTrimmable=true MSBuild property, so we get the analyzers, too?
There was a problem hiding this comment.
We'll need to switch to $(GenerateAssemblyInfo)=true. I'll look into what other changes that will require tomorrow.
There was a problem hiding this comment.
I moved the attributes to MSBuild properties. please take another look.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
jonathanpeppers
left a comment
There was a problem hiding this comment.
Verified the migration from AssemblyInfo.cs.in to MSBuild GenerateAssemblyInfo by extracting the produced Mono.Android.Runtime.dll from the CI build (build 1496564, Microsoft.Android.Runtime.37.android...gh11669.0.nupkg) and reading its assembly manifest directly.
All original assembly attributes are preserved:
AssemblyTitle=Mono.Android.Runtime.dllAssemblyProduct=.NET for AndroidAssemblyCompany=Microsoft CorporationAssemblyInformationalVersion=37.0.0.0; git-rev-head:...; git-branch:...(same format as before, no+shasuffix thanks toIncludeSourceRevisionInInformationalVersion=false)TargetPlatform=Android37.0SupportedOSPlatform=Android24.0InternalsVisibleTo→Mono.Android(correct public key)
Intended additions look correct:
InternalsVisibleTo→Microsoft.Android.Runtime.NativeAOTandMono.Android.NET-Tests(needed now thatRuntimeFeaturelives in this assembly)IsTrimmablemetadata from the new<IsTrimmable>true</IsTrimmable>
Correctly suppressed via the new Generate*Attribute=false properties: no AssemblyConfiguration, AssemblyFileVersion, AssemblyVersion, or RepositoryUrl attributes. Signing/identity is unchanged (PublicKey flag, product.snk, version 0.0.0.0 — matching prior behavior).
LGTM. 👍
Supersedes #11999 (that PR was from a fork; this one is rebased on latest `main` and pushed to an origin branch so it runs the full CI). #11999 will be closed. ## Summary Reduces the C# build warnings in `src/Mono.Android` by fixing the warnings that originate in **hand-written source**, and completes the API-37 public API baseline so the public API analyzer passes. It **intentionally does not** remove every `NoWarn` suppression, nor the `Mono.Android.csproj` entry in `_AllowProjectWarnings` (in `Directory.Build.props`). The warnings that remain all originate in **generated code** and require changes to the code generators — see "Why suppressions remain" below. ## What is fixed (hand-written code) - **CS8765** - override parameter nullability aligned to the base member (`System.Drawing` `TypeConverter` subclasses, `SyncContext`, Java stream adapters, `Color`/`AndroidBitmapInfo` equality, `AdapterView.RawAdapter`). - **CS8764** - `JavaObject.ToString()` returns non-null to match `Java.Lang.Object.ToString()`. - **CS8767** - interface-implementation parameter nullability aligned to the interface (`IComparer`, `ISpliterator`, `ISetCookie`, `IX509TrustManager`/`ISSLSession`, `IXmlPullParser`). - **CS0114 / CS0108** - `new` added to members that intentionally hide an inherited member (generic collection specializations, static helpers, `IXmlResourceParser` disambiguation, `StringBuffer`/`StringBuilder.Append`, `AsyncTask.class_ref`, `JavaProxyThrowable.InnerException`, `SparseArray<E>`, `ArrayAdapter<T>`, `JavaList.Equals`). ### Public API baseline (RS0016 / RS0017) Some of the nullability fixes change the annotations of public members, and the API-37 baseline was missing a large number of generated binding members. `PublicAPI/API-37/PublicAPI.Unshipped.txt` is regenerated (via the `RS0016` code fix, plus `*REMOVED*` markers for stale signatures) so **`RS0016`/`RS0017` are satisfied and remain enforced** (they are not in `NoWarn`). ## Why suppressions remain The remaining warnings are all in **generated code** and cannot be fixed here without changing the generators: - **`mcw/*.cs`** (binding generator): `CS0108`, `CS0114`, `CS0618`, `CS0809`, `CS8613`, `CS8764`, `CS8765`, `CS8766`, `CS8767`. - **`JNIEnv.g.cs`** (`jnienv-gen`, `// Generated file; DO NOT EDIT!`): `RS0041` (public members using oblivious reference types). These files are regenerated on every build, so the fix must happen in the generator. Until those follow-ups land, we keep the corresponding codes in `<NoWarn>` and keep `<_AllowProjectWarnings Condition=" '$(MSBuildProjectFile)' == 'Mono.Android.csproj' ">true</_AllowProjectWarnings>`. Removing either now would turn hundreds of generated-code warnings into build errors under `TreatWarningsAsErrors`. ## Follow-ups - **Binding generator** - emit warning-free `mcw/*.cs`, then drop `CS0108;CS0114;CS0618;CS0809;CS8613;CS8764;CS8765;CS8766;CS8767` from `NoWarn`. - **`jnienv-gen`** - annotate `JNIEnv.g.cs` output, then drop `RS0041` from `NoWarn`. - **CS0436** - handled in #11669. Once those land, the remaining `NoWarn` codes and the `_AllowProjectWarnings` opt-in for `Mono.Android.csproj` can be removed. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Summary
Microsoft.Android.Runtime.RuntimeFeaturewas compiled into two assemblies:Mono.Android.Runtime.dll(src/Mono.Android.Runtime/Mono.Android.Runtime.csproj)Mono.Android.dll(src/Mono.Android/Mono.Android.csproj)Because
Mono.AndroidreferencesMono.Android.Runtime, compilingMono.Android.dllemitted duplicate-type warnings like:This PR makes
RuntimeFeaturelive in exactly one assembly:Mono.Android.Runtime.dll.Changes
Mono.Android.csproj— removes the duplicate<Compile>ofRuntimeFeature.cs, so the type is no longer compiled intoMono.Android.dll.AndroidRuntime.cs,JNIEnv.cs,TypeManager.cs— addsusing RuntimeFeature = Microsoft.Android.Runtime.RuntimeFeature;because onceRuntimeFeatureis imported instead of source-compiled intoMono.Android, the bare name conflicts withSystem.Runtime.CompilerServices.RuntimeFeature.Mono.Android.Runtime.csproj/Mono.Android.Runtime.targets— migrates assembly metadata from the hand-writtenProperties/AssemblyInfo.cs.intemplate to MSBuildGenerateAssemblyInfo:Properties/AssemblyInfo.cs.inand the_BuildAssemblyInfo_cstarget (which ranReplaceFileContentson the template) fromMono.Android.Runtime.targets.<GenerateAssemblyInfo>true</GenerateAssemblyInfo>withGenerateAssemblyConfigurationAttribute,GenerateAssemblyFileVersionAttribute,GenerateAssemblyVersionAttribute,GenerateRepositoryUrlAttribute, andIncludeSourceRevisionInInformationalVersionall set tofalseso no new attributes are introduced vs. the old template.AssemblyTitle,Product,Company, and theInternalsVisibleToitems. A new_SetGeneratedAssemblyInfoPropertiestarget (beforeGetAssemblyAttributes) suppliesInformationalVersion,TargetPlatformIdentifier/TargetPlatformVersion, andSupportedOSPlatformVersionfrom the existingGetXAVersionInfoversion info.InternalsVisibleToforMicrosoft.Android.Runtime.NativeAOTandMono.Android.NET-Tests, which previously reachedRuntimeFeaturethroughMono.Android.dll.Mono.Android.Runtime.dlltrimmable with<IsTrimmable>true</IsTrimmable>. This keeps the cross-assemblyRuntimeFeaturefeature switches visible to ILLink in partial-trimmed apps.Why
IsTrimmableis neededMoving
RuntimeFeatureintoMono.Android.Runtime.dllmakesMono.Android.dllconsume feature-switch properties across an assembly boundary. In partial trimming, ILLink only substitutes feature-switch getters in assemblies it processes. Without markingMono.Android.Runtime.dlltrimmable, some runtime-specific branches stayed live, causing the CoreCLR APK size-regression test to fail.Marking
Mono.Android.Runtime.dlltrimmable lets ILLink fold thoseRuntimeFeatureguards again.Relationship to #11625
This is a focused subset of #11625. It intentionally avoids the broader class rename (
RuntimeFeature→AndroidRuntimeFeature) and resolves the resultingCS0104ambiguity with localusingaliases instead.Follow-up
The
BuildHasTrimmerWarningsdiagnostic improvement was split out into #11981 so this PR remains focused on theRuntimeFeaturesingle-assembly change.Verification
Latest PR validation: dotnet-android #1496564 ✅
The produced
Mono.Android.Runtime.dllfrom that build was inspected to confirm theGenerateAssemblyInfomigration is faithful — all attributes from the oldAssemblyInfo.cs.in(AssemblyTitle,Product,Company,AssemblyInformationalVersion,TargetPlatform=Android37.0,SupportedOSPlatform=Android24.0,InternalsVisibleToforMono.Android) are present, the newInternalsVisibleTo(NativeAOT, NET-Tests) andIsTrimmablemetadata are added, and no unexpected attributes (AssemblyConfiguration,AssemblyFileVersion,AssemblyVersion,RepositoryUrl) were introduced.