programacion - Depuración de la biblioteca de C++ con Android Studio
ndk android studio (2)
La información de depuración registra la ubicación de los archivos de origen cuando se crearon.
(lldb) image lookup -vrn Clory::Engine::instance
La línea CompileUnit muestra el archivo fuente. Supongamos que dice:
"/BuildDirectory/Sources/Clory/CloryEngine.cpp"
Supongamos que tiene la fuente en su máquina aquí:
"Users/me/Sources/Clory"
Así que puedes decirle a lldb: encuentra el archivo fuente enraizado en / BuildDirectory / Sources / Clory en Users / me / Sources / Clory en su lugar.
(lldb) settings set target.source-map /BuildDirectory/Sources/Clory Users/me/Sources/Clory
Puede usar estos comandos en la consola lldb de Android Studio o colocarlos en un archivo .lldbinit para uso general.
Estoy trabajando en un proyecto de Android
que utiliza una clase de Java
que es un contenedor en una biblioteca de C++
. La biblioteca de C ++ es una biblioteca interna de la empresa y tenemos acceso a su código fuente, pero en el proyecto de Android solo está enlazado dinámicamente, por lo que se usa solo en forma de encabezados ( .h ) y objetos compartidos ( .so ). Al tener acceso al código fuente de la biblioteca, ¿es posible especificar a Android Studio la ruta al código fuente para que pueda ingresar dentro de la biblioteca usando el depurador?
El depurador funciona. Puedo Java_clory_engine_sdk_CloryNative_nativeInit
función Java_clory_engine_sdk_CloryNative_nativeInit
, pero también me gustaría depurar más la biblioteca correspondiente a la clase Clory::Engine
que, como mencioné, es una biblioteca interna a la que tenemos acceso al código fuente.
Por ejemplo, la Clory::Engine::instance
es parte de la biblioteca y me gustaría especificar a Android Studio la ubicación del archivo CloryEngine.cpp
para que pueda CloryEngine.cpp
la CloryEngine.cpp
Clory::Engine::instance
con el depurador, por lo que depura esta función miembro estática.
Estoy usando Android Studio 3.1.4.
es posible?
EDITAR:
El archivo clory-sdk.gradle
especifica el archivo CMakeLists.txt
que configura la capa C ++.
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
Así que estoy usando una aplicación interna que usa el SDK de Clory . Dentro del archivo app.gradle
utilizo:
dependencies {
...
compile project('':clory-sdk-core'')
compile project('':clory-sdk'')
...
}
así que no creo que estemos usando las aar
para el proyecto app.gradle
. Los aar
se envían al cliente, pero estamos usando el proyecto app.gradle
para probar nuestras pequeñas funcionalidades de SDK antes de hacerlo. La capa JNI está dentro del proyecto clory-sdk-core
.
EDIT 2:
Aquí está el CMakeLists.txt
que maneja la capa JNI:
cmake_minimum_required(VERSION 3.4.1)
set(CMAKE_AUTOMOC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_BUILD_TYPE Debug)
add_library(
clory-lib
SHARED
# JNI layer and other helper classes for transferring data from Java to Qt/C++
src/main/cpp/clory-lib.cpp
src/main/cpp/JObjectHandler.cpp
src/main/cpp/JObjectResolver.cpp
src/main/cpp/JObjectCreator.cpp
src/main/cpp/DataConverter.cpp
src/main/cpp/JObjectHelper.cpp
src/main/cpp/JEnvironmentManager.cpp
)
find_library(
log-lib
log
)
target_compile_options(clory-lib
PUBLIC
-std=c++11
)
# Hardcoded for now...will fix later...
set(_QT_ROOT_PATH /Users/jacob/Qt/5.8)
if(${ANDROID_ABI} MATCHES ^armeabi-v7.*$)
set(_QT_ARCH android_armv7)
elseif(${ANDROID_ABI} MATCHES ^x86$)
set(_QT_ARCH android_x86)
else()
message(FATAL_ERROR "Unsupported Android architecture!!!")
endif()
set(CMAKE_FIND_ROOT_PATH ${_QT_ROOT_PATH}/${_QT_ARCH})
find_package(Qt5 REQUIRED COMPONENTS
Core
CONFIG
)
target_include_directories(clory-lib
PUBLIC
${CMAKE_CURRENT_LIST_DIR}/src/main/cpp
)
set(_CLORYSDK_LIB_PATH ${CMAKE_CURRENT_LIST_DIR}/src/main/jniLibs/${ANDROID_ABI})
target_link_libraries(clory-lib
${log-lib}
-L${_CLORYSDK_LIB_PATH}
clorysdk
Qt5::Core
)
La biblioteca clorysdk
es en realidad nuestra biblioteca interna de la que estaba hablando, que contiene, por ejemplo, Clory::Engine::instance
me gustaría intervenir con el depurador. Fue construido con qmake
y se construye en modo de depuración ( CONFIG+=debug
se agregó en la llamada qmake efectiva).
EDITAR 3:
En la sesión de LLDB
que se abrió después de que llegó al punto de interrupción Java_clory_engine_sdk_CloryNative_nativeInit
, obtuve lo siguiente:
(lldb) image lookup -vrn Clory::Engine::instance
2 matches found in /Users/jacob/.lldb/module_cache/remote-android/.cache/6EDE4F0A-0000-0000-0000-000000000000/libclorysdk.so:
Address: libclorysdk.so[0x0001bb32] (libclorysdk.so..text + 8250)
Summary: libclorysdk.so`Clory::Engine::instance(Clory::Engine::Purpose)
Module: file = "/Users/jacob/.lldb/module_cache/remote-android/.cache/6EDE4F0A-0000-0000-0000-000000000000/libclorysdk.so", arch = "arm"
Symbol: id = {0x0000005e}, range = [0xcb41eb32-0xcb41ebc0), name="Clory::Engine::instance(Clory::Engine::Purpose)", mangled="_ZN4Clory2Engine8instanceENS0_7PurposeE"
Address: libclorysdk.so[0x0001b82c] (libclorysdk.so..text + 7476)
Summary: libclorysdk.so`Clory::Engine::instance(Clory::RuntimeConfiguration const&, Clory::Engine::Purpose)
Module: file = "/Users/jacob/.lldb/module_cache/remote-android/.cache/6EDE4F0A-0000-0000-0000-000000000000/libclorysdk.so", arch = "arm"
Symbol: id = {0x000000bd}, range = [0xcb41e82c-0xcb41e970), name="Clory::Engine::instance(Clory::RuntimeConfiguration const&, Clory::Engine::Purpose)", mangled="_ZN4Clory2Engine8instanceERKNS_20RuntimeConfigurationENS0_7PurposeE"
(lldb) settings show target.source-map
target.source-map (path-map) =
En primer lugar, no había una sección CompileUnit
en el resultado del comando de image lookup -vrn Clory::Engine::instance
. ¿Cómo es posible que no se haya definido ningún mapa de origen (segundo comando lldb ) si libclorysdk.so
se creó en modo de depuración ? ¿Es posible configurarlo explícitamente para que el depurador busque allí los archivos de origen de la biblioteca?
EDITAR 4:
Después de buscar más, descubrí que el proceso de creación del APK en realidad *.so
bibliotecas *.so
de sus símbolos de depuración. libclorysdk.so
integrado en el modo de depuración tiene aproximadamente 10 MB, mientras que el archivo libclorysdk.so
que libclorysdk.so
después de desarchivar el archivo *.apk
generado es de 350 KB. Como se indica here , la ejecución de greadelf --debug-dump=decodedline libclorysdk.so
en la versión de depuración genera referencias a los archivos de origen, pero si el comando se ejecuta en la biblioteca extraída *.apk
, no genera nada.
¿Hay alguna manera de evitar que Android Studio elimine los *.so
s? Intenté cómo evitar la eliminación de símbolos de código nativo para la aplicación de Android, pero no tuvo ningún efecto, el archivo *.apk
tiene el mismo tamaño que antes y la depuración de las bibliotecas nativas todavía no funciona.
Estoy usando Gradle 3.1.4
.
EDIT 5:
La solución de extracción funciona, pero en mi caso necesitaba una limpieza y construcción antes de llegar a los puntos de interrupción en la biblioteca. La implementación de *.so
s que no se eliminan le permite tener sesiones de depuración y pasar a las bibliotecas nativas.
Nota:
Si las bibliotecas se crean utilizando la cadena de herramientas Qt for Android
, también se $SHADOW_BUILD/android-build
los *.so
implementados en $SHADOW_BUILD/android-build
(donde $SHADOW_BUILD
es el directorio de compilación que generalmente comienza con build-*
). Por lo tanto, para depurar aquellos, debe copiarlos desde fuera del directorio de android-build
donde se genera cada *.so
.
Si no hay símbolos de depuración disponibles, es posible que deba compilar la biblioteca a la que se hace referencia en el modo de depuración.
ya sea con -DCMAKE_BUILD_TYPE=DEBUG
:
externalNativeBuild {
cmake {
arguments "-DANDROID_TOOLCHAIN=gcc", "-DCMAKE_BUILD_TYPE=DEBUG"
cppFlags "-std=c++14 -fexceptions -frtti"
}
}
o agregue esto a CMakeLists.txt
de la biblioteca:
set(CMAKE_BUILD_TYPE Debug)
Consulte la documentación de CMake y Simbolización con LLDB .
elsewhere , explica (lldb) settings set target.source-map /buildbot/path /my/path
:
Reasignar nombres de ruta de archivo de origen para la sesión de depuración. Si sus archivos de origen ya no están ubicados en la misma ubicación que cuando se creó el programa, quizás el programa se creó en una computadora diferente, debe decirle al depurador cómo encontrar las fuentes en su ruta de archivo local. de la ruta del archivo del sistema de compilación.
también (lldb) settings show target.source-map
, para ver qué se asigna. (lldb) set append target.source-map /buildbot/path /my/path
parece bastante adecuado, para no sobrescribir las asignaciones existentes.