You need to enable JavaScript to run this app. GNU Make 如何实现无硬依赖的分层细粒度可控并行构建配置
优惠活动
大模型
产品
解决方案
定价
更多

GNU Make 如何实现无硬依赖的分层细粒度可控并行构建配置

精细化并行控制的Makefile实现方法

根本不用靠全局.NOTPARALLEL硬关并行,靠GNU Make本身的局部约束机制,就能同时满足构建顺序要求、无硬依赖、细粒度并行的需求,不会浪费构建效率。

核心原理

很多人以为.NOTPARALLEL只能是全局声明,实际上GNU Make 3.82及以上版本,完全支持把.NOTPARALLEL绑定到单个目标上,只约束这个目标的直接依赖的执行方式,不影响其他任务的并行能力。所有并行限制都可以拆到最小粒度,不需要全量串行跑构建。

分需求适配

1. 实现全量构建的顶层顺序,不加跨目标硬依赖

用户的要求是全量跑all的时候,必须等host做完再跑kernel,kernel做完再跑app;但单独跑kernel、单独跑app的时候,不能自动触发前面的构建,所以不能给kernel加host依赖、给app加kernel依赖。
解决方法很简单:直接给all目标本身绑定局部.NOTPARALLEL属性,让它的直接依赖按书写顺序串行执行就行:

# 只有all目标的依赖会强制串行,严格按host → kernel → app的顺序执行
all: .NOTPARALLEL host kernel app

实际效果:

  • 跑make -j8 all的时候,会完整等host构建完再启动kernel,kernel跑完再启动app,完全符合顺序要求
  • 三个顶层目标之间没有任何硬依赖关联,单独跑make kernel、make app的时候,根本不会自动触发前置目标的构建,完全避免了硬依赖带来的非预期流程。

2. 实现内核模块编译的局部互斥,不影响其他应用并行

对于app/switch/compile和app/wifi/compile不能并行的问题,同样不需要全局关并行,只需要给这两个任务建一个专属的串行执行组伪目标,给伪目标绑定局部.NOTPARALLEL:

# 这个组里的两个编译任务强制串行,只作用于这两个任务本身
app/kmod_compile_group: .NOTPARALLEL app/switch/compile app/wifi/compile

随后调整app目标的依赖,把原来直接挂在app下的两个编译任务,替换成这个串行组的依赖,同时保留两个install任务的独立并行能力:

# app下的依赖中:busybox全流程、kmod编译组、两个install任务都可以跨组并行
app: app/busybox app/kmod_compile_group app/switch/install app/wifi/install

实际效果:

  • 并行构建时,app/busybox的全流程、两个模块的install任务,还有后续新增的boa、自研应用的编译,都可以和其他可并行的任务一起跑,不会因为内核模块的限制被全量卡住
  • 编译组内部会严格顺序执行switch和wifi的compile环节,不会出现两个内核模块并行编译的冲突
  • 只要某个模块的compile跑完,对应的install可以立刻启动,不用等组里其他无关的任务,没有多余的串行开销。

调整后的完整Makefile示例

# 没有全局.NOTPARALLEL声明,默认开全量并行
all: .NOTPARALLEL host kernel app

host: host/kconfig
kernel: kernel/compile kernel/install

# 内核模块编译串行组
app/kmod_compile_group: .NOTPARALLEL app/switch/compile app/wifi/compile

app: app/busybox app/kmod_compile_group app/switch/install app/wifi/install

app/busybox: app/busybox/compile app/busybox/install
app/switch: app/switch/compile app/switch/install
app/wifi: app/wifi/compile app/wifi/install

app/busybox/compile:
    make -C busybox

注意事项

  • 这种局部绑定.NOTPARALLEL的写法需要GNU Make 3.82及以上版本,现在绝大多数嵌入式开发环境的Make版本都满足要求
  • 后续如果有新的无法并行的任务,直接把对应任务加到对应的串行组依赖列表里就行,不需要改全局配置
  • 比起传统的空锁文件互斥方案,这种原生机制没有额外的文件IO开销,也不会出现锁文件残留导致的构建异常。

内容的提问来源于stack exchange,提问作者yuanjianpeng

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.31 07:54:03