編譯aosp 的辛酸
這幾天想編譯一個(gè)能脫殼的 aosp (Android源碼),我進(jìn)行了如下嘗試:
1、用我的Mac(15年15寸的那款,當(dāng)前MacOS 版本為 10.15.2 (19C57))從6.0 編譯到9.0 ,就一個(gè) 8.0.0_r2 編譯成功了。又是下載 MacOSX10.12.sdk 又是搞 bison 補(bǔ)丁的、亂七八糟
2、后來看aosp官網(wǎng)推薦說Docker 也可以編譯,所以抱著試試看的態(tài)度,就想搞個(gè)Docker 試試,源碼里面的Dockerfile,結(jié)果 編譯鏡像的時(shí)候報(bào)錯(cuò) groupadd: GID '20' already exists
,從語義上來說,不就是GID 沖突嗎,閱讀Dockerfile 改掉,改成了3000,鏡像倒是編譯成功了,但是編譯源碼各種錯(cuò)誤,一個(gè)也沒成功,據(jù)說Mac 下的docker和Linux下的docker還是有區(qū)別的。算了搞個(gè)Linux吧。
3、VM ware Fusion Mac上的虛擬機(jī),然后里面按照Ubuntu,編譯依然出錯(cuò),經(jīng)過一番搜索,我發(fā)現(xiàn)我解決不了,現(xiàn)在回過頭來想想應(yīng)該是移動硬盤格式化不對,我為了編譯Android源碼,特意買了個(gè)移動硬盤,然后格式化成,區(qū)分大小寫的 Mac 格式,然后把,7.0,8.0,9.0 的源碼下載下來,(http://www.lxweimin.com/p/53e590eb237a),然后虛擬機(jī)和Mac選擇共享目錄的方式,現(xiàn)在想想應(yīng)該用虛擬磁盤的方式就可以了
4、搞個(gè)真實(shí)的Ubuntu系統(tǒng)吧。。Mac 上安裝雙系統(tǒng)在移動硬盤
官方推薦編譯方式
主要分為這么幾步
0、我搞了個(gè)移動硬盤,格式化成了ext4格式,如果電腦硬盤夠,那就不用移動硬盤了
1、先在Ubuntu 18.04 上下載Android 源碼
2、在Ubuntu 18.04 上安裝docker,并制作用于編譯aosp的鏡像
3、啟動docker 鏡像,映射本地aosp源碼目錄到docker 目錄
源碼下載
官網(wǎng)的方式里面,是下載aosp 到 本地磁盤,然后交互模式啟動Linux(ubuntu:14.04)的docker鏡像,然后把 本地文件夾和 docker Ubuntu 下的文件夾做映射,從而docker Ubuntu能夠直接讀取本機(jī)上的文件。
1、下載 repo 工具:
mkdir ~/bin
PATH=~/bin:$PATH
curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
chmod a+x ~/bin/repo
2、建立工作目錄:
我用的是移動硬盤來存儲aosp源碼,并且在Ubuntu下把硬盤掛載到了 ~/Desktop/aosp/
cd ~/Desktop/aosp/
mkdir android-8.0.0_r2
cd android-8.0.0_r2
3、初始化倉庫
repo init -u git://mirrors.ustc.edu.cn/aosp/platform/manifest
## 如果提示無法連接到 gerrit.googlesource.com,可以編輯 ~/bin/repo,把 REPO_URL 一行替換成下面的:
## REPO_URL = 'https://gerrit-googlesource.proxy.ustclug.org/git-repo'
如果需要某個(gè)特定的 Android 版本(Android 版本列表),可以通過下面的方式指定版本號,如果不指定則代碼下載當(dāng)前最新的代碼。
repo init -u git://mirrors.ustc.edu.cn/aosp/platform/manifest -b android-8.0.0_r2
4、步源碼樹(以后只需執(zhí)行這條命令來同步)如果中途出現(xiàn)網(wǎng)絡(luò)錯(cuò)誤,可以停止后在執(zhí)行下面的命令:
repo sync
等待下載吧,漫長的過程。。。
如果想要編譯真機(jī)的系統(tǒng)還要下載真機(jī)對應(yīng)驅(qū)動,對應(yīng)關(guān)系從這兩個(gè)地址獲取 https://source.android.google.cn/setup/start/build-numbers#source-code-tags-and-builds 和 https://developers.google.cn/android/drivers
制作docker鏡像
- Ubuntu 是上安裝 docker (略)
- docker 的基本命令 && 生成docker 鏡像 Dockerfile 的編寫方式(略)
- 啟動docker
- 打包 docker 對應(yīng)的Android編譯環(huán)境的docker鏡像
- 官網(wǎng)地址 https://android.googlesource.com/platform/build/+/master/tools/docker 打不開,不要慌,我摘錄一下
# 先創(chuàng)建一個(gè)文件夾,這個(gè)文件夾用于docker打包用,不創(chuàng)建也沒關(guān)系,為了環(huán)境干凈而已
$ mkdir docker
# 然后把官網(wǎng)下載的Dockerfile 移動到當(dāng)前目錄下,沒有的話可以下載git并配置
# Copy your host gitconfig, or create a stripped down version
# 把當(dāng)前Mac電腦的git配置copy到當(dāng)前環(huán)境,以便于傳遞到docker鏡像里面用
$ cp ~/.gitconfig gitconfig
# 創(chuàng)建一個(gè) 名字叫做 android-build-trusty 的docker 鏡像,名字可以隨便取
$ docker build --build-arg userid=$(id -u) --build-arg groupid=$(id -g) --build-arg username=$(id -un) -t android-build-trusty .
官網(wǎng) Dockerfile 摘錄入下,<font color=red>這里面的兩個(gè)url可能因?yàn)槟承┎豢煽挂蛩夭荒茉L問請自信替換</font>:
jdk 的url可以自己網(wǎng)上找個(gè) open jdk8 的壓縮包就行。記住是openjdk8
repo 的地址可以用科大的鏡像替換 ,做好能直接訪問,替換url之后,需要修改Dockerfile的腳本,把驗(yàn)證hash的地方替換掉。我直接用的官網(wǎng)的。
FROM ubuntu:14.04
ARG userid
ARG groupid
ARG username
RUN apt-get update && apt-get install -y git-core gnupg flex bison gperf build-essential zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 lib32ncurses5-dev x11proto-core-dev libx11-dev lib32z-dev ccache libgl1-mesa-dev libxml2-utils xsltproc unzip python openjdk-7-jdk
RUN curl -o jdk8.tgz https://android.googlesource.com/platform/prebuilts/jdk/jdk8/+archive/master.tar.gz \
&& tar -zxf jdk8.tgz linux-x86 \
&& mv linux-x86 /usr/lib/jvm/java-8-openjdk-amd64 \
&& rm -rf jdk8.tgz
RUN curl -o /usr/local/bin/repo https://storage.googleapis.com/git-repo-downloads/repo \
&& echo "d06f33115aea44e583c8669375b35aad397176a411de3461897444d247b6c220 /usr/local/bin/repo" | sha256sum --strict -c - \
&& chmod a+x /usr/local/bin/repo
RUN groupadd -g $groupid $username \
&& useradd -m -u $userid -g $groupid $username \
&& echo $username >/root/username \
&& echo "export USER="$username >>/home/$username/.gitconfig
COPY gitconfig /home/$username/.gitconfig
RUN chown $userid:$groupid /home/$username/.gitconfig
ENV HOME=/home/$username
ENV USER=$username
ENTRYPOINT chroot --userspec=$(cat /root/username):$(cat /root/username) / /bin/bash -i
下面是我修改后的,
FROM ubuntu:14.04
ARG userid
ARG groupid
ARG username
RUN apt-get update && apt-get install -y git-core gnupg flex bison gperf build-essential zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 lib32ncurses5-dev x11proto-core-dev libx11-dev lib32z-dev ccache libgl1-mesa-dev libxml2-utils xsltproc unzip python openjdk-7-jdk
## 這里
RUN curl -o jdk8.tgz http://weishu.dimensionalzone.com/jdk8-master.tar.gz \
&& tar -zxf jdk8.tgz linux-x86 \
&& mv linux-x86 /usr/lib/jvm/java-8-openjdk-amd64 \
&& rm -rf jdk8.tgz
## 和這里
RUN curl -o /usr/local/bin/repo http://weishu.dimensionalzone.com/repo \
#&& echo "e147f0392686c40cfd7d5e6f332c6ee74c4eab4d24e2694b3b0a0c037bf51dc5 /usr/local/bin/repo" | sha256sum --strict -c - \
&& chmod a+x /usr/local/bin/repo
RUN groupadd -g $groupid $username \
&& useradd -m -u $userid -g $groupid $username \
&& echo $username >/root/username \
&& echo "export USER="$username >>/home/$username/.gitconfig
COPY gitconfig /home/$username/.gitconfig
RUN chown $userid:$groupid /home/$username/.gitconfig
ENV HOME=/home/$username
ENTRYPOINT chroot --userspec=$(cat /root/username):$(cat /root/username) / /bin/bash -i
開始編譯
啟動一個(gè)docker 實(shí)例:
# 配置一個(gè)變量,標(biāo)志 Android 源碼的位置,這個(gè)路徑自己配置,這個(gè)就是上面下載的源碼的路徑
$ export ANDROID_BUILD_TOP=~/Desktop/aosp/android-8.0.0_r2
# docker 啟動命令,以交互模式啟動docker,
# 并且映射 真機(jī)下 $ANDROID_BUILD_TOP 指向的路徑 到 docker Ubuntu 下的 /src目錄
# 從而在docker Ubuntu 里面訪問 /src 就會直接訪問真機(jī) 下的 $ANDROID_BUILD_TOP
$ docker run -it --rm -v $ANDROID_BUILD_TOP:/src android-build-trusty
理論上來說這時(shí)候命令行就進(jìn)入了docker 內(nèi)部,這時(shí)候的shell 是 Ubuntu的shell了,接下來開始編譯:
$ cd /src # ls 一下觀察是不是下載的Android源碼
# 下面是編譯 aosp 的基本命令,和直接編譯沒啥區(qū)別
$ source build/envsetup.sh
# 直接指定編譯的版本類型,或者輸入 lunch 之后再選則,我編譯的是個(gè)模擬器 aosp_arm64-eng
$ lunch aosp_arm-eng
$ m -j50
- 7.1.1 7.x 的代碼,下載到90%多的時(shí)候,特別慢、
- 8.0.0 源碼文件在我的機(jī)械硬盤上,大概編譯了4小時(shí)32分,總共有73575 個(gè)文件。
- 9.0.0 編譯正常,感覺9.0 的docker編譯比較快,總體文件沒法統(tǒng)計(jì)了,我編譯了一次因?yàn)閮?nèi)存崩潰了,后來再編譯可能會使用緩存文件
我500G的硬盤,竟然沒法編譯完,這三個(gè)版本的系統(tǒng),編譯過程提示硬盤空間不足,于是我就把,三個(gè)源碼的下的 .repo 文件夾都刪除了,以后不再更新就是了
錯(cuò)誤處理
7.1.1_r20 問題
同 8.0.0_r2 ,
9.0.0_r46
8.0.0_r2
8.0 編譯出現(xiàn)如下錯(cuò)誤
FAILED: out/target/common/obj/JAVA_LIBRARIES/sdk_v16_intermediates/classes.jack
/bin/bash -c "(mkdir -p out/target/common/obj/JAVA_LIBRARIES/sdk_v16_intermediates/classes.jack.tmpjill.res ) && (unzip -qo prebuilts/sdk/16/android.jar -d out/target/common/obj/JAVA_LIBRARIES/sdk_v16_intermediates/classes.jack.tmpjill.res ) && (find out/target/common/obj/JAVA_LIBRARIES/sdk_v16_intermediates/classes.jack.tmpjill.res -iname \"*.class\" -delete ) && (JACK_VERSION=4.31.CANDIDATE out/host/linux-x86/bin/jack @build/core/jack-default.args -D jack.import.resource.policy=keep-first -D jack.import.type.policy=keep-first -D jack.android.min-api-level=16 --import prebuilts/sdk/16/android.jar --import-resource out/target/common/obj/JAVA_LIBRARIES/sdk_v16_intermediates/classes.jack.tmpjill.res --output-jack out/target/common/obj/JAVA_LIBRARIES/sdk_v16_intermediates/classes.jack ) && (rm -rf out/target/common/obj/JAVA_LIBRARIES/sdk_v16_intermediates/classes.jack.tmpjill.res )"
out/host/linux-x86/bin/jack: line 80: USER: unbound variable
解決方法 :
export USER=$(whoami)
https://blog.csdn.net/RonnyJiang/article/details/55812305?locationNum=15&fps=1
刷機(jī)
這時(shí)候不用在docker 下了,因?yàn)榻酉聛砭退阄募僮?/p>
設(shè)置 ANDROID_PRODUCT_OUT 環(huán)境變量,就是編譯后生成的img文件的路徑
adb reboot bootloader
$ fastboot flashall -w