There are several *.dot files and I make graph images from them. A couple of graphs require special options, and the rest are converted by one template command.

Makefile:

 DOTS = ex1.dot ex2.dot ex4.dot IMGS = $(DOTS:.dot=.png) all: ex1.png ex2.png ex3.png ex4.png ex1.png: ex1.dot dot -Tpng -o ex1.png ex1.dot ex2.png: ex2.dot dot -Tpng -o ex2.png ex2.dot ex3.png: ex3.dot dot -Kfdp -n -Tpng -o ex3.png ex3.dot ex4.png: ex4.dot dot -Tpng -o ex4.png ex4.dot ... 

And here the situation may change. Some .dot files may require a special option, some may not need to be converted. I would not want to write and delete goals again and again, but I would just like to change a couple of variables.

PS Can you advise another tool (preferably programmable as, for example, SCons )?

    1 answer 1

    I abstract file names a bit so that all these dot/png not confusing.

    So, we have a1.src a2.src a3.src a4.src , and we need to convert them (in a known way) to a1.res a2.res a3.res a4.res .

    First, we list the source files:

     srcs=a1.src a2.src a3.src a4.src 

    and automatically generate a list of result files from them, replacing the .src suffix with .res :

     results=$(srcs:.src=.res) 

    The first of the goals (the word all as the first goal is just a tribute to the tradition, you can use an arbitrary name) indicates that to accomplish it you need to “collect” a1.res a2.res a3.res a4.res (this list is stored in the variable $(results) :

     all: $(results) 

    and then you need a rule for “assembling” the *.res file from the “eponymous” *.src file:

     %.res: %.src 

    below the rule, we indicate the “recipe” for the assembly (here is a fake recipe, which simply prints a string on the screen, in reality, you will need to enter the appropriate command):

      @echo 'собираем $@ из $<' 

    get this file:

     srcs=a1.src a2.src a3.src a4.src results=$(srcs:.src=.res) all: $(results) %.res: %.src @echo 'собираем $@ из $<' 

    check by interpreting it with the make program:

     $ make собираем a1.res из a1.src собираем a2.res из a2.src собираем a3.res из a3.src собираем a4.res из a4.src 

    and now, as if, one of the commands, for example, for assembling a3.res , is replaced with something else?

    elementary - you need to add another rule. for this very purpose ( a3.res ):

     a3.res: a3.src @echo 'собираем $@ из $< по-особому' 

    now the output of the make program will be slightly different:

     $ make собираем a1.res из a1.src собираем a2.res из a2.src собираем a3.res из a3.src по-особому собираем a4.res из a4.src 

    and if it is also “special”, it is necessary to “collect” and, for example, a2.res ?

    need to add another rule. for this very purpose ( a2.res ):

     a2.res: a2.src @echo 'собираем $@ из $< по-особому' 

    but we have duplication: for the purposes of a2.res and a3.res , the same recipe. Is it possible to do without duplication?

    of course it is possible. but you have to use a little bit of street magic.

    First, we will slightly rewrite the “universal” rule of “assembly” (removing the additional ones for a2.res and a3.res ), adding a substitution to an a2.res variable (for example, $(subs) ):

     %.res: %.src @echo 'собираем $@ из $< $(subs)' 

    secondly, add a list of goals that should be collected "in a special way":

     list=a2.res a3.res 

    and thirdly, we write the implementation of the “magic” variable $(subs) (the “magic exposure session” will be below):

     subs=$(if $(filter $@,$(list)),по-особому,обычным образом) 

    you end up with this file:

     srcs=a1.src a2.src a3.src a4.src results=$(srcs:.src=.res) list=a2.res a3.res subs=$(if $(filter $@,$(list)),по-особому,обычным образом) all: $(results) %.res: %.src @echo 'собираем $@ из $< $(subs)' 

    from which, when interpreted, we get the following conclusion:

     $ make собираем a1.res из a1.src обычным образом собираем a2.res из a2.src по-особому собираем a3.res из a3.src по-особому собираем a4.res из a4.src обычным образом 

    magic exposure session

    • the $(if выражение,если да,если нет) function $(if выражение,если да,если нет) (option without “if not”: $(if выражение,если да) checks the “expression” for emptiness: if not empty, then returns “if yes”, otherwise - if no "(or nothing in the version without" if not ")
    • The $(filter набор слов,текст) function $(filter набор слов,текст) returns all the words from the “word set” that appear in the “text” (if none were encountered, it will return an empty string).
    • All automatic variables can be seen in the list of functions, variables and directives (in particular, $@ and $< used above).