模塊編譯調試方法
(此處舉例framework、installd、SystemUI等模塊的編譯調試,其他類似)
1. Framework模塊編譯
Android系統代碼的framework目錄內,一共有3個模塊單獨編譯:framework、services、framework-res.apk。
注意:偶爾會有改了代碼但沒檢測到,編譯結束后產物并未更新的情況,所以可以考慮先剪切掉原先的產物或者檢查產物更新時間確保已經重新編譯。
步驟:
- 完成根目錄下
source build/envsetup.sh
命令、lunch qssi-userdebug-mars
命令(準備好編譯環境、選擇好編譯分支,才可以開始編譯)。 - 整編命令如
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.jar
后adb 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 SystemUI
、make 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進行生效。
編譯調試注意點
- 編譯最好把已經生成的先刪掉,不然有可能文件不更新(push前check下文件的生成時間)。
- 編譯終端最后提示的生成路徑不一定是唯一生成路徑,同級目錄、對稱lib或lib64目錄里可能都有你需要的生成物。library要把生成的庫文件在system/lib和system/lib64下都做相應的push。
- 如果是push替換庫文件,最好留一個原本的備份避免push了開不了機器。
- 編譯調試的時候如果是自己陌生的模塊,建議每次都加行特殊log以確認自己的修改已經生效。
二、使用ninja替代make進行快速編譯
為什么要使用ninja?
通常使用make編譯會有兩個階段:
- 先分析Android.bp,將所有需要參與編譯的文件的路徑都記錄下,writing build rules并打包到
out/soong/combined-.ninja
中。(普遍耗時15-20min) - 然后ninja工具通過第一步生成的文件,編譯要編譯的模塊。(不同模塊速度不同,比如services模塊只需要大約20s)
優點:直接使用ninja就可以省去第一部分耗時,尤其在反復編譯時調試效率提高。
注意點
- 進行ninja之前必須要先make一次(當然要想make必須先根目錄source和lunch一次),以生成路徑文件;如果你的修改增刪了模塊中文件的名字路徑,就必須重新make生成路徑文件。
ninja的獲取
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文件內容
#!/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 ]thenecho "can't find ninja buildfile $ninja_build_file"exit -1fiif [ ! -f $ninja_bin ]thenecho "can't find ninja binary $ninja_bin"exit -1fi$ninja_bin -f $ninja_build_file $1}
#usage:ninja<modulename>
ninja $*
ninja的執行
如果執行ninja進行快速編譯時,遇到如下錯誤:
ninja: error while loading shared libraries: libjemalloc5.so: cannot open shared object file: No such file or directory
使用如下解決方法:
sudo cp prebuilts/build-tools/linux-x86/lib64/libjemalloc5.so /usr/lib