构建场景下如何捕获用户指定核心数?无需新增输入变量
捕获构建时的并行核心数(无需新增输入变量)
嘿,这个场景我之前在嵌套多项目构建时刚好折腾过,分享几个不用加新输入变量就能搞定的方法:
1. 针对 Make 构建的情况
Make 本身会把命令行参数存到 MAKEFLAGS 环境变量里——比如你跑 make -j5,MAKEFLAGS 里就包含 -j5。我们可以直接从这个变量里提取核心数:
在你的 Makefile 里加这段代码:
# 从 MAKEFLAGS 中提取 -j 后面的数字 JOBS := $(patsubst -j%,%,$(filter -j%,$(MAKEFLAGS))) # 如果用户没指定 -j,可选:默认用系统核心数(按需开启) ifeq ($(JOBS),) JOBS := $(shell nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 4) endif # 传递给外部项目时直接用 $(JOBS) external-build: cd external-project && make -j$(JOBS)
不管用户输入 make -j5 还是 make -j12,JOBS 都会自动捕获到对应的数字。
2. 针对 Ninja 构建的情况
Ninja 本身没有直接暴露并行数的变量,但可以通过系统命令或构建生成工具来获取核心数:
方法一:直接读取系统核心数
在你的 build.ninja 里可以这么写:
# 获取系统逻辑核心数(兼容 Linux/macOS) rule get_jobs command = echo $$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 10) > jobs.tmp build jobs.tmp: get_jobs pool = console # 读取核心数变量 JOBS = $$(cat jobs.tmp) # 调用外部项目时使用 build external: phony command = cd external-project && make -j$(JOBS)
这里的 10 是你提到的本地核心数,作为兜底值;用系统命令自动获取会更通用。
方法二:如果是 CMake 生成 Ninja 文件
CMake 里自带核心数检测的工具,可以直接在 CMakeLists.txt 里定义参数:
# 引入核心数检测模块 include(ProcessorCount) ProcessorCount(NUM_CORES) # 配置外部项目的构建命令 set(EXTERNAL_BUILD_CMD "make -j${NUM_CORES}") # 把变量传递给 Ninja 构建模板 configure_file( ${CMAKE_SOURCE_DIR}/build_external.ninja.in ${CMAKE_BINARY_DIR}/build_external.ninja @ONLY )
生成的 Ninja 文件会自动带上对应核心数的 -j 参数。
3. 跨构建工具的统一处理
如果你的项目同时支持 Make 和 Ninja,可以写个 shell 脚本作为入口,自动判断并捕获核心数:
#!/bin/bash if [ "$1" = "ninja" ]; then # Ninja 模式:获取系统核心数 JOBS=$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 10) ninja -j$JOBS # 传递给外部项目 cd external-project && make -j$JOBS else # Make 模式:从 MAKEFLAGS 提取用户指定的核心数 JOBS=$(echo "$MAKEFLAGS" | grep -oE '-j[0-9]+' | cut -c2-) if [ -z "$JOBS" ]; then JOBS=$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 4) fi make -j$JOBS cd external-project && make -j$JOBS fi
这样用户不管用 make -j5 还是直接跑 ninja,都能自动把核心数传递给外部项目。
内容的提问来源于stack exchange,提问作者Raul Laasner
相关产品推荐
相关产品推荐

