如何在GNU Make中拆分单词列表为小块并动态生成编译规则
GNU Make 纯内置实现源文件分块动态编译规则方案
以下实现完全使用GNU Make内置功能,无外部shell调用,跨平台兼容:
# 基础配置 SOURCE_FILES := one.c two.c three.c four.c five.c six.c CHUNKS := 2 # 分块数量,按需调整即可 TARGET := executable.elf # 计算总文件数 TOTAL_FILES := $(words $(SOURCE_FILES)) # 纯Make内置向上取整除法:计算每块最少文件数 define div_ceil $(if $(word $2,$1),$(words x $(call div_ceil,$(wordlist $2,$(words $1),$1),$2)),0) endef PER_CHUNK := $(call div_ceil,$(SOURCE_FILES),$(CHUNKS)) # 递归生成每个分块的编译规则(GNU Make 4.0+ 内置math函数实现数值计算,无shell调用) define generate_chunk_rules $(eval START := $1) $(eval END := $(math EVAL,$(START) + $(PER_CHUNK) - 1)) # 处理最后一块超出总文件数的情况 $(if $(word $(END),$(SOURCE_FILES)),,$(eval END := $(TOTAL_FILES))) # 提取当前块的源文件和对应目标文件 $(eval CHUNK_SRCS := $(wordlist $(START),$(END),$(SOURCE_FILES))) $(eval CHUNK_OBJS := $(patsubst %.c,%.o,$(CHUNK_SRCS))) # 生成分块编译规则,替换为实际的专有编译器命令即可 $(CHUNK_OBJS): $(CHUNK_SRCS) @echo 编译分块文件: $^ @你的专有编译器命令 -c $^ # 递归生成下一个块的规则 $(eval NEXT_START := $(math EVAL,$(END) + 1)) $(if $(word $(NEXT_START),$(SOURCE_FILES)),$(call generate_chunk_rules,$(NEXT_START))) endef # 触发所有分块规则生成 $(call generate_chunk_rules,1) # 所有目标文件列表 ALL_OBJS := $(patsubst %.c,%.o,$(SOURCE_FILES)) # 链接规则 $(TARGET): $(ALL_OBJS) @echo 链接生成目标文件: $@ @你的链接命令 $^ -o $@ # 清理规则 .PHONY: clean clean: rm -f $(ALL_OBJS) $(TARGET)
方案说明
- 只需修改
CHUNKS变量即可灵活调整分块数量,适配不同并行构建需求 - 自动处理文件总数无法被分块数整除的场景,最后一个分块会自动包含剩余所有文件
- 生成的规则完全兼容
make -j N并行构建,既避免了单文件调用编译器的高额开销,也解决了全量单任务编译耗时过长的问题 - 无任何外部shell调用,完全符合跨平台兼容性要求
- 如果使用GNU Make 4.0以下版本,可替换
math函数为纯Make递归加法实现,逻辑完全一致
内容的提问来源于stack exchange,提问作者Plazgoth
相关产品推荐
相关产品推荐

