сделать .SECONDEXPANSION рецепт выполнить дважды - PullRequest
0 голосов
/ 25 декабря 2018

Используя GNU make, я пытаюсь решить проблему, аналогичную make recipe execute дважды - то есть дважды запустить рецепт Makefile.В моем случае, однако, рецепт запускается с целью .SECONDEXPANSION, и два разных запуска будут вызываться с разными параметрами, чтобы генерировать разные версии выходного файла из одного и того же входного файла.То есть для входного файла foo этот примерный Makefile должен вызываться через make foo.pdf или make foo.expanded.pdf для создания одного файла .pdf или make all для построения обоих файлов .pdf:

.PHONY: all

all: foo.pdf foo.expanded.pdf

.SECONDEXPANSION:
%.expanded.pdf %.pdf: %
    @echo building $(basename $@)

Из двух решений, приведенных в этом ответе, первое не подходит, потому что всегда выполняет правило дважды;Я хочу, чтобы он запускался дважды, когда пользователь запрашивает его.

Второе опубликованное решение - это концептуально то, что я искал и реализовало в приведенном выше примере Makefile, только с небольшой проблемой, которая не работает: хотя цель all перечисляет оба файла .pdf как зависимости, при запуске make all создается только один файл.

Существует ли способ заставить GNU make создавать два разных файла, используя одно и то же правило вa .SECONDEXPANSION?

РЕДАКТИРОВАТЬ: Уточнил в описании проблемы, что один и тот же входной файл используется для построения обеих версий выходного файла, и измененный образец Makefile для включения этой зависимости.

РЕДАКТИРОВАТЬ: Я хотел бы, чтобы решение было как можно более масштабируемым;то есть, он должен работать, если входное имя файла содержит точки, указание дополнительного выходного файла foo.reduced.pdf должно требовать только корректировки целей и рецепта в зависимости от ситуации и т. д. Это ограничивает выполнение строковой операции, которая основывается на именах файлов, которые выглядят точно так, как указано в этом узкомпример (например, изменение правила на %.pdf: $$(firstword $$(subst ., ,$$*)) завершится неудачно, если входной файл может быть foo или foo.bar).

Ответы [ 2 ]

0 голосов
/ 25 декабря 2018

Вы, вероятно, ищете Значения переменной для конкретного шаблона .Давайте предположим, что ваш рецепт зависит от переменной make с именем BUILDFLAGS, которая принимает значение normal по умолчанию и special для целей " extended ".Затем этот Makefile:

BUILDER    := builder
BUILDFLAGS := normal

.PHONY: all

all: foo.pdf foo.expanded.pdf

%.expanded.pdf: BUILDFLAGS := special

%.pdf:
    $(BUILDER) $(BUILDFLAGS) $@

должен делать то, что вы хотите, с тем же правилом для всех целей, плюс одно объявление значения переменной для конкретного шаблона.Замените builder, normal и special тем, что имеет смысл в вашем случае.Демо:

$ make foo.pdf
builder normal foo.pdf
$ make foo.expanded.pdf
builder special foo.expanded.pdf
$ make
builder normal foo.pdf
builder special foo.expanded.pdf
0 голосов
/ 25 декабря 2018

Ваша проблема не имеет ничего общего с .SECONDEXPANSION.Вы можете просто отбросить это, и проблема будет той же.

Ваша проблема в том, что вы используете правило шаблона с несколькими шаблонами целей и ожидаете, что оно работает аналогично явному правилу с несколькими целями.Но это не так (и на самом деле вы не можете иметь правило с шаблоном и явными целями).

Для правила шаблона с несколькими шаблонами целей Make сопоставляет один и тот же шаблон всем %, включая несколькораз в целях, а затем предполагает, что он просто должен выполнить рецепт с этим шаблоном один раз, и он сделает все совпадающие цели.

В вашем случае лучший способ - это использовать несколько правил (я изменилваш рецепт, потому что использование echo в качестве рецепта Make - плохая идея):

.PHONY: all
all: foo.expanded.pdf foo.pdf 

RECIPE = touch $@

%.expanded.pdf:
    $(RECIPE)

%.pdf:
    $(RECIPE)
...