GNU Make:如何为单次生成多模块的代码生成器配置依赖规则
解决方案
GNU Make本身没有直接的内置函数可以传入目标和依赖,直接返回该目标的recipe是否需要执行的结果。但你现有的实现思路是正确的,可以进一步优化,完全避免生成临时文件、后续sed解析的额外步骤,直接在Make层面完成参数构造和生成器调用。
优化后实现
你可以直接在ALL_GEN_READY的recipe中完成模块提取、输入文件去重、生成器调用的全流程:
# 提前定义的基础变量(示例) GEN_OUTPUT_PATH := ./gen CMD_TOUCH := touch # 你已提前定义好的各模块输入文件 module_A_INPUT_FILES := infile infile_A1 infile_A2 module_B_INPUT_FILES := infile infile_A1 infile_B module_C_INPUT_FILES := infile_C module_D_INPUT_FILES := infile_D infile_D1 # 单模块依赖检查规则,和原有逻辑一致 define PROC_MODULE $(GEN_OUTPUT_PATH)/$1_GEN: $($1_INPUT_FILES) $(CMD_TOUCH) $$@ endef define GEN_MODULES $(foreach m,$1,$(eval $(call PROC_MODULE,$m))) # 注册模块对应的输入文件映射,方便后续查询 $(foreach m,$1,$(eval MODULE_INPUT_MAP_$m := $($1_INPUT_FILES))) $(GEN_OUTPUT_PATH)/ALL_GEN_READY: $(foreach m,$1,$(GEN_OUTPUT_PATH)/$m_GEN) @# 提取所有需要重新生成的模块名 @modules=$$(echo "$$?" | sed 's|$(GEN_OUTPUT_PATH)/\([^ ]*\)_GEN|\1|g'); \ if [ -n "$$modules" ]; then \ # 收集所有模块的输入文件并去重 input_files=$$(for m in $$modules; do echo "$(MODULE_INPUT_MAP_$$m)"; done | tr ' ' '\n' | sort -u | tr '\n' ' '); \ # 构造-m参数列表 module_args=$$(for m in $$modules; do echo "-m $$m"; done); \ # 直接调用生成器 generator $$module_args $$input_files; \ fi $(CMD_TOUCH) $$@ endef # 注册需要管理的模块 $(call GEN_MODULES,module_A module_B module_C) $(call GEN_MODULES,module_D)
优化点说明
- 省去了中间文件
MODULES_TO_GENERATE的生成和后续解析步骤,所有逻辑在同一个recipe中完成 - 直接利用shell的
sort -u完成输入文件去重,不需要额外处理 - 逻辑和原有实现兼容,不需要改动你已经定义好的
MODULE_INPUT_FILES配置
内容的提问来源于stack exchange,提问作者vjalle
相关产品推荐
相关产品推荐

