首页 > 解决方案 > 使用 Makefile 中的模式自定义目标

问题描述

我有一棵看起来像这样的文件树:

.
├── Makefile
├── README.md
├── exercises
│   ├── 100-exercises.ipynb
│   ├── 200-exercises.ipynb
│   ├── 300-exercises.ipynb
│   └── 400-exercises.ipynb
├── notes
│   ├── 101-notes-pandas.ipynb
│   ├── 102-notes-matplotlib-1.ipynb
│   ├── 103-notes-numpy-scipy.ipynb
│   └── 104-notes-matplotlib-seaborn.ipynb
└── tasks
    ├── 101-tasks-pandas.ipynb
    ├── 102-tasks-matplotlib-1.ipynb
    ├── 103-tasks-numpy-scipy.ipynb
    └── 104-tasks-matplotlib-seaborn.ipynb

我想添加一些仅根据文件名中的模式对文件进行操作的目标。例如:

make lecture-1
make lecture-1-notes
make lecture-1-exercises
make lecture-2
make notes
make exercises
...
etc.

wherelecture-1指的是文件名以1eg开头的目标集tasks/101-tasks-pandas.ipynb- 要清楚,模式是:

很长的路要走,每个目标都有一个单独的目标,但我觉得必须有某种模式/正则表达式匹配可以避免这种情况。

编辑:

有关在每个目标上完成的操作的更多信息,我有一个可执行命令,它基本上将 IPython 笔记本转换为 HTML。这在 make 中存储为变量RENDER_HTML

例如,目前要渲染 notes 文件夹中的所有内容,我的 Makefile 中有以下部分:

RENDER_HTML=jupyter nbconvert --execute --to html
NOTES_TARGETS=$(wildcard ./notes/*.ipynb)

...

.PHONY: notes
notes:  ${NOTES_TARGETS}
    @mkdir -p $@/html/
    ${RENDER_HTML} $^
    @mv $@/*.html $@/html/

标签: makefile

解决方案


如果您提供示例说明您想要什么样的规则以及它们会做什么,那么我们为您提供帮助会容易得多:也许可​​以手动为其中一个规则实施规则,这可以作为示例。

在不知道目标和先决条件是什么的情况下,我建议您使用递归 make 来计算要构建的目标列表;像这样的东西:

lecture-%:
        $(MAKE) $(patsubst ???,???,$(wildcard */$(*)*))

我只是???在这里使用,因为您没有提供有关如何将源文件转换为目标的任何信息:您必须自己完成那部分:)。

如果您可以定义构建单个输出文件的规则,如下所示:

notes/%:
       @mkdir -p $(@D)/html/
       ${RENDER_HTML} $@.ipynb
       @mv $(@D)/*.html $(@D)/html/

那么你可以这样做:

lecture-%:
        $(MAKE) $(patsubst %.ipynb,%,$(wildcard */$(*)*))

那里的mv命令让我有些困惑(似乎应该有更好的方法来做到这一点)但这是你在你的问题中所拥有的,所以我猜它是正确的。

我怀疑这对你不起作用,这取决于我上面问题的答案。如果渲染命令需要查看所有文件(例如构建 index.html 或其他文件),那么当它只构建一些文件时,我不太明白你希望它如何工作。基本上,问题仍然没有明确说明,无法让我们给出一个可行的解决方案。但也许这里有足够的信息让你开始。


推荐阅读