I'm using a Makefile to compile my Clean code. My Clean files have file names of the format *.icl
and are compiled to binaries with the same name but without .icl
. This is done with the rule:
$(EXE): % : %.icl | copy
$(CLM) $(CLM_LIBS) $(CLM_INC) $(CLM_OPTS) $@ -o $@
I would now like to add a rule which allows me to run a binary. Currently, I'm often doing
make some_module && ./some_module
I would like to have a make target which depends on the rule above and runs the module. However, the name of the module is already a target itself for compilation alone and I'd like to keep it that way. What I would like is a target with two words that I can call with make run some_module
which then depends on the rule above and runs ./some_module
afterwards.
Is it possible to create targets with multiple words?
I tried to make a rule (now still without dependency) with the following:
run $(EXE):
./$@
Running make run some_module
results in many recipes being 'overridden' and 'ignored' and finally ./run
not existing.
Makefile:24: warning: overriding recipe for target 'tut7_2_2'
Makefile:21: warning: ignoring old recipe for target 'tut7_2_2'
Makefile:24: warning: overriding recipe for target 'support_check'
Makefile:21: warning: ignoring old recipe for target 'support_check'
[...]
Makefile:24: warning: overriding recipe for target 'drawingframe'
Makefile:21: warning: ignoring old recipe for target 'drawingframe'
./run
/bin/bash: ./run: No such file or directory
Makefile:24: recipe for target 'run' failed
make: *** [run] Error 127
Best Answer
You can inspect
MAKECMDGOALS
to detect the presence of one goal while building another goal. Either make the%: %.icl
run detect the presence of therun
goal, or make therun
goal inspect what executables are mentioned as targets. If you pass more than one executable as a target, the first method causes each to be run right after it's built, while the second causes all the runs to happen at the end.The downside of this approach is that it doesn't scale well with other features. For example, if you define a target with multiple executables as dependencies, the method with a
run
target won't work.Here
make released run
won't run anything.What I normally do for this case is to define a “run” target for each executable. This keeps each target expressed as a single word, which is a major advantage. It's simple and doesn't break other features.
Then I run
make {foo,bar}.run
if I want to built and testfoo
andbar
, ormake all.run
to build and run them all.