Makefile:对子目录中的所有文件进行操作吗? [英] Makefile: operate on all files in a subdirectory?

查看:76
本文介绍了Makefile:对子目录中的所有文件进行操作吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Makefile和GNU make基于源Markdown文件创建各种文档输出目标.

I am using a Makefile and GNU make to create various document output targets based on a source Markdown file.

这包括使用latexpdflatex创建DVI文件.使用非EPS或PS格式的图像会导致错误.

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

我可以在源Markdown文件中搜索并替换图像名称,并且已经做到了.

I can search-and-replace image names within the source markdown file, and have done so.

我想做的是为images/子目录中的所有图像文件创建一个makefile规则,然后运行convert创建这些文件的eps版本.

What I'd like to do is create a makefile rule for all image files in the images/ subdirectory, and to run convert to create eps versions of those files.

所以:

images/myimage1.png
images/myimage2.jpeg

已保留,但已创建其他版本:

Are retained, but have additional versions created:

images/myimage1.eps
images/myimage2.eps

(是的,我必须保持跟踪,否则在其他地方不会发生名称冲突.)

(And yes, I've got to keep track otherwise that there aren't name collisions elsewhere.)

要运行的命令类似于:

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

我想在所有非EPS图像文件上运行此文件:gif,jpg,jpeg,png,bmp等.这些文件将在Makefile中专门列出.

I'd want to run this on any non-EPS image files: gif, jpg, jpeg, png, bmp, etc. These will be specifically listed in the Makefile.

虽然有点长,但如果扩展了,它仍然可以工作(对其他错误取模) 到Imagemagick支持的全部193种图形格式将是... 不耐烦.

It works (modulo other errors), though it's a bit long, and if extended to the full 193 graphics formats supported by Imagemagick would be ... unweildy.

我的目标是构建DVI,因此我展示了相关目标

My goal here is to build the DVI, so I'm showing the related targets

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's 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 that's all the relevant rules)

它成功了,因为它在我的转换脚本中出现了图像失败 转换失败.

And it succceeds, in that it fails with an image my conversion script had failed to convert.

但这不是Make的错.

But that's not Make's fault.

我们知道了! 77行代码减少到17行(包括空格).

And we've got it! 77 lines of code reduced to 17 (inclusive of whitespace).

IMG_DIR=images
EPS_DIR=images-eps

# We can handle any of about 193 formats Imagemagick will read, but
# let's 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 $$< $$@) \
)

当前输出(紧随make clean之后):

Current output (following 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 

推荐答案

尝试如下操作:

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 $< $@

但是,如果同时具有image1.pngimage1.jpeg,则此操作将失败.

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

要处理其他图像类型,您将需要复制其他图像类型的规则和变量.但是我认为,如果您在另一个文件夹中构建eps文件,可以避免这种情况(建议BTW,这被称为源外"构建,主要思想是您不要混合源文件并在同一文件夹中构建文件).如果这样做,我认为您只能设法拥有一个变量和构建规则.

To process other image types, you will need to replicate the rules and variables for the other image types. But I think this could be avoided if you build the eps files in another folder (which is BTW recommended, it's called an "out of source" build, the main idea is you don't mix source files and build files in the same folder). If you do so, I think you can manage to have only one variable and build rule.

编辑,好的,我想我有一个简化所有步骤的解决方案:

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

首先,定义一个变量,其中包含所有需要的文件类型(读取:扩展名):

First, define a variable holding all the needed file types (read: extensions):

EXT=gif png jpg jpeg

然后,构建一个包含所有图像的变量(假设这里仅图像,这是必需的):

Then, build a variable holding ALL your images (assuming there are only images here, this is requested):

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

然后,我们需要构建包含所有输入文件但扩展名为.eps的相应目标变量.我们不能直接使用patsubst,因为它不能继续使用倍数扩展名.因此,我们需要一个技巧:用img1_gif替换img1.gif,然后添加.eps扩展名.这分两个步骤完成:

Then we need to build the corresponding target variables holding all the input files, but with .eps extension. We can't use patsubst directly because it cannot proceed with multiples extensions. So we need a trick: replace img1.gif by img1_gif and then add the .eps extension. This is done in two steps:

首先,在输入文件中将.替换为_:

First, replace . by _ in the input files:

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

第二,添加.eps扩展名(假设输出文件夹为out):

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

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

好的,我们完成了:

all: $(DEST2)
    @echo "Done"

嗯,不完全是.这是最后一个技巧:使用foreach函数从EXT变量自动生成所有需要的配方:

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

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

这将在prereq中实例化EXT中的所有值,并调用eval函数来生成配方.

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

这篇关于Makefile:对子目录中的所有文件进行操作吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆