目錄
- 背景
- Android源碼下載
- 源碼編譯及遇到的問(wèn)題
- 使用CLion 導(dǎo)入
- 資料
- 收獲
一、背景
對(duì)Framework層的了解學(xué)習(xí)是我們進(jìn)階的一個(gè)重要階段。通過(guò) AS 查看 Framework 代碼體驗(yàn)非常好,無(wú)論是索引還是界面都讓人很滿意,但是當(dāng)你跟蹤代碼,發(fā)現(xiàn)進(jìn)入 native 邏輯時(shí),就會(huì)發(fā)現(xiàn) Android Studio 對(duì) native 代碼的支持非常不好,不能索引不支持符號(hào)搜索不能跳轉(zhuǎn)等。
網(wǎng)頁(yè)上可以通過(guò)cs.android.com 或者 http://androidxref.com/ 比較方便的查看源碼。但是還是不夠,因?yàn)槲覀內(nèi)绻胂到y(tǒng)的追蹤分析流程,往往會(huì)需要跳來(lái)跳去,有時(shí)候還會(huì)加些注釋。這時(shí)候網(wǎng)頁(yè)端的就不太方便。如果能在本地端方便的實(shí)現(xiàn)上述功能,可定是一個(gè)比較高效率而有愉悅的事情。
Source Insight可以比較方便的進(jìn)行跳轉(zhuǎn),但是只是在window支持(雖然Mac上可以通過(guò)Parallels 方便的安裝window環(huán)境;Ubuntu上也可以win的方式使用Source Insight但是總是不太方便)。
那么有沒有其他的工具或者方式,比較方便的查看native代碼吶?
可以通過(guò)CLion導(dǎo)入,但是需要有對(duì)應(yīng)的cmakelist,這就需要對(duì)下載源碼,然后進(jìn)行編譯,然后再用CLion導(dǎo)入。下面我們來(lái)看下具體的實(shí)踐。
二、Android源碼下載
查看官方文檔
主要分為3步,
- 下載安裝repo 啟動(dòng)器
- 下載mainfest
- 開始sync下載: repo sync -c -j8
其中第2步配置manifest時(shí)需要注意,如果直接使用epo init -u https://android.googlesource.com/platform/manifest -b master因?yàn)榫W(wǎng)絡(luò)原因會(huì)比較難下載成功。 我們可以使用清華的鏡像來(lái)配置 `repo init -u https://mirrors.tuna.tsinghua.edu.cn/git/AOSP/platform/manifest -b master
即將 https://android.googlesource.com/ 全部使用 https://mirrors.tuna.tsinghua.edu.cn/git/AOSP/ 代替即可
還有一點(diǎn)需要注意,如果沒有特殊的要求,可以根據(jù)需要下載對(duì)應(yīng)的分支,比如上面第2步中配置的是 master分支,這樣只會(huì)同步master最新分支,保證代碼的最新和下載的量比較小比較快。
如果是linux系統(tǒng)就可以直接進(jìn)入編譯階段。但是如果是mac上如果只是按照上面的操作進(jìn)入編譯,就會(huì)遇到問(wèn)題。我們?cè)诰幾g階段來(lái)一起看下,怎么處理。
三、源碼編譯及遇到的問(wèn)題
3.1 配置和編譯命令
- 編譯前配置下生成cmakelist文件這樣后面才可以使用CLion導(dǎo)入
export SOONG_GEN_CMAKEFILES=1
export SOONG_GEN_CMAKEFILES_DEBUG=1
- 然后執(zhí)行envsetup.sh腳本 進(jìn)行配置
. envsetup.sh
再執(zhí)行 choosecombo ,這個(gè)命令用阿里選擇編譯目標(biāo),比如硬件平臺(tái)、開發(fā)者還是使用者等,一般默認(rèn)配置就好。
最后開始make。 make -j8
Android平臺(tái)提供了三個(gè)命令用于編譯,它們分別是make、mmm和mm
make 用于編譯整個(gè)系統(tǒng),時(shí)間比較長(zhǎng),
make xxx:用于編譯某個(gè)模塊,比如編譯framework。 make framework即可
mmm xxx:用于編譯指定目錄下的模塊,不會(huì)編譯它依賴的模塊
mm xxx: 該命令和mmm差不多,區(qū)別在于它會(huì)先cd到xxx目錄然后在編譯。
在具體的編譯中遇到了很多問(wèn)題,匯總?cè)缦隆?/p>
3.2 編譯中遇到的問(wèn)題
問(wèn)題1: Mac make時(shí)報(bào)如下錯(cuò)誤
% make -j16 frameworks
19:44:38 You are building on a case-insensitive filesystem.
19:44:38 Please move your source tree to a case-sensitive filesystem.
19:44:38 ************************************************************
19:44:38 Case-insensitive filesystems not supported
#### failed to build some targets (1 seconds) ####
這個(gè)問(wèn)題就是上面提到的,如果是linux系統(tǒng)可以直接編譯,但是如果是mac系統(tǒng)編譯就會(huì)遇到這個(gè)問(wèn)題。
問(wèn)題的原因是
在默認(rèn)安裝過(guò)程中,Mac OS 會(huì)在一個(gè)保留大小寫但不區(qū)分大小寫的文件系統(tǒng)中運(yùn)行。Git 并不支持此類文件系統(tǒng),而且此類文件系統(tǒng)會(huì)導(dǎo)致某些 Git 命令(例如
git status)的行為出現(xiàn)異常
參考: https://source.android.com/source/initializing#setting-up-a-mac-os-x-build-environment 和 Move Android source into case-sensitive image
那么該如何解決吶?
上面鏈接給出的建議始終在區(qū)分大小寫的文件系統(tǒng)中對(duì) AOSP 源文件進(jìn)行操作
有了適當(dāng)?shù)奈募到y(tǒng),在新型 Mac OS 環(huán)境中編譯master分支就會(huì)變得非常簡(jiǎn)單
但是我代碼已經(jīng)下載好了。。。。,
所以只能在創(chuàng)建下區(qū)分大小寫的文件系統(tǒng),然后把代碼copy過(guò)去。
Mac上建立區(qū)分大小的文件系統(tǒng)
hdiutil create -type SPARSE -fs 'Case-sensitive Journaled HFS+' -size 40g ~/android.dmg
然后進(jìn)行掛載
hdiutil attach ~/android.dmg.sparseimage -mountpoint /Volumes/android;
對(duì)應(yīng)的detach命令如下:
hdiutil detach /Volumes/android;
如果以后需要更大的存儲(chǔ)卷,還可以使用以下命令來(lái)調(diào)整稀疏映像的大小:
hdiutil resize -size <new-size-you-want>g ~/android.dmg.sparseimage
需要注意的時(shí),:如果系統(tǒng)創(chuàng)建的是 .dmg.sparseimage 文件,請(qǐng)將 ~/android.dmg 替換成 ~/android.dmg.sparseimage。
解決方案來(lái)源:Building Android O with a Mac
問(wèn)題2 : copy過(guò)去之后不再報(bào)上面的錯(cuò)誤了,但是出現(xiàn)如下錯(cuò)誤
error: external/kotlinx.atomicfu/Android.bp:13:1: module "external_kotlinx.atomicfu_license": glob: stat /Volumes/android/androidsource/external/kotlinx.atomicfu/NOTICE: no such file or directory
error: external/kotlinx.coroutines/Android.bp:24:1: module "external_kotlinx.coroutines_license": module source path "external/kotlinx.coroutines/LICENSE" does not exist
20:50:19 soong bootstrap failed with: exit status 1
ninja: build stopped: subcommand failed.
#### failed to build some targets (16 seconds) ####
在網(wǎng)上搜了下也有人遇到同樣的問(wèn)題但是沒有解決方案。。。
我的處理方案是 修改bp腳本,把上面的NOTICE和LICENSE依賴給去掉,然后就編譯過(guò)去了。
問(wèn)題3: 提示文件描述超過(guò)了上限(具體錯(cuò)誤信息忘記保存了)
# set the number of open files to be 1024
ulimit -S -n 1024
設(shè)置文件描述符數(shù)量上限
在 Mac OS 中,可同時(shí)打開的文件描述符的默認(rèn)數(shù)量上限太低,在高度并行的編譯流程中,可能會(huì)超出此上限。
要提高此上限,請(qǐng)將下列行添加到 ~/.bash_profile 中:
調(diào)大了文件描述符數(shù)量,同時(shí) 把并行的線程從16減4(這個(gè)是關(guān)鍵),不報(bào)上面的錯(cuò)誤了,但是又有如下錯(cuò)誤
問(wèn)題4: ninja: build stopped: subcommand failed
error: bionic/libc/Android.bp:1860:1: module "libc_llndk_headers" variant "android_recovery_arm_armv7-a-neon": glob failed: &fs.PathError{Op:"fcntl", Path:"/Volumes/android/androidsource/bionic/libc/kernel/uapi/asm-arm", Err:0x18}
21:17:37 soong bootstrap failed with: exit status 1
ninja: build stopped: subcommand failed.
---》重新運(yùn)行了了 make -j4 framework, 上嗎的編譯又通過(guò)了,不知道為什么。
本來(lái)還想在降低并發(fā)的線程數(shù)量到2. make -j2
經(jīng)過(guò)15分鐘左右終于編譯完成。哈哈哈
#### build completed successfully (14:16 (mm:ss)) ####
此時(shí)可以在/Volumes/android/androidsource/out/development/ide/clion/frameworks 路徑下看到各個(gè)子文件夾下都有CMakeLists.txt生成,但是卻是分散在各個(gè)子文件夾下面的。
編譯出來(lái)的是各個(gè)模塊單獨(dú)的CMakeLists.txt,一個(gè)CMakeLists.txt表示一個(gè)CLion工程,所以不能直接導(dǎo)入全部的工程。
那該怎么辦吶?
可以新建一個(gè)總的/Volumes/android/androidsource/out/development/ide/clion/frameworks/CMakeLists.txt然后可以先add一個(gè)工程,導(dǎo)入到CLion后再add其他工程
當(dāng)導(dǎo)入時(shí),有些cmakelist找不到。懷疑時(shí)沒有全編譯引起的?于是索性 make -j4來(lái)個(gè)全編譯,
下面是全編譯遇到的問(wèn)題
問(wèn)題5: fatal error: 'linux/netfilter/xt_DSCP.h'
external/iptables/include/linux/netfilter_ipv4/ipt_ECN.h:13:10: fatal error: 'linux/netfilter/xt_DSCP.h' file not found
#include <linux/netfilter/xt_DSCP.h>
1 error generated.
09:04:41 ninja failed with: exit status 1
#### failed to build some targets (01:34:26 (hh:mm:ss)) ####
從Building Android O with a Mac這里找了個(gè)解決方案
---> In this case create a symbolic name xt_dscp.h for the original file xt_DSCP.h with the following command lines:
cd external/iptables/extensions/../include/linux/netfilter
ln -s xt_dscp.h xt_DSCP.h
按照上面的修改,但是沒什么用還是報(bào)相應(yīng)的錯(cuò)誤
于是手動(dòng)的找到對(duì)應(yīng)的文件,external/iptables/include/linux/netfilter/xt_dscp.h -->對(duì)其進(jìn)行重命名為xt_DSCP.h,解決掉這個(gè)問(wèn)題。
問(wèn)題6: 漫長(zhǎng)的編譯過(guò)程 出現(xiàn)了main.go:171:9: undefined: syscall.Sysinfo
build/soong/cmd/multiproduct_kati/main.go:170:11: undefined: syscall.Sysinfo_t
build/soong/cmd/multiproduct_kati/main.go:171:9: undefined: syscall.Sysinfo
10:27:57 ninja failed with: exit status 1
網(wǎng)上搜了下也沒有找到相關(guān)的解決方案。于是找對(duì)對(duì)應(yīng)的文件,把修改相關(guān)的代碼(把對(duì)應(yīng)的代碼注釋掉),繼續(xù)編譯
經(jīng)過(guò)上述折騰終于編譯完了,哈哈哈。
[100% 19269/19269] Target vbmeta image: out/target/product
#### build completed successfully ####
四、使用CLion 導(dǎo)入
具體步驟如下
- 打開CLion
- 選擇「New CMake Project from Sources」
- 指定包含 CMakeLists.txt 的目錄out/development/ide/clion
- 選擇「Open Existing Project」
然后就可以很愉快的進(jìn)行Android Native源碼的跳轉(zhuǎn)查看。
其中在 androidsource/out/development/ide/clion/CMakeLists.txt如下(目前主要是看 av相關(guān)的代碼,所有只加了相關(guān)的子路徑)

五、資料
- 搭建編譯環(huán)境
- https://source.android.com/source/initializing#setting-up-a-mac-os-x-build-environment
- Move Android source into case-sensitive image
- 清華大學(xué) android source 鏡像站
- http://blog.hanschen.site/2019/10/11/aosp-native-ide/
- 自己動(dòng)手調(diào)試Android源碼
- Android Opensource Project build error
FAILED: out/soong/build.ninja - CLion調(diào)試Android 11 Native代碼
- AOSP Native代碼導(dǎo)入IDE(CLion)
六、收獲
- 源碼的下載、編譯以及通過(guò)CLion導(dǎo)入方便的查看Native源碼
- 解決編譯中遇到的各種問(wèn)題
感謝你的閱讀
下一篇我們分析學(xué)習(xí)H264的編碼技術(shù)之幀內(nèi)預(yù)測(cè),歡迎關(guān)注公眾號(hào)“音視頻開發(fā)之旅”,一起學(xué)習(xí)成長(zhǎng)。
歡迎交流