Make: make all that fit rule
I’m trying to learn makefiles. I have the following 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
As you can see, all three prerequisites are directories; rst
, ctx
and pdf
. The prerequisites recurse down to “rst”. I’ll edit files in ctx
manually and files in rst
, which get converted into files in ctx
.
What should I开发者_如何学JAVA do to make make
make pdf
:) the following way:
- Look if something in
ctx
and/or something inrst
has changed. - If only something in
ctx
was changed, makepdf
, else makectx
. - If something in
rst
has changed, use the first rule to make the corresponding file inctx
, then makectx
and then makepdf
.
My problem is now that I don’t know how to tell make
“In order to make ctx
when files in rst
are changed, use the first rule (ctx/%.ctx: ctx/%.rst
) to make each matching file in ctx
from the corresponding one in rst
”
Your question is a little unclear (e.g. you're confusing the directory pdf/
with the makefile target pdf
), but this should do what I think you want:
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
And the reason a plain make
builds pdf
is that when you invoke Make without a target it chooses the default target, which is the first target (unless you do some tinkering), which in this case is pdf
. (The pattern rule doesn't count.)
EDIT:
Now that I think of it, what I posted above is kind of clunky, and it will always run the pdf
rule, even if nothing has changed. This is somewhat better:
# 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
I made ctx
PHONY because I was wrestling with the case when the directory exists, but the rule should still be run. It turned out to be unnecessary (as you might guess from the fact that I didn't catch the typo).
And yes, prerequisites are the names of files or dirs (or PHONY
targets). My point was that phrases like "make pdf
" are a little confusing if pdf is both a directory and a rule which builds it (and does other things).
The problem with using directories as targets is that they don't obey intuitive rules of modification time: if you modify a file in a directory, the directory's mod time doesn't change. It's also tricky to change the mod time deliberately, since touch
doesn't do it (don't ask me why it's legal to touch
a directory if it does nothing). It can be done, e.g. by adding and deleting a dummy file, but it's ugly.
精彩评论