Ubuntu 18.04 下运行docker 编译aosp (android 7.1.2, 8.0.0,9.0.0)

编译aosp 的辛酸

这几天想编译一个能脱壳的 aosp (Android源码),我进行了如下尝试:

1、用我的Mac(15年15寸的那款,当前MacOS 版本为 10.15.2 (19C57))从6.0 编译到9.0 ,就一个 8.0.0_r2 编译成功了。又是下载 MacOSX10.12.sdk 又是搞 bison 补丁的、乱七八糟

2、后来看aosp官网推荐说Docker 也可以编译,所以抱着试试看的态度,就想搞个Docker 试试,源码里面的Dockerfile,结果 编译镜像的时候报错 groupadd: GID '20' already exists,从语义上来说,不就是GID 冲突吗,阅读Dockerfile 改掉,改成了3000,镜像倒是编译成功了,但是编译源码各种错误,一个也没成功,据说Mac 下的docker和Linux下的docker还是有区别的。算了搞个Linux吧。

3、VM ware Fusion Mac上的虚拟机,然后里面按照Ubuntu,编译依然出错,经过一番搜索,我发现我解决不了,现在回过头来想想应该是移动硬盘格式化不对,我为了编译Android源码,特意买了个移动硬盘,然后格式化成,区分大小写的 Mac 格式,然后把,7.0,8.0,9.0 的源码下载下来,(https://www.jianshu.com/p/53e590eb237a),然后虚拟机和Mac选择共享目录的方式,现在想想应该用虚拟磁盘的方式就可以了

4、搞个真实的Ubuntu系统吧。。Mac 上安装双系统在移动硬盘

官方推荐编译方式

主要分为这么几步

0、我搞了个移动硬盘,格式化成了ext4格式,如果电脑硬盘够,那就不用移动硬盘了

1、先在Ubuntu 18.04 上下载Android 源码

2、在Ubuntu 18.04 上安装docker,并制作用于编译aosp的镜像

3、启动docker 镜像,映射本地aosp源码目录到docker 目录

源码下载

官网的方式里面,是下载aosp 到 本地磁盘,然后交互模式启动Linux(ubuntu:14.04)的docker镜像,然后把 本地文件夹和 docker Ubuntu 下的文件夹做映射,从而docker Ubuntu能够直接读取本机上的文件。

下载源码的方式见:清华镜像 或者 科大镜像

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'

如果需要某个特定的 Android 版本(Android 版本列表),可以通过下面的方式指定版本号,如果不指定则代码下载当前最新的代码。

repo init -u git://mirrors.ustc.edu.cn/aosp/platform/manifest -b android-8.0.0_r2

4、步源码树(以后只需执行这条命令来同步)如果中途出现网络错误,可以停止后在执行下面的命令:

repo sync

等待下载吧,漫长的过程。。。

如果想要编译真机的系统还要下载真机对应驱动,对应关系从这两个地址获取 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 对应的Android编译环境的docker镜像
  • 官网地址 https://android.googlesource.com/platform/build/+/master/tools/docker 打不开,不要慌,我摘录一下
Ubuntu 18.04 下运行docker 编译aosp (android 7.1.2, 8.0.0,9.0.0)_第1张图片
官网代码截图
# 先创建一个文件夹,这个文件夹用于docker打包用,不创建也没关系,为了环境干净而已
$ mkdir docker 
# 然后把官网下载的Dockerfile 移动到当前目录下,没有的话可以下载git并配置
# Copy your host gitconfig, or create a stripped down version
# 把当前Mac电脑的git配置copy到当前环境,以便于传递到docker镜像里面用
$ cp ~/.gitconfig gitconfig
# 创建一个 名字叫做 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 .

官网 Dockerfile 摘录入下,这里面的两个url可能因为某些不可抗因素不能访问请自信替换

jdk 的url可以自己网上找个 open jdk8 的压缩包就行。记住是openjdk8

repo 的地址可以用科大的镜像替换 ,做好能直接访问,替换url之后,需要修改Dockerfile的脚本,把验证hash的地方替换掉。我直接用的官网的。

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

开始编译

启动一个docker 实例:

# 配置一个变量,标志 Android 源码的位置,这个路径自己配置,这个就是上面下载的源码的路径
$ export ANDROID_BUILD_TOP=~/Desktop/aosp/android-8.0.0_r2
# docker 启动命令,以交互模式启动docker,
# 并且映射 真机下 $ANDROID_BUILD_TOP 指向的路径 到 docker Ubuntu 下的 /src目录
# 从而在docker Ubuntu 里面访问 /src 就会直接访问真机 下的 $ANDROID_BUILD_TOP
$ docker run -it --rm -v $ANDROID_BUILD_TOP:/src android-build-trusty

理论上来说这时候命令行就进入了docker 内部,这时候的shell 是 Ubuntu的shell了,接下来开始编译:

$ cd /src # ls 一下观察是不是下载的Android源码
# 下面是编译 aosp 的基本命令,和直接编译没啥区别
$ source build/envsetup.sh
# 直接指定编译的版本类型,或者输入 lunch 之后再选则,我编译的是个模拟器 aosp_arm64-eng
$ lunch aosp_arm-eng
$ m -j50
  • 7.1.1 7.x 的代码,下载到90%多的时候,特别慢、
  • 8.0.0 源码文件在我的机械硬盘上,大概编译了4小时32分,总共有73575 个文件。
  • 9.0.0 编译正常,感觉9.0 的docker编译比较快,总体文件没法统计了,我编译了一次因为内存崩溃了,后来再编译可能会使用缓存文件

我500G的硬盘,竟然没法编译完,这三个版本的系统,编译过程提示硬盘空间不足,于是我就把,三个源码的下的 .repo 文件夹都删除了,以后不再更新就是了

错误处理

7.1.1_r20 问题

同 8.0.0_r2 ,

9.0.0_r46
8.0.0_r2

8.0 编译出现如下错误

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

刷机

这时候不用在docker 下了,因为接下来就算文件操作

设置 ANDROID_PRODUCT_OUT 环境变量,就是编译后生成的img文件的路径
adb reboot bootloader
$ fastboot flashall -w

你可能感兴趣的:(Ubuntu 18.04 下运行docker 编译aosp (android 7.1.2, 8.0.0,9.0.0))