Makefile: work with all files in a subdirectory?

I use Makefile and GNU make to create various output goals for a document based on the Markdown source file.

This includes using latex or pdflatex to create a DVI file. Using images in formats other than EPS or PS causes errors.

I can search and replace image names in the original markdown file and did it.

What I need to do is create a make file rule for all image files in the images/ subdirectory and run convert to create versions of these files.

So:

 images/myimage1.png images/myimage2.jpeg 

Saved, but additional versions created:

 images/myimage1.eps images/myimage2.eps 

(And yes, I have to make sure there are no name conflicts in other places.)

The command to run will look something like this:

 convert -format eps images/myimage1.png images/myimage1.eps 

I would like to run this in any image files other than EPS: gif, jpg, jpeg, png, bmp, etc. They will be specifically specified in the Makefile.


And here is the first iteration

It works (modulo other errors), although it is a little long, and if it is extended to all 193 image formats supported by Imagemagick, it will be ... unweildy.

My goal here is to create DVI, so I show related goals

 dvi: docfs-Manifesto.dvi latex: docfs-Manifesto.tex epsimg.md: docfs-Manifesto.md docfs-Manifesto.tex: docfs-Manifesto-epsimg.md all-img pandoc -s --from=markdown --to=latex -o docfs-Manifesto.tex docfs-Manifesto-epsimg.md docfs-Manifesto-epsimg.md: docfs-Manifesto.md ./img-ref-to-eps.sed docfs-Manifesto.md > docfs-Manifesto-epsimg.md docfs-Manifesto.dvi: latex pdflatex -output-format dvi -halt-on-error docfs-Manifesto.tex 2>pdflatex.log MG_DIR=images EPS_DIR=images-eps # We can handle any of about 193 formats Imagemagick will read, but # let start with some basics # ... Source formats SRC_GIF = $(wildcard $(IMG_DIR)/*.gif) SRC_JPG = $(wildcard $(IMG_DIR)/*.jpg) # ... Destination formats EPS_GIF = $(patsubst $(IMG_DIR)/%.gif,$(EPS_DIR)/%.eps,$(SRC_GIF)) EPS_JPG = $(patsubst $(IMG_DIR)/%.jpg,$(EPS_DIR)/%.eps,$(SRC_JPG)) # And the actual conversions. This ... could be shorter? all-img: $(EPS_DIR) $(EPS_GIF) $(EPS_JPG) @echo "Done" $(EPS_DIR) : mkdir $(EPS_DIR) $(EPS_DIR)/%.eps : $(IMG_DIR)/%.gif convert -format eps $< $@ $(EPS_DIR)/%.eps : $(IMG_DIR)/%.jpg convert -format eps $< $@ 

(I think all the relevant rules)

And this succeeds since it fails with the image of my conversion script failed to convert.

But this is not a mistake.


Now handling code length with foreach loop

And we did it! 77 lines of code reduced to 17 (including spaces).

 IMG_DIR=images EPS_DIR=images-eps # We can handle any of about 193 formats Imagemagick will read, but # let start with some basics # Thanks @kebs: https://stackoverflow.com/a/47857821/9105048 IMG_EXT=bmp dot gif jpg jpeg png raw tiff xcf pnm ppm ps # ... Source formats IMG_FILES = $(wildcard $(IMG_DIR)/*) # Rename files s/./_/ so: img1.gif => img1_gif Then add extension IMG_FILES2 = $(subst .,_,$(IMG_FILES)) EPS_FILES = $(patsubst $(IMG_DIR)/%,$(EPS_DIR)/%.eps,$(IMG_FILES2)) all-img: $(EPS_DIR) $(EPS_FILES) @echo "all-img: done" $(EPS_DIR) : mkdir $(EPS_DIR) $(foreach \ prereq, \ $(IMG_EXT), \ $(eval $(EPS_DIR)/%_$(prereq).eps: $(IMG_SRC)/%.$(prereq); convert -format eps $$< $$@ ) \ ) 

Current output (after make clean ):

 $ make all-img convert -format eps images/browser-of-a-scientist.jpg images-eps/browser-of-a-scientist_jpg.eps convert -format eps images/nukewaste.jpg images-eps/nukewaste_jpg.eps convert -format eps images/standards.png images-eps/standards_png.eps $ ls images-eps/ browser-of-a-scientist_jpg.eps standards_png.eps nukewaste_jpg.eps 
+2
source share
1 answer

Try something like this:

 SRC_DIR=images SRC_FILES1 = $(wildcard $(SRC_DIR)/*.png) SRC_FILES2 = $(wildcard $(SRC_DIR)/*.jpeg) DEST_FILES1 = $(patsubst $(SRC_DIR)/%.png,$(SRC_DIR)/%.eps,$(SRC_FILES1)) DEST_FILES2 = $(patsubst $(SRC_DIR)/%.jpeg,$(SRC_DIR)/%.eps,$(SRC_FILES2)) all: $(DEST_FILES1) $(DEST_FILES2) @echo "Done" $(SRC_DIR)/%.eps : $(SRC_DIR)/%.png convert -format eps $< $@ $(SRC_DIR)/%.eps : $(SRC_DIR)/%.jpeg convert -format eps $< $@ 

However, this will fail if you have both image1.png and image1.jpeg .

To process other types of images, you will need to replicate the rules and variables for other types of images. But I think this can be avoided if you create eps files in a different folder (which is recommended by BTW, it is called an "outside source" assembly), the main idea is that you do not mix the source files and do not create files in one folder ) If you do this, I think you can only have one rule and an assembly rule.


EDIT ok, I think I have a solution to simplify all this:

First, define a variable containing all the necessary file types (read: extensions):

 EXT=gif png jpg jpeg 

Then create a variable containing ALL of your images (assuming there are only images here):

 SRC_FILES = $(wildcard $(SRC_DIR)/*) 

Then we need to build the appropriate target variables containing all the input files, but with the extension .eps. We cannot use patsubst directly because it cannot continue to expand patsubst . So we need a trick: replace img1.gif with img1_gif , and then add the .eps extension. This is done in two stages:

Replace first . on _ in the input files:

 DEST1 = $(subst .,_,$(SRC_FILES)) 

Second, add the extension .eps (assuming the output folder is out ):

 DEST2 = $(patsubst $(SRC_DIR)/%,out/%.eps,$(DEST1)) 

Ok, now we are done:

 all: $(DEST2) @echo "Done" 

Well, not quite. Here's the final trick: use the foreach function to automatically generate all the necessary recipes from the EXT variable:

 $(foreach \ prereq, \ $(EXT), \ $(eval out/%_$(prereq).eps: $(SRC_DIR)/%.$(prereq); convert -format eps $$< $$@ ) \ ) 

This will prereq all the values ​​in EXT and call the eval function to generate the recipe.

+1
source

Source: https://habr.com/ru/post/1211113/


All Articles