在 Android Studio 中调试动态加载的本机库?
Debug a dynamically loaded native library in Android Studio?
我有一个看起来像这样的项目:
- project
- app
- src.../cpp/
- src.../java/
- other modules...
cpp代码是在build.gradle中使用cmake构建的:
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
和
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"
}
}
}
}
其中 CMakeLists.txt 是:
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/)
生成的 .so 库通过 SQL:
作为扩展加载到 SQLite
Select load_extension('libsqlite_gcd_func', null)
之后库中定义的函数可用于 SQL 查询。
一切正常。
调试不行; CPP代码中设置的断点不触发。
我认为这是因为代码是在 运行 时动态加载的;我还尝试使用 java 通过以下方式直接加载模块:
java.lang.System.loadLibrary("sqlite_gcd_func");
但是断点还是不行
我对 lldb 的了解很少;我假设我需要告诉它加载的模块(通过 lldb 中的 'image list' 可见)是一个已知模块,但不知道该怎么做(如果这甚至是问题的话)。
如能帮助 gradle/lldb/Android Studio 调试此代码,我们将不胜感激!
编辑:
我用类似的设置创建了一个更简单的项目,它是可调试的。在不可调试的情况下,当我进入 lldb 和 运行 'image list' 时,有问题的 .so 显示为:
C:\Users\ME\.lldb\module_cache\remote-android\.cacheD1C60AA-E947-56CA-CBA5-0AA7A46B955E-73E37532\libname.so
(即看起来像是从 AVD 复制的版本)。
而在我可以调试的那个中,它显示在:
C:\...\project\app\build\intermediates\cmake\debug\obj\x86\libname.so
即。构建区域中的实际库。
lldb 由于某些原因似乎没有使用本地应用程序版本。
知道是什么原因造成的吗?
原来这是由于AS中的一个老bug。显然,在过去,IML 文件中 "native-android-gradle" 部分中的 "SELECTED_BUILD_VARIANT" 可能会与实际选择的口味不一致。导致加载.so文件失败
更正后,此值现在似乎仍然是最新的,以下是 link 对(现已修复)错误的讨论:
https://issuetracker.google.com/issues/37114841
据我所知,项目同步 可能 也可以解决问题(对我来说不是)。
我有一个类似的问题,我无法调试动态加载的本机库。事实证明,Android 构建系统在将调试信息放入 APK 之前从我的库中剥离了调试信息。当我意识到我的 300MB 库在打包到 APK 后缩小到 30MB 时,我就清楚了。
您可以使用 Android Gradle Packaging Options 来禁用该行为。
将类似的内容添加到您的 build.gradle
文件中:
android {
packagingOptions {
// By default .so libraries are striped from debug information when creating APK
// To prevent this make sure your .so files are matching that doNotStrip pattern
// See Gradle pattern document for details:
// https://docs.gradle.org/current/javadoc/org/gradle/api/tasks/util/PatternFilterable.html
doNotStrip "**"
}
}
这与 Android Studio 2.3.3 相关。
缓存无效并重新启动。适合我。
我有一个看起来像这样的项目:
- project
- app
- src.../cpp/
- src.../java/
- other modules...
cpp代码是在build.gradle中使用cmake构建的:
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
和
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"
}
}
}
}
其中 CMakeLists.txt 是:
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/)
生成的 .so 库通过 SQL:
作为扩展加载到 SQLiteSelect load_extension('libsqlite_gcd_func', null)
之后库中定义的函数可用于 SQL 查询。
一切正常。
调试不行; CPP代码中设置的断点不触发。
我认为这是因为代码是在 运行 时动态加载的;我还尝试使用 java 通过以下方式直接加载模块:
java.lang.System.loadLibrary("sqlite_gcd_func");
但是断点还是不行
我对 lldb 的了解很少;我假设我需要告诉它加载的模块(通过 lldb 中的 'image list' 可见)是一个已知模块,但不知道该怎么做(如果这甚至是问题的话)。
如能帮助 gradle/lldb/Android Studio 调试此代码,我们将不胜感激!
编辑:
我用类似的设置创建了一个更简单的项目,它是可调试的。在不可调试的情况下,当我进入 lldb 和 运行 'image list' 时,有问题的 .so 显示为:
C:\Users\ME\.lldb\module_cache\remote-android\.cacheD1C60AA-E947-56CA-CBA5-0AA7A46B955E-73E37532\libname.so
(即看起来像是从 AVD 复制的版本)。
而在我可以调试的那个中,它显示在:
C:\...\project\app\build\intermediates\cmake\debug\obj\x86\libname.so
即。构建区域中的实际库。
lldb 由于某些原因似乎没有使用本地应用程序版本。
知道是什么原因造成的吗?
原来这是由于AS中的一个老bug。显然,在过去,IML 文件中 "native-android-gradle" 部分中的 "SELECTED_BUILD_VARIANT" 可能会与实际选择的口味不一致。导致加载.so文件失败
更正后,此值现在似乎仍然是最新的,以下是 link 对(现已修复)错误的讨论:
https://issuetracker.google.com/issues/37114841
据我所知,项目同步 可能 也可以解决问题(对我来说不是)。
我有一个类似的问题,我无法调试动态加载的本机库。事实证明,Android 构建系统在将调试信息放入 APK 之前从我的库中剥离了调试信息。当我意识到我的 300MB 库在打包到 APK 后缩小到 30MB 时,我就清楚了。
您可以使用 Android Gradle Packaging Options 来禁用该行为。
将类似的内容添加到您的 build.gradle
文件中:
android {
packagingOptions {
// By default .so libraries are striped from debug information when creating APK
// To prevent this make sure your .so files are matching that doNotStrip pattern
// See Gradle pattern document for details:
// https://docs.gradle.org/current/javadoc/org/gradle/api/tasks/util/PatternFilterable.html
doNotStrip "**"
}
}
这与 Android Studio 2.3.3 相关。
缓存无效并重新启动。适合我。