Android系统模块编译调试与Ninja使用指南

作者:龙之叶日期:2025/10/6

模块编译调试方法

(此处举例framework、installd、SystemUI等模块的编译调试,其他类似)

1. Framework模块编译

Android系统代码的framework目录内,一共有3个模块单独编译:framework、services、framework-res.apk。

注意:偶尔会有改了代码但没检测到,编译结束后产物并未更新的情况,所以可以考虑先剪切掉原先的产物或者检查产物更新时间确保已经重新编译。

步骤

  1. 完成根目录下 source build/envsetup.sh 命令、lunch qssi-userdebug-mars 命令(准备好编译环境、选择好编译分支,才可以开始编译)。
  2. 整编命令如 bash build.sh -j32 dist --qssi_only 2>&1 | tee buildlog.log
1.1 修改frameworks/base/core/res下的内容
  • 在执行 source build/envsetup.sh 命令的版本源代码根目录执行 make framework-res -j32
  • 产物位于 out/target/product/qssi/system/framework 下面(如 framework-res.apk 之类),push到手机的 /system/framework/ 下面重启即可。
1.2 修改framework/base/services下的内容
  • 在执行 source build/envsetup.sh 命令的版本源代码根目录执行 make services -j32
  • 产物位于 out/target/product/qssi/system/framework 下面,拿出来push到手机的 /system/framework/ 下面重启即可。
1.3 修改framework/base/core下的内容
  • 在执行 source build/envsetup.sh 命令的版本源代码根目录执行 make framework-minus-apex -j32
  • 产物位于 out/target/product/qssi/system/framework 下面,拿出来push到手机的 /system/framework/ 下面重启即可。
  • 问题处理:如果卡在开机过程里(常在小于Android13版本中发生),而且不是自己原因导致而是一些AndroidRuntime错误导致的signal 6的内存错误,可尝试在push framework.jaradb shell rm -rf system/framework/oat system/framework/arm system/framework/arm64 再重启。
1.4 其他目录下的代码修改
  • 在framework/base下的其他很多目录下的代码修改也可以被编译到,但需要自行确认:
    • 故意改错去编译。
    • 搜Android.bp文件内容看看framework-minus-apex library的srcs是否包含了被修改的文件。
1.5 作SDK
  • 如果是要make出jar包给apk调用而不是push到系统里调试,那要拿此目录的jar包:out/target/common/obj/JAVA_LIBRARIES/framework-minus-apex_intermediates/classes.jar
  • 版本改动注意:在Android11之前修改了framework相关代码,只需 make framework 就可以编译出 framework.jar。在Android11,这个编译命令不起作用了,根据framework/base/目录下Android.bp中的提示,编译命令需要改为 make framework-minus-apex

2. 修改frameworks/native/cmds/abcd的任意模块代码

  • 通过 make abcd -j32 编译,比如 make installd -j16 make atrace -j16 等。
  • 产物位于 out/target/product/qssi/system/bin 下面,拿出来push到手机的 /system/bin/ 下面重启即可。

3. 修改packages/modules/abcd的代码

  • 通过找被修改文件属于的同/上级目录的Android.bp文件中哪个模块内编译,在此模块library中找到apex_available标签,即标识该library可以被name为xxxx的apex包进去,通过 make xxxx -j32 编译。
  • 产物位于 out/target/product/qssi/system/apex/ 下面,拿出来push到手机的 /system/apex/ 下面重启即可。
  • 示例:修改了 /packages/modules/Wifi/framework/java/android/net/wifi/WifiManager.java,那么在 /packages/modules/Wifi/framework/Android.bp 中找到 apex_available: ["com.android.wifi", "test_com.android.wifi"],就知道 make com.android.wifi -j16 可以编译到被修改文件。

4. 改动SystemUI、Settings等模块的代码

  • 可以通过 make SystemUImake Settings 来进行编译,产物在 /system/app/system/priv-app 下面,将结果apk直接install,然后重启此应用相关服务,如直接重启手机,或者如SystemUI在install后 adb shell am restart 也可以。
  • 注意:不要push已经存在的apk到手机,重启系统不会扫描,新的apk不会重新安装,测试效果将还是原先的效果,除非此系统apk可以先删掉重启再push再重启。

5. 通用编译模块的方法

  • 如修改位于 framework/native/services 下的文件,可以通过在同级或上级目录中的Android.bp文件内容中查找修改的文件名字或具体目录,来找到所属sources,再逐级向上找到被编译进哪个“name”的目标产物xxx中,再 make xxx -j32 对其编译。
  • 如果xxx编译出的产物是中间产物或手机中没有的无法替换的产物可以再向上查找更大name的目标产物xxxx(如:cc_library_shared、cc_library、java_library、apex_available等)进行编译或直接push进system/lib和system/lib64重启。

6. 编译system.img

  • 当你确定修改的内容能在编译system.img时带入,可以使用 make systemimage -j16 编译。通过进入fastboot模式后刷system.img进行生效。

编译调试注意点

  1. 编译最好把已经生成的先删掉,不然有可能文件不更新(push前check下文件的生成时间)。
  2. 编译终端最后提示的生成路径不一定是唯一生成路径,同级目录、对称lib或lib64目录里可能都有你需要的生成物。library要把生成的库文件在system/lib和system/lib64下都做相应的push。
  3. 如果是push替换库文件,最好留一个原本的备份避免push了开不了机器。
  4. 编译调试的时候如果是自己陌生的模块,建议每次都加行特殊log以确认自己的修改已经生效。

二、使用ninja替代make进行快速编译

为什么要使用ninja?

通常使用make编译会有两个阶段:

  1. 先分析Android.bp,将所有需要参与编译的文件的路径都记录下,writing build rules并打包到 out/soong/combined-.ninja 中。(普遍耗时15-20min)
  2. 然后ninja工具通过第一步生成的文件,编译要编译的模块。(不同模块速度不同,比如services模块只需要大约20s)

优点:直接使用ninja就可以省去第一部分耗时,尤其在反复编译时调试效率提高。

注意点

  1. 进行ninja之前必须要先make一次(当然要想make必须先根目录source和lunch一次),以生成路径文件;如果你的修改增删了模块中文件的名字路径,就必须重新make生成路径文件。

ninja的获取

1cd到android系统源码的根目录下,执行
2cp prebuilts/build-tools/linux-x86/bin/ninja out/host/linux-x86/bin/
3cp prebuilts/build-tools/linux-x86/bin/ninja /usr/local/bin/
4cp prebuilts/build-tools/linux-x86/bin/ninja /usr/bin/
5ln -sf out/combined-***.ninja build.ninja
6

ninja文件内容

1#!/bin/bash
2ninja(){
3 ninja_bin="$ANDROID_BUILD_TOP/prebuilts/build-tools/linux-x86/bin/ninja"
4 ninja_build_file="$ANDROID_BUILD_TOP/out/combined-$TARGET_PRODUCT.ninja"
5 if [ ! -f $ninja_build_file ]
6 then
7 echo "can't find ninja buildfile $ninja_build_file"
8 exit -1
9 fi
10 if [ ! -f $ninja_bin ]
11 then
12 echo "can't find ninja binary $ninja_bin"
13 exit -1
14 fi
15 $ninja_bin -f $ninja_build_file $1
16 }
17#usage:ninja<modulename>
18ninja $*
19

ninja的执行

如果执行ninja进行快速编译时,遇到如下错误:

1ninja: error while loading shared libraries: libjemalloc5.so: cannot open shared object file: No such file or directory
2

使用如下解决方法:

1sudo cp prebuilts/build-tools/linux-x86/lib64/libjemalloc5.so /usr/lib
2

Android系统模块编译调试与Ninja使用指南》 是转载文章,点击查看原文


相关推荐


精选 4 款开源免费、美观实用的 MAUI UI 组件库,助力轻松构建美观且功能丰富的应用程序!
追逐时光者2025/10/5

前言 一套优秀的 UI 组件库不仅能大幅提升开发效率,还能显著增强应用的视觉体验与交互质感。今天大姚给大家分享 4 款开源免费、美观实用的 MAUI UI 组件库,助你轻松打造专业级的跨平台应用程序。 .NET MAUI介绍 .NET 多平台应用 UI (.NET MAUI) 是一个跨平台框架,用于使用 C# 和 XAML 创建本机移动和桌面应用。使用 .NET MAUI,可从单个共享代码库开发可在 Android、iOS、macOS 和 Windows 上运行的应用。 .NET开源免费的跨平


医院病人信息管理系统 Web 版开发实战(一)
FPGA+护理+人工智能2025/10/3

医院病人信息管理系统Web版开发实战 文章目录 医院病人信息管理系统Web版开发实战一、概述二、项目结构搭建2.1 Flask 项目结构原理2.2 创建项目文件夹2.3 初始化 Flask 应用 三、路由设计3.1 Flask 路由机制原理3.2 定义核心路由3.3 数据存储函数 四、模板开发4.1 Jinja2 模板引擎原理4.2 基础模板设计4.3 首页模板(index.html)4.4 添加病人模板(add.html)4.5 详情和编辑模板 未完待续


Java-Spring入门指南(十一)代理模式与Spring AOP实战
珹洺2025/10/2

Java-Spring入门指南(十一)代理模式与Spring AOP实战 前言一、代理模式1.1 静态代理步骤1:定义租房接口(抽象行为)步骤2:实现房东类(真实对象)步骤3:编写中介类(代理对象)步骤4:测试静态代理静态代理的优缺点 1.2 动态代理 二、AOP是什么?2.1 AOP是什么?2.2 AOP有什么用?2.3 AOP的使用场景是什么?2.4 AOP的核心特点是什么? 三、AOP在Spring中的应用3.1 准备依赖3.2 配置Spring的AOP命名空间3.3 定义


(14)ASP.NET Core2.2 中的日志记录
老葱头蒸鸡2025/10/2

1.前言 ASP.NET Core支持适用于各种内置和第三方日志记录提供应用程序的日志记录API。本文介绍了如何将日志记录API与内置提供应用程序一起使用。 2.添加日志提供程序 日志记录提供应用程序显示或存储日志。例如,控制台提供应用程序在控制台上显示日志,Azure Application Insights提供应用程序将这些日志存储在Azure Application Insights中。要添加提供应用程序,请在Program.cs中调用提供程序的Add{provider name}扩


Python 的内置函数 abs
IMPYLH2025/10/2

Python 内建函数列表 > Python 的内置函数 abs 无论是在数学计算、数据分析,还是日常编程中,我们经常需要获取一个数的绝对值。Python 提供的 abs() 函数,可以让我们轻松地计算数字的绝对值,而无需手动判断正负。 abs 函数的参数和返回值如下: def abs(x): ''' 计算参数的绝对值 :param x: 要计算的值 :return: x 的绝对值 ''' 示例 在线运行 print(abs(-50)) p


[论文阅读] 人工智能 + 软件工程 | 从“人工扒日志”到“AI自动诊断”:LogCoT框架的3大核心创新
张较瘦_10/1/2025

随着软件服务系统日益庞大、复杂,基于日志的故障诊断对保证软件服务的可靠性至关重要。已有的日志故障诊断方法虽能确定故障类型,但无法为推理过程提供解释,导致难以在生产环境部署。为此,本文提出LogCoT框架,通过Auto-FSC算法利用超大规模闭源LLM提取日志语义,生成可解释根因分析报告;结合无类别标注指令优化与有类别标注参数微调,优化Mistral基座模型;再用LLMf-IPO算法纠正错误结果,对齐用户意图。在两大生产日志数据集上的实验表明,LogCoT在Accuracy、Macro-F1、Weighted


WPS文字如何合并多个文档:两种方法
揭老师高效办公9/30/2025

要合并多个Word文档,使用WPS文字有两种方法,一种是插入附件,引用附件中的文字,会把所有文档中的文字依次合并。第二种方式需要会员,使用WPS的“文档合并拆分”应用,每个文档都会从新的一页开始插入。


Webpack实战笔记:从自动构建到本地服务器搭建的完整流程
XiangCoder2025/10/7

作为前端开发者,Webpack 是绕不开的构建工具。最近系统学习了 Webpack 的自动构建和服务器搭建,整理了一套从基础到实战的操作笔记,包含具体案例和踩坑经验,适合新手跟着实操。 前言:为什么需要 Webpack 构建工具? 刚开始写前端项目时,我们习惯在 index.html 里手动引入各种 js、css 文件。但随着项目变大,会遇到两个核心问题: 资源越来越多,手动管理引入路径容易出错(尤其是加哈希值优化缓存时); 开发时需要频繁刷新页面看效果,效率太低。 Web


单机已达上限?PerfTest 分布式压测登场,轻松模拟百万用户洪峰
Go有引力2025/10/9

前言 在前一篇文章中,我们详细介绍了 perftest 的单机压测能力,展示了它如何通过极简的命令行实现对 HTTP/1.1、HTTP/2、HTTP/3 与 WebSocket 的高性能测试。然而,当业务系统庞大、服务部署分布式、网络链路复杂时,单机的压测能力显然无法满足真实生产环境的模拟需求。 幸运的是,perftest 不止于单机。它同样支持 分布式集群压测,通过 Collector + Agent 的架构,让你轻松在多台机器上同时发起测试,实现百万乃至千万级并发的性能评估。 为什么选择分


老题新解|十进制转二进制
程序员莫小特2025/10/10

《信息学奥赛一本通》第160题:十进制转二进制 题目描述 给定一个十进制整数 n n n,请将其转换为对应的二进制表示,并输出。 输入格式 输入包含一行,一个整数 n

首页编辑器站点地图

Copyright © 2025 聚合阅读

License: CC BY-SA 4.0