Reputation: 7673
I am trying to make a self-contained Makefile. My Makefile has a rule like the following one:
benchmark:
(something that depends on variable CXX)
That rule represents a single benchmark for a single compiler. I want to benchmark several compilers.
So what I would like to accomplish is the following without invoking $(MAKE)
recursively from inside the plot rule (pseudo-syntax):
plot: benchmark CXX=clang++ benchmark CXX=g++
(generate a plot)
Namely, I want this goal to depend on the prerequisite benchmark + one flag and treat both as two different prerequisites, even if they are the same rule.
Upvotes: 0
Views: 619
Reputation: 29375
As suggested by reinierpost you can define a pseudo target for each of your compilers. A pseudo-target is a target that has no real file production associated with it.
But as make is really happy with real file targets (targets are considered up-to-date or not based on their last modification date) you could also use your plot result as a target. And, as also suggested, you could wrap all this in a foreach
-eval
-call
construct to factorize your code. Something like:
COMPILERS = clang++ g++
define PLOT_compiler
plotfile-$(1): CXX = $(1)
plotfiles += plotfile-$(1)
endef
$(foreach compiler,$(COMPILERS),$(eval $(call PLOT_compiler,$(compiler))))
all: $(plotfiles)
plotfile-%:
<generate plot file using the CXX variable>
The foreach
-eval
-call
construct instantiates one set of make statements per compiler, as defined by the PLOT_compiler
variable.
If you prefer collecting all results in a single file named, let's say, plots.txt
you can instead use:
COMPILERS = clang++ g++
define PLOT_compiler
plotfile-$(1): CXX = $(1)
plotfiles += plotfile-$(1)
endef
$(foreach compiler,$(COMPILERS),$(eval $(call PLOT_compiler,$(compiler))))
plots.txt: $(plotfiles)
cat $(plotfiles) > $@
plotfile-%:
<generate plot file using the CXX variable>
clean:
rm -f $(plotfiles)
ultraclean:
rm -f $(plotfiles) plots.txt
The clean
and ultraclean
targets will help you keeping your workspace clean. You can easily test all this by replacing the <generate plot file using the CXX variable>
recipe by echo $(CXX) > $@
, and:
make
make clean
cat plots.txt
Upvotes: 1
Reputation: 8611
Assuming GNU Make, I think the logic you're looking for can be expressed in this way:
CXXES := clang++ g++
benchmark: $(CXXES:%=benchmark-%)
Then have a single rule to generate the benchmarks:
benchmark-%:
# generate a plot using $(CXX), which will be equal to $@
or multiple ones if your plot generation rules are compiler specific:
benchmark-clang++: CXX = clang++
# generate a plot using $(CXX)
(...)
benchmark-g++: CXX = g++
# generate a plot using $(CXX)
(...)
It would be better to identify output files (plots?) whose file names depend on the value of $(CXX)
and use those as intermediate targets.
Upvotes: 1