Search code examples
androidc++gradlecmakelldb

Debug a dynamically loaded native library in Android Studio?


I have a project that looks like this:

- project
    - app
       - src.../cpp/
       - src.../java/
    - other modules...

The cpp code is built using cmake in build.gradle:

externalNativeBuild {
    cmake {
        path "CMakeLists.txt"
    }
}

and

buildTypes {
   ...
    debug {
        debuggable true
        jniDebuggable true
        externalNativeBuild {
            cmake {
                arguments "-DCMAKE_BUILD_TYPE=Debug"
                abiFilters "armeabi-v7a", "armeabi", "x86"
            }
        }
    }
}

productFlavors {
    ...
    experimental {
        externalNativeBuild {
            cmake {
                targets "sqlite_gcd_func"
            }
        }
    }
}

where CMakeLists.txt is:

cmake_minimum_required(VERSION 3.6)

add_library( # Specifies the name of the library.
         sqlite_gcd_func
         # Sets the library as a shared library.
         MODULE
         # Provides a relative path to your source file(s).
         src/Experimental/cpp/GreatCircleDistance.cpp )
# Specifies a path to native header files.
include_directories(src/Experimental/cpp/include/)

The generated .so library is loaded into SQLite as an extension via SQL:

Select load_extension('libsqlite_gcd_func', null)

after which the function defined in the library is available to SQL queries.

This all works.

What does not work s debugging; breakpoints set in the CPP code do not trigger.

I assume this is because the code is dynamically loaded at run time; I have also tried directly loading the module using java via:

java.lang.System.loadLibrary("sqlite_gcd_func");

But break points still do not work.

My knowledge of lldb is minimal; I assume I need to tell it that the loaded module (visible via 'image list' in lldb) is a known module, but have no idea how to do so (if that is even the problem).

Any assistance in telling gradle/lldb/Android Studio how to debug this code would be much appreciated!

EDIT:

I've created a much simpler project with similar settings and it is debuggable. In the non-debugable one, when I go into lldb and run 'image list', the .so in question shows up as in:

C:\Users\ME\.lldb\module_cache\remote-android\.cache\8D1C60AA-E947-56CA-CBA5-0AA7A46B955E-73E37532\libname.so

(ie. what looks like a version copied off the AVD).

Whereas in the one that I can debug, it shows up in:

C:\...\project\app\build\intermediates\cmake\debug\obj\x86\libname.so

ie. the actual library in the build area.

lldb seems not to use the local app version for some reason.

Any idea what would cause that?


Solution

  • It turns out this is due to an old bug in AS. Apparently in the past the "SELECTED_BUILD_VARIANT" in the "native-android-gradle" section in the IML file could become out of step with the actual selected flavour. This resulted in the failure to load the .so files.

    Once corrected, this value seems to remain up to date now, and the following is a link to the discussion of the (now-fixed) bug:

    https://issuetracker.google.com/issues/37114841

    From what I can tell, a project sync may also fix the problem (it didn't for me).