我正在尝试学习makefile。 我有以下Makefile:
ctx/%.ctx: rst/%.rst
texlua rst_parser.lua $< $@
pdf: ctx
mkdir -p pdf
cd pdf; context ../ctx/main.ctx
ctx: rst
mkdir -p ctx
.PHONY: clean
clean:
rm -f pdf/*.log pdf/*.aux pdf/*.pgf pdf/*.top pdf/*.tuc
如您所见,所有三个先决条件都是目录; rst
,ctx
和pdf
。先决条件递归到“rst”。我将手动编辑ctx
中的文件和rst
中的文件,这些文件将转换为ctx
中的文件。
我应该如何通过以下方式使make
成为pdf
:):
ctx
中的某些内容和/或rst
中的内容是否已更改。ctx
中的内容,请创建pdf
,否则生成ctx
。rst
中的内容发生了变化,请使用第一条规则在ctx
中制作相应的文件,然后制作ctx
,然后制作pdf
。现在我的问题是我不知道如何告诉make
“为了在ctx
中的文件发生更改时rst
,请使用第一条规则({{1 } {}使ctx/%.ctx: ctx/%.rst
中的每个匹配文件来自ctx
“
答案 0 :(得分:1)
您的问题有点不清楚(例如,您将目录pdf/
与makefile目标pdf
混淆),但这应该是我认为您想要的:
TARGETS := $(wildcard rst/*.rst)
TARGETS := $(patsubst rst/%.rst,%,$(TARGETS))
ctx/%.ctx: rst/%.rst # I assume you didn't mean ctx/%.rst
texlua rst_parser.lua $< $@
pdf: ctx
mkdir -p pdf
cd pdf; context ../ctx/main.ctx
.PHONY:cxt
ctx: $(patsubst %,ctx/%.ctx, $(TARGETS))
mkdir -p ctx
普通make
构建pdf
的原因是,当你调用没有目标的Make时,它选择默认目标,这是第一个目标(除非你做一些修补),在此案例是pdf
。 (模式规则不计算在内。)
修改:
现在我想到了,我上面发布的内容有点笨拙,即使没有任何改变,也会始终运行pdf
规则。这有点好:
# You're right, this is better.
CTX_TARGETS := $(patsubst rst/%.rst,ctx/%.ctx, $(wildcard rst/*.rst))
pdf: $(CTX_TARGETS)
mkdir -p pdf
cd pdf; context ../ctx/main.ctx
$(CTX_TARGETS): ctx/%.ctx: rst/%.rst ctx
texlua rst_parser.lua $< $@
ctx:
mkdir -p ctx
我做了ctx
PHONY,因为当目录存在时,我正在努力解决这个问题,但仍应运行规则。事实证明这是不必要的(正如你可能从我没有发现错字的事实中猜到的那样)。
是的,先决条件是文件或目录(或PHONY
目标)的名称。我的观点是,如果pdf既是目录又是构建它的规则(以及做其他事情),那么像“make pdf
”这样的短语会有点混乱。
使用目录作为目标的问题是它们不遵守修改时间的直观规则:如果修改目录中的文件,目录的mod时间不会改变。故意改变模拟时间也很棘手,因为touch
没有这样做(如果它什么也没做的话,不要问我为什么touch
目录是合法的。它可以完成,例如,通过添加和删除虚拟文件,但它很难看。