Ubuntu 18.04 下運(yùn)行docker 編譯aosp (android 7.1.2, 8.0.0,9.0.0)

編譯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-buildshttps://developers.google.cn/android/drivers

制作docker鏡像

官網(wǎng)代碼截圖
# 先創(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文件的路徑
export ANDROID_PRODUCT_OUT=android-8.0.0_r2/out/target/product/sailfish adb reboot bootloader
$ fastboot flashall -w

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容