安卓構建系統(tǒng)
時間:2023-04-29 12:54:02 | 來源:網站運營
時間:2023-04-29 12:54:02 來源:網站運營
安卓構建系統(tǒng):
同步發(fā)布平臺
- 博客園: https://www.cnblogs.com/jiangxinnju/
- CSDN: https://blog.csdn.net/jiangxinnju
- 掘金: https://juejin.cn/user/166781500533079
- 本站: https://www.zhihu.com/people/jiangxinnju/posts
未經允許,謝絕轉載在以下位置描述了Android構建系統(tǒng): 你可以使用
build/envsetup.sh
設置一個"便利環(huán)境"來處理Android源代碼。在當前shell環(huán)境中執(zhí)行
source build/envsetup.sh
后,你可以輸入hmm作為已定義函數(shù)的列表,這些函數(shù)有助于與源進行交互。
概述
構建系統(tǒng)使用一些預設的環(huán)境變量和一系列"make"文件來構建Android系統(tǒng)并準備將其部署到平臺上。
子項目的Android構建文件叫做Android.bp和Android.mk。
整個存儲庫的源樹頂部只有一個名為"Makefile"的官方文件。你設置了一些環(huán)境變量,然后鍵入"make"或僅鍵入m來構建內容。你可以在make命令行(其他目標)中添加一些選項以打開詳細輸出或執(zhí)行其他操作。
構建輸出放置在
out/host
和
out/target
中。
out/host
下的東西是為你的主機平臺(臺式機)編譯的東西。最終在
out/target/product/<platform-name>
下的內容會以特定方式被放到目標設備(或模擬器)。
目錄
out/target/product/<platform-name>/obj
用于暫存"object"文件,這些文件是用于構建最終程序的中間二進制映像。實際落在目標文件系統(tǒng)中的內容存儲在
out/target/product/<platform-name>
下的root,system和data目錄中。通常,這些文件捆綁成名為system.img,ramdisk.img和userdata.img的映像文件。
這與大多數(shù)Android設備上使用的文件系統(tǒng)分區(qū)相匹配。
一些細節(jié)
使用什么工具
在構建期間,你將使用soong,ninja和'make'控制構建步驟。主機工具鏈(編譯器,鏈接器和其他工具)和庫將用于構建將在主機上運行的程序和工具。使用不同的工具鏈來編譯將在目標(嵌入式板,設備或模擬器)上運行的C和C++代碼。這通常是在X86平臺上運行的"交叉"工具鏈,但會為其他平臺(最常見的是ARM)生成代碼。內核被編譯為獨立的二進制文件(它不使用程序加載器或鏈接到任何外部庫)。其他項目,例如本機程序(例如init或工具箱),守護程序或庫,將鏈接到仿生庫或其他系統(tǒng)庫。
你將使用Java編譯器和大量與Java相關的工具來構建大多數(shù)應用程序框架,系統(tǒng)服務和Android應用程序本身。最后,使用工具打包應用程序和資源文件,并創(chuàng)建可以安裝在設備上或與模擬器一起使用的文件系統(tǒng)映像。
告訴系統(tǒng)Java工具鏈在哪里
在構建任何東西之前,你必須告訴Android構建系統(tǒng)Java SDK的位置。(安裝Java SDK是構建的先決條件)。 通過設置JAVA_HOME環(huán)境變量來執(zhí)行此操作。
指定要構建的內容
為了決定要構建什么以及如何構建,構建系統(tǒng)要求設置一些變量??梢詮耐辉创a樹構建具有不同軟件包和選項的不同產品。可以通過帶有"make"變量聲明的文件來設置控制此變量的變量,也可以在環(huán)境中指定該變量。
設備供應商可以創(chuàng)建定義文件,以描述特定板或特定產品要包含的內容。定義文件稱為:buildspec.mk,它位于頂級源目錄中。你可以手動編輯此選項以對選擇進行硬編碼。
如果你有一個buildspec.mk文件,它會設置構建所需的所有make變量,而你不必弄亂選項。
指定選項的另一種方法是設置環(huán)境變量。構建系統(tǒng)具有一種相當華麗的方法來為你管理這些選項。
要設置你的構建環(huán)境,你需要在
build/envsetup.sh
中加載變量和函數(shù)。通過將文件
source
到你的shell環(huán)境中來執(zhí)行此操作,如下所示:
. build/envsetup.sh
你可以在此時輸入"help"(或"hmm")以查看一些實用程序功能,這些功能可以使你更輕松地使用源代碼。
要選擇要構建的一組東西以及要構建的項目,請使用"choosecombo"功能或"lunch"功能。"choosecombo"將一步一步地引導你完成必須選擇的不同項目,而"lunch"則允許你選擇一些預設組合。
必須為構建定義的項目是:
? 產品("generic"或某些特定的芯片或平臺名稱) ? 構建變體("user","userdebug"或"eng") ? 是否在模擬器上運行("true"或"false") ? 構建類型("發(fā)布"或"調試")
這些不同的構建變體的說明位于
http://source.android.com/porting/build_system.html#androidBuildVariants在這篇博客文章中,從用戶角度很好地描述了構建過程:
http://blog.codepainters.com/2009/12/18/first-android-platform-build/實際構建系統(tǒng)
設置完畢后,實際上就可以使用"make"命令來構建系統(tǒng)。
要構建整個內容,請在頂層目錄中運行"make"。如果要構建所有內容(例如,第一次進行構建),則構建將花費很長時間。
構建技巧
查看用于構建軟件的實際命令
在"make"行上使用"showcommands"目標:
make -j4 showcommands
可以將其與另一個make目標結合使用,以查看該構建的命令。也就是說,"showcommands"本身不是目標,而只是指定構建的修飾符。
在上面的示例中,-j4與showcommands選項無關,并且用于執(zhí)行4個并行運行的make會話。
制定目標
這是可用于構建系統(tǒng)不同部分的不同make目標的列表:
?
make sdk
- 構建屬于SDK的工具(adb,fastboot等) ?
make snod
- 從當前軟件二進制文件構建系統(tǒng)映像 ?
make services
?
make runtime
?
make droid
- make droid是正常的構建。 ?
make all
- 構建所有內容,無論是否包含在產品定義中 ?
make clean
- 刪除所有構建的文件(準備進行新的構建)。與
rm -rf out/<configuration>/
相同 ?
make modules
- 顯示可以構建的子模塊的列表(所有LOCAL_MODULE定義的列表) ?
make <local_module>
- 構建一個特定的模塊(請注意,這與目錄名稱不同。它是Android.mk文件中的LOCAL_MODULE定義) ?
make clean <local_module>
- 清理特定模塊 ?
make bootimage TARGET_PREBUILT_KERNEL=/path/to/bzImage
- 使用自定義bzImage創(chuàng)建新的啟動映像
輔助宏和函數(shù)
當你獲取envsetup.sh時,會安裝一些輔助宏和函數(shù)。它們記錄在envesetup.sh的頂部,但是這里是其中一些信息:
?
hmm
- 列出幫助內容 ?
lunch <product_name>-<build_variant>
- 加載產品和構建變體配置(驅動程序文件,設備特定的配置等)。 ?
tapas [<App1> <App2> ...] [arm | x86 | mips | armv5 | arm64 | x86_64 | mips64] [eng | userdebug | user]
- 該命令用于構建未捆綁的應用程序。如果你不提供構建版本,則默認為eng。 ?
provision
- 燒錄具有所有必需分區(qū)的設備。選項將傳遞給fastboot。
構建宏和函數(shù)
?
croot
- 將目錄更改為樹的頂部 ?
m
- 從樹的頂部執(zhí)行"make"(即使當前目錄位于其他位置) ?
mm
- 構建當前目錄中的所有模塊 ?
mmm <dir1> ...
- 構建提供的目錄中的所有模塊,但不構建其依賴項。要限制正在構建的模塊,請使用以下語法:
mmm dir /:target1,target2
。 ?
mma
- 構建當前目錄中的所有模塊及其依賴項。 ?
mmma <dir1> ...
- 構建提供的目錄中的所有模塊及其依賴項。
Grep宏和函數(shù)
?
cgrep <PATTERN>
在所有本地C/C++文件上顯示。 ?
ggrep <PATTERN>
在所有本地Gradle文件上顯示。 ?
jgrep <PATTERN>
在所有本地Java文件上使用。 ?
resgrep <PATTERN>
在所有本地res/*。xml文件上進行鎖定。 ?
mangrep <PATTERN>
在所有本地AndroidManifest.xml文件上進行掃描。 ?
mgrep <PATTERN>
在所有本地Makefile文件上進行抓緊。 ?
sepgrep <PATTERN>
在所有本地Sepolicy文件上進行鎖定。 ?
sgrep <PATTERN>
在所有本地源文件上進行抓緊。 ?
godir <文件名>
轉到包含文件的目錄
加快構建
你可以在make中使用'-j'選項,以同時啟動多個make執(zhí)行線程。
根據(jù)我的經驗,你應該指定比計算機上具有處理器多2個線程。如果你有2個處理器,請使用'make -j4';如果它們是超線程的(意味著你有4個虛擬處理器),請嘗試'make -j6。
你還可以指定使用"ccache"編譯器緩存,這將在你首次構建內容后加快處理速度。為此,請在你的shell命令行中指定"export USE_CCACHE = 1"。(請注意,ccache包含在存儲庫的預構建部分中,不必單獨安裝在主機上。)
對于最新的Android版本,沒有預建的ccache,并且需要根據(jù)此commit,使用CCACHE_EXEC將路徑設置為本地二進制文件。
僅構建單個程序或模塊
如果使用
build/envsetup.sh
,則可以使用某些已定義的函數(shù)來僅構建樹的一部分。使用"mm"或"mmm"命令執(zhí)行此操作。
"mm"命令在當前目錄(和子目錄,我相信)中進行填充。使用"mmm"命令,你可以指定目錄或目錄列表,然后將其構建。 要安裝你的更改,請從樹的頂部開始"make snod"。"make snod"從當前的二進制文件構建新的系統(tǒng)映像。
設置模塊特定的構建參數(shù)
Android系統(tǒng)中的某些代碼可以按照其構建方式進行自定義(與構建變體以及發(fā)行版和調試選項分開)。你可以設置變量來控制各個構建選項,方法是在環(huán)境中進行設置,或者將其直接傳遞給"make"(或稱為"make"的"m ..."函數(shù))。
例如,可以通過設置INIT_BOOTCHART變量來構建支持bootchart日志記錄的'init'程序。(有關為什么你可能要執(zhí)行此操作,請參見在Android上使用Bootchart。)
你可以使用以下任一方法來完成:
touch system/init/init.cexport INIT_BOOTCHART=truemake
或者
touch system/init/init.cm INIT_BOOTCHART=true
Makefile技巧
這些是你可以在自己的Android.mk文件中使用的東西的一些提示。
建立助手功能
在文件build/core/definitions.mk中定義了很多構建幫助器函數(shù)
嘗試列出詳盡的清單。
grep define build/core/definitions.mk
通過以下方式調用它們:或不帶參數(shù):
$(call <FUNCTION>, <PARAM-1>, <PARAM-2>)$(call <FUNCTION>)
以下是一些可能有趣的功能:
?
print-vars
- 打印所有Makefile變量,以進行調試(而不是它們的值)。 ?
emit-line
- 在構建期間將線輸出到文件 ?
dump-words-to-file
- 將單詞列表輸出到文件 ?
copy-one-file
- 將文件從一個地方復制到另一個地方(目標是否在目的地?) ?
all-subdir-makefiles
- 從當前目錄開始遞歸調用所有文件(用法:)。Android.mkinclude $(調用all-subdir-makefiles)
構建變量
?
$(ANDROID_BUILD_TOP)
- AOSP文件系統(tǒng)根文件夾 ?
$(LOCAL_PATH)
- 通常為當前目錄。由開發(fā)人員/用戶在每個Android.mk文件中設置。 它會在文件樹下的其他文件中被覆蓋(例如,使用時)。
Android.mk include $(call all-subdir-makefiles)
解決方法:
SAVED_LOCAL_PATH := $(call my-dir) include $(call all-subdir-makefiles) LOCAL_PATH:= $(SAVED_LOCAL_PATH)
將文件直接添加到輸出區(qū)域
你可以使用add-prebuilt-files函數(shù)將文件直接復制到輸出區(qū)域,而無需構建任何內容。
從
prebuilt/android-arm/gdbserver/Android.mk
中提取的以下行將文件列表復制到輸出區(qū)域的EXECUTABLES目錄中:
$(call add-prebuilt-files, EXECUTABLES, $(prebuilt_files))
添加新程序以進行構建
將新程序添加到Android源代碼樹的步驟
? 在"外部"下建立目錄 ? 例如ANDROID/external/myprogram ? 創(chuàng)建你的C/cpp文件。 ? 創(chuàng)建Android.mk作為external/ping/Android.mk的克隆 ? 更改名稱ping.c和ping以匹配你的C/cpp文件和程序名稱 ? 在external/zlib之后將ANDROID/build/core/main.mk中的目錄名稱添加為external/myprogram(至少從Android 7.1起不再需要)
? 從源代碼樹的根開始 ? 你的文件將顯示在構建輸出區(qū)域和系統(tǒng)映像中。 ? 如果要將文件單獨復制到目標(而不執(zhí)行整個安裝),則可以從構建輸出區(qū)域的out/target/product/...下復制文件。
有關更多詳細信息,請參見
http://www.aton.com/android-native-development-using-the-android-open-source-project/。
構建內核
內核是普通Android構建系統(tǒng)的"外部"(實際上,默認情況下,Android Open Source Project中不包括該內核)。但是,AOSP中有一些用于構建內核的工具。如果要構建內核,請從此頁面開始:http : //
http://source.android.com/source/building-kernels.html 如果你正在為模擬器構建內核,則可能還需要查看:http : //
http://stackoverflow.com/questions/1809774/android-kernel-compile-and-test-with-android-emulator 而且,Ron M寫道(在2012年5月21日在android-kernel郵件列表中):
這篇文章很老-但就AOSP而言,什么都沒有改變,所以如果有人對QEMU感興趣并遇到此問題,請執(zhí)行以下操作: 實際上,為AOSP提供的QEMU目標構建內核是一種不錯的,更短的方法:
- cd到你的內核源目錄(僅金魚2.6.29在模擬器中可用)
- $ {ANDROID_BUILD_TOP} /external/qemu/distrib/build-kernel.sh -j = 64 --arch = x86 --out = $ YourOutDir
- emulator -kernel ${YourOutDir}/kernel-qemu # run emulator:
步驟#2 調用toolbox.sh包裝程序腳本,該腳本可在SSE禁用gcc警告的情況下工作-在GCC <4.5時發(fā)生(如AOSP預先構建的X86工具鏈中一樣)。
如果它是X86,該腳本會添加"-mfpmath = 387 -fno-pic",從而消除了上面看到的編譯錯誤。
為了更好地控制構建過程,可以使用"toolbox.sh"包裝器并設置一些其他內容,而無需修改腳本文件。
下面是構建相同模擬器的示例:
# Set archexport ARCH=x86# Have make refer to the QEMU wrapper script for building android over x86 (eliminates the errors listed above)export CROSS_COMPILE=${ANDROID_BUILD_TOP}/external/qemu/distrib/kernel-toolchain/android-kernel-toolchain-# Put your cross compiler here. I am using the AOSP prebuilt one in this exampleexport REAL_CROSS_COMPILE=${ANDROID_BUILD_TOP}/prebuilt/linux-x86/toolchain/i686-android-linux-4.4.3/bin/i686-android-linux-# Configure your kernel - here I am taking the default goldfish_defconfigmake goldfish_defconfig# buildmake -j64# Run emulator:emulator -kernel arch/x86/boot/bzImage -show-kernel
這適用于2.6.29 goldfish 分支。
譯自https://elinux.org/Android_Build_System