如何在Makefile中遍历两个列表?实现多模块跨路径编译
解决Makefile多模块多路径自动生成目标的问题
核心思路
Makefile的foreach无法直接同时遍历两个列表,需要通过索引遍历的方式,把模块名和对应路径一一配对。具体来说,先获取模块列表的长度,然后遍历每个索引,分别取出对应位置的模块名和路径,再传入模板。
修改后的完整代码
MODULE_NAMES = exact_adder_1bit exact_multiplier_2bit MODULE_PATHS = adder/exact_adder_1bit/ multiplier/ # 定义支持路径参数的模板,$(1)=模块名,$(2)=模块路径 define MODULE_TEMPLATE $(1)_tb.vcd: $(1) vvp $$< $(1).vvp: iverilog -o $(1) $(2)$(1)_tb.v $(2)$(1).v vvp $(1) sim_$(1): iverilog -o $(1) $(2)$(1)_tb.v $(2)$(1).v vvp $(1) endef # 通过索引遍历配对两个列表 $(foreach idx,$(shell seq 1 $(words $(MODULE_NAMES))), \ $(eval $(call MODULE_TEMPLATE, \ $(word $(idx),$(MODULE_NAMES)), \ $(word $(idx),$(MODULE_PATHS)) \ )) \ )
关键修改点说明
- 模板适配路径:在模板里的文件引用前加上
$(2),也就是对应模块的路径,这样就能找到不同目录下的.v文件。 - 索引遍历实现配对:
$(words $(MODULE_NAMES))获取模块总数;$(shell seq 1 N)生成从1到N的索引序列;$(word $(idx),$(MODULE_NAMES))取出第idx个模块名,$(word $(idx),$(MODULE_PATHS))取出对应位置的路径;- 把这两个参数传入
MODULE_TEMPLATE,实现一一配对。
替代方案:使用配对列表
如果觉得索引遍历麻烦,也可以直接定义一个包含模块名和路径的配对列表,再拆分:
# 用冒号分隔模块名和路径,每个配对作为一个元素 MODULES = exact_adder_1bit:adder/exact_adder_1bit/ exact_multiplier_2bit:multiplier/ define MODULE_TEMPLATE $(1)_tb.vcd: $(1) vvp $$< $(1).vvp: iverilog -o $(1) $(2)$(1)_tb.v $(2)$(1).v vvp $(1) sim_$(1): iverilog -o $(1) $(2)$(1)_tb.v $(2)$(1).v vvp $(1) endef # 遍历配对列表,拆分出模块名和路径 $(foreach mod,$(MODULES), \ $(eval $(call MODULE_TEMPLATE, \ $(firstword $(subst :, ,$(mod))), \ $(lastword $(subst :, ,$(mod))) \ )) \ )
这个方案通过subst :, ,$(mod)把配对元素拆分成两个部分,再用firstword和lastword分别取出模块名和路径,逻辑更直观。
内容的提问来源于stack exchange,提问作者Ronnie Coleman
相关产品推荐
相关产品推荐

