Question

I have a shell program that generates 3 files from one source file. For instance I can have 'makedocumentation' that take in input foo.tex and generates foo.pdf, foo.dvi and foo.ps.

Because of performances issues I have to call my Makefile with the option -j8.

With this example file:

names = a b 
src = $(addsuffix .def,$(names))

a = $(patsubst %.def,%.inc,$(src))
b = $(patsubst %.def,%.asm,$(src))
c = $(patsubst %.def,%.h,$(src))

obj = $(a) $(b) $(c)

command= cp $(1) $(basename $(1)).inc; \
         cp $(1) $(basename $(1)).asm; \
         cp $(1) $(basename $(1)).h

all: $(obj)

init: clean $(src) 

$(src): %:
    touch $@

$(a): %.inc: %.def
    $(call command, $<)

$(b): %.asm: %.def
    $(call command, $<)

$(c): %.h: %.def
    $(call command, $<)

clean: 
    -rm -f *.def
    -rm -f *.inc
    -rm -f *.asm
    -rm -f *.h  

If I run it without -j I get:

$ make
cp  a.def a.inc;  cp  a.def a.asm;  cp  a.def a.h
cp  b.def b.inc;  cp  b.def b.asm;  cp  b.def b.h

And in the other case:

$ make -j8
cp  a.def a.inc;  cp  a.def a.asm;  cp  a.def a.h
cp  b.def b.inc;  cp  b.def b.asm;  cp  b.def b.h
cp  a.def a.inc;  cp  a.def a.asm;  cp  a.def a.h
cp  b.def b.inc;  cp  b.def b.asm;  cp  b.def b.h
cp  a.def a.inc;  cp  a.def a.asm;  cp  a.def a.h
cp  b.def b.inc;  cp  b.def b.asm;  cp  b.def b.h

We can observe that in parallel mode, make regenerates files that already exists.

I would like to avoid it...

I also tried something like:

a.inc a.asm a.h: a.def
   command $<

But I don't get any better result.

Any help ?

Was it helpful?

Solution

As you wrote the original makefile you haven't told make that the output files share any relationship so it can't know that they've already been built and so it has to try to build each one each time.

Your modified idea is the right idea but unforunately make doesn't interpret that sort of definition as indicating that the single command will generate all the files and instead it sees it as a way to build each individual file (written in a compact shorthand).

A rule with multiple targets is equivalent to writing many rules, each with one target, and all identical aside from that.

The only way to tell make that N output files are generated from 1 rule body is with multiple pattern rules

Pattern rules may have more than one target. Unlike normal rules, this does not act as many different rules with the same prerequisites and recipe. If a pattern rule has multiple targets, make knows that the rule's recipe is responsible for making all of the targets. The recipe is executed only once to make all the targets. When searching for a pattern rule to match a target, the target patterns of a rule other than the one that matches the target in need of a rule are incidental: make worries only about giving a recipe and prerequisites to the file presently in question. However, when this file's recipe is run, the other targets are marked as having been updated themselves.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top