tags:

views:

60

answers:

2

Hi,

I looking to optimize an existing Makefile. It's used to create multiple plots (using Octave) for every logfile in a given directory using an scriptfile for every plot which takes a logfilename as an argument. In the Moment, I use one single rule for every kind of plot available, with a handwritten call to Octave, giving the specific scriptfile/logfile as an argument.

It would be nice, if every plot has "his" octave-script as a dependency (plus the logfile, of course), so only one plot is regenerated if his script is changed.

Since I don't want to type that much, I wonder how I can simplifiy this by using only one general rule to build "a" plot?

To make it clearer:

  • Logfile: "$(LOGNAME).log"
  • Scriptfile: "plot$(PLOTNAME).m" creates "$(LOGNAME)_$(PLOTNAME).png"

The first thing I had in mind:

%1_%2.png: %1.log
    $(OCTAVE) --eval "plot$<2('$<1')"

But this seems not to be allowed. Could someone give me a hint?

A: 

Pattern rules can use only 1 pattern (i.e. you cannot have %1 and %2, just %).

Therefore, depending on the number of PLOTNAME and LOGNAME you have, choose the smallest and write as many pattern rules as needed.

%_plot1.png: %.log
        $(OCTAVE) --eval "plot1('$*')"

If you do not want to write as many rules as you have different plots (or logs), you can use a double Makefile mechanism. In the sub-Makefile, use the above command, but use a parameter for the plot name. In a master Makefile, call it with the various values of the plotname you want.

Makefile.sub:

%_$(PLOTNAME).png: %.log
        $(OCTAVE) --eval "plot$(PLOTNAME)('$*')"

Makefile:

all:
        $(MAKE) PLOTNAME=plot1 -f Makefile.sub
        $(MAKE) PLOTNAME=plot2 -f Makefile.sub
        $(MAKE) PLOTNAME=plot3 -f Makefile.sub

It saves writing the rule many times (and saves updating it as many times when needed), but then requires special handling for other targets than all, such as clean.

Didier Trosset
Hm, seems relatively complex, not like somehing I looked for. But I tried and it works, so thanks, anyways!
marvin2k
+1  A: 

It's pretty crazy that make doesn't support this directly, I need it all the time.

The technique I use at the moment (with GNU make) (building on Didier Trosset's example):

define OCT_template

all: %_$(1).png

%_$(1).png: %.log
    $$(OCTAVE) --eval "plot$(1)('$$*')"

endef

PLOT_NAMES = plot1 plot2 plot3

$(foreach p, $(PLOT_NAMES), \
  $(eval $(call OCT_template,$(p))) \
)

This is in the GNU make documentation.

reinierpost
oh, thanks a lot! Very helpfull. Works like a charm -- just for the sake of making the Makefile smaller but more complicated ;)
marvin2k