如何制作将相同命令应用于子目录的单个makefile?
Posted
技术标签:
【中文标题】如何制作将相同命令应用于子目录的单个makefile?【英文标题】:How to make a single makefile that applies the same command to sub-directories? 【发布时间】:2018-07-08 12:56:21 【问题描述】:为了清楚起见,我使用 GnuWin32 make
在 Windows 上运行它。
我有一组目录,其中包含多个不同级别的降价文件-理论上它们可能位于分支节点中,但我认为目前它们仅位于叶节点中。我有一组 pandoc/LaTeX 命令可以运行以将降价文件转换为 PDF - 显然,如果降价文件已更新,则只想重新创建 PDF,因此 makefile
似乎合适。
我想要的是根中的单个makefile
,它遍历所有子目录(到任何深度)并应用我将为运行 pandoc 指定的 make 规则.
据我所知,recursive makefiles
要求您在每个子目录中都有一个 makefile
(这似乎是我想避免的管理开销)和/或要求您列出删除makefile
开头的所有子目录(同样,希望避免这种情况)。
理论文件夹结构:
root
|-make
|-Folder AB
| |-File1.md
| \-File2.md
|-Folder C
| \-File3.md
\-Folder D
|-Folder E
| \-File4.md
|-Folder F
\-File5.md
我该如何编写一个makefile来处理这种情况?
【问题讨论】:
【参考方案1】:这里有一小部分 Makefile 规则,希望可以帮助您进行操作
%.pdf : %.md
pandoc -o $@ --pdf-engine=xelatex $^
PDF_FILES=FolderA/File1.pdf FolderA/File2.pdf \
FolderC/File3.pdf FolderD/FolderE/File4.pdf FolderD/FolderF/File5.pdf
all: $PDF_FILES
让我解释一下这里发生了什么。首先,我们有一个模式规则,告诉 make 如何将 Markdown 文件转换为 PDF 文件。 --pdf-engine=xelatex
选项仅用于说明目的。
然后我们需要告诉 Make 要考虑哪些文件。我们将名称放在一个变量PDF_FILES
中。这个变量的这个值可以通过一个单独的脚本来构建,该脚本扫描所有子目录中的.md
文件。
注意如果文件名或目录名包含空格,则必须格外小心。
然后我们要求 Make 检查是否应该更新任何 PDF_FILES
。
如果您的 makefile 中有其他目标,请确保 all
是第一个非模式目标,或者将 make 调用为 make all
更新 Makefile
如果shell
函数适用于您并且sed 和find 等基本实用程序可用,您可以用一行代码使您的makefile 动态化。
%.pdf : %.md
pandoc -o $@ --pdf-engine=xelatex $^
PDF_FILES:=$(shell find -name "*.md" | xargs echo | sed 's/\.md/\.pdf/g' )
all: $PDF_FILES
MadScientist 只是在 cmets 中提出了这个建议
否则,您可以使用操作系统上可用的工具来实现脚本,并添加一个额外的目标 update:
,该目标将计算文件列表并将以 PDF_FILES
开头的行替换为更新的文件列表。
【讨论】:
感谢@dmitrichubarov 的起点,但我专门寻找一个不需要在makefile
中按名称指定子目录的版本,以便makefile
保留随着项目的发展和变化而保持不变。您提到另一个脚本可以建立子目录列表 - 您建议如何处理该部分?
如果您使用的是基于 POSIX 的系统,例如 GNU/Linux,这将是微不足道的;使用:PDF_FILES := $(shell find . -name \*.pdf)
。也许了解 Windows 的人可以为您提供适用于那里的类似答案。
@Vecna vonder 如果 MadScientist 的建议对您有用。我已经用一些细节更新了帖子。
@DmitriChubarov - 谢谢。我已经取得了一些进展,但遇到了 make 似乎真的不喜欢文件路径中的空格的问题。有什么简单的方法吗?不确定重命名项目中的所有文件夹和文件是否可行。
@Vecna 对于 Makefile 中的文件名中的空格,恐怕没有好的解决方案(请参阅 ***.com/q/9838384/1328439 并在那里回答以了解任务的复杂性)。【参考方案2】:
根据@DmitiChubarov 和@MadScientist 的建议,适用于Windows 的代码的最终版本如下:
%.pdf: %.md
pandoc $^ -o $@
PDF_FILES:=$(shell dir /s /b *.md | sed "s/\.md/\.pdf/g")
all: $PDF_FILES
【讨论】:
以上是关于如何制作将相同命令应用于子目录的单个makefile?的主要内容,如果未能解决你的问题,请参考以下文章