2023年9月1日: 更新了大伙儿常遇到的 breakfast 命令失败的问题处理办法, 可以参考一下.
最近给手头的 Xiaomi 6 刷了 LneageOS, 体验了一把 Android 15, 挺香的! 但是这个系统有那么一丢丢水土不服, 于是决定自己来改改然后编译一个出来玩玩.
主机描述
- CPU >= 4C
- MEM >= 16G
- DISK >= 200G
- NET >= 100M
- OS >= Debian 11/12/13
- Docker >= Debian 13 Image
环境准备
基础环境镜像
构建镜像
docker build -t build-base - <<\EOF
FROM debian:13
RUN <<EOT
sed -i -e 's|deb.debian.org|mirrors.aliyun.com|g' /etc/apt/sources.list.d/debian.sources
apt update
# install base tool
apt install -y sudo bash-completion command-not-found procps vim wget curl net-tools
# install version control
apt install git subversion python3
wget https://mirrors.tuna.tsinghua.edu.cn/git/git-repo -O /usr/local/bin/repo
chmod +x /usr/local/bin/repo
# build command not found data
apt update
apt clean && rm -rf /var/lib/apt/lists/*
EOT
ENV TZ=Asia/Shanghai
RUN <<EOT
useradd --create-home --uid 1000 --groups users,sudo --shell /bin/bash user
echo "user:1111" | chpasswd
ln -snf /usr/share/zoneinfo/${TZ} /etc/localtime
echo "${TZ}" > /etc/timezone
EOT
COPY <<EOT /etc/profile.d/aliases.sh
alias ll='ls -lh -F --color=auto --time-style=long-iso'
alias la='ls -lhA -F --color=auto --time-style=long-iso'
alias lt='ls -lht -F --color=auto --time-style=long-iso'
alias lat='ls -lhAt -F --color=auto --time-style=long-iso'
EOT
USER user
WORKDIR /home/user/
EOF
- 使用管道输入
Dockerfile内容,自定义镜像标签为build-base。
https://docs.docker.com/build/building/context/#how-to-build-without-a-context- 使用
Here-Documents运行RUN、COPY指令,注意如果是在Dockerfile中使用需要保证文件换行符是LF。
https://docs.docker.com/reference/dockerfile/#here-documents- 备用镜像站:
- mirrors.aliyun.com
- mirrors.cernet.edu.cn
- mirrors.tuna.tsinghua.edu.cn
使用镜像
docker run -ti --rm build-base bash -l
- 默认为
non-login的shell,需要使用 ‘-l’ 参数登录以生效/etc/profile配置。
https://github.com/gliderlabs/docker-alpine/issues/443
编译环境镜像
构建镜像
docker build -t build-lineage - <<\EOF
FROM build-base
USER root
RUN <<EOT
apt update
# toolchain
apt install -y bc bison build-essential ccache curl flex g++-multilib gcc-multilib git git-lfs gnupg gperf imagemagick protobuf-compiler python3-protobuf lib32readline-dev lib32z1-dev libdw-dev libelf-dev libgnutls28-dev lz4 libsdl1.2-dev libssl-dev libxml2 libxml2-utils lzop pngcrush rsync schedtool squashfs-tools xsltproc zip zlib1g-dev
apt clean && rm -rf /var/lib/apt/lists/*
EOT
USER user
EOF
软件列表请参考: https://wiki.lineageos.org/devices/sagit/build#install-the-build-packages
使用镜像
docker run -ti --rm --privileged -v ~/projects/:/projects/ build-lineage bash -l
拉取代码
配置 git 用户信息
配置基本信息:
git config --global user.email "you@example.com"
git config --global user.name "Your Name"
指定 LineageOS 仓库镜像(清华大学镜像源):
cat >> ~/.gitconfig <<EOF
#[http "https://gerrit.googlesource.com/"]
# proxy = socks5://192.168.8.12:10808
#[http "https://android.googlesource.com/"]
# proxy = socks5://192.168.8.12:10808
#[http "https://review.lineageos.org/"]
# proxy = socks5://192.168.8.12:10808
#[http "https://github.com/LineageOS/"]
# proxy = socks5://192.168.8.12:10808
[url "https://mirrors.tuna.tsinghua.edu.cn/git/git-repo"]
insteadof = https://gerrit.googlesource.com/git-repo
[url "https://mirrors.tuna.tsinghua.edu.cn/git/AOSP/"]
insteadof = https://android.googlesource.com/
[url "https://mirrors.tuna.tsinghua.edu.cn/git/lineageOS/"]
insteadof = https://review.lineageos.org/
[url "https://mirrors.tuna.tsinghua.edu.cn/git/lineageOS/LineageOS/"]
insteadof = https://github.com/LineageOS/
EOF
有时候镜像源可能出现代码尚未完成同步的情况, 这个时候建议屏蔽镜像开启代理尝试直接同步.
同步代码
mkdir -p ~/projects/android/android_lineage_22
cd ~/projects/android/android_lineage_22
repo init -u https://github.com/LineageOS/android.git -b lineage-22.2 --git-lfs --depth=1
repo sync -c -d
--depth=1表示浅克隆, 只拉取一层代码.
启动容器
docker run -ti --rm --privileged -v ~/projects/:/projects/ build-lineage bash -l
编译
配置 ccache 加速(可选)
cat >> ~/.bashrc <<EOF
export USE_CCACHE=1
export CCACHE_EXEC=/usr/bin/ccache
export CCACHE_DIR=~/.cache/ccache
EOF
ccache -M 50G
ccache -o compression=true
mkdir -p ~/.cache/ccache/
初始化编译环境
cd /projects/android/android_lineage_22/
source build/envsetup.sh
breakfast sagit
这个环节会根据设备型号拉取对应的产品构建组件仓库, 建议使用镜像仓库加速.
对于Xiaomi 6, 这个环节第一次执行会因为没有导入二进制文件而失败, 请参考踩坑记录.
如果碰到Can not locate config makefile for product "lineage_sagit".的问题也请参考踩坑记录.
导入厂商二进制文件
厂商代码是不开源的, 需要引用现有的二进制; 可以从设备提取, 也可以从现有的 ROM 包里面提取, 二选一即可.
-
从现有 ROM 包里面提取(推荐)
sudo apt update sudo apt install -y python3 e2fsprogs sudo ln -s /usr/bin/python3 /usr/bin/python cd /projects/android/android_lineage_22/device/xiaomi/sagit/ ./extract-files.py path/to/lineage-*.zip所需要的工具可以在
tools/extract-utils/extract_utils/extract.py文件中看到. -
从设备提取
cd /projects/android/android_lineage_22/device/xiaomi/sagit/ ./extract-files.py这个环节需要开启
Xiaomi 6设备的 开发者选项的调试模式 , 并连接至编译主机. 然后执行上述命令.
正常导入完成之后, 能够在 vendor 下面看到编译依赖:
user@5e613a9deb71:/projects/android/android_lineage_22$ ls -lh vendor/xiaomi/sagit/
total 104K
-rw-r--r-- 1 user user 77K Dec 24 20:11 Android.bp
-rw-r--r-- 1 user user 80 Dec 24 20:11 Android.mk
-rw-r--r-- 1 user user 50 Dec 24 20:11 BoardConfigVendor.mk
drwxr-xr-x 3 user user 4.0K Dec 24 20:11 proprietary
-rw-r--r-- 1 user user 9.2K Dec 24 20:11 sagit-vendor.mk
之后重新执行 breakfast sagit 初始化环境.
启动编译
cd /projects/android/android_lineage_22/
brunch sagit
踩坑记录
git lfs 同步失败
- 错误示例
Downloading webview.apk (91 MB) Error downloading object: webview.apk (e35a2a1): Smudge error: Error downloading webview.apk (e35a2a15f6dd1055ba3320f280849474eafc73d56ee26cecb7a3273ffbaa24c2): batch response: Repository or object not found: https://mirrors.tuna.tsinghua.edu.cn/git/lineageOS/LineageOS/android_external_chromium-webview_prebuilt_arm.git/info/lfs/objects/batch Check that it exists and that you have proper access to it Errors logged to /home/liux/projects/android_lineage/.repo/projects/external/chromium-webview/prebuilt/arm.git/lfs/logs/20230510T215212.15094947.log Use `git lfs logs last` to view the log. error: 外部过滤器 'git-lfs filter-process' 失败 fatal: webview.apk:smudge 过滤器 lfs 失败 error.GitError: Cannot checkout LineageOS/android_external_chromium-webview_prebuilt_arm: Cannot initialize work tree for LineageOS/android_external_chromium-webview_prebuilt_arm error: Cannot checkout LineageOS/android_external_chromium-webview_prebuilt_arm 正在更新文件: 100% (2237/2237), 完成. 正在更新文件: 100% (3547/3547), 完成.error: 工作区中下列未跟踪的文件将会因为检出操作而被覆盖: .gitattributes .lfsconfig 请在切换分支前移动或删除。 正在终止 error: external/chromium-webview/prebuilt/arm64/: LineageOS/android_external_chromium-webview_prebuilt_arm64 checkout ed88096ab28a21d2fb785899532194b3a67438f1 error: Cannot checkout LineageOS/android_external_chromium-webview_prebuilt_arm64error: Unable to fully sync the tree. error: Checking out local projects failed. Failing repos: external/chromium-webview/prebuilt/arm external/chromium-webview/prebuilt/arm64 external/chromium-webview/prebuilt/x86 external/chromium-webview/prebuilt/x86_64 Try re-running with "-j1 --fail-fast" to exit at the first error.由于上面拉取代码是配置了镜像仓库的, 但是镜像仓库中
git lfs的部分文件不全, 导致同步失败.
拉取代码偶现无法解析主机名
-
错误示例
略 -
解决办法
避免使用过多的线程, 宽带带宽不够的情况下某些线程抢不到资源, 导致连接失败;
检查网络连接质量, 必要时可以考虑科学上网;# http git config --global http.proxy 'http://192.168.8.12:10808' git config --global https.proxy 'http://192.168.8.12:10808' # socks git config --global http.proxy 'socks5://192.168.8.12:10808' git config --global https.proxy 'socks5://192.168.8.12:10808' # cancel git config --global --unset http.proxy git config --global --unset https.proxy
运行 breakfast 找不到产品
-
错误示例
In file included from build/make/core/config.mk:406: In file included from build/make/core/envsetup.mk:351: build/make/core/product_config.mk:226: error: Cannot locate config makefile for product "lineage_sagit". 15:20:28 dumpvars failed with: exit status 1 Device sagit not found. Attempting to retrieve device repository from LineageOS Github (http://github.com/LineageOS). Failed to fetch data from GitHub In file included from build/make/core/config.mk:406: In file included from build/make/core/envsetup.mk:351: build/make/core/product_config.mk:226: error: Cannot locate config makefile for product "lineage_sagit". 15:20:41 dumpvars failed with: exit status 1 In file included from build/make/core/config.mk:406: In file included from build/make/core/envsetup.mk:351: build/make/core/product_config.mk:226: error: Cannot locate config makefile for product "lineage_sagit". 15:20:44 dumpvars failed with: exit status 1 ** Don't have a product spec for: 'lineage_sagit' ** Do you have the right repo manifest?这是我新硬盘重新拉取代码后出现的问题, 第一次搭建环境的时候并没有出现, 折腾了很久. 最终通过看源码的方式定位原来是访问不到
Github的文件服务器(刚好我上次同步代码的时候可以访问, 这个问题出现的频次挺高的, 我发了博客之后好几个人找我说了这个问题, 当时是不知所云, 现在明白了~).
LineageOS源码在第一次初始化某个产品到时候, 会去Github上检索对应的配置便于拉取对于的代码仓库, 这个过程是通过访问Github的接口来实现的, 出现这个错误就是访问不到Github的文件服务器了. -
解决办法
在文件vendor/lineage/build/tools/roomservice.py中作如下修改:diff --git a/build/tools/roomservice.py b/build/tools/roomservice.py index 8c55c51..d59dc00 100755 --- a/build/tools/roomservice.py +++ b/build/tools/roomservice.py @@ -51,6 +51,9 @@ repositories = [] if not depsonly: githubreq = urllib.request.Request("https://raw.githubusercontent.com/LineageOS/mirror/main/default.xml") + proxy = urllib.request.ProxyHandler({'http': '192.168.8.12:10808', 'https': '192.168.8.12:10808'}) + opener = urllib.request.build_opener(proxy, urllib.request.HTTPHandler) + urllib.request.install_opener(opener) try: result = ElementTree.fromstring(urllib.request.urlopen(githubreq, timeout=10).read().decode()) except urllib.error.URLError:就是给访问
Github的请求加上代理服务器即可. 也可以尝试给shell环境加代理试试, 我这不想污染环境就没尝试了.
运行 breakfast 报错没有找到文件
-
错误示例
In file included from build/make/core/config.mk:353: In file included from build/make/core/envsetup.mk:352: In file included from build/make/target/product/telephony_vendor.mk:21: device/xiaomi/sagit/device.mk:54: error: vendor/xiaomi/sagit/sagit-vendor.mk does not exist.. 09:32:24 dumpvars failed with: exit status 1 Device sagit not found. Attempting to retrieve device repository from LineageOS Github (http://github.com/LineageOS). Found repository: android_device_xiaomi_sagit Default revision: lineage-20.0 Checking branch info Using fallback branch: lineage-20 Checking if device/xiaomi/sagit is fetched from android_device_xiaomi_sagit LineageOS/android_device_xiaomi_sagit already fetched to device/xiaomi/sagit Syncing repository to retrieve project. Fetching: 100% (1/1), done in 1.015s repo sync has finished successfully. Repository synced! Looking for dependencies in device/xiaomi/sagit Looking for dependencies in device/xiaomi/msm8998-common Looking for dependencies in hardware/xiaomi hardware/xiaomi has no additional dependencies. Looking for dependencies in kernel/xiaomi/msm8998 kernel/xiaomi/msm8998 has no additional dependencies. Done In file included from build/make/core/config.mk:353: In file included from build/make/core/envsetup.mk:352: In file included from build/make/target/product/telephony_vendor.mk:21: device/xiaomi/sagit/device.mk:54: error: vendor/xiaomi/sagit/sagit-vendor.mk does not exist.. 09:32:29 dumpvars failed with: exit status 1 In file included from build/make/core/config.mk:353: In file included from build/make/core/envsetup.mk:352: In file included from build/make/target/product/telephony_vendor.mk:21: device/xiaomi/sagit/device.mk:54: error: vendor/xiaomi/sagit/sagit-vendor.mk does not exist.. 09:32:30 dumpvars failed with: exit status 1 ** Don't have a product spec for: 'lineage_sagit' ** Do you have the right repo manifest? -
解决办法
IMPORTANT: Some devices require a vendor directory to be populated before breakfast will succeed. If you receive an error here about vendor makefiles, jump down to Extract proprietary blobs. The first portion of breakfast should have succeeded, and after completing you can rerun breakfast某些设备需要填充供应商目录,然后才能成功
breakfast。需要先执行导入厂商二进制文件步骤然后再breakfast。