Я пытаюсь написать Makefile, который создает выходные данные PDF с помощью LaTeX, используя Latexmk. Выходные данные имеют в основном одно и то же правило с разными предварительными условиями, поэтому я попытался обобщить свой исходный Makefile, используя вторичное расширение GNU Make. (Я также создал .PHONY
цели, также с дополнительным расширением, чтобы сделать их более удобными для пользователя.) Однако это приводит к тому, что обязательные правила всегда выполняются, даже если в них нет необходимости. . К счастью, Latexmk достаточно умен, чтобы избежать ненужной работы, но мне интересно, делаю ли я что-то не так...
Чтобы попытаться абстрагироваться от того, что я пытаюсь:
,-> foo -> build/foo.pdf
all -{
`-> bar -> build/bar.pdf
То есть цель all
строит foo
и bar
. Эти цели открывают соответствующий PDF-файл, для которого предварительное условие равно build/X.pdf
(где X
равно foo
или bar
). Это подлинные цели, которые создают соответствующий файл PDF.
Вот что я придумал:
TARGETS = foo bar
BUILD_DIR = build
OUTPUTS = $(TARGETS:%=$(BUILD_DIR)/%.pdf)
commonSRC = src/preamble.tex src/header.tex # etc...
fooSRC = src/foo.tex $(commonSRC) # etc...
barSRC = src/bar.tex $(commonSRC) # etc...
all: $(TARGETS)
.SECONDEXPANSION:
$(TARGETS): $(BUILD_DIR)/[email protected]
open $<
# FIXME This isn't quite right: This rule is still getting called by the
# above rule, even when it doesn't need to be. Latexmk is clever enough
# not to do any extra work, but it shouldn't run at all.
.SECONDEXPANSION:
$(OUTPUTS): $$($$(subst .pdf,SRC,$$(@F))) $(BUILD_DIR)
latexmk -outdir=$(BUILD_DIR) -auxdir=$(BUILD_DIR) -pdf $<
$(BUILD_DIR):
mkdir $@
clean:
rm -rf $(BUILD_DIR)
.PHONY: all $(TARGETS) clean
Просто для ясности: правило для build/X.pdf
должно выполняться всякий раз, когда файлы, перечисленные в XSRC
(опять же, где X
— это foo
или bar
), новее, чем PDF-файлы, или PDF-файлы не существуют; но он не должен работать иначе.