This is my problem: I can build a binary in one of two ways and each has checks that can be done on them (under their own make targets); I would like a check
target to run whichever target is appropriate dependent on which build target was run under a previous call of make
: can this be done internally without touching files or some other "external" way of recording which build target was run?
An illustration may help:
.PHONY: all modified
all: $(obj)
$(CXX) ... -o $(BIN)
modified: $(obj) $(extra_objs)
$(CXX) ... -o $(BIN)
.PHONY: check check_all check_modified
check_all: all
...
check_modified: modified
...
check:
# ??? Some makefile variable I don't know about?
so that I can ask this of the shell:
make X # <-- X = {all, modifie开发者_StackOverflow社区d}
... # <-- this is important: this is not a question of target dependency
make check # <-- have `check' run `check_X' target
I figure that the only way for a particular make
call to know which target was run before is by determining if it needs updating or not. Id est, if all
is up-to-date, then run check_all
, if modified
is up-to-date then run check_modified
, and default to check_all
.
So, can I ask make
"internally" whether target X would be updated if I asked to run it? "Internal" meaning no calling of $(MAKE) -n
, or no touch Y
and then asking the shell if [ -f Y ] ...
.
As you can see, it's not quite a question of dependency because that, clearly, will build the dependency when all I want to do is check to see whether it has been run before. So, any ideas or (alternative suggestions)?
UPDATE:
OK, I guess the answer is: No. The best I can probably do is this:
.PHONY: check
check: $(if $(wildcard $(firstword $(extra_objs))),check_modified,check_all)
Obviously, this method is functionally the same as creating a file when creating one of the targets and then checking for that, but in this case the file I'm checking for is created anyway and unique to the target that creates it, which I suppose makes it slightly less ugly.
(Note: I ran into the problem that:
.PHONY: check
check:
$(MAKE) -q modified && $(MAKE) check_modified || $(MAKE) check_all
won't exactly work for the code I had above because all
and modified
are phony and so will always need updating as far as make
is concerned, so that kind of rules that one out! But, it's a simple and concise way of solving the problem for targets named after the file they'd create so I'll mention it for reference.)
Maybe spawning another make internally with the -q flag helps?
Usage: make [options] [target] ...
Options:
[...]
-q, --question Run no commands; exit status says if up to date.
You could record the build type in a file and read that back later to pick the right "check" target like so:
all: $(obj)
$(CXX) ... -o $(BIN)
echo $@ > $(BIN)-kind
modified: $(obj) $(extra_objs)
$(CXX) ... -o $(BIN)
echo $@ > $(BIN)-kind
check: $(if $(wildcard $(BIN)-kind),check_$(shell cat $(BIN)-kind))
To answer the title of your question, see double colon rules. Quoting the manual:
Double-colon rules are somewhat obscure and not often very useful; they provide a mechanism for cases in which the method used to update a target differs depending on which prerequisite files caused the update, and such cases are rare.
Sounds (almost) just what you are after.
精彩评论