Je travaille sur un projet Android
qui utilise une classe Java
qui est un wrapper sur un C++
bibliothèque. La bibliothèque C++ est une bibliothèque interne à l'entreprise et nous avons accès à son code source, mais dans le projet Android, elle n'est liée que dynamiquement, elle n'est donc utilisée que sous la forme d'en-têtes (.h) et les objets partagés (. so). Ayant accès au code source de la bibliothèque, est-il possible de spécifier à Android Studio le chemin d'accès au code source pour que je puisse entrer dans la bibliothèque à l'aide du débogueur?
Le débogueur fonctionne, je peux entrer dans le Java_clory_engine_sdk_CloryNative_nativeInit
, mais je voudrais également déboguer davantage la bibliothèque correspondant à Clory::Engine
classe qui, comme je l'ai mentionné, est une bibliothèque interne à laquelle nous avons accès en code source.
Par exemple, Clory::Engine::instance
fait partie de la bibliothèque et je voudrais spécifier à Android Studio l'emplacement du CloryEngine.cpp
fichier pour que je puisse entrer Clory::Engine::instance
avec le débogueur, déboguant ainsi cette fonction membre statique.
J'utilise Android Studio 3.1.4.
Est-ce possible?
MODIFIER:
Le clory-sdk.gradle
le fichier spécifie le CMakeLists.txt
fichier qui configure la couche C++.
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
J'utilise donc une application interne qui utilise le Clory SDK. À l'intérieur de app.gradle
fichier que j'utilise:
dependencies {
...
compile project(':clory-sdk-core')
compile project(':clory-sdk')
...
}
donc je ne pense pas que nous utilisons les aar
s pour les app.gradle
projet. Les aar
sont expédiés au client, mais nous utilisons app.gradle
projet de tester nos petites fonctionnalités du SDK avant de le faire. La couche JNI est à l'intérieur clory-sdk-core
projet.
EDIT 2:
Voici la CMakeLists.txt
qui gère la couche 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 bibliothèque clorysdk
est en fait notre bibliothèque interne dont je parlais, qui contient par exemple Clory::Engine::instance
Je voudrais intervenir avec le débogueur. Il a été construit avec qmake
et est construit en mode débogage (CONFIG+=debug
a été ajouté dans l'appel qmake effectif).
EDIT 3:
Dans la session LLDB
qui s'est ouverte après avoir atteint le Java_clory_engine_sdk_CloryNative_nativeInit
point d'arrêt, j'ai obtenu ce qui suit:
(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) =
Tout d'abord, il n'y avait pas de section CompileUnit
dans le résultat de la commande image lookup -vrn Clory::Engine::instance
. Comment est-il possible de n'avoir aucune source-map définie (seconde lldb commande) si la commande libclorysdk.so
a été construit en mode Débogage? Est-il possible de le définir explicitement pour que le débogueur y recherche les fichiers source de la bibliothèque?
EDIT 4:
Après avoir cherché plus, j'ai découvert que le processus de création de l'APK supprime en fait le *.so
bibliothèques à partir de leurs symboles de débogage. libclorysdk.so
construit en mode débogage a environ 10 Mo tandis que le libclorysdk.so
fichier que j'ai extrait après désarchivage du *.apk
le fichier ne fait que 350 Ko. Comme indiqué ici , exécutant greadelf --debug-dump=decodedline libclorysdk.so
sur la version de débogage renvoie des références aux fichiers source, mais si la commande est exécutée sur le *.apk
bibliothèque extraite, elle ne produit rien.
Existe-t-il un moyen d'empêcher Android Studio de supprimer le *.so
s? J'ai essayé Comment éviter de supprimer les symboles de code natif pour Android mais je n'ai eu aucun effet, *.apk
le fichier a la même taille qu'auparavant et le débogage des bibliothèques natives ne fonctionne toujours pas.
J'utilise Gradle 3.1.4
.
EDIT 5:
La solution de décapage fonctionne, mais dans mon cas, il fallait un Clean & Build avant d'atteindre les points d'arrêt dans la bibliothèque. Déploiement de *.so
s qui ne sont pas supprimés vous permet d'avoir des sessions de débogage et de pénétrer dans les bibliothèques natives.
Remarque:
Si les bibliothèques sont construites en utilisant le Qt for Android
chaîne d'outils, le *.so
s déployés sur $SHADOW_BUILD/Android-build
sont également supprimés (où $SHADOW_BUILD
est le répertoire de construction commençant généralement par build-*
). Donc, pour déboguer ceux-ci, vous devez les copier de l'extérieur du Android-build
répertoire où chaque *.so
est généré.
Les informations de débogage enregistrent l'emplacement des fichiers source lors de leur génération.
(lldb) image lookup -vrn Clory::Engine::instance
La ligne CompileUnit affiche le fichier source. Supposons qu'il indique:
"/BuildDirectory/Sources/Clory/CloryEngine.cpp"
Supposons que vous ayez la source sur votre machine ici:
"Users/me/Sources/Clory"
Vous pouvez donc dire à lldb: recherchez plutôt le fichier source enraciné dans/BuildDirectory/Sources/Clory dans Users/me/Sources/Clory.
(lldb) settings set target.source-map /BuildDirectory/Sources/Clory Users/me/Sources/Clory
Vous pouvez utiliser ces commandes dans la console lldb de Android Studio ou les placer dans un fichier .lldbinit pour une utilisation générale.
si aucun symbole de débogage n'est disponible, vous devrez peut-être créer la bibliothèque référencée en mode débogage.
soit avec -DCMAKE_BUILD_TYPE=DEBUG
:
defaultConfig {
externalNativeBuild {
cmake {
arguments "-DANDROID_TOOLCHAIN=gcc", "-DCMAKE_BUILD_TYPE=DEBUG"
cppFlags "-std=c++14 -fexceptions -frtti"
}
}
}
externalNativeBuild {
cmake {
path file('src/main/cpp/CMakeLists.txt')
}
}
ou ajoutez ceci au CMakeLists.txt
de la bibliothèque:
set(CMAKE_BUILD_TYPE Debug)
voir la documentation CMake et Symbolicating with LLDB .
ailleurs ça explique (lldb) settings set target.source-map /buildbot/path /my/path
:
Remappez les noms de chemin du fichier source pour la session de débogage. Si vos fichiers source ne se trouvent plus au même endroit que lorsque le programme a été construit --- peut-être que le programme a été construit sur un autre ordinateur - - vous devez indiquer au débogueur comment trouver les sources sur leur chemin de fichier local au lieu du chemin de fichier du système de génération.
il y a aussi (lldb) settings show target.source-map
, pour voir ce qui est mappé. (lldb) set append target.source-map /buildbot/path /my/path
semble plutôt approprié, afin de ne pas écraser les mappages existants.