Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Xamarin.Android.Build.Tasks] libxamarin-app.so generation (#2718)
Xamarin.Android needs a lot of information in the runtime in order to do its tasks. Among this is are two bits of information that are used during startup: type mappings (java-to-managed `.jm` files and managed-to-java `.mj` files) and environment settings (variables and system properties). Historically, Xamarin.Android used these bits of data (generated on the application build time) by writing them into separate files (`*.mj`, `*.jm`, `environment`), storing them in the `.apk`, and reading these files dynamically during startup. an `environment` However, none of this data is *actually* dynamic - it's known beforehand and could be stored as static data right in the `.apk`. The problem with this idea was that we had no way to put that information into the application native bits at build time: it would require the presence of a compiler (or native assembler) as well as the native linker for the target platforms. This would have required having the Android NDK installed, which is a hefty requirement. That said, the Android SDK currently ships a native linker within its `build-tools` package, and we can also bundle within our packages the `gas` native assembler for all the architectures we support. This allows us to generate simple native assembler code, compile it and link into a shared library ***when packaging*** the application. The way it works is that during the Xamarin.Android *SDK* build we build a "stub" `libxamarin-app.so` library which the Xamarin.Android `libmono-android.*.so` neé `libmonodroid.so` runtime libraries are linked against. The stub `libxamarin-app.so` library is *not* distributed with the Xamarin.Android SDK; instead, the "real" version is generated at build/packaging time and packaged with the runtime within the `.apk`. Since the "real" version is ABI-compatible with the stub version, the dynamic loader doesn't care and loads and resolves symbols just fine. This allows us to dispense with memory allocation, loading (potentially large) files from the `.apk` (lots of I/O, slow), parsing text files to set environment variables (additional memory allocation), etc. All of the data is loaded for us by Android and we simply access global variables from the `libxamarin-app.so` library. The process, however, can be time consuming (sort of...) and in order to allow fast deployment to work as quickly as possible, the debug (and desktop/host - for the benefit of the UI Designer) builds of the runtime also contain code to load both type maps and environment variables from files stored inside one of the override directories. The changes provide a speed-up of ~10ms, reducing the startup time down to around 233ms for a release build of a Xamarin.Forms app on a Pixel 3 XL.
- Loading branch information