转载请注明出处:https://blog.csdn.net/qq_43522781/article/details/95039848
系统:Ubuntu 16.04
Clion:2019.1.4
Android:7.1.2_r36
gdb:7.11
2.1 源码下载与编译
Android源码下载与编译请参见Android系统源代码的下载与编译(https://www.jianshu.com/p/aeaceda41798)
注意:编译时选择eng版本,我此次选择编译的项目为:aosp_x86-eng版本
2.2 源码编译常见问题
1、unsupported reloc 43错误:
cp /usr/bin/ld.gold /media/guoke/LENOVO/Android_srource/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/x86_64-linux/bin/ld
修改
/art/build/Android.common_build.mk
中的
# Host.
ART_HOST_CLANG := false
ifneq ($(WITHOUT_HOST_CLANG),true)
# By default, host builds use clang for better warnings.
ART_HOST_CLANG := true
endif
为:
# Host.
ART_HOST_CLANG := false
ifneq ($(WITHOUT_HOST_CLANG),false)
# By default, host builds use clang for better warnings.
ART_HOST_CLANG := true
endif
修改
/build/core/clang/HOST_x86_common.mk
在其中的
ifeq ($(HOST_OS),linux)
CLANG_CONFIG_x86_LINUX_HOST_EXTRA_ASFLAGS := \
下添加:
-B$($(clang_2nd_arch_prefix)HOST_TOOLCHAIN_FOR_CLANG)/x86_64-linux/bin
结果为:
ifeq ($(HOST_OS),linux)
CLANG_CONFIG_x86_LINUX_HOST_EXTRA_ASFLAGS := \
--gcc-toolchain=$($(clang_2nd_arch_prefix)HOST_TOOLCHAIN_FOR_CLANG) \
--sysroot=$($(clang_2nd_arch_prefix)HOST_TOOLCHAIN_FOR_CLANG)/sysroot \
-no-integrated-as\
-B$($(clang_2nd_arch_prefix)HOST_TOOLCHAIN_FOR_CLANG)/x86_64-linux/bin
2、Try increasing heap size with java option ‘-Xmx’ 错误:
按照上述发现的提示语句,我们对prebuilts/sdk/tools/jack-admin文件进行如下修改:
首先找到如下语句:
JACK_SERVER_COMMAND="java -XX:MaxJavaStackTraceDepth=-1 -Djava.io.tmpdir=$TMPDIR $JACK_SERVER_VM_ARGUMENTS -cp $LAUNCHER_JAR $LAUNCHER_NAME"
然后将上述语句修改为:
JACK_SERVER_COMMAND="java -XX:MaxJavaStackTraceDepth=-1 -Djava.io.tmpdir=$TMPDIR $JACK_SERVER_VM_ARGUMENTS -Xmx4096m -cp $LAUNCHER_JAR $LAUNCHER_NAME"
主要是添加了-Xmx4096m参数。
最后在源码目录下执行如下命令重启jack-admin服务:
./prebuilts/sdk/tools/jack-admin stop-server
./prebuilts/sdk/tools/jack-admin start-server
重启完jack-admin服务后,此时再重新执行编译命令就能编译通过ninja了。
3、源码编译过程中卡死:
项目中遇到编译Android源码的过程中会卡住很久没有任何动静的情况,用top命令查看当前资源状态,发现是卡在aapt进程上面。
修改以下两个地方以后可以解决问题:
修改
build/target/product/languages_full.mk
和
build/target/product/locales_full.mk
中的
PRODUCT_LOCALES := en_US en_AU en_IN fr_FR it_IT es_ES et_EE de_DE nl_NL cs_CZ pl_PL ja_JP zh_TW zh_CN zh_HK ru_RU ko_KR nb_NO es_US da_DK el_GR tr_TR pt_PT pt_BR rm_CH sv_SE bg_BG ca_ES en_GB fi_FI hi_IN hr_HR hu_HU in_ID iw_IL lt_LT lv_LV ro_RO sk_SK sl_SI sr_RS uk_UA vi_VN tl_PH ar_EG fa_IR th_TH sw_TZ ms_MY af_ZA zu_ZA am_ET hi_IN en_XA ar_XB fr_CA km_KH lo_LA ne_NP si_LK mn_MN hy_AM az_AZ ka_GE my_MM mr_IN ml_IN is_IS mk_MK ky_KG eu_ES gl_ES bn_BD ta_IN kn_IN te_IN uz_UZ ur_PK kk_KZ
为
PRODUCT_LOCALES := en_US zh_CN
2.3 Android Studio及Clion下载及安装
安装完成后,利用Android Studio的Avd Manager中下载API 25 的x86镜像并建立avd模拟器。模拟器运行成功后,将自己编译的镜像替换原始镜像进行运行检查。
具体:将out/target/product/generic_x86目录下的system.img、userdata.img、ramdisk.img复制到Sdk/system-images/android-25/google_apis_playstore/x86中,替换掉同名文件,并将其余无用文件删除,其中Sdk/为我的Android Studio sdk存放位置。替换后如下:
运行测试:
cd ~/Android/Sdk/tools
./emulator -avd Nexus_5X_API_25
Build number中为我自己编译的版本,测试通过,可以继续开始下面的调试。
2.4、Clion中导入Android系统源码
由于Clion 仅支持Cmake,而Android采用的是Makefile 格式,因此需要参考Android Native C/C++ 使用CLion阅读/编译技巧
(https://blog.csdn.net/li864804994/article/details/79487834)
中的方式进行导入。
首先将下在后的android-cmake-project(https://github.com/Ahren-Li/android-cmake-project)文件拷贝到你的Android源码目录下。
然后导入源码,File→New Cmake Project From Source选择你的系统文件夹,后一路OK即可。
并修改env_android.cmake文件为:
set(ANDROID_LUNCH generic_x86)
set(ANDROID_TARGET_ARCH x86)
set(ANDROID_ABI "x86")
#set(ANDROID_ABI "armeabi-v7a with NEON")
#set(ANDROID_ABI "arm-v7")
set(ANDROID_TOOLCHAIN_NAME "clang")
set(ANDROID_STL c++_static)
set(ANDROID_PLATFORM android-25)
set(ANDROID_NATIVE_API_LEVEL 25)
注意:/media/u/LENOVO/Android_srource/修改为你自己路径。
等待Clion index完成。
如上,表示导入成功。
3.1 使用gdb shell进行调试
这一步主要是为了测试调试文件及命令等是否正常,排除Clion以外的问题。
以调试init为例
在桌面新建一个文件夹,并在其中
新建run_emulator.sh文件
内容为:
cd ~/Android/Sdk/tools
./emulator -avd Nexus_5X_API_25
新建start_android_gdb_server.sh(该文件在搭建Android源码调试环境(三)——调试C/C++(使用CLion)的基础上添加了部分调试信息)
#!/usr/bin/env bash
gdbServerPid=`adb shell ps | grep gdbserver | awk '{print $2}'`
echo "gdbserver进程Pid为: ${gdbServerPid} "
if [[ "" != ${gdbServerPid} ]]; then
adb shell su -c "kill ${gdbServerPid}"
echo "Kill进程: ${gdbServerPid} "
fi
adb forward tcp:1234 tcp:1234
echo "端口转发成功,端口为:1234"
if [[ `adb shell whoami` == 'root' ]]; then
is_root=true
echo "Shell为ROOT模式"
fi
if [[ -n $1 ]]; then
appPid=`adb shell ps | grep ${1} | awk '{print $2}'`
echo "要调试进程的Pid为: ${appPid}"
if [[ -n ${appPid} ]]; then
if [[ $is_root == true ]]; then
adb shell gdbserver :1234 --attach ${appPid}
echo "附加到进程 ${appPid} "
else
adb shell su -c "gdbserver :1234 --attach ${appPid} "
echo "附加到进程 ${appPid} "
fi
else
echo "$1 进程没有启动!"
fi
else
echo "请设置要调试的进程名(app的进程名是包名)。例如 $0 "
fi
新建gdb_shell_init文件
内容为:
shell adb forward tcp :1234 tcp :1234
target remote localhost:1234
file '/media/u/LENOVO/Android_srource/out/target/product/generic_x86/symbols/init'
set sysroot '/media/u/LENOVO/Android_srource/out/target/product/generic_x86/symbols'
set dir '/media/u/LENOVO/Android_srource'
list
新建main_init.sh文件
内容为:
#!/usr/bin/env bash
clion_pid=`ps -u | grep sh | grep clion.sh | awk '{print $2}'`
if [[ "" == ${clion_pid} ]]; then
cd ~/桌面/clion-2019.1.4/bin
gnome-terminal -x bash -c "sh clion.sh;"
echo "启动clion: ${clion_pid} "
read -p "clion是否启动完成" var
fi
echo "clion已启动完成。"
cd ~/桌面/run_emulator
emulator_pid=`ps -u | grep emulator | grep Nexus_5X_API_25 | awk '{print $2}'`
if [[ "" == ${emulator_pid} ]]; then
gnome-terminal -x bash -c "sh run_emulator.sh;"
echo "启动模拟器: ${emulator_pid} "
read -p "模拟器是否已启动完成。" var
fi
echo "模拟器已启动完成。"
cd ~/Android/Sdk/platform-tools
./adb shell getenforce
./adb shell "echo 0 > /sys/fs/selinux/enforce"
while true
do
echo "停止zygote运行。"
./adb shell stop zygote
zygote_pid=`adb shell ps | grep zygote | awk '{print $2}'`
cd ~/桌面/run_emulator
#gnome-terminal -x bash -c "./start_android_gdb_server.sh zygote;"
gnome-terminal -x bash -c "./start_android_gdb_server.sh init;"
read -p "gdbserver是否启动完成。" var
cd /media/u/LENOVO/Android_srource/prebuilts/gdb/linux-x86/bin/
echo "在clion中下断点,并运行调试。"
#./gdb --command=~/桌面/run_emulator/gdb_shell_zygote
./gdb --command=~/桌面/run_emulator/gdb_shell
read -p "gdb是否已连接上远程gdbserver。" var
cd ~/Android/Sdk/platform-tools
echo "开始运行zygote。"
./adb shell start zygote
read -p "是否继续." var
old_win_pid=`ps -u | grep start_android_gdb_server.sh | grep zygote | awk '{print $2}'`
kill ${old_win_pid}
done
其中
~/桌面/clion-2019.1.4/为我的Clion安装目录,
~/Android/Sdk/为我的sdk目录,
/media/u/LENOVO/Android_srource/为我的android源码目录,
~/桌面/run_emulator/为我存放上述文件的目录。
在目录中运行main_init.sh
出现如下图,说明gdb连接成功,端口为1234
出现:
说明调试符号、源文件、系统镜像等没有问题,可以进行调试。
3.2 使用Clion进行调试
按照搭建Android源码调试环境(三)——调试C/C++(使用CLion)
(https://blog.csdn.net/lylwo317/article/details/86545130)进行,在system/core/Init/service.cpp中的Start()函数设置好断点,
并设置Run/Debug Configurations如下:
其中注意:
gdb为android源码中的gdb
特别注意设置Path mappings,否则Clion会出现找不到源代码的情况。
设置Sysroot,让Clion可以找到符号文件
Symbool file,根据自己许调试的文件进行修改
设置完成后,在上面的脚本文件夹中新建main.sh文件,内容为:
#!/usr/bin/env bash
clion_pid=`ps -u | grep sh | grep clion.sh | awk '{print $2}'`
clion_pid_num=`ps -u | grep sh | grep clion.sh | wc -l`
if [[ "1" == ${clion_pid_num} ]]; then
cd ~/桌面/clion-2019.1.4/bin
gnome-terminal -x bash -c "sh clion.sh;"
echo "启动clion: ${clion_pid} "
read -p "clion是否启动完成" var
fi
echo "clion已启动完成。"
cd ~/桌面/run_emulator
emulator_pid=`ps -u | grep emulator | grep Nexus_5X_API_25 | awk '{print $2}'`
if [[ "" == ${emulator_pid} ]]; then
gnome-terminal -x bash -c "sh run_emulator.sh;"
echo "启动模拟器: ${emulator_pid} "
read -p "模拟器是否已启动完成。" var
fi
echo "模拟器已启动完成。"
cd ~/Android/Sdk/platform-tools
./adb shell getenforce
./adb shell "echo 0 > /sys/fs/selinux/enforce"
while true
do
echo "停止zygote运行。"
./adb shell stop zygote
cd ~/桌面/run_emulator
gnome-terminal -x bash -c "./start_android_gdb_server.sh init;"
read -p "gdbserver是否启动完成。" var
cd /media/u/LENOVO/Android_srource/prebuilts/gdb/linux-x86/bin/
echo "在clion中下断点,并运行调试。"
#./gdb --command=~/桌面/run_emulator/gdb_shell
read -p "gdb是否已连接上远程gdbserver。" var
cd ~/Android/Sdk/platform-tools
echo "开始运行zygote。"
./adb shell start zygote
read -p "是否继续." var
old_win_pid=`ps -u | grep start_android_gdb_server.sh | grep init | awk '{print $2}'`
kill ${old_win_pid}
done
且clion中点击调试后在Console串口出现:Debugger connected to 127.0.0.1:1234
出现
在Debugger的GDB窗口出现:
说明,gdb连接正确,Clion能够正确加载符号文件和源码。
后按照脚本提示操作,回车后脚本恢复zygote运行,执行./adb shell start zygote命令。Clion中的源码中断在断点处,可以进行调试。
1、搭建Android源码调试环境(三)——调试C/C++(使用CLion)
(https://blog.csdn.net/lylwo317/article/details/86545130)
2、Android Native C/C++ 使用CLion阅读/编译技巧
(https://blog.csdn.net/li864804994/article/details/79487834)
3、Android系统源代码的下载与编译
(https://www.jianshu.com/p/aeaceda41798)