惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
博客园 - 【当耐特】
阮一峰的网络日志
阮一峰的网络日志
S
Secure Thoughts
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
T
Tenable Blog
T
Tailwind CSS Blog
WordPress大学
WordPress大学
宝玉的分享
宝玉的分享
Webroot Blog
Webroot Blog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
The Cloudflare Blog
T
Threat Research - Cisco Blogs
V
Visual Studio Blog
Jina AI
Jina AI
V
V2EX
I
InfoQ
Latest news
Latest news
P
Proofpoint News Feed
T
Threatpost
Engineering at Meta
Engineering at Meta
P
Proofpoint News Feed
美团技术团队
The Register - Security
The Register - Security
L
LangChain Blog
Apple Machine Learning Research
Apple Machine Learning Research
aimingoo的专栏
aimingoo的专栏
GbyAI
GbyAI
Cloudbric
Cloudbric
Microsoft Azure Blog
Microsoft Azure Blog
C
Cisco Blogs
U
Unit 42
Microsoft Security Blog
Microsoft Security Blog
MyScale Blog
MyScale Blog
V
Vulnerabilities – Threatpost
TaoSecurity Blog
TaoSecurity Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Recent Commits to openclaw:main
Recent Commits to openclaw:main
W
WeLiveSecurity
博客园 - 司徒正美
T
The Exploit Database - CXSecurity.com
小众软件
小众软件
Y
Y Combinator Blog
Recent Announcements
Recent Announcements
量子位
酷 壳 – CoolShell
酷 壳 – CoolShell
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
博客园_首页
N
News and Events Feed by Topic

chenhang 的博客

Android 12 - WMS 层级结构 && DisplayAreaGroup 引入 Android 12 - 跟踪利器 WinScope Android 12 - Letterbox 模式 Android 列表滚动优化之 OverScroller 揭秘 Android Q 黑暗模式(Dark Mode)源码解析 如何顺滑地查看 Android Native 代码 AOSP 编译和烧写 Protocol Buffers 手册 设计模式之装饰模式 设计模式之桥接模式 设计模式之代理模式 依赖注入利器 - Dagger ‡ Robolectric使用教程 设计模式之模板方法模式和策略模式 设计模式之工厂模式(Factory) Fragment源码分析 Fragment事务管理源码分析 java动态代理 Android分包MultiDex源码分析
使用 Ninja 提升模块编译速度
2019-11-20 · via chenhang 的博客

1. 简介

从 Android 7 开始,Android 源码编译时默认使用 Ninja,编译时,会先把 makefile 和 bp 转换成 ninja 再进行编译。这个转换过程非常慢(需要遍历处理所有关联的 makefile、bp 文件),即使只是通过 mmmmm 编译某个模块,也会有很多因素触发 ninja 文件的重新生成,而这对基于源码开发的模块很不友好,编译好慢!

AOSP 在源码中已经内置了一个 ninja 执行文件,路径为:./prebuilts/build-tools/linux-x86/bin/ninja

我们先看看它的 help:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
➜  ~ ./prebuilts/build-tools/linux-x86/bin/ninja -h
usage: ninja [options] [targets...]

if targets are unspecified, builds the 'default' target (see manual).

options:
--version print ninja version ("1.9.0")
-v, --verbose show all command lines while building

-C DIR change to DIR before doing anything else
-f FILE specify input build file [default=build.ninja]

-j N run N jobs in parallel (0 means infinity) [default=10 on this system]
-k N keep going until N jobs fail (0 means infinity) [default=1]
-l N do not start new jobs if the load average is greater than N
-n dry run (don't run commands but act like they succeeded)

-d MODE enable debugging (use '-d list' to list modes)
-t TOOL run a subtool (use '-t list' to list subtools)
terminates toplevel options; further flags are passed to the tool
-w FLAG adjust warnings (use '-w list' to list warnings)

简单使用的话,我们关注它的两个参数就行了

  • -f:这个参数指定的就是输入文件,也就是 makefile 和 bp 转换后的 ninja 文件,一般位于 ./out 目录,后面会说
  • targets:目标,这个和 makefile 是类似的,就是我们最终需要的产物,例如:Launcher3QuickStep、SystemUI。那么这些 targets 名是哪里定义的呢?要知道对应模块的对应的 target 名,只需要:
    • 若模块使用的是 Android.mk:查找 LOCAL_PACKAGE_NAMELOCAL_MODULE 等对应的值
    • 若模块使用的是 Android.bp:查找 module 中 name 对应的值

举个栗子:

1
2
3
4
5
6
7
➜ android-10.0.0_r11 ./prebuilts/build-tools/linux-x86/bin/ninja -f out/combined-aosp_walleye.ninja Launcher3QuickStep
[3/13] Target Java: out/target/common/obj/JAVA_LIBRARIES/Launcher3QuickStepLib_intermediates/classes-full-debug.jar
注: 某些输入文件使用或覆盖了已过时的 API。
注: 有关详细信息, 请使用 -Xlint:deprecation 重新编译。
注: 某些输入文件使用了未经检查或不安全的操作。
注: 有关详细信息, 请使用 -Xlint:unchecked 重新编译。
[13/13] Install: out/target/product/walleye/system/product/priv-app/Launcher3QuickStep/Launcher3QuickStep.apk

就这样,不需要通过 mm 或者 mmm 命令,目标产物同样生成了。我们看看耗时:

1
2
3
4
5
6
7
8
9
10
11
➜ android-10.0.0_r11 time ./prebuilts/build-tools/linux-x86/bin/ninja -f out/combined-aosp_walleye.ninja Launcher3QuickStep
[3/13] Target Java: out/target/common/obj/JAVA_LIBRARIES/Launcher3QuickStepLib_intermediates/classes-full-debug.jar
注: 某些输入文件使用或覆盖了已过时的 API。
注: 有关详细信息, 请使用 -Xlint:deprecation 重新编译。
注: 某些输入文件使用了未经检查或不安全的操作。
注: 有关详细信息, 请使用 -Xlint:unchecked 重新编译。
[13/13] Install: out/target/product/walleye/system/product/priv-app/Launcher3QuickStep/Launcher3QuickStep.apk

real 0m18.994s
user 1m20.548s
sys 0m2.872s

可以看到,整个编译在 18s 完成了,相比动辄七八分钟的 mmm,效率提升还是很可观的。

3. 注意事项

虽然 ninja 很方便,但要用它来编译单个模块,还是有一些限制和注意事项的:

  • 使用前需把对应模块编译一遍,用于生产 ninja 文件(全编或 mmm 都可以)
  • 全编后,生成的 ninja 文件为:./out/combined-[TARGET-PRODUCT].ninja
  • mmm 编译后,生成的 ninja 文件为:./out/combined-[TARGET-PRODUCT]-_[path_to_your_module_makefile].ninja,比如:./out/combined-aosp_walleye-_packages_apps_Launcher3_Android.mk.ninja
  • 如果修改了 Android.mk 或 Android.bp,需使用传统的 make 命令进行编译以重新生成包含新依赖规则的 ninja 文件
  • 可以把 ninja 放到 PATH 环境变量中,这样就不用每次都敲 ./prebuilts/build-tools/linux-x86/bin/ninja 这个路径了

4. 最后

为 Launcher 和 SystemUI 准备一份开箱即用的指令,尽情玩耍吧~

Launcher:

1
./prebuilts/build-tools/linux-x86/bin/ninja -f out/combined-qssi-_packages_apps_Launcher3_Android.mk.ninja Launcher3QuickStep

SystemUI:

1
./prebuilts/build-tools/linux-x86/bin/ninja -f out/combined-qssi-_frameworks_base_packages_SystemUI_Android.mk.ninja SystemUI