假设目录输入中有 1000 个扩展名为 .xhtml 的文件,并且这些文件的某个子集(例如,输出路径在 $(FILES) 中)需要通过 xslt 转换为目录输出中具有相同名称的文件。一个简单的 make 规则是:
$(FILES): output/%.xhtml : input/%.xhtml
saxon s:$< o:$@ foo.xslt
当然,这可以一次转换一个文件。问题是我想使用 saxon 的批处理一次处理所有文件,因为考虑到为每个文件加载 java 和 saxon 的开销,考虑到文件的数量,这会快得多。Saxon 允许 -s(源)选项作为目录并处理该目录中的所有文件,将具有相同名称的结果放置在 -o: 选项中指定的目录中。
我知道让 GNU make 使用模式规则执行单个命令来更新多个文件的众所周知的技术:
output/%.xhtml: input/%.xhtml
saxon s:input -o:output foo.xslt
但就我而言,这有两个问题。首先,它将在输入目录中的所有文件上运行转换,而不仅仅是已更改的文件;其次,它不会将转换限制在 $(FILES) 中指定的文件子集。在所谓的“静态模式规则”(参见[这里])的情况下,GNU make 功能对于所有匹配的目标只运行一次模式规则中给出的配方,因为在顶部给出的规则帖子是已知的。
为了使用 saxon 批处理功能,我需要创建一个临时目录,仅将要处理的文件复制到其中,然后使用该临时目录作为输入目录运行转换。我尝试创建一个临时目录,并使用特定于目标的变量记住它的名称以备将来使用,使用
$(FILES): TMPDIR:=$(shell mktemp -d)
但这会为每个过时的目标创建一个新的临时目录。无论如何,我不确定如何构建规则,然后将必要的文件复制到该目录中。我不想在解析 makefile 时创建临时目录,因为我有一个非递归的 make 系统,它将解析所有 make 文件,甚至那些与当前顶级目标无关的文件,并且不要想要为不需要/不会使用的情况创建临时目录。
我很清楚过去在 SO 上提出了许多关于从单个输入创建多个文件的问题。一种解决方案是(非静态)模式规则;其他解决方案涉及虚假目标。但是,在这种情况下,我不知道如何将所有这些放在一起。
我可以使用静态模式规则识别更改并复制它们的文件
$(FILES): output/%.xhtml : input/%.xhtml
TMPDIR=`mktemp -d`
cp $< $(TMPDIR)
但实际上我更喜欢使用单个 cp 命令复制文件,而这会一一复制它们。也许这里有一些应用cp -u
?
我还考虑为那些需要更新的文件使用临时扩展,但也看不出如何让它工作。当所有文件发生变化时,我即将放弃并在所有文件上运行撒克逊变换,但有没有更好的方法?