-
Notifications
You must be signed in to change notification settings - Fork 537
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
assemblies.ARCH.blob should be per-ARCH .so files #8168
Comments
Or should there only be 1 set of BCL assemblies instead? In theory, we could make:
Benefits:
Drawbacks:
|
@mosammo we brought what you noticed here up with Google: google/bundletool#190 There is not a way to split up custom files per-architecture for App Bundles. Our only option appears to rework .NET assemblies to be (Or make it so there are no architecture-specific files at all 😄) |
Yes and no: Yes, you are absolutely correct that the However, "No" because For example, you upload a The Amazon Appstore also supports Android App Bundles. Consequently, you (generally) shouldn't care about Finally, it looks like the Archive Manager supports App Bundles; see: https://learn.microsoft.com/xamarin/android/deploy-test/release-prep/?tabs=windows#android-app-bundles |
The glorious thing about using There could thus be benefits to using However, Last time I heard, there was no intention to have an "architecture neutral" "1 set of assemblies" is only truly viable if there is a way to tell the linker to ignore all link descriptors (or all link descriptors which would introduce architecture-specific changes, which can't currently be done). This would also mean "no use of linker feature flags", which I suspect will go over like a lead balloon. My "fear", then, is that "1 set of assemblies" is not viable, multi-arch assemblies are the present and future, and we need to ensure that we support them. (Note: We do support them! It's just that how we support them has various tradeoffs wrt |
To expand upon "
System.Private.CoreLib has 773 uses of
In particular note the 32 instances of |
One downside of the .so idea is its potential to double memory usage for the assemblies. The blobs we have now are mmapped and only data that's actually needed is read from them. Even if the assemblies are compressed, we won't waste much more memory over what would normally be used by the runtime loading the assembly from disk, since we decmpress the mmapped data to a pre-allocated (at build time) memory buffer, which we then pass as a pointer to the runtime. However, with an .so we will have the entire library loaded into memory (since data will be kept in a R/O data section, that's entirely loaded) and, if compression is involved, we'll repeat the same action as with blobs, but the original compressed data will remain in memory. We won't be able to unload the shared library since we won't know when all the assemblies have been decompressed. If compression isn't involved, we'll have to keep the .so with assemblies around forever, since the runtime will use its data but the memory usage won't be doubled. However, in either case we will pay the up-front cost of allocated memory whether or not all the assemblies will be used by the application. |
The problem is some projects do not use Google Play store for app distribution and instead using the .apk files which on Xamarin android didn't include such files of unselected architectures and were much smaller than the apk files currently generated by .net 7+ for android. Such unselected architectures files (like in "assemblies" and "lib" folders) should be excluded or removed from the generated apk. |
Are you using the If you are only targeting say intel x86/64 you should be using the following <PropertyGroup>
<!-- Used going forward in .NET -->
<RuntimeIdentifiers>android-x86;android-x64</RuntimeIdentifiers>
</PropertyGroup> This should exclude the arm based abi's from the final apk. If it doesn't that is a bug. |
Thank you!! it works!! turns out it's just a UI bug in visual studio, selecting "Platform target" in visual studio project settings should set the related settings in the project file, but it only sets After setting |
@mosammo Great :) On a side note you probably want to leave the |
Context: c927026 Context: 6836818 Context: 929e701 Context: #8478 Context: #8155 Context: #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 c927026. 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 6836818, 929e701. 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: <dotnet/android-libraries#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]: https://github.com/xamarin/AndroidX/blob/17e596fafe20331d7feb69240c38e0fbdc3ea640/source/migration/BuildTasks/Xamarin.AndroidX.Migration.targets#L205-L206 [2]: https://android-developers.googleblog.com/2016/04/build-beautifully-for-android-wear.html
Context: #8165 (comment)
assemblies.x86.blob
and similar are always stored in theassemblies
directory, meaning our per-archassemblies*.blob
files are present when downloaded for every architecture. This means that arch-specific.apk
files are larger than is necessary.We should move the per-arch
assemblies.*.blob
files into per-archlib/ARCH/libassemblies.so
files. This way when a per-arch.apk
is produced, assemblies for other architectures can be properly skipped/removed from the.apk
.The text was updated successfully, but these errors were encountered: