makefile - 将先决条件扩展推迟到目标扩展之后
问题描述
编辑我扩展了 Makefile。
获取以下生成文件:
VERILATOR:=/usr/sbin/verilator
COMMONPREPARAMS:=-Wall
COMMONPOSTPARAMS:=--trace
# Multishot timer
MULTISHOT_TIMER_OBJDIR:=multishot_timer_dir
MULITSHOT_TIMER_VERILOG_FILES:=common/multishot_timer_tb.v common/multishot_timer.v
MULITSHOT_TIMER_TOPLEVEL:=multishot_timer_top.cpp
MULTISHOT_TIMER_TARGET:=$(MULTISHOT_TIMER_OBJDIR)/multishot
#incrementer
INCREMENTER_OBJDIR:=incrementer_dir
INCREMENTER_VERILOG_FILES:=common/incrementer.v
INCREMENTER_TOPLEVEL:=src/incrementer_top.cpp
INCREMENTER_TARGET:=$(INCREMENTER_OBJDIR)/incrementer
ALLTARGETS := $(MULTISHOT_TIMER_TARGET)
ALLOBJDIRS := $(MULTISHOT_TIMER_OBJDIR)
.PHONY: all multishot_timer incrementer
all: multishot_timer incrementer
multishot_timer: OBJDIR:=$(MULTISHOT_TIMER_OBJDIR)
multishot_timer: VERILOG_FILES:=$(MULITSHOT_TIMER_VERILOG_FILES)
multishot_timer: TOPLEVEL:=$(MULITSHOT_TIMER_TOPLEVEL)
multishot_timer: $(MULTISHOT_TIMER_TARGET)
incrementer: OBJDIR:=$(INCREMENTER_OBJDIR)
incrementer: VERILOG_FILES:=$(INCREMENTER_VERILOG_FILES)
incrementer: TOPLEVEL:=$(INCREMENTER_TOPLEVEL)
incrementer: $(INCREMENTER_TARGET)
$(ALLTARGETS): $(TOPLEVEL) $(VERILOG_FILES)
$(VERILATOR) $(COMMONPREPARAMS) -cc $(VERILOG_FILES) --exe $(TOPLEVEL) -o $@
我的实际问题是 $(ALLTARGETS) 的先决条件评估得太早,因此该规则永远不会有任何先决条件。
我想将 ALLTARGETS 规则的先决条件的评估推迟到目标先决条件评估之后,因为那是声明 $(TOPLEVEL) 等变量的地方。此外,我希望能够键入 all 然后启动多个不同的目标,每个目标都有自己的变量,如 $(TOPLEVEL)。
一种方法是为 $(ALLTARGETS) 中的每个目标创建一个新规则,但由于每个目标的工作完全相同,我想只使用一个目标。可能吗?
解决方案
你似乎很困惑。我很困惑。
multishot_timer: TOPLEVEL := $(MULITSHOT_TIMER_TOPLEVEL)
这是一个特定于目标的变量。
仅当make扩展 的配方或其任何先决条件${TOPLEVEL}
的配方时才会具有该值。当make扩展这一行时,情况并非如此:multishot_timer_top.cpp
multishot_timer
$(ALLTARGETS): $(TOPLEVEL) $(VERILOG_FILES)
使固定?只需制作TOPLEVEL
一个普通的全局变量。
TOPLEVEL := $(MULITSHOT_TIMER_TOPLEVEL)
我认为你有一个更大的模式,你没有告诉我们。
编辑
好的。有两件事要管理。
依赖项
一个目标可以有许多依赖行,但其中只有一个可以有一个配方。
multishot_timer: common/multishot_timer_tb.v common/multishot_timer.v
incrementer: common/incrementer.v
multishot_timer incrementer:
${VERILATOR} ${COMMONPREPARAMS} -cc $^ --exe ${TOPLEVEL} -o $@
根据目标更改配方
这里有很多选择。以下是针对当前问题的建议:
基本上 ${TOPLEVEL}
是不同的取决于$@
是multishot_timer
或incrementer
。
TOPLEVEL<multishot_timer> := multishot_timer_top.cpp
TOPLEVEL<incrementer> := src/incrementer_top.cpp
TOPLEVEL = ${TOPLEVEL<$@>}
好的。可能不值得定义TOPLEVEL
(注意=
,它是一个惰性变量很重要),${TOPLEVEL<$@>}
直接在配方中使用。
加分项:目标列表
获取表单的所有变量名TOPLEVEL<%>
,去掉TOPLEVEL<
前缀和>
后缀。
ALLTARGETS := $(patsubst TOPLEVEL<%>,%,$(filter TOPLEVEL<%>,${.VARIABLES}))
(注意我如何${…}
为变量和$(…)
函数保留。我发现它有帮助。YMMV。)
推荐阅读
- c++ - 如果读取文件时间超过 5 分钟,则停止 (C++ std::ifstream)
- django - 在 Django ModelForm 中使用 Postgres 默认值
- c# - 使用 App.Config 在 MVC 中共享库
- pyspark - Glue AWS:调用 o60.getDynamicFrame 时发生错误
- java - 在 JWT/JSON 中添加字节数组
- javascript - IMG 元素内的 SVG(作为数据 URL)与 DIV 内的 SVG - 性能差异
- mysql - MySQL 中的排除
- c++ - 游戏功能和阻塞接受,socket c++
- c# - 如何在数据库 C# 的数据网格视图中显示 Double 类型的数据?
- c++ - C++ 的新手,对这个结果感到困惑“没有合适的构造函数可以从”const char [18] 转换为“SimpleWordSearch”