Android源码本地编译实战
解决源码本地编译步骤,短时间编译出对应产物
准备工作:
权限申请:
确认自己是否有对应机型,对应 android 大版本,miui 大版本权限
https://project.pt.miui.com/#/v2/authority/requestlist
其他配置
- 进入 CloudDev 申请云服务器,如果已有云服务器,可跳过此步骤,如果使用本地编译也可以跳过这一步。
- 进入 权限管理平台 申请对应设备权限,本例采用 M2 设备作为例子。
- 确保当前设备上,小米在线刷机平台可用 , Win上无法连接设备可以参考 Win USB 驱动安装。另外某些数据线也可能导致无法连接设备,可以尝试更换数据线。
下载代码:
搜索对应机型,准备 repo init 环境
https://bbm.pt.miui.com/releases
以 O2 为例:

在您希望存放源码的目录中,使用 repo init 命令来初始化仓库,并通过 -m 参数指定您要使用的 manifest 文件,如果你想了解更多的Repo使用方法点击这里。例如:
// 在本地新建一个目录用于存放源码
mkdir o2_w_stable
cd o2_w_stable
// 进入目录后执行如上复制的repo init命令
repo init -u ssh://zhoubencheng@git.mioffice.cn:29418/platform/manifest.git -b release-25q2-3.0.0 -m release-25q2-qcom-xiaomi.xml --repo-url=ssh://zhoubencheng@git.mioffice.cn:29418/tools/repo.git --no-repo-verify --depth=1 --git-lfs
代码下载过程中可能发生 repo版本过老,具体报错如下,解决办法如
https://xiaomi.f.mioffice.cn/docs/dock4p0dybTjn253HRhQ85fFOkc

建议:
在执行 repo sync 的时候,同时在 corgi 上打一个对应机型对应版本的 userdebug 刷机包
https://corgi.pt.miui.com/next/pangu/rom/list
刷机包打好后把这个包刷入手机,本地代码的修改都 push 进这个手机即可,可以保证本地代码与手机代码一致性更好,避免其他模块有依赖,导致 push 后手机起不来。
其中:
-
-u参数指定了manifest仓库的 URL。 -
-m参数指定了仓库中具体的manifest文件名(例如my_manifest.xml)。如果不指定,默认使用default.xml。 -
-u:指定清单(manifest)仓库的 URL。该 URL 指向了一个 Git 仓库,其中包含了多个项目的配置文件。CSDN Blog+1Cnblogs+1 -
ssh://xiaoming@git.oppeoffice.cn:29418/platform/manifest.git -
-b:指定要检出的分支名称。 比如这里的master-t分支 -
-m:指定清单仓库中的具体清单文件名。Android Open Source Project+5git-repo.info+5360doc+5 比如这里的missi_t_qcom.xml -
--repo-url:指定用于初始化 Repo 工具的 Git 仓库 URL。阿里云开发者社区-云计算社区-阿里云+1CSDN Blog+1 , 比如这里的ssh://xiaoming@git.oppeoffice.cn:29418/tools/repo.git -
--no-repo-verify:在初始化 Repo 时跳过对 Repo 仓库的验证检查。 -
--depth=1:在克隆仓库时仅获取最新的提交记录,减少下载的数据量。 -
--git-lfs:启用 Git 大文件存储(Git LFS)支持,用于管理大型二进制文件。
用途
repo init 用于初始化一个新的 repo 工作区(workspace),相当于告诉系统:
我要从某个 manifest 仓库拉取一组项目配置,用它来管理多个 git 子仓库的同步。
Android 系统、嵌入式项目、小米 / 高通平台的源码同步,常用这种结构。
🧱 参数详细解释
| 参数 | 含义 |
|---|---|
repo init | 初始化 repo 工作区的命令。必须首先执行(之后才会用 repo sync 拉代码)。 |
-u ssh://zhoubencheng@git.mioffice.cn:29418/platform/manifest.git | manifest 仓库地址。这是一个特殊的 Git 仓库,里面的 default.xml 或指定的 release-25q2-qcom-xiaomi.xml 文件描述了所有子项目的路径、分支、远程源等。这里使用了 SSH 协议,说明要通过个人帐号 zhoubencheng 的权限访问公司 Git 服务。 |
-b release-25q2-3.0.0 | 指定 manifest 仓库的分支。相当于 git clone 后的 git checkout release-25q2-3.0.0。这个分支对应一个特定版本(这里是 Q2 2025 release 3.0.0)。 |
-m release-25q2-qcom-xiaomi.xml | 指定 manifest 文件名。默认是 default.xml,这里用的是 release-25q2-qcom-xiaomi.xml,表示针对小米定制的高通平台配置。这个 XML 文件定义了要同步的源码模块。 |
--repo-url=ssh://zhoubencheng@git.mioffice.cn:29418/tools/repo.git | 指定使用的 repo 工具仓库地址。通常 repo 默认从 Google 的 https://gerrit.googlesource.com/git-repo 下载,这里替换成了公司内部(小米)镜像。这样可以避免被墙或加快下载。 |
--no-repo-verify | 跳过 repo 工具签名验证。某些公司内部修改过 repo(非官方版本),加上这个参数可以防止验证失败。 |
--depth=1 | 浅克隆(shallow clone),只拉取最新一层提交记录(不包含历史),可以显著减少下载时间和磁盘占用。适合只需要编译、不改底层代码的情况。 |
--git-lfs | 启用 Git Large File Storage (LFS) 支持,用于拉取大文件(如图片、固件、模型等)。确保代码同步时不会丢失大文件。 |
⚙️ 示例目录结构
执行完 repo init 后,你的项目结构大致如下:
编辑/
├── .repo/
│ ├── manifests/ # 存放 manifest 仓库内容
│ ├── manifest.xml # 当前使用的 XML 配置
│ └── repo/ # repo 工具脚本
└── (子项目将在 repo sync 后出现)注意,上述地址仓库需要在申请对应设备权限后,换成自己的仓库地址,具体地址可以参考BBM中对应机型的命令下载提示,但注意,不要直接使用BBM中的初始化命令,仅拷贝ssh开头的地址链接即可。另外,branch 可以替换成你需要的分支,如果不知道分支名,可以参考柯基编译平台 中对应的
system编译日志(右侧操作下的齿轮图标,点选System日志,进入后左侧栏目右键点选View as plain text下载到本地,查找repo init字段,可以找到该次编译使用的--repo-branch对应的值。
指定下载的xml文件:
- 上面命令中
<release-25q2-qcom-xiaomi.xml>这个xml是可以替换成你自己的xml的,如果机器当前使用了不同的xml,并且你需要debug机器代码,那么这个时候,你可以下载机器代码对应manifest文件
repo init -u ssh://zhoubencheng@git.mioffice.cn:29418/platform/manifest.git -b release-25q2-3.0.0 -m release-25q2-qcom-xiaomi.xml --repo-url=ssh://zhoubencheng@git.mioffice.cn:29418/tools/repo.git --no-repo-verify --depth=1 --git-lfs

- 然后cp到
.repo中对应.repo/manifests目录下

- 打开对应manifest替换所有的
username_placeholder关键字为自己的邮箱

repo下载信息基参考这个命令就可以
但是如果需要确定的manifest和分支信息需要进一步下载对应机器的manifest文件



查找repo init字段,提取分支信息

当然最好还是参考corgi平台的编译思路

repo init -g all -u ssh://ci-autobuilder@git.mioffice.cn:29418/platform/manifest.git -b master --repo-url=ssh://ci-autobuilder@git.mioffice.cn:29418/tools/repo.git --repo-branch=stable-2.16.5-build --no-repo-verify --reference=/home/work/REPO_LOCAL_MIRROR --depth=1
》》》》》》Downloading manifest from git@c3dns.pt.miui.com:miui/platform/manifest.git
》》》》》》repo has been initialized in /home/work/mnt/miui_codes1/build_home_rom
cd /home/work/data/miui_codes/build_home_rom/.repo
rm -f manifest.xml
ln -s qcom-manifest-system-OS2.0.250410.1.VNUCNXM.STABLE-TEST-15.0-719ec08298.xml manifest.xml
// repo sync拉取整套代码即可
// 一般建议在执行repo sync的时候,同时在corgi上打一个对应机型对应版本的userdebug刷机包
// 使用8线程下载代码,且只下载manifest文件内默认的分支,且不下载仓库的tags
repo sync -cd --no-tags -j8
// 如果只想拉取某个仓库的代码,只需加上仓库位置即可,不写就默认全部下载
repo sync frameworks/base -cd --no-tags -j8
指定manifest再repo sync(非必须)
不同版本源代码、ROM所对应的manifest不同,因此我们可以使用manifest文件来保证即将下载的源代码和ROM版本完全一致。(若源代码和ROM版本不匹配,后续进行到push framework时可能会有重启卡在开机界面的Android Logo、无限重启等问题,需要刷ROM使手机恢复正常。而且,还需要重新下载源码、ROM使得版本匹配,这会耗费大量的时间。)
打开柯基编译平台,如下图所示按序操作(想要详细了解该平台可以参考柯基打包平台使用说明 - MiPhone系统软件部 - Formal)。
在序号3的红框处选择和获取init命令时同样的信息(q对应安卓Q版本即安卓10版本、r对应安卓R版本即安卓11版本;dev对应开发版、stable对应稳定版、native对应原生版、factory对应工厂版),作为版本号的日期选最新的(其实和下载ROM时保持一致就行)。
在序号4处点击复制链接,新建标签页粘贴链接,下载此版本的manifest文件到.repo目录下。

在命令行终端执行:
# 当前路径:/home/mi/sda/mymiui/picasso
cd .repo # 进入.repo目录
# ls -l # 查看当前软链接manifest.xml指向
# 令manifest.xml指向我们刚下载的manifest文件,注意替换刚下载的文件名称
ln -sf picasso_21.7.20_11.0_manifest_20210720.000515.xml manifest.xml
# ls -l # 确认软链接manifest.xml指向改变
cd .. # 返回上一级目录
# 使用4线程下载代码,且只下载manifest文件内默认的分支,且不下载仓库的tags
repo sync -j4 -d -c --no-tags等待几个小时后,几百个G的代码下载完成,内容如图所示。

编译
环境配置
每次新打开一个终端,如果想要编译源码,都需要在源码根目录下执行如下操作:
source build/envsetup.sh
# w版本
# qcom
lunch missi-feature_phone_qcom_cn_only64-userdebug # O2、o3
lunch missi-feature_pad_qcom_cn_only64-userdebug # O81 平板项目
# mtk
export OUT_DIR=out_sys && lunch missi-feature_phone_mtk_cn-userdebug # M12
# xring
lunch missi-feature_phone_xring_cn_only64-userdebug #O2S
# v版本
# qcom
lunch missi-feature_phone_qcom_cn_only64-userdebug
# mtk
lunch missi-feature_phone_mtk_cn-userdebug
# xring
lunch missi-feature_phone_xring_cn_only64-userdebug
# u版本
lunch missi_phone_cn-userdebug可选输入如下命令来跳过 XX 功能,会快一点
| export SKIP_DOWNLOAD_CUST_APPS=true | 不下载商业预装应用 |
|---|---|
| export SKIP_DOWNLOAD_DECOUPLED_APPS=true | 不下载解耦应用 miui/prebuilts/decoupled_appsmiui/prebuilts/miui_decoupled_apps |
| export SKIP_DOWNLOAD_VENDOR_GOOGLE_APPS=true | 不下载 GMS 预装应用 |
| export SKIP_DOWNLOAD_OPERATOR_APPS=true | # 不下载运营商 |
| export SKIP_SETTINGS_PROGUARD=true | 关闭混淆, 方便 debug |
| export ENABLE_MIUI_DEBUGGING=true | 允许调试 |
| export WITH_DEXPREOPT_BOOT_IMG_AND_SYSTEM_SERVER_ONLY=true | 关闭 odex 优化 |
| export XMS_BULDER_DISABLED=true | 关闭 xms(Xiaomi Mobile Services 类似与 GMS,包含一些 SDK 和应用等) |
根据需要编译对应模块
framework 的修改主要涉及目录:

根据自己的代码所在位置,选择不同的模块进行编译,
找到对应代码所在目录下的 Android.bp 文件,即可确认需要编译的模块名。
例:
- 本地修改了 frameworks/native/services/surfaceflinger/Layer.cpp
- 查找该文件所在模块 bp 文件,frameworks/native/services/surfaceflinger/Android.bp,对应编译名字为 libsurfaceflinger,则模块名为 libsurfaceflinger。
- 首次编译需要使用 make
- 如果涉及到了文件的添加或删除,或 Android.bp 的修改,也需要 make
- 常用模块名:
framework-minus-apex`` ``services`` ``libsurfaceflinger`` ``miui-framework`` ``miui-services`` ``libhwui`` ``libandroid_runtime
// 源码根目录下执行如下编译命令即可
make <模块名> -j8如需整编,可以执行make target-files-package -j10 ,整编根据个人机器性能,一般需要 3-4 小时,可参见:刷机 aosp 版本-刷机
后续再次编译时,可使用 ninja 加快编译速度
每套源码下载完成后,首次使用 ninja 前需要先配置 ninja
cp prebuilts/build-tools/linux-x86/bin/ninja out/host/linux-x86/bin/
ln -sf out/combined-missi.ninja build.ninja之后即可使用 ninja 来加快编译速度
ninja <模块名> -j8编译结束,push 之前的需要执行的命令
在往 push 编译得到的 Jar 包或者是。so 文件前,都需要对手机进行以下命令
adb root
adb remount
adb disable-verity
adb reboot
//开机后需要重新 root和remount一下
adb root
adb remountpush 结束后如何生效
push framework 或 services 后,需要执行adb reboot 修改才能生效
push surfaceflinger,hwui,gui,jni 后,执行adb shell stop;adb shell start 后,修改即可生效
省事版 push 脚本
<object data=“file:///” type=“text/plain” width=“100%” height=“500px”>
执行完命令需要 adb reboot
执行完命令需要 adb shell stop;adb shell start各模块详细编译及 push 命令
framework
文件范围:frameworks/base/core
make framework-minus-apex -j8
// 如果涉及到了miui/frameworks/base的修改,还需要编译
make miui-framework -j8push 命令
adb root;adb remount
adb push $OUT/system/framework/framework.jar /product/pangu/system/framework/
adb push $OUT/system_ext/framework/miui-framework.jar /system_ext/framework/
adb rebootservices
文件范围:frameworks/base/services
make services -j8
// 如果涉及到了miui/frameworks/base的修改,还需要编译
make miui-services -j8push 命令
adb root;adb remount
adb push $OUT/system/framework/services.jar /product/pangu/system/framework/
adb push $OUT/system_ext/framework/miui-services.jar /system_ext/framework/
adb rebootsurfaceflinger
文件范围:
frameworks/native/services/surfaceflinger
frameworks/native/libs/renderengine
W版本编译及push命令
make surfaceflinger -j80
adb push out/target/product/missi/system/bin/surfaceflinger system/bin/surfaceflinger
adb shell stop;adb shell startV及以下编译命令
make libsurfaceflinger -j8V 版本 push 命令
adb root;adb remount
adb push $OUT/system_ext/lib64/libsurfaceflinger.so system_ext/lib64/libsurfaceflinger.so
adb shell stop;adb shell startU 版本 push 命令
adb root;adb remount
adb push $OUT/system/lib/libsurfaceflinger.so system/lib/libsurfaceflinger.so
adb push $OUT/system/lib64/libsurfaceflinger.so system/lib64/libsurfaceflinger.so
adb shell stop;adb shell startlibmisurfaceflinger
文件范围:vendor/xiaomi/frameworks/native/services/surfaceflinger
make libmisurfaceflinger -j8push 命令
adb root;adb remount
adb push $OUT/system_ext/lib/libmisurfaceflinger.so system_ext/lib/libmisurfaceflinger.so
adb push $OUT/system_ext/lib64/libmisurfaceflinger.so system_ext/lib64/libmisurfaceflinger.so
adb shell stop;adb shell starthwui
文件范围:frameworks/base/libs/hwui
hwui 编译前,需要先打开 frameworks/base/libs/hwui/Android.bp
将对应文件中所有的 host_supported: true 都注释掉,才能开始本地编译,否则会报错
- V版本bp修改可apply该diff
- W版本bp修改可apply该diff
[下载并应用diff文件 bp_diff_w](./sh/bp_diff _w)
make libhwui -j8push 命令
adb root;adb remount
adb push $OUT/system/lib/libhwui.so system/lib/libhwui.so
adb push $OUT/system/lib64/libhwui.so system/lib64/libhwui.so
adb shell stop;adb shell startgui
文件范围:frameworks/native/libs/gui
make libgui -j8push 命令
adb root;adb remount
adb push $OUT/system/lib/libgui.so system/lib/libgui.so
adb push $OUT/system/lib64/libgui.so system/lib64/libgui.so
adb shell stop;adb shell startjni
文件范围:frameworks/base/core/jni
android_runtime 编译前,需要先打开 frameworks/base/core/jni/Android.bp
将对应文件中所有的 host_supported: true 都注释掉,才能开始本地编译,否则会报错,也可一并应用hwui中的diff
make libandroid_runtime -j8push 命令
adb root;adb remount
adb push $OUT/system/lib/libandroid_runtime.so system/lib/libandroid_runtime.so
adb push $OUT/system/lib64/libandroid_runtime.so system/lib64/libandroid_runtime.so
adb shell stop;adb shell startMiuiSystemUI
文件范围:
- packages/apps/MiuiSystemUI
- frameworks/base/libs/WindowManager/Shell
make MiuiSystemUI -j10push 命令
adb root;adb remount
adb push $OUT/system_ext/priv-app/MiuiSystemUI/MiuiSystemUI.apk /system_ext/priv-app/MiuiSystemUI/MiuiSystemUI.apk
adb shell stop;adb shell start
# 如果不想重启手机,也可以直接kill掉原来的Systemui进程,等待Systemui重启后就可以生效
# 可以直接使用2.5的脚本其它注意事项
adb 跳过开机引导
adb root;adb shell settings put secure user_setup_complete 1;adb shell settings put global device_provisioned 1;adb rebootpython 编译版本问题
print SyntaxError: invalid syntax 错误
Python 3 编译,print 函数出现语法错误(SyntaxError: invalid syntax)的问题
以上问题是因为 python 版本不对导致的语法错误,需要使用 python2 去编译
使用以下命令可以实现 python 版本切换
sudo update-alternatives --install /usr/bin/python python /usr/bin/python2 1
sudo update-alternatives --install /usr/bin/python python /usr/bin/python3 2参考链接:https://www.jianshu.com/p/3c844d965e5a
Android 中打印 C++代码中的调用堆栈
1. 首先在Android.bp中添加依赖库:libutilscallstack
cc_input_flinger_library_shared {
name: "libinputflinger",
......
shared_libs: [
"libinputflinger_base",
"libinputreporter",
"libinputreader",
"libutilscallstack" // Here
],
}
2. 在对应的文件中,引入头文件:
#include <utils/CallStack.h>
3. android::CallStack stack("TAGXXX");
4. 添加完成之后,需要make一遍即可具体操作见下:
-
添加链接库
surfaceflinger 加堆栈
frameworks/native/services/surfaceflinger/Android.bp
搜索 libsurfaceflinger_defaults

hwui 加堆栈
frameworks/base/libs/hwui/Android.bp
搜索 hwui_static_deps

libgui 中加堆栈
frameworks/native/libs/gui/Android.bp
搜索 libgui-defaults

skia 中加堆栈
external/skia/Android.bp
搜索 libpng

包含头文件
#include <utils/CallStack.h>在需要打栈的地方加入
android::CallStack stack("TagXXX");查看 log 时过滤”TagXXX”即可。
ninja 报错
error while loading shared libraries…No such file or directory
ninja: error while loading shared libraries: libc++.so: cannot open shared object file: No such file or directory
ninja: error while loading shared libraries: libjemalloc5.so: cannot open shared object file: No such file or directory
解决:
# 根据缺少的lib提示,执行对应的cp命令即可
sudo cp prebuilts/build-tools/linux-x86/lib64/libc++.so /usr/lib
sudo cp prebuilts/build-tools/linux-x86/lib64/libjemalloc5.so /usr/lib// 配置 ninja 环境时有时候会遇到目录out/host/linux-x86/bin/不存在,这时候手动新建bin文件夹即可,如果还报少libc++库,就执行上面的命令
ninja 报错 unexpected variable ‘symlink_outputs’

解决:
sudo apt remove ninja-build
sudo cp ./prebuilts/build-tools/linux-x86/bin/ninja /usr/bin
sudo cp ./prebuilts/build-tools/linux-x86/lib64/libjemalloc5.so /usr/lib
sudo cp ./prebuilts/build-tools/linux-x86/lib64/libc++.so /usr/lib/编译报错
build/make/core/artifact_path_requirements.mk:40 error: Build failed

打开报错的文件,将报错部分注释掉,重新编译即可。

corgi编译报错解决
step1 找到日志
找到编译记录 - > 编译日志 - > system\product\vendor → View as plain text


step2 搜索报错信息
搜索关键字 1 error generated.,进而可以定位到报错信息附近
1 error generated
如上图就是 frameworks/base/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp 中android::uirenderer::RenderProperties.getName报错导致BB,修复重新编译即可
frameworks/base/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp:504:101: error: no member named 'getName' in 'android::uirenderer::RenderProperties'
[2025-04-14T07:47:38.954Z] 504 | trace_begin_formatStringCTM("isLayer[%s] clipFlags[%d] Alpha[%.1f] ignoreLayer[%s]", properties.getName(),clipFlags,properties.getAlpha(),ignoreLayer?"true":"false");
[2025-04-14T07:47:38.954Z] | ~~~~~~~~~~ ^