Context: c92702619f
Context: 68368189d6
Context: 929e701241
Context: https://github.com/xamarin/xamarin-android/pull/8478
Context: https://github.com/xamarin/xamarin-android/issues/8155
Context: https://github.com/xamarin/xamarin-android/issues/8168
Our build process has a bit of a "consistent sanity" problem: large
portions of the build process assume that the output of a `.csproj`
is a single assembly, and that single assembly is (eventually)
embedded into the `.apk`, to be loaded at runtime.
Unfortunately, that wasn't strictly true starting with .NET 5:
there were *multiple* `System.Private.CoreLib.dll` assemblies, which
needed to be treated specially; see also c9270261.
We discovered that this assumption was even *less* true because of
the linker, which would quite happily *replace* `IntPtr.get_Size()`
method invocations with a *constant*, specific for the target ABI;
see also 68368189, 929e7012. This in turn could be responsible for
all sorts of weirdness if e.g. a 64-bit assembly were used in a
32-bit process, or vice versa.
Which brings us to the original assumption: there is (usually) only
one "source" assembly, which is (optionally) linked into one "linked"
assembly, which is packaged into one assembly in the `.apk`.
With the linker, though, we can have one "source" assembly, which
when linked becomes *N* assemblies, which *should be* separately
packaged as per-ABI assemblies within the `.apk`, but
*probably aren't*, which we *think* is the "root cause" of #8155.
PR #8478 is attempting fix this assumption, imbuing the build system
with knowledge that the linker may produce *multiple outputs* for a
single input assembly.
Unfortunately, in trying to fix things, various intermediate assembly
locations have *changed*, which in turn breaks
[AndroidX Migration in Xamarin.Forms][0], as it makes assumptions
about where various assemblies are located within `obj`:
(_AndroidXCecilfy target) ->
/Users/runner/.nuget/packages/xamarin.androidx.migration/1.0.8/buildTransitive/monoandroid90/Xamarin.AndroidX.Migration.targets(227,9): error : Source assembly does not exist: 'obj/Debug/android/assets/UnnamedProject.dll'.
as [`@(_AndroidXFileToCecilfy)`][1] uses
`$(MonoAndroidIntermediateAssetsDir)`, which does not account for the
ABI which is now in the path:
<ItemGroup>
<_AndroidXFileToCecilfy Include="@(ResolvedUserAssemblies->'$(MonoAndroidIntermediateAssetsDir)%(Filename)%(Extension)')"
Condition="('%(ResolvedUserAssemblies.TargetFrameworkIdentifier)' == 'MonoAndroid' or '%(ResolvedUserAssemblies.HasMonoAndroidReference)' == 'true') and ('%(ResolvedUserAssemblies.AndroidXSkipAndroidXMigration)' != 'true')" />
</ItemGroup>
Given that AndroidX Migration is mostly for Xamarin.Forms customers
(and *kinda* buggy, and unmaintained), and MAUI doesn't support the
Android Support libraries, and thus doesn't need AndroidX Migration,
we'd like to just *not worry about this*.
The problem? The above error message is not actionable, and doesn't
tell anybody how to fix it.
Introduce a new `XA1039` *actionable* error in .NET 9:
error XA1039: The Android Support libraries are not supported in .NET 9 and later,
please migrate to AndroidX. See https://aka.ms/xamarin/androidx for more details.
The XA1039 error is generated if any NuGet packages are found matching:
* `Xamarin.Android.Support.*`
* `Xamarin.Android.Arch.*`
TODO: "port" XA1039 to .NET 8 *as a warning*, so that customers will
have some time to migrate off of the Android Support libraries before
.NET 9 is released in 2024-Nov.
--<AndroidError Code="XA1039"
++<AndroidWarning Code="XA1039"
ResourceName="XA1039"
Condition=" '@(_AndroidUnsupportedPackages->Count())' != '0' "
/>
The biggest impact here is going to be many of our old tests, which
use the support libraries in various forms.
Improvements & general cleanup:
* Removed all old/unused packages in `KnownPackages.cs`
* Updated `KnownPackages.cs` to latest versions, including Xamarin.Forms
* [Android Wear tests are now migrated from support to AndroidX][2]
* `AndroidUpdateResourcesTest.CheckEmbeddedSupportLibraryResources()`
is renamed to `.CheckEmbeddedAndroidXResources()`.
* `BuildTest2.BuildHasNoWarnings()` was not appropriately applying
`IsRelease`.
* `Android.Support.v8.RenderScript` removed in favor of an inline
`.so` file.
* A few tests that used support libraries to create a project large
numbers of dependencies, moved to
`XamarinFormsAndroidApplicationProject`.
* `IncrementalBuildTest.ResolveLibraryProjectImports()` now sorts
items before comparing them.
* `XamarinFormsAndroidApplicationProject` has a workaround for Guava:
<https://github.com/xamarin/AndroidX/issues/535>
* Fix a bug in `AndroidFastDeploymentType=Assemblies::Dexes`;
see "AndroidFastDeploymentType=Assemblies::Dexes" section, below.
Removed tests:
* `AndroidXMigration`, `AndroidXMigrationBug`
* `ResolveLibraryImportsWithReadonlyFiles`, seemed duplicate of other
Android Wear tests, and used support libraries.
* `ExtraAaptManifest` as it depends on `Xamarin.Android.Fabric` and
`Xamarin.Android.Crashlytics`. These are deprecated and depend on
support libraries.
* `BuildProguardEnabledProjectSource` now only tests `Release` mode.
Since updating to AndroidX, `Debug` mode was triggering multi-dex.
Making it difficult to assert contents of `*.dex` files.
~~ AndroidFastDeploymentType=Assemblies::Dexes ~~
The runtime test in `ApplicationRunsWithDebuggerAndBreaks()` was
crashing at runtime with:
E monodroid-assembly: typemap: failed to stat TypeMap index file '/data/user/0/com.xamarin.applicationrunswithdebuggerandbreaks/files/.__override__/typemaps/typemap.index': No such file or directory
F monodroid-assembly: typemap: unable to load TypeMap data index from '/data/user/0/com.xamarin.applicationrunswithdebuggerandbreaks/files/.__override__/typemaps/typemap.index'
This only happens when `AndroidFastDeploymentType=Assemblies::Dexes` is
used, as it is the case when typemap files like this are fast deployed
and used at runtime.
What was even more odd, was the file seems to exist after a
`-t:Install`, but ends up missing after `-t:Run`:
> adb shell run-as com.xamarin.applicationrunswithdebuggerandbreaks ls -la files/.__override__/typemaps/typemap.index
ls: files/.__override__/typemaps/typemap.index: No such file or directory
It appears that `-t:Install` successfully deploys the file:
Pushed 3969 to /data/local/tmp/.xatools/typemap.index
DEBUG RunShellCommand emulator-5554 "run-as" "com.xamarin.applicationrunswithdebuggerandbreaks" "--user" "0" "files/.__tools__/xamarin.cp" "/data/local/tmp/.xatools/typemap.index" "files/.__override__/typemaps/typemap.index" "1705432079367" [5ms]
files/.__tools__/xamarin.cp returned: moved [/data/local/tmp/.xatools/typemap.index] to [files/.__override__/typemaps/typemap.index] modifieddate [1705432079367]
moved /data/local/tmp/.xatools/typemap.index to files/.__override__/typemaps/typemap.index
Installed files/.__override__/typemaps/typemap.index. [12ms]
NotifySync CopyFile obj\Debug\android\typemaps\typemap.index. [0ms]
But then `-t:Run` deletes the file!
Remove redundant file files/.__override__/typemaps/typemap.index
DEBUG RunShellCommand 0A041FDD400327 "run-as" "com.xamarin.applicationrunswithdebuggerandbreaks" "rm" "-Rf" "files/.__override__/typemaps/typemap.index" [29ms]
This happens because the `@(_AndroidTypeMapping)` item group is empty
during an incremental build:
* The `<GenerateJavaStubs/>` MSBuild task, during the first build
outputs `@(_AndroidTypeMapping)` items
* During an incremental build, the `_GenerateJavaStubs` MSBuild
*target* is skipped, and so the `@(_AndroidTypeMapping)` item
group is empty!
* The `<FastDeploy/>` task happily deletes files that it thinks
should be removed.
For now, let's add logic to the `_GenerateJavaStubs` target to fill
in the `@(_AndroidTypeMapping)` item group during incremental builds:
<ItemGroup Condition=" '$(_InstantRunEnabled)' == 'True' and '@(_AndroidTypeMapping->Count())' == '0' ">
<_AndroidTypeMapping Include="$(_NativeAssemblySourceDir)typemaps\*" />
</ItemGroup>
`<ItemGroup>`s are still evaluated when a target is *skipped*,
solving the problem.
I assume this is working in `main`, because Xamarin.AndroidX.Migration
package was involved. It likely was running the `_GenerateJavaStubs`
target on every build.
[0]: https://learn.microsoft.com/xamarin/xamarin-forms/platform/android/androidx-migration
[1]: 17e596fafe/source/migration/BuildTasks/Xamarin.AndroidX.Migration.targets (L205-L206)
[2]: https://android-developers.googleblog.com/2016/04/build-beautifully-for-android-wear.html