Android系统模块编译调试与Ninja使用指南

模块编译调试方法

(此处举例framework、installd、SystemUI等模块的编译调试,其他类似)

1. Framework模块编译

Android系统代码的framework目录内,一共有3个模块单独编译:framework、services、framework-res.apk。

注意:偶尔会有改了代码但没检测到,编译结束后产物并未更新的情况,所以可以考虑先剪切掉原先的产物或者检查产物更新时间确保已经重新编译。

步骤

  1. 完成根目录下 source build/envsetup.sh 命令、lunch qssi-userdebug-mars 命令(准备好编译环境、选择好编译分支,才可以开始编译)。
  2. 整编命令如 bash build.sh -j32 dist --qssi_only 2>&1 | tee buildlog.log
1.1 修改frameworks/base/core/res下的内容
  • 在执行 source build/envsetup.sh 命令的版本源代码根目录执行 make framework-res -j32
  • 产物位于 out/target/product/qssi/system/framework 下面(如 framework-res.apk 之类),push到手机的 /system/framework/ 下面重启即可。
1.2 修改framework/base/services下的内容
  • 在执行 source build/envsetup.sh 命令的版本源代码根目录执行 make services -j32
  • 产物位于 out/target/product/qssi/system/framework 下面,拿出来push到手机的 /system/framework/ 下面重启即可。
1.3 修改framework/base/core下的内容
  • 在执行 source build/envsetup.sh 命令的版本源代码根目录执行 make framework-minus-apex -j32
  • 产物位于 out/target/product/qssi/system/framework 下面,拿出来push到手机的 /system/framework/ 下面重启即可。
  • 问题处理 :如果卡在开机过程里(常在小于Android13版本中发生),而且不是自己原因导致而是一些AndroidRuntime错误导致的signal 6的内存错误,可尝试在push framework.jaradb shell rm -rf system/framework/oat system/framework/arm system/framework/arm64 再重启。
1.4 其他目录下的代码修改
  • 在framework/base下的其他很多目录下的代码修改也可以被编译到,但需要自行确认:
    • 故意改错去编译。
    • 搜Android.bp文件内容看看framework-minus-apex library的srcs是否包含了被修改的文件。
1.5 作SDK
  • 如果是要make出jar包给apk调用而不是push到系统里调试,那要拿此目录的jar包:out/target/common/obj/JAVA_LIBRARIES/framework-minus-apex_intermediates/classes.jar
  • 版本改动注意 :在Android11之前修改了framework相关代码,只需 make framework 就可以编译出 framework.jar。在Android11,这个编译命令不起作用了,根据framework/base/目录下Android.bp中的提示,编译命令需要改为 make framework-minus-apex

2. 修改frameworks/native/cmds/abcd的任意模块代码

  • 通过 make abcd -j32 编译,比如 make installd -j16 make atrace -j16 等。
  • 产物位于 out/target/product/qssi/system/bin 下面,拿出来push到手机的 /system/bin/ 下面重启即可。

3. 修改packages/modules/abcd的代码

  • 通过找被修改文件属于的同/上级目录的Android.bp文件中哪个模块内编译,在此模块library中找到apex_available标签,即标识该library可以被name为xxxx的apex包进去,通过 make xxxx -j32 编译。
  • 产物位于 out/target/product/qssi/system/apex/ 下面,拿出来push到手机的 /system/apex/ 下面重启即可。
  • 示例 :修改了 /packages/modules/Wifi/framework/java/android/net/wifi/WifiManager.java,那么在 /packages/modules/Wifi/framework/Android.bp 中找到 apex_available: ["com.android.wifi", "test_com.android.wifi"],就知道 make com.android.wifi -j16 可以编译到被修改文件。

4. 改动SystemUI、Settings等模块的代码

  • 可以通过 make SystemUImake Settings 来进行编译,产物在 /system/app/system/priv-app 下面,将结果apk直接install,然后重启此应用相关服务,如直接重启手机,或者如SystemUI在install后 adb shell am restart 也可以。
  • 注意:不要push已经存在的apk到手机,重启系统不会扫描,新的apk不会重新安装,测试效果将还是原先的效果,除非此系统apk可以先删掉重启再push再重启。

5. 通用编译模块的方法

  • 如修改位于 framework/native/services 下的文件,可以通过在同级或上级目录中的Android.bp文件内容中查找修改的文件名字或具体目录,来找到所属sources,再逐级向上找到被编译进哪个"name"的目标产物xxx中,再 make xxx -j32 对其编译。
  • 如果xxx编译出的产物是中间产物或手机中没有的无法替换的产物可以再向上查找更大name的目标产物xxxx(如:cc_library_shared、cc_library、java_library、apex_available等)进行编译或直接push进system/lib和system/lib64重启。

6. 编译system.img

  • 当你确定修改的内容能在编译system.img时带入,可以使用 make systemimage -j16 编译。通过进入fastboot模式后刷system.img进行生效。

编译调试注意点

  1. 编译最好把已经生成的先删掉,不然有可能文件不更新(push前check下文件的生成时间)。
  2. 编译终端最后提示的生成路径不一定是唯一生成路径,同级目录、对称lib或lib64目录里可能都有你需要的生成物。library要把生成的库文件在system/lib和system/lib64下都做相应的push。
  3. 如果是push替换库文件,最好留一个原本的备份避免push了开不了机器。
  4. 编译调试的时候如果是自己陌生的模块,建议每次都加行特殊log以确认自己的修改已经生效。

二、使用ninja替代make进行快速编译

为什么要使用ninja?

通常使用make编译会有两个阶段:

  1. 先分析Android.bp,将所有需要参与编译的文件的路径都记录下,writing build rules并打包到 out/soong/combined-.ninja 中。(普遍耗时15-20min)
  2. 然后ninja工具通过第一步生成的文件,编译要编译的模块。(不同模块速度不同,比如services模块只需要大约20s)

优点:直接使用ninja就可以省去第一部分耗时,尤其在反复编译时调试效率提高。

注意点

  1. 进行ninja之前必须要先make一次(当然要想make必须先根目录source和lunch一次),以生成路径文件;如果你的修改增删了模块中文件的名字路径,就必须重新make生成路径文件。

ninja的获取

bash 复制代码
cd到android系统源码的根目录下,执行
cp prebuilts/build-tools/linux-x86/bin/ninja out/host/linux-x86/bin/
cp prebuilts/build-tools/linux-x86/bin/ninja /usr/local/bin/
cp prebuilts/build-tools/linux-x86/bin/ninja /usr/bin/
ln -sf out/combined-***.ninja build.ninja

ninja文件内容

bash 复制代码
#!/bin/bash
ninja(){
 ninja_bin="$ANDROID_BUILD_TOP/prebuilts/build-tools/linux-x86/bin/ninja"
 ninja_build_file="$ANDROID_BUILD_TOP/out/combined-$TARGET_PRODUCT.ninja"
 if [ ! -f $ninja_build_file ]
 then
 echo "can't find ninja buildfile $ninja_build_file"
 exit -1
 fi
 if [ ! -f $ninja_bin ]
 then
 echo "can't find ninja binary $ninja_bin"
 exit -1
 fi
 $ninja_bin -f $ninja_build_file $1
 }
#usage:ninja<modulename>
ninja $*

ninja的执行

如果执行ninja进行快速编译时,遇到如下错误:

bash 复制代码
ninja: error while loading shared libraries: libjemalloc5.so: cannot open shared object file: No such file or directory

使用如下解决方法:

bash 复制代码
sudo cp prebuilts/build-tools/linux-x86/lib64/libjemalloc5.so /usr/lib
相关推荐
程序员JerrySUN12 分钟前
OP-TEE + YOLOv8:从“加密权重”到“内存中解密并推理”的完整实战记录
android·java·开发语言·redis·yolo·架构
TeleostNaCl1 小时前
Android | 启用 TextView 跑马灯效果的方法
android·经验分享·android runtime
TheNextByte12 小时前
Android USB文件传输无法使用?5种解决方法
android
quanyechacsdn3 小时前
Android Studio创建库文件用jitpack构建后使用implementation方式引用
android·ide·kotlin·android studio·implementation·android 库文件·使用jitpack
程序员陆业聪4 小时前
聊聊2026年Android开发会是什么样
android
编程大师哥4 小时前
Android分层
android
极客小云6 小时前
【深入理解 Android 中的 build.gradle 文件】
android·安卓·安全架构·安全性测试
Juskey iii6 小时前
Android Studio Electric Eel | 2022.1.1 Patch 2 版本下载
android·ide·android studio
Android技术之家6 小时前
2025年度Android行业总结:AI驱动生态重构,跨端融合开启新篇
android·人工智能·重构
洞见前行6 小时前
Android第二代加固技术原理详解(附源码)
android