這將是醜陋的,但它會工作。
因爲它往往是與製作,我們的問題分爲以下兩個問題:
1.構建一個目標列表
2.建立他們
假設我們有五個MD文件,這映射爲PDF文件(他們的名字我們不事先知道):
file1.md => file1-v1.pdf
file2.md => file2-v1.pdf
file3.md => file3-v1.pdf
file4.md => file4-v1.pdf
file5.md => file5-v1.pdf
我們不能用真實的輸出文件名作爲目標,因爲我們不知道他們事前,但我們看到五個輸入文件,並知道我們必須爲每個構建一個輸出文件。 現在,假目標名稱將做:
file1-dummy.pdf: file1.md
zap file1.md
當make執行這個規則,它產生的文件file1-v1.pdf
。它不生成名爲file1-dummy.pdf
的文件的事實令人不安,但不是一個嚴重的問題。我們可以把它變成一個模式規則:
%-dummy.pdf: %.md
zap $<
那麼我們要做的就是把現有的輸入文件(file1.md
,file2.md
...)的名單到的假目標(file1-dummy.pdf
,file2-dummy.pdf
名單, ...),並建立它們。到現在爲止還挺好。
但是假設一些輸出文件已經存在。如果file2-v2.pdf
已經存在 - 並且比file2.md
更新 - 那麼我們寧願Make不重建它(通過嘗試構建file2-dummy.pdf
)。在這種情況下,我們更希望file2-v2.pdf
是在目標列表中,用規則的工作是這樣的:
file2-v2.pdf: file2.md
zap $<
這不容易變成一個模式規則,因爲製作不處理通配符很好,並且不能用一個單詞來處理多個通配符,而不是沒有很多笨拙。但是有一種方法可以編寫一個覆蓋兩種情況的規則。首先要注意的是,我們可以用這個雜牌連字符之前獲得可變的部分:
$(basename $(subst -,.,$(VAR)))
有了這些,並與secondary expansion,我們可以寫一個模式規則,將與這兩種情況下工作,構建目標名單將利用它:
# There are other ways to construct these two lists, but this will do.
MD := $(wildcard *.md)
PDF := $(wildcard *.pdf)
PDFROOTS := $(basename $(subst -,.,$(basename $(PDF))))
MDROOTS := $(filter-out $(PDFROOTS), $(basename $(MD)))
TARGETS:= $(addsuffix -foo.pdf, $(MDROOTS)) $(PDF)
.SECONDEXPANSION:
%.pdf: $$(basename $$(subst -,., $$*)).md
# perform actions on $<
你願意有一些額外的標記文件嗎? – Beta
我會對有或沒有解決方案感興趣。很明顯,沒有更好的,但如果這是不可能的...... – wannymahoots