Makefile 使先决条件扩展延迟到目标扩展之后

Makefile 使先决条件扩展延迟到目标扩展之后,makefile,gnu-make,Makefile,Gnu Make,编辑我扩展了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_

编辑我扩展了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为
multishot\u timer
扩展配方或其任何先决条件的配方时,
${TOPLEVEL}
将仅具有值
multishot\u timer\u top.cpp
。make扩展此行时并非如此:

$(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\u定时器
还是
递增器

TOPLEVEL<multishot_timer> := multishot_timer_top.cpp
TOPLEVEL<incrementer> := src/incrementer_top.cpp
TOPLEVEL = ${TOPLEVEL<$@>}

(注意我是如何为变量保留
${…}
,为函数保留
$(…)
。我发现它有助于.YMMV。)

如果您使用GNU make,则可以使用

在您的示例中,您将使用:

.SECONDEXPANSION:
$(ALLTARGETS): $$(TOPLEVEL) $$(VERILOG_FILES)

注意先决条件列表中额外的
$
转义。

为了进一步解释我的意思,我在OP中做了一个更大的例子,但基本上:我有许多不同的可能设置,每个设置都有另一个重要变量的值,但它们都有相同的创建可执行文件的一般规则。我尝试实现了这一点,但我似乎做了错事或被误解了。我无法得到正确展开变量的最终规则。你能给出一个更详细的例子吗?两个提示:运行make with
——警告未定义的变量并研究输出。还要注意,您必须正确使用
=
:=
。它们不一样。
.SECONDEXPANSION:
$(ALLTARGETS): $$(TOPLEVEL) $$(VERILOG_FILES)