For loop through names in GNU make - for-loop

I have a bunch of .dot files (for example, a.dot, b.dot, c.dot) and I want to compile them to .png files with neato. Currently, the make command I have to do that looks something like this:
neato -Tpng -o a.png a.dot
neato -Tpng -o b.png b.dot
neato -Tpng -o c.png c.dot
Obviously, this is completely non-scalable, and I'd like to write something that will take every file with a .dot extension, and compile it to an equivalently-named .png file. I'm not sure how to write such a loop in make - any help would be appreciated.

This is pretty much basic make 101:
SRCS = a.dot b.dot c.dot
OBJS = $(SRCS:%.dot=%.png)
all: $(OBJS)
%.png : %.dot
neato -Tpng -o $# $<
You don't do "loops" in make; you define targets and prerequisites.

Related

Makefile seems to take both inputs instead of one at a time

I have two files 1.gv and 2.gv which are Graphviz files.
I wrote this Makefile from what I could figure out:
DOT=dot
FORMAT=svg
SRC=$(wildcard *.gv)
OUT=$(subst .gv,.$(FORMAT),$(SRC))
all: $(OUT)
$(OUT): $(SRC)
$(DOT) -T$(FORMAT) $^ -o $#
.PHONY: clean
clean:
rm -f $(OUT)
The clean seems to work, the only problem seems to be is it runs:
dot -Tsvg 1.gv 2.gv -o 1.svg
dot -Tsvg 1.gv 2.gv -o 2.svg
instead of:
dot -Tsvg 1.gv -o 1.svg
dot -Tsvg 2.gv -o 2.svg
In your Makefile make sees that it needs all gv-files (SRC) to make one file: 1.gv (OUT) so in the loop the prerequisite changes $< but not the target $#.
You need to match a pattern and use patsubst instead of subst so OUT is a pattern of files.
I removed most variables for clarity. Feel free to add them back.
SRC = $(wildcard *.gv)
OUT = $(patsubst %.gv,%.svg,$(SRC))
%.svg: %.gv
dot -Tsvg $< -o $#
all: $(OUT)
.PHONY: clean
clean:
$(RM) *.svg

Makefile, rule for all rule patterns

Context
I am using the pattern rule
%.png: %.tex
compile.sh $<
to generate png files from all available (changed) tex files.
Problem
What I do not get right is that I want to use make all to do that for all of them at once.
all: *.tex
compile.sh $^
However, $^ seems to be always replaced by all tex files and not only the changed ones (obviously, the Makefile does not really know about the connection to the png files).
Not working alternative
Using
all: *.png
compile.sh $^
does not make sense when the png files do not exist yet, right?
Is there really some specific reason that you have to do them all with a single command? Why can't you just have all depend on all the .png files?
%.png: %.tex
compile.sh $<
TEXFILES := $(wildcard *.tex)
all: $(TEXFILES:.tex=.png)

makefile latex DVI=$(TEX:.tex=.dvi) meaning

I have a makefile for a Latex document which contains the following rules:
TEX=index.tex
DVI=$(TEX:.tex=.dvi)
PS=$(TEX:.tex=.ps)
PDF=$(TEX:.tex=.pdf)
all: images $(PDF)
images:
make -C $#
%.dvi: %.tex
latex $<
%.ps: %.dvi
dvips $<
%.pdf: %.ps
ps2pdf $<
what does the syntax DVI=$(TEX:.tex=.dvi) exactly do? how is it expanded? I tried to print the result with an echo but nothing is printed.
That line sets DVI to the same thing as TEX but substitutes .tex for .dvi

Makefile for dotfiles (graphviz)

As part of generating a PDF from a latex file, I got a makefile from tex.stackexchange.com.
# You want latexmk to *always* run, because make does not have all the info.
# Also, include non-file targets in .PHONY so they are run regardless of any
# file of the given name existing.
.PHONY: paper-1.pdf all clean
# The first rule in a Makefile is the one executed by default ("make"). It
# should always be the "all" rule, so that "make" and "make all" are identical.
all: paper-1.pdf
# CUSTOM BUILD RULES
# In case you didn't know, '$#' is a variable holding the name of the target,
# and '$<' is a variable holding the (first) dependency of a rule.
# "raw2tex" and "dat2tex" are just placeholders for whatever custom steps
# you might have.
%.tex: %.raw
./raw2tex $< > $#
%.tex: %.dat
./dat2tex $< > $#
# MAIN LATEXMK RULE
# -pdf tells latexmk to generate PDF directly (instead of DVI).
# -pdflatex="" tells latexmk to call a specific backend with specific options.
# -use-make tells latexmk to call make for generating missing files.
# -interaction=nonstopmode keeps the pdflatex backend from stopping at a
# missing file reference and interactively asking you for an alternative.
paper-1.pdf: paper-1.tex
latexmk -bibtex -pdf -pdflatex="pdflatex -interaction=nonstopmode" -use-make paper-1.tex
clean:
latexmk -bibtex -CA
My figures are .dot files that I turn into PNG files. I can make the PNGs with some basic shell commands, but that it doesn't make sense to use a shell script because you lose the advantages of make.
Here's what I've been trying after reading some documentation.
%.png: %.dot
dot -Tpng $(.SOURCE) -o $(.TARGET)
and
.dot.png:
dot -Tpng $(.SOURCE) -o $(.TARGET)
However, whenever I try to run the target directly the terminal prints is:
dot -Tpng -o
and it holds because it waits for input from STDIN because there was no input file.
If I try to invoke the rule by running make *.dot I get the output:
make: Nothing to be done for `figure-1a.dot'.
make: Nothing to be done for `figure-1b.dot'.
I'm clearly not understanding what I need to do. How do I get the makefile to take all the .dot files and create .png files every time I run through the creation of the PDF?
UPDATE: Here is another attempt I tried
graphs := $(wildcard *.dot)
.dot.png: $(graphs)
dot -Tpng $(.SOURCE) -o $(.TARGET).png
GNU make uses $< and $#, not .SOURCE and .TARGET, the recipe should be
.PHONY: all
all: $(patsubst %.dot,%.png,$(wildcard *.dot))
%.png: %.dot
dot -Tpng $< -o $#

Wildcard targets in a Makefile

How can I compact the folllowing Makefile targets?
$(GRAPHDIR)/Complex.png: $(GRAPHDIR)/Complex.dot
dot $(GRAPHDIR)/Complex.dot -Tpng -o $(GRAPHDIR)/Complex.png
$(GRAPHDIR)/Simple.png: $(GRAPHDIR)/Simple.dot
dot $(GRAPHDIR)/Simple.dot -Tpng -o $(GRAPHDIR)/Simple.png
$(GRAPHDIR)/IFileReader.png: $(GRAPHDIR)/IFileReader.dot
dot $(GRAPHDIR)/IFileReader.dot -Tpng -o $(GRAPHDIR)/IFileReader.png
$(GRAPHDIR)/McCabe-linear.png: $(GRAPHDIR)/McCabe-linear.dot
dot $(GRAPHDIR)/McCabe-linear.dot -Tpng -o $(GRAPHDIR)/McCabe-linear.png
graphs: $(GRAPHDIR)/Complex.png $(GRAPHDIR)/Simple.png $(GRAPHDIR)/IFileReader.png $(GRAPHDIR)/McCabe-linear.png
--
Using GNU Make 3.81.
The concept is called pattern rules. You can read about it in GNU make manual.
$(GRAPHDIR)/%.png: $(GRAPHDIR)/%.dot
dot $< -Tpng -o $#
graphs: $(patsubst %,$(GRAPHDIR)/%.png, Complex Simple IFileReader McCabe)\
or just
%.png: %.dot
dot $< -Tpng -o $#
graphs: $(patsubst %,$(GRAPHDIR)/%.png, Complex Simple IFileReader McCabe)
You can also remove all repetition by extracting one of the patterns into a separate variable PNG_PATTERN like so:
PNG_pattern=$(GRAPHDIR)/%.png
$(PNG_pattern): $(GRAPHDIR)/%.dot
dot $< -Tpng -o $#
graphs: $(patsubst %,$(PNG_pattern), Complex Simple IFileReader McCabe)
Just in case you actually want to generate a .PNG for every .DOT within current directory:
%.png : %.dot
dot -Tpng -o $# $<
all: $(addsuffix .png, $(basename $(wildcard *.dot)))
I came up with this Makefile after reading the answer from #Pavel.
I think you want some pattern rules. Try this out.
TARGETS = $(GRAPHDIR)/Complex.png \
$(GRAPHDIR)/Simple.png \
$(GRAPHDIR)/IFileReader.png \
$(GRAPHDIR)/McCabe-linear.png
%.png : %.dot
dot $^ -Tpng -o $#
graphs: $(TARGETS)

Resources