You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 01:36:08