luminixinc / XamarinAndroidNativeDebugTest

Xamarin.Android testcase that shows problem building Release AAB

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

XamarinAndroidNativeDebugTest

This test case shows that you cannot create an AAB bundle of a Release build of a native Android app (containing C++ code compiled to the 4 architecture ABIs). The Release build AAB bundling process fails because it appears that MSBuild is attempting to bundle gdbserver into the AAB. (Note that the same issue of including gdbserver also occurs if bundling as APK, including multiple arch+ABI specific APKs, however in this case including gdbserver is not a fatal build error).

Dramatis Personae

  • XamarinAndroidNativeDebugTest this repo, and a Visual Studio solution file of the same name
  • NativeHello : A C++ project for Android (reachable from C#/CLR via PInvoke and SWIG bridge)
  • NativeHelloApp : A C# Xamarin.Android project that simply calls into the native library to get back a string

Verify that a Debug build of the app builds and you can debug natively

  • In Visual Studio, right click on the NativeHelloApp project and select Set as Startup Project
  • Attach an Android device to your PC and verify that Visual Studio sees it
  • Select a Debug build configuration and select a architecture platform for the build (ARM, ARM64, etc) that matches the attached Android device
  • Now open the NativeHello.cpp file that lives in the NativeHello project, and set a breakpoint in the getPlatformABI() function
  • Open the Properties of the NativeHelloApp, switch to the Android Options tab, and change the Debugger to be C++
  • Now build and debug the NativeHelloApp on your Android device and verify that you can hit the breakpoint you set in C++

Attempt to create a Release AAB bundle of the app

Once you are satistifed that the NativeHelloApp works and is natively debuggable, now we show that you cannot create a Release AAB bundle of the app without hitting the error of the erroneously included gdbserver.

  • Switch your build Configuration to Release with Platform Any CPU
  • From the Build menu, choose Batch Build
  • In the batch build popup, checkmark all the NativeHello project Release variants : (ARM, ARM64, x64, x86) and first click Clean
  • After clean, go back to the batch build popup, make sure all the projects are still checked and click Rebuild
  • After all the architectures are built, right-click on the NativeHelloApp project and choose Rebuild
  • After the final build, right-click on the NativeHelloApp project and choose Archive...

Note that you will see the following failure: Files under lib/ must have .so extension, found 'lib/x86/gdbserver'.

Futile attempt #1 to work-around this failure to bundle

In the NativeHelloApp Properties, under the Android Options tab (for a Release Configuration), uncheck the Enable developer instrumentation (debugging and profiling). (NOTE that it is not particularly clear/discoverable what this checkbox is for exactly, but it does change the <DebugSymbols> in the project file which would lead us to suspect it has something more to do with PDB generation than whether gdbsever is bundled).

Repeat the Release AAB bundle process in the above section, and you should still see the same bundling failure.

Attempt #2 which gets the AAB bundle working, to the exclusion of native debugging

In the NativeHelloApp Project References, remove the reference to the NativeHello project.

Repeat the Release AAB bundle process, and this time it should complete with SUCCESS! But the price of this success is that we no longer get a bundled gdbserver for Debug build configurations. To verify this new problem:

  • Switch the build Configuration to Debug and choose a Platform arch that matches your attached Android device (e.g., ARM, ARM64, etc)
  • Manually clean and rebuild the NativeHello project
  • Manually clean and rebuild the NativeHelloApp project
  • This time when you debug the NativeHelloApp project, you will NOT hit the breakpoint you previously set in the NativeHello.cpp file
  • At the command line, you can verify that the debug APK (in WSL: ./NativeHelloApp/bin/Debug/com.companyname.nativehelloapp-Signed.apk) that was built does NOT have any gdbserver included

So unfortunately we are stuck in a "Catch-22" situation here between the unwanted inclusion of gdbserver in Release bundles, and the lack of gdbserver in Debug builds.

Questions

So obviously this is a contrived example, but it illustrates a real issue we are having in our published Xamarin.Forms/Xamarin.Android app(s). We have native-compiled libraries across all Android supported arch+ABIs, and we need the ability to debug into this layer for Debug builds, as well as the ability to create Release AAB bundles.

  • Are we are overlooking some simple project fix that will unstick us from this Catch-22 situation?
  • Could the previous inclusion of gdbserver in official Release APKs (non-AAB bundling procedure) be deemed a security risk?
  • Is the above batch build process and the inclusion of the four arch+ABIs ./NativeHello/lib/<ARCH+ABI>/libNativeHello.so files in the app the "recommended best practice" for building this type of "hybrid" (managed/native) Xamarin.Android app from Visual Studio?

An MSBuild fix that appears to Work For Us

So we have taken the liberty to sleuth into MSBuild and have hit upon a potential solution that appears to work just fine for us.

The problem appears to happen in the MSBuild file Microsoft.Cpp.Android.targets.

The following patch gets us unstuck for both building a Release AAB bundle, while also not losing the ability to perform native debugging for Debug builds.

--- Microsoft.Cpp.Android.targets       2020-08-11 09:05:14.115831100 -0700
+++ "/mnt/c/Program Files (x86)/Microsoft Visual Studio/2019/Community/MSBuild/Xamarin/Android/Xamarin.Android.Common/ImportAfter/Microsoft.Cpp.Android.targets"                                                  2020-08-11 09:09:31.283389000 -0700
@@ -66,7 +68,7 @@
         <Error Text="Native library references target platform $(NativeLibraryAbi) which is not supported by this project. Configured supported ABIs are: $(AndroidSupportedAbis)."
                Condition="$(AndroidSupportedAbis.Contains('$(NativeLibraryAbi)').ToString().ToLowerInvariant()) == 'false'" />

-        <ItemGroup Condition="'@(NativeLibraryPaths)' != ''">
+        <ItemGroup Condition="'$(Configuration)' == 'Debug' And '@(NativeLibraryPaths)' != ''">
             <AndroidNativeLibrary Include="@(NativeLibraryPaths)"
                                   Condition="'%(Extension)' == '.so' Or '%(FileName)' == 'gdbserver'">
                 <Abi>$(NativeLibraryAbi)</Abi>
@@ -76,6 +78,16 @@
                <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
             </Content>
         </ItemGroup>
+        <ItemGroup Condition="'$(Configuration)' != 'Debug' And '@(NativeLibraryPaths)' != ''">
+            <AndroidNativeLibrary Include="@(NativeLibraryPaths)"
+                                  Condition="'%(Extension)' == '.so'">
+                <Abi>$(NativeLibraryAbi)</Abi>
+            </AndroidNativeLibrary>
+            <Content Include="@(NativeLibraryPaths)"
+                     Condition="'%(Extension)' == '.so'">
+                <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+            </Content>
+        </ItemGroup>

     </Target>

About

Xamarin.Android testcase that shows problem building Release AAB

License:MIT License


Languages

Language:HTML 31.8%Language:C++ 17.9%Language:SWIG 16.9%Language:C 9.5%Language:Java 4.6%Language:C# 2.8%Language:Makefile 2.7%Language:Python 2.3%Language:D 1.6%Language:Yacc 1.4%Language:Ruby 1.1%Language:Perl 0.9%Language:M4 0.8%Language:Lua 0.7%Language:Go 0.6%Language:PHP 0.6%Language:Shell 0.6%Language:Scilab 0.5%Language:Scheme 0.5%Language:OCaml 0.5%Language:MATLAB 0.4%Language:M 0.3%Language:JavaScript 0.3%Language:Tcl 0.2%Language:R 0.1%Language:Objective-C 0.1%Language:Common Lisp 0.1%Language:Pike 0.0%Language:Mercury 0.0%Language:Forth 0.0%Language:Standard ML 0.0%Language:CSS 0.0%Language:GDB 0.0%Language:Raku 0.0%Language:Batchfile 0.0%Language:Limbo 0.0%Language:Assembly 0.0%