I have a command that can take multiple types of input files and generate relevant output. IT does something similar to producing thumbnails from images. I want to write the recipe once and have a list of implicit rules that each call the recipe, e.g.:
%.png : %.jpg
%.png : %.jpeg
%.png : %.svg
%.png : %.gif
convert $< -resize 100x100 $#
This works for .gif but for the other file types I get "No rule to make target".
Is there a way to express this set of rules without duplicating the recipe?
The following should be close to what you want:
PICTURES := $(wildcard *.jpg *.jpeg *.svg *.gif)
THUMBNAILS := $(addsuffix .png,$(basename $(PICTURES)))
.PHONY: all
all: $(THUMBNAILS)
$(THUMBNAILS):
convert $< -resize 100x100 $#
%.png: %.jpg
%.png: %.jpeg
%.png: %.svg
%.png: %.gif
You could add one rule with no prerequisites:
%.png : %.jpg
%.png : %.jpeg
%.png : %.svg
%.png : %.gif
%.png :
convert $< -resize 100x100 $#
THE DRAWBACK is that if you try to build foo.png when none of the prereqs exist, Make will gamely attempt to build it with no input file. You could put a test in the recipe, to get a more graceful exit in that case, but it wouldn't be very elegant.
Related
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)
I've some similar files on which I want to do an operation using makefile. So I'm doing this:
INPUT := $(wildcard *.png)
OUTPUT := $(INPUT:.png=.jpeg)
.PHONY: all
all: $(OUTPUT)
$(OUTPUT): $(INPUT)
convert $< -resize 30x30 $#
I'm getting correct jpeg file names but the image is the same (first dependency) in the all the files.
I know that using $< only refers to the first dependency in the list, and using $^ is giving all the deps but for all the ouputs.
Is there any way that dep1 for output1, dep2 for output2 and so on?
This way you declare that each output file depends on every input file. You should be using a pattern rule instead, i.e.:
$(OUTPUT): %.jpeg: %.png
convert $< -resize 30x30 $#
I'd be inclined just to use:
%.jpeg: %.png
convert $< -resize 30x30 $#
In any case, you don't want to have to remake all of your thumbnails any time one of the original images changes -- they each only depend on the single corresponding png file.
I'm trying to build a Makefile that simplifies compilation for a C assignment. The Makefile works fine for now, however, I would like to add a new target that executes a previous target and creates files.
The objective is the following:
Compile a given program (figures.c)
Execute it (this creates a bunch of .gv files)
Transform every .gv file to a .pdf file
I know how to transform a single file (I have the command), but can't seem to figure out how to loop through every file, without typing them all out.
I've already tried doing a different type of target, but does not work (see commented target)
# COMPILATION
CC=gcc
CFLAGS=-Wall -ansi -pedantic
# DOSSIERS
SOURCEDOC=sourcedoc
DOC=doc
SRC=src
INC=inc
OBJ=build
FIGS=images
FILES=$(wildcard $(FIGS)/*.gv)
.PHONY: clean doc archive author all
.SILENT : clean
# Targets
all : clean test images
test : $(OBJ)/Test_arbre.o $(OBJ)/aux.o $(OBJ)/Affichage.o $(OBJ)/ArbreBinaire.o $(OBJ)/arbres.o
$(CC) $^ -o $# $(CFLAGS)
figures : $(OBJ)/figures.o $(OBJ)/Affichage.o $(OBJ)/ArbreBinaire.o $(OBJ)/aux.o $(OBJ)/arbres.o
$(CC) $^ -o $# $(CFLAGS)
%.pdf: $(FIGS)/%.gv
dot -Tpdf -o $(FIGS)/$# $^
#$(FILES): $(FIGS)/%.pdf : $(FIGS)/%.gv
# dot -Tpdf -o $# $^
images : figures $(FILES)
#=========== Objets ===========
$(OBJ)/arbres.o : $(INC)/arbres.h $(INC)/aux.h $(INC)/Affichage.h $(INC)/ArbreBinaire.h
$(OBJ)/Affichage.o : $(INC)/Affichage.h $(INC)/ArbreBinaire.h
$(OBJ)/exemple*_arbre.o : $(INC)/Affichage.h $(INC)/ArbreBinaire.h
$(OBJ)/aux.o : $(INC)/aux.h
$(OBJ)/figures.o : $(INC)/Affichage.h $(INC)/ArbreBinaire.h $(INC)/arbres.h
$(OBJ)/Test_arbre.o : $(INC)/arbres.h $(INC)/ArbreBinaire.h $(INC)/Affichage.h
# Dummy rule
$(OBJ)/%.o : $(SRC)/%.c
#mkdir -p $(#D)
#$(CC) $< $(CFLAGS) -I $(INC)/ -c -o $#
# Miscellaneous
clean:
rm -f *~ */*~
rm -rf __pycache__ src/__pycache__
rm -rf $(DOC)
rm -f $(PROJECT)_$(AUTHOR12)_$(AUTHOR22).zip
rm -f conf.py-e
rm -rf $(OBJ)
rm -f $(FIGS)/*.pdf $(FIGS)/*.gv
rm -f test
The current Makefile works fine on all other commands than images.
If any of you could help, it would mean a lot!
Your definition of FILES should map the *.gv files to the corresponding *.pdf files;
FILES=$(patsubst %.gv,%.pdf,$(wildcard $(FIGS)/*.gv))
The rule which says how to generate a PDF should factor out the directory name;
%.pdf: %.gv
dot -Tpdf -o $# $^
Now, if make tries to create $(FIGS)/ick.pdf, the input will be $(FIGS)/ick.gv - the pattern says to substitute the extension .gv with the extension .pdf, and the rest of the file name stays unmodified, exactly like you'd want. A rule like
%.pdf: $(FIGS)/%.gv # error, don't use
says you need to find the source file in a subdirectory $(FIGS); so if you tried to make $(FIGS)/ick.pdf, that means make would need to find or generate $(FIGS)/$(FIGS)/ick.gv as input according to this rule.
If you absolutely cannot predict what files will be created on step (2) (and so confined to using $(wildcard ...)), you still must execute it after (2) is finished.
It's ugly but I can't think of better alternative than using "recursive make". I mean something like this:
...
.PHONY: images pdf
images: figures
# use figures to generate all .gv files
##figures --create-all-gv-files
# invoke make recursively
#$(MAKE) --no-print-directory pdf
# ensure $(wildcard ...) is invoked only if needed
ifeq ($(MAKECMDGOALS),pdf)
PDF_FILES:=$(patsubst %.gv,%.pdf,$(wildcard $(FIGS)/*.gv))
endif
pdf: $(PDF_FILES)
%.pdf: %.gv
dot -Tpdf -o $# $<
I have created a Makefile to generate pdf and html for a md file mentioned while invoking make like make a.md should generate a.pdf and a.html, and should not convert other md files present in the directory.
My make file
But I am, getting error Nothing to be done for a.md
Could you please suggest changes?
Because a.md is already in place, make indeed does have nothing further to do. You can either just use for instance a as the specified target (which can depend on pdf and html files as prerequisites). Or pass the desired source through a variable and determine your desired target from that.
One (the latter) option would be this:
EXPORTED= $(SOURCE:%.md=%.html) $(SOURCE:%.md=%.pdf)
%.html : %.md
pandoc -o $# $<
%.pdf : %.md
pandoc -o $# $<
all: $(EXPORTED)
Which you can call with make SOURCE=a.md.
The other option (former):
%.html : %.md
pandoc -o $# $<
%.pdf : %.md
pandoc -o $# $<
.PHONY: $(MAKECMDGOALS)
$(MAKECMDGOALS): $(MAKECMDGOALS:%=%.html) $(MAKECMDGOALS:%=%.pdf)
Allows you to call make a.
But to reiterate. You cannot use (existing) source as a target, because make would (as it did) conclude it's done making that target.
Except (but I personally do not really like this as it is IMO confusing), if you insisted, you could do a variation on the previous take... but work with *.md targets... which you all declare as .PHONY. I.e. not real files and always to be considered/remade:
%.html : %.md
echo pandoc -o $# $<
%.pdf : %.md
echo pandoc -o $# $<
.PHONY: $(MAKECMDGOALS)
$(MAKECMDGOALS): $(MAKECMDGOALS:%.md=%.html) $(MAKECMDGOALS:%.md=%.pdf)
Now you could indeed call make a.md. I'd still prefer one of the two above.
I have some trouble with my Makefile:
# Manage rendering of images
.PHONY: explode
all: explode anime.apng
out.ppm: file.code
./pgm -f $<
explode: out.ppm
split -d -a 3 --lines=$(N) --additional-suffix=.ppm $< frame
# Convert to multiple png
%.png: %.ppm
convert $< $#
optipng $#
# Assemble in one animated png
anime.apng: %.png
apngasm $# frame000.png
My problem is: I don't know how many intermediate files I will have to produce my final target, so I can't specify them in advance. Schematically:
1 file.code -> 1 out.ppm |> LOADS of .ppm |> LOADS of .png -> 1 anime.apng
+> … +> …
+> … +> …
For that I use an implicit rule %.png: %.ppm. But then I cannot specify a prerequisite for my last merge step! Any ideas? With another tool than make? Anything elegant?
I think a simple and rather clean approach would be to have a variable record the list of those 'LOADS' of ppm, in my example it's variable STEP2.
Surely you can use the program that gets you from '1 out.ppm' to 'LOADS of .ppm' to list the .ppm files that you will obtain.
With a very trivial exemple where out.ppm would be a text file listing the names of the .ppm to produce, you would write something like :
SOURCE = file.code
STEP1 = out.ppm
STEP2 = $(shell cat $(STEP1))
STEP3 = $(STEP2:%.ppm=%.png)
TARGET = anime.apng
Then you'll need to write a rule to get all the files listed in STEP2 from the file $(STEP1). This is done file by file as if it was an implicit rule with a % pattern, assuming your program is called 'extractor' :
$(STEP2): $(STEP1)
extractor $^ $#
This rule will be applied once for each file listed in STEP2. This assumes that your program only wants the names of the source and output files. Should you prefer to pass the stem of the output file, you can still use a plain ol' implicit rule :
$(STEP2):%.ppm: $(STEP1)
extractor $^ $*
(The $(STEP2): at the begining is to prevent make from using this rule to generate out.ppm)
Then, everything is as usual when it comes to compilation and you can adapt rules for compiling and linking any C projet. The %.ppm -> %.png step is like compiling %.c to %.o :
%.png: %.ppm
convert $< $#
optipng $#
To group everything at the end (equivalent of linking several %.o into only one binary) :
$(TARGET): $(STEP3)
apngasm $# $^
I'm assuming here that apngasm can take the list of everything to put together as arguments à la tar.
Hope it's clear and helpful enough.
A temporary workaround would be to take inspiration from a close question and render the images in a subfolder with a sub-make call. Something like:
Makefile:
# Manage rendering of images
.PHONY: explode
all: explode anime.apng
out.ppm: file.code
./pgm -f $<
explode: out.ppm
split -d -a 3 --lines=$(N) --additional-suffix=.ppm $< subfolder/frame
ppm2png: explode
$(MAKE) -C subfolder
# Assemble in one animated png
anime.apng: ppm2png
apngasm $# subfolder/frame000.png
temp/Makefile:
SOURCES := $(wildcard *.ppm)
OUTPUTS = $(patsub %.ppm,%.png,%(SOURCES))
.PHONY: all
all: $(OUTPUTS)
# Convert to multiple png
%.png: %.ppm
convert $< $#
optipng $#
I'm sure better can be done. With another tool than make?