Отложить обязательное расширение до окончания целевого расширения - PullRequest
0 голосов
/ 27 сентября 2019

Изменить Я расширил Makefile.

Возьмите следующий make-файл:

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).Более того, я хочу иметь возможность вводить все и затем запускать несколько разных целей, каждая со своими собственными переменными, такими как $ (TOPLEVEL).

Способ сделать это - создать новое правило для каждой цели в$ (ALLTARGETS), но поскольку работа для каждой цели в точности одинакова, я хотел бы сделать это только с одной целью.Возможно ли это?

Ответы [ 2 ]

0 голосов
/ 27 сентября 2019

Вы можете сделать это, если используете GNU make с вторичным расширением .

. В вашем примере вы должны использовать:

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

Обратите внимание надополнительные $ экранирование в списке предпосылок.

0 голосов
/ 27 сентября 2019

Вы, кажется, смущены.Я в замешательстве.

multishot_timer: TOPLEVEL := $(MULITSHOT_TIMER_TOPLEVEL)

Это целевая переменная .${TOPLEVEL} будет иметь значение multishot_timer_top.cpp только тогда, когда make расширяет рецепт для multishot_timer или рецепты для любого из его предварительных условий .Это не тот случай, когда 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 $@

Изменение рецепта в зависимости отtarget

Здесь много вариантов.Вот предложение для рассматриваемой проблемы:

В основном ${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.)

...