在gnu make中使用一个命令从多个文件制作多个文件 [英] Making multiple files from multiple files with one command in gnu make

查看:76
本文介绍了在gnu make中使用一个命令从多个文件制作多个文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假定目录输入中包含1000个扩展名为.xhtml的文件,并且这些文件的某些子集(例如,输出路径位于$(FILES)中)需要通过xslt转换为目录输出中具有相同名称的文件.一个简单的制造规则是:

Assume 1000 files with extension .xhtml are in directory input, and that a certain subset of those files (with output paths in $(FILES), say) need to be transformed via xslt to files with the same name in directory output. A simple make rule would be:

$(FILES): output/%.xhtml : input/%.xhtml
    saxon s:$< o:$@ foo.xslt

这当然可以一次转换一个文件.问题是我想使用saxon的批处理一次处理所有文件,因为考虑到为每个文件加载java和saxon的开销,给定文件数,这样做会快得多. Saxon允许-s(源)选项成为目录并处理该目录中的所有文件,并将结果同名放置在-o:选项中指定的目录中.

This works, of course, doing the transform one file at a time. The problem is that I want to use saxon's batch processing to do all the files at one time, since, given the number of files, that would be much faster, considering the overhead of loading java and saxon for each file. Saxon allows the -s (source) option to be a directory and processes all files in that directory, placing the results with the same name in the directory specified in the -o: option.

我知道让GNU make通过使用模式规则执行单个命令来更新多个文件的众所周知的技术:

I'm aware of the well-known technique to get GNU make to do a single command to update multiple files by using pattern rules:

output/%.xhtml: input/%.xhtml
    saxon s:input -o:output foo.xslt

但是对于我来说,这有两个问题.首先,它将对输入目录中的所有文件(不仅是已更改的文件)运行转换.其次,它不会将转换限制为$(FILES)中指定的文件子集.对于所谓的静态模式规则"(请参阅​​[here]),GNU make功能仅对所有匹配的目标运行一次在模式规则中给出的配方,该功能不起作用,因为在规则顶部给出的规则帖子是已知的.

But in my case this suffers from two problems. First, it will run the transform on all files in the input directory, not just the ones that have changed; and second, it will not limit the transform to the subset of files specified in $(FILES). The GNU make feature of running a recipe given in a pattern rule only once for all matched targets does not work in the case of so-called "static pattern rules" (see [here]), as the rule given at the top of the post is known.

为了使用saxon批处理功能,我需要创建一个临时目录,仅将要处理的文件复制到该目录,然后使用该临时目录作为输入目录运行转换.我尝试创建一个临时目录,并使用一个特定于目标的变量来记住其名称,以供将来使用,使用

In order to use the saxon batching feature, I need to create a temporary directory, copy to it only those files to be processed, then run the transform with that temporary directory as the input directory. I tried creating a temporary directory, and remember its name using a target-specific variable for future use, using

$(FILES): TMPDIR:=$(shell mktemp -d)

但是这会为每个过期的单个目标创建一个新的临时目录.无论如何,我不确定如何构造规则,然后将必要的文件复制到该目录中.我不想在分析makefile时创建临时目录,因为我有一个非递归的make系统,该系统可以解析所有make文件,即使那些与当前顶级目标不相关的文件,也不会想要在不需要/将不使用的情况下创建临时目录.

but this creates a new temporary directory for every single target that is out-of-date. In any case, I'm not sure how to structure the rule that would then copy the necessary files into that directory. I don't want to create the temporary directory at the time the makefile is parsed, since I have a non-recursive make system that will parse all make files, even those not related to the current top-level target, and don't want to create the temporary directory for situations in which it is not necessary/will not be used.

我很清楚,过去关于SO从单个输入创建多个文件的问题很多.一种解决方案是(非静态)模式规则;其他解决方案涉及伪造目标.但是,在这种情况下,我对如何将所有这些组合在一起感到困惑.

I'm well aware that many questions have been asked on SO in the past about creating multiple files from a single input; one solution is (non-static) pattern rules; other solutions involve phony targets. However, in this case I'm stuck as to how to put all this together.

我可以识别出已更改的文件,并使用静态模式规则将其复制

I can identify the files that changed and copy them using the static pattern rule

$(FILES): output/%.xhtml : input/%.xhtml
    TMPDIR=`mktemp -d`
    cp $< $(TMPDIR)

但是实际上我更希望使用单个cp命令复制文件,而这会一个接一个地复制它们.也许cp -u在这里有一些应用?

but actually I would prefer to copy the files with a single cp command, whereas this copies them one by one. Perhaps there is some application here of cp -u?

我还考虑过对那些需要更新的文件使用临时扩展名,但是也看不到如何使它工作.我要放弃,只在所有文件发生更改时对所有文件运行saxon转换,但是还有更好的方法吗?

I also considered using an ad-hoc extension for those files needing updating but could not see how to get this to work either. I'm about to give up and just run the saxon transform on all files when any of them have changed, but is there any better way?

推荐答案

我个人不会尝试从命令行执行此操作.部分原因是我不是shell脚本向导.我也不是Ant向导,但是因为要求是处理未更改的文件,所以这似乎很容易落入Ant领域.另一方面,Ant将为每个转换重新编译样式表,这是您可能要避免的开销;如果是这种情况,那么最好的选择就是编写一个小的Java应用程序.大概只有100行或更少.

Personally, I wouldn't try to do this from the command line. That's partly because I'm not a shell scripting wizard. I'm not an Ant wizard either, but because the requirement is to process files that haven't changed, this seems to fall very much into Ant territory. On the other hand, Ant will recompile the stylesheet for each transformation, which is an overhead you might want to avoid; if that's the case then your best bet is probably to write a little Java application. It's probably only 100 lines or less.

最终的可能性是在Saxon中进行处理:即,一个单一的转换,该转换使用collection()函数读取多个输入文件,并使用xsl:result-document生成多个结果文件. Saxon(商业版)提供了最后修改的扩展功能,使您可以过滤要处理的文件.对于1000个文件,您可能还需要扩展函数saxon:discard-document()来防止堆填充.

Final possibility is to do the processing within Saxon: that is, a single transformation that reads multiple input files using the collection() function and generates multiple result files using xsl:result-document. Saxon (commercial editions) offers an extension function last-modified that allows you to filter the files to be processed. With 1000 files you might also want the extension function saxon:discard-document() to prevent the heap filling.

这篇关于在gnu make中使用一个命令从多个文件制作多个文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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