build.ninja 目标查找与编译指南(以 camera_framework 为例)
本文面向OpenHarmony GN + Ninja构建体系,覆盖以下内容:
- “camera_framework 同名导致 unknown target”的根因与解决办法
out/arm64/targets/build.ninja怎么产生的build.ninja语法/规则怎么读(重点包含行末$与$:转义)- 像
camera_framework这种重名/多形态 target,如何区分“部件target”和“库产物target” - 如何用grep / ninja -t targets / ninja -t query快速定位,并给出可直接复制的编译指令(
build.sh -T)
说明:文中的命令示例以当前环境路径为准:
/root/633/out/arm64/targets/build.ninja。
1. 问题背景:为什么最开始-T camera_framework编译失败(同名导致误解)
1.1 初始现象
初始尝试命令如下:
./build.sh --product-name 633_rk3588j_isdt-2 -T camera_framework该命令无法编译成功(典型表现为 ninja 报unknown target)。
1.2 “同名”的起点:两处都叫 camera_framework(但含义完全不同)
误解的根源是:camera_framework这个字符串在两处被定义,但属于不同层面的“名字”:
- bundle.json(部件/组件名):
component.name = "camera_framework"
"component": { "name": "camera_framework", "subsystem": "multimedia", "syscap": ["SystemCapability.Multimedia.Camera.Core"], "features": [],- BUILD.gn(GN 目标名/模块名):
ohos_shared_library("camera_framework")
ohos_shared_library("camera_framework") { branch_protector_ret = "pac_ret" install_enable = true sources = [这两处“同名”本身不是错误,但非常容易误以为
-T camera_framework可以直接编译。
1.3 为什么-T camera_framework会失败(真正原因)
./build.sh -T传给的是ninja 的 target 名(不是 bundle.json 的component.name)。
因此当写-T camera_framework时,ninja 会去查找一个名为camera_framework的 target;但在当前build.ninja中,这个“短名字 target”并不存在,通常存在的是“带路径的 target”。
可用下面命令快速验证(返回空表示“没有这个 target”):
grep-n'^build camera_framework:'/root/633/out/arm64/targets/build.ninja真正存在的是这类带路径的定义(举例):
grep-n'^build .*camera_framework'/root/633/out/arm64/targets/build.ninja|head另外在bundle.json中也能看到:该部件并不是直接写“camera_framework”去编译,而是列出了它包含的GN label(带路径 + 冒号):
"fwk_group": [ "//foundation/multimedia/camera_framework/frameworks/native/camera:camera_framework", "//foundation/multimedia/camera_framework/frameworks/native/ndk:ohcamera", "//foundation/multimedia/camera_framework/interfaces/kits/js/camera_napi:camerapicker_napi", "//foundation/multimedia/camera_framework/interfaces/kits/js/camera_napi:camera_napi", "//foundation/multimedia/camera_framework/interfaces/kits/js/camera_napi:camera_js", "//foundation/multimedia/camera_framework/interfaces/kits/js/camera_napi:camerapicker_js" ],注意:GN label 里常见的
//是“源码根路径”语义;但build.ninja里的 ninja target不会带//,而是类似foundation/...这样的路径。
在out/arm64/targets/build.ninja中可以看到对应的ninja target(phony 聚合目标,带路径):
build foundation/multimedia/camera_framework/common$:camera_utils: phony obj/foundation/multimedia/camera_framework/common/camera_utils.stamp build foundation/multimedia/camera_framework/frameworks/native/camera$:camera_framework: phony multimedia/camera_framework/libcamera_framework.z.so build foundation/multimedia/camera_framework/frameworks/native/camera$:camera_framework__check: phony obj/foundation/multimedia/camera_framework/frameworks/native/camera/camera_framework__check.stamp build foundation/multimedia/camera_framework/frameworks/native/camera$:camera_framework__collect: phony obj/foundation/multimedia/camera_framework/frameworks/native/camera/camera_framework__collect.stamp build foundation/multimedia/camera_framework/frameworks/native/camera$:camera_framework__notice: phony obj/foundation/multimedia/camera_framework/frameworks/native/camera/camera_framework__notice.stamp build foundation/multimedia/camera_framework/frameworks/native/camera$:camera_framework_info: phony obj/foundation/multimedia/camera_framework/frameworks/native/camera/camera_framework_info.stamp因此正确做法是:使用带路径的目标名进行编译(见第 2 节)。
1.3.1 速查表:多个“camera_framework”的含义对照
- bundle.json 的
component.name:camera_framework(部件/组件名,不是 ninja target) - BUILD.gn 的 GN target 名:
camera_framework(需要配合路径才能唯一定位) - bundle.json 里用于构建的 GN label:
//foundation/.../camera:camera_framework(GN 语义) - build.ninja 里的目标写法:
foundation/.../camera$:camera_framework(Ninja 文件内部写法,$:表示字面量:) - 命令行应使用的 ninja target:
foundation/.../camera:camera_framework(把$:还原成:) - 库产物 target:
multimedia/camera_framework/libcamera_framework.z.so
1.3.2 为什么-T graphic_2d能“编译整个部件”(对比说明)
在foundation/graphic/graphic_2d/bundle.json中可见(组件名 + 子系统):
"component": { "name": "graphic_2d", "subsystem": "graphic", "syscap": [当一个部件被纳入产品配置后,构建系统通常会在build.ninja里为其生成一个同名的顶层聚合目标(phony)。当前 out 目录中存在:
build graphic_2d: phony obj/out/arm64/targets/build_configs/graphic/graphic_2d/graphic_2d.stamp build graphic_2d_info: phony obj/out/arm64/targets/build_configs/graphic/graphic_2d/graphic_2d_info.stamp build graphic_2d_inner_kits: phony obj/out/arm64/targets/build_configs/graphic/graphic_2d/graphic_2d_inner_kits.stamp build graphic_2d_innerkit_remove_check_so: phony obj/out/arm64/targets/build_configs/graphic/graphic_2d/graphic_2d_innerkit_remove_check_so.stamp build graphic_2d_sdk_info: phony obj/out/arm64/targets/build_configs/graphic/graphic_2d/graphic_2d_sdk_info.stamp build graphic_2d_test: phony obj/out/arm64/targets/build_configs/graphic/graphic_2d/graphic_2d_test.stamp因此执行:
./build.sh --product-name 633_rk3588j_isdt-2 -T graphic_2d等价于让 ninja 构建这个“部件级 phony target”。该 target 依赖并触发build_configs/.../graphic_2d.stamp,从而把bundle.json里配置的各个 group(base/fwk/service 等)相关目标一并拉起构建——表现上就是“编译整个部件”。
补充关键点:要严格证明“编译整个部件”,需要展开依赖链并确认其覆盖范围。
- 第一步(聚合目标只依赖一个 stamp):
graphic_2d的 phony 依赖graphic_2d.stamp(见上面build graphic_2d: phony ...graphic_2d.stamp)。 - 第二步(看 stamp 的输入是什么):
graphic_2d.stamp的输入里包含graphic_2d_install_modules.json/graphic_2d_dep_modules.json(可以用ninja -t query查看)。 - 第三步(看 install_modules.json 里列了什么):
graphic_2d_install_modules.json明确列出了该部件的模块清单,每条都带module_def(GN label)且part_name为graphic_2d,例如:
[ { "module_def": "//foundation/graphic/graphic_2d/frameworks/opengl_wrapper:EGL(//build/toolchain/ohos:ohos_clang_arm64)", "module_info_file": "obj/foundation/graphic/graphic_2d/frameworks/opengl_wrapper/EGL_module_info.json", "part_name": "graphic_2d", "subsystem_name": "graphic", "toolchain": "//build/toolchain/ohos:ohos_clang_arm64", "toolchain_out_dir": "." }, { "module_def": "//foundation/graphic/graphic_2d/frameworks/opengl_wrapper:GLESv3(//build/toolchain/ohos:ohos_clang_arm64)", "module_info_file": "obj/foundation/graphic/graphic_2d/frameworks/opengl_wrapper/GLESv3_module_info.json", "part_name": "graphic_2d", "subsystem_name": "graphic", "toolchain": "//build/toolchain/ohos:ohos_clang_arm64", "toolchain_out_dir": "." }, { "module_def": "//foundation/graphic/graphic_2d/utils/color_manager:color_manager(//build/toolchain/ohos:ohos_clang_arm64)", "module_info_file": "obj/foundation/graphic/graphic_2d/utils/color_manager/color_manager_module_info.json", "part_name": "graphic_2d", "subsystem_name": "graphic", "toolchain": "//build/toolchain/ohos:ohos_clang_arm64", "toolchain_out_dir": "." }, { "module_def": "//foundation/graphic/graphic_2d/rosen/modules/2d_graphics:2d_graphics(//build/toolchain/ohos:ohos_clang_arm64)", "module_info_file": "obj/foundation/graphic/graphic_2d/rosen/modules/2d_graphics/2d_graphics_module_info.json", "part_name": "graphic_2d", "subsystem_name": "graphic", "toolchain": "//build/toolchain/ohos:ohos_clang_arm64", "toolchain_out_dir": "." }, { "module_def": "//foundation/graphic/graphic_2d/utils/socketpair:socketpair(//build/toolchain/ohos:ohos_clang_arm64)", "module_info_file": "obj/foundation/graphic/graphic_2d/utils/socketpair/socketpair_module_info.json", "part_name": "graphic_2d", "subsystem_name": "graphic", "toolchain": "//build/toolchain/ohos:ohos_clang_arm64", "toolchain_out_dir": "." }, // ... 后续还有大量 graphic_2d 部件内模块 ... ]因此,“-T graphic_2d会编译整个部件”的更严格表述为:
-T graphic_2d会触发部件级 phony → 部件 stamp → 部件模块清单(install_modules.json)这条链路;install_modules.json枚举了该部件内的模块(module_def),构建系统据此拉起这些模块的编译/安装信息生成;- 所以它的效果等价于“把 graphic_2d 部件配置覆盖的模块整体拉起来构建”,而不是只编单个
.so。
对比camera_framework:可用 grep 验证当前build.ninja里没有build camera_framework: phony ...这种顶层部件目标:
grep-n'^build camera_framework:'/root/633/out/arm64/targets/build.ninja因此-T camera_framework会失败,需要改用带路径的目标(如foundation/.../camera:camera_framework)或直接编库产物(如multimedia/camera_framework/libcamera_framework.z.so)。
1.3.3 归纳:何时可以“直接用名字 -T”构建(必要条件)
按“部件名”构建整个部件(例如
-T graphic_2d):- 一般规律:若部件名在该部件的构建命名空间中不与部件内其它 GN 目标短名冲突,构建系统往往会生成同名的顶层聚合目标(
build <part_name>: phony ...),从而支持-T <part_name>直接构建整个部件。 - 必要条件(可验证):当前
build.ninja中确实存在build <part_name>: phony ...这一类短名目标。 - 冲突提示:当部件名与部件内某个 GN 目标短名同名(例如部件名
camera_framework,部件内又存在ohos_shared_library("camera_framework")),为避免短名歧义,顶层短名聚合目标可能不会生成;此时通常会生成“带路径的部件聚合目标”,例如build out/.../build_configs/<subsystem>/<part>$:<part>: phony ...,需要用该目标来编整个部件。
- 一般规律:若部件名在该部件的构建命名空间中不与部件内其它 GN 目标短名冲突,构建系统往往会生成同名的顶层聚合目标(
按“GN 目标短名”构建单个目标(例如
-T <target_name>):- 必要条件:当前
build.ninja中存在名为<target_name>的可构建 target,且无歧义。 - 更稳妥做法:直接使用“带路径的 target”(
path:target形式)进行构建,避免短名不存在或重名导致unknown target/歧义。
- 必要条件:当前
结论:是否能用短名-T,最终以build.ninja中是否存在对应 target为准;可用grep '^build <name>:' build.ninja或ninja -t targets验证。
1.4 常见误用:从 build.ninja 直接复制$:写法到命令行(“二级坑”:$:转义)
常见误用命令如下:
./build.sh --product-name 633_rk3588j_isdt-2\-T'foundation/multimedia/camera_framework/frameworks/native/camera$:camera_framework'该写法会报错,因为build.ninja文件里为了表达字面量:,会写成$:;但命令行里 target 名应使用真实的冒号:。即:
.../camera$:camera_framework(build.ninja 内部写法).../camera:camera_framework(命令行应使用)
一句话总结:
- 从 build.ninja 复制目标名时:把
$:还原为:;把行末续行用的$去掉。
2. 解决方案:如何正确编译“部件 target”与“库 target”
编译部件聚合 target(phony)
✅ 编译整个camera_framework部件(部件级 build_configs 聚合 target):
./build.sh --product-name 633_rk3588j_isdt-2\-T'out/arm64/targets/build_configs/multimedia/camera_framework:camera_framework'build.ninja中对应的目标定义为:
build out/arm64/targets/build_configs/multimedia/camera_framework$:camera_framework: phony obj/out/arm64/targets/build_configs/multimedia/camera_framework/camera_framework.stamp build out/arm64/targets/build_configs/multimedia/camera_framework: phony obj/out/arm64/targets/build_configs/multimedia/camera_framework/camera_framework.stampout/arm64/targets/build_configs/multimedia/camera_framework/BUILD.gn可以作为**辅助判断“部件构建名”**的依据:直接查看其中的ohos_part("<构建名>")(例如ohos_part("camera_framework"))即可确认该部件的聚合目标名称,并可顺带确认该部件聚合的模块清单(module_list)。
进一步推导:
- 若对源码目录/子系统划分比较熟悉,可直接在
out/arm64/targets/build_configs/<subsystem>/<part>/下通过“目录定位”快速确认部件的聚合构建名(以ohos_part("<构建名>")为准),再回到build.ninja验证其是否已生成对应的 Ninja target。 - 推荐使用带路径的 target(例如
out/.../build_configs/...:camera_framework);但在少数场景下build.ninja会额外提供短名别名(如graphic_2d),此时也可直接用短名进行-T构建。
但需要区分清楚:-T的参数必须是Ninja target 名,而不是某个BUILD.gn的文件路径。构建整个部件时使用的是build.ninja里已经生成出来的聚合目标out/arm64/targets/build_configs/multimedia/camera_framework:camera_framework(phony -> *.stamp)。
该 target 名的来源:在633/out/arm64/targets/build.ninja中搜索build_configs/multimedia/camera_framework,可直接命中build out/arm64/targets/build_configs/multimedia/camera_framework$:camera_framework: phony ...;命令行使用时把$:还原为:,得到可用于-T的 target。
✅ 编译单个 GN 模块//foundation/multimedia/camera_framework/frameworks/native/camera:camera_framework(对应libcamera_framework.z.so):
./build.sh --product-name 633_rk3588j_isdt-2\-T'foundation/multimedia/camera_framework/frameworks/native/camera:camera_framework'❌ 错误(把 build.ninja 内部转义写法$:原样拿去当 target):
./build.sh --product-name 633_rk3588j_isdt-2\-T'foundation/multimedia/camera_framework/frameworks/native/camera$:camera_framework'编译库产物 target(.z.so)
./build.sh --product-name 633_rk3588j_isdt-2\-T multimedia/camera_framework/libcamera_framework.z.so同时编“部件 + 库”(一次命令)
-T/--build-target支持指定多个(build 系统里明确支持),所以可以一次编两个目标。
./build.sh --product-name 633_rk3588j_isdt-2\-T'foundation/multimedia/camera_framework/frameworks/native/camera:camera_framework'\-T multimedia/camera_framework/libcamera_framework.z.so3. build.ninja 是怎么产生的(生成链路)
OpenHarmony 的构建大体分为:
- preloader / loader:解析产品配置、子系统/部件/模块信息
- gn:执行
gn gen生成 Ninja 构建文件(核心产物就是build.ninja) - ninja:根据
build.ninja的规则执行实际编译/链接
在仓内文档build/docs/how-to-add-a-build-parameter.md里明确写到:
“执行 gn gen 编译命令,产生的 build.ninja 文件可以类比与 makefile 文件。”
在build/hb/services/gn.py中也可以看到gn gen的执行方式(hb 调用 gn)大体就是:
- 组装
gn gen ... <out_dir>命令- out 目录即
self.config.out_path(对应out/arm64/targets这一类产物目录)
- out 目录即
结论:
/root/633/out/arm64/targets/build.ninja是GN 阶段(gn gen)生成的;- 后续
ninja -C /root/633/out/arm64/targets ...读取它来执行编译。
4. build.ninja 的语法规则:建议掌握的核心要点
build行:定义一个“可构建目标”
最重要的一句:
build <输出target>: <rule> <输入依赖...><输出target>:这个字符串就是 Ninja 的target 名(可被构建/被依赖)。<rule>:使用哪个规则来生成它。
rule:规则定义(编译/链接/拷贝等)
build.ninja里会有很多rule xxx,比如编译 C/C++ 的、链接 so 的等。
在“判断目标类型/行为”时,更关键的是build 行里使用的 rule 名字:
phony:聚合/别名 target,它本身不产生文件,只是把依赖串起来。- 其他(例如
cxx/cc/alink/solink/stamp等):一般对应真实动作。stamp常见于“收集/检查/notice”等阶段性标记文件(*.stamp)。
注意:不同产品/工具链生成的 rule 命名可能略有差异,但
phony的语义是 Ninja 固定语法。
$在 Ninja 里的两种常见用法:行末续行 vs$:转义
在 Ninja 语法里,$最常见有两种用途,千万别混淆:
- 行末
$:续行符(line continuation),表示这一行还没写完,下一行继续。 $::转义后的冒号:。因为:在build <out>: <rule>里有语法含义,如果目标名本身包含冒号(例如 GN label 形式path:target),Ninja 文件里会把这个冒号写成$:来避免歧义。
典型例子是all目标的依赖列表非常长,因此会写成:
build all: phony $ obj/.../xxx.stamp $ multimedia/camera_framework/libcamera_framework.z.so $ obj/.../yyy.stamp $ ...这里的含义是:
build all: phony $:定义了一个all聚合目标- 后续每一行(缩进的)都是
all的依赖 - 每行末尾
$表示依赖列表继续(不是 target 名的一部分)
因此可以看到(行末$):
multimedia/camera_framework/libcamera_framework.z.so $应当理解为:
- 真实 target 名:
multimedia/camera_framework/libcamera_framework.z.so - 行末
$:仅表示“下一行还有依赖项”,不是 target 名的一部分
另外还有一种常见$用法:$:转义。build.ninja中会出现这种形式:
build foundation/multimedia/camera_framework/frameworks/native/camera$:camera_framework: phony multimedia/camera_framework/libcamera_framework.z.so这行里camera$:camera_framework的含义是:
- Ninja 文件内部写法:
camera$:camera_framework - 真实 target 名(命令行/日志里应使用):
camera:camera_framework
结论:命令行里不要带$:,需要把$:还原成:。否则会触发unknown target报错。
unknown target '...camera$:camera_framework', did you mean '...camera:camera_framework'?
5. camera_framework 这种“多形态 target”怎么区分:部件 vs 库
核心问题在于:camera_framework在多个层面都有名字:
- GN target 名(
path:target形式) - 部件/模块聚合目标(通常是
phony) - 真实产物(
.z.so/.so/ 可执行程序等)
部件/聚合 target(phony)
在build.ninja中可以找到如下示例(注意这里的$:是 Ninja 文件里的转义写法):
build foundation/multimedia/camera_framework/frameworks/native/camera$:camera_framework: phony multimedia/camera_framework/libcamera_framework.z.so解读:
- build.ninja 内部写法:
foundation/multimedia/camera_framework/frameworks/native/camera$:camera_framework - 真实 target 名(命令行应使用):
foundation/multimedia/camera_framework/frameworks/native/camera:camera_framework - 规则:
phony(说明这就是“别名/聚合目标”) - 它依赖的真实产物:
multimedia/camera_framework/libcamera_framework.z.so
库产物 target(真实 so 输出名)
在all目标的依赖清单中也能看到库产物本身:
multimedia/camera_framework/libcamera_framework.z.so $这类.so(或.z.so)通常才是期望的“真实编译结果/链接结果”。
常见疑问:为什么 grep
^build multimedia/camera_framework/libcamera_framework.z.so:有时找不到?
- 因为不同生成策略下,
.so可能是最终输出,也可能还会经过 wrapper/重命名/打包步骤;- 更稳妥的方法是用
ninja -t query来追溯它的生成规则(见下文第 7 节)。
6. 在 build.ninja 里“怎么搜”:推荐的定位套路
只看 target 定义:搜^build
找 camera_framework 相关定义(最快):
grep-n"^build .*camera_framework"/root/633/out/arm64/targets/build.ninja|head-n50通常会看到两类信息:
...$:camera_framework: phony ...(部件/聚合;$:是 build.ninja 内部转义,命令行要还原成:)...camera_framework__check/__collect/__notice...(一般是 stamp 相关目标)
想知道某个库是否进入“全量编译”:看build all
all目标基本代表“全量构建入口”,做全量编译时会走到它依赖的所有项。
可按如下方式搜索all:
grep-n"^build all:"/root/633/out/arm64/targets/build.ninja然后在build all的依赖区域进一步 grep:
grep-n"multimedia/camera_framework/libcamera_framework.z.so"/root/633/out/arm64/targets/build.ninja注意:
build all的依赖非常长,直接打开文件会很难读;用 grep 定位行号再看局部上下文更高效。
7. 不要“盲 grep”:用 ninja 自带工具精确查 target(推荐)
Ninja 提供了非常实用的“自省”命令,比直接肉眼阅读build.ninja更稳定:
列出所有 target(然后 grep 关注项)
说明:当前环境里系统
ninja可能不在 PATH,建议直接用预置 ninja:/root/633/prebuilts/build-tools/linux-x86/bin/ninja。
另外,out 目录可能存在重复规则,-t targets建议加-w dupbuild=warn以避免直接报错中断。
/root/633/prebuilts/build-tools/linux-x86/bin/ninja -wdupbuild=warn\-C /root/633/out/arm64/targets -t targets all|grepcamera_framework|head-n50该步骤最适合解决以下问题:
unknown target 'camera_framework'(说明传入的不是 Ninja 目标名)- “同名太多不知道选哪个”
查询某个 target 的生成关系(追溯它由谁生成)
/root/633/prebuilts/build-tools/linux-x86/bin/ninja -wdupbuild=warn\-C /root/633/out/arm64/targets -t query multimedia/camera_framework/libcamera_framework.z.so该命令会输出:
- 这个输出由哪个 rule 生成(例如链接/拷贝)
- 它依赖了哪些输入(对象文件、其他库、stamp 等)
这一步是“找真实编译规则”的最可靠方式。
8. 用 build.sh 精准编译:部件名 vs 库名(camera_framework 示例)
先确认:-T/--build-target支持指定多个
仓内build/README_zh.md明确写了:
-T BUILD_TARGET, --build-target=BUILD_TARGET # 指定编译目标,可以指定多个
并且build/scripts/entry.py里参数解析也是:
parser.add_option('-T', '--build-target', action='append', default=[])
结论:-T支持重复传参,从而在一次构建中同时指定多个目标。
说明:本节与第 2 节避免重复
本节的“部件/库/同时编译”命令已在本文第 2 节给出(避免重复)。
9. 常见坑位速查
unknown target 'camera_framework'
原因:
- 传入的是部件/模块在 bundle.json 里的名字,而不是 Ninja 的 target 名。
解决:
- 用
ninja -t targets all | grep camera_framework找到真实 target(通常是path:target或具体产物路径)。 - 如果目标名来自
build.ninja的复制:需要先把$:还原为:。
修改out/.../build_configs/.../BUILD.gn后出现 “Regenerating ninja files / Unresolved dependencies”
原因:
out/arm64/targets/build_configs/<subsystem>/<part>/BUILD.gn属于 GN 构建图的输入(很多场景下还是生成物)。改动其中的ohos_part("<构建名>")/依赖列表,可能导致gn gen重建build.ninja时出现依赖无法解析,从而使构建直接失败。
建议:
- 该类文件用于“辅助定位/确认部件聚合目标与模块清单”即可;需要改动部件构建配置时,应回溯并修改上游生成来源(例如产品配置、bundle/部件配置、loader 生成逻辑),再重新生成 out。
从 build.ninja 复制目标名:记得把$:还原为:
例如 build.ninja 里写:
foundation/.../camera$:camera_framework
命令行里应使用:
foundation/.../camera:camera_framework
“这行只有xxx.z.so $,找不到build xxx.z.so: ...”
解释:
- 这行很可能只是
all的依赖项之一(依赖列表里出现),不代表它的build规则一定就在附近。
解决:
- 优先使用
ninja -t query xxx.z.so追溯生成链路; - 或者 grep 整个文件的
build头:grep -n "^build .*xxx\.z\.so" ...(注意有时输出名会被包装/重命名)。
10. 建议的“实战操作流程”(最省时间)
- 列出所有相关 targets:
/root/633/prebuilts/build-tools/linux-x86/bin/ninja -wdupbuild=warn\-C /root/633/out/arm64/targets -t targets all|grepcamera_framework- 对目标做 query,确认其类型(phony 还是产物):
/root/633/prebuilts/build-tools/linux-x86/bin/ninja -wdupbuild=warn\-C /root/633/out/arm64/targets -t query'foundation/multimedia/camera_framework/frameworks/native/camera:camera_framework'/root/633/prebuilts/build-tools/linux-x86/bin/ninja -wdupbuild=warn\-C /root/633/out/arm64/targets -t query multimedia/camera_framework/libcamera_framework.z.so- 用
build.sh -T精准编译(注意$转义):
./build.sh --product-name 633_rk3588j_isdt-2\-T'foundation/multimedia/camera_framework/frameworks/native/camera:camera_framework'11. 附:快速理解 “部件 target” 为啥在 build.ninja 里长得像...$:camera_framework
这类...$:形式并不是“目标名里真的有$”,而是 Ninja 为了表达path:target这种包含冒号的 label,在build.ninja文件中使用的转义写法($:表示字面量:)。
因此在需要“按模块/部件维度构建”时,通常应使用完整路径 + 冒号 + target 名的形式,而不是只写短名字。