Making multiple files from multiple files with one command in gnu make

倾然丶 夕夏残阳落幕 提交于 2019-12-06 12:26:16

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.

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.

Personally, I like your original one-compiler-per-file formulation. Does not this work well with make's -j n flag?

You can of course batch up files by copying, and then running saxon at the end. Recursive make (ugh!) can sort out the ordering. Something like:

.PHONY: all
all:
    rm -rf tmpdir
    ${MAKE} tmpdir/sentinel
    saxon -s:tmpdir -o:output foo.xslt

tmpdir/sentinel: $(FILES) ; touch $@

$(FILES): output/%.xhtml: input/%.xhtml
    ln $< $(patsubst input/%,tmpdir/%,$<)

This does work, though I am very queasy about lying to make (the static pattern rule purports to create the target in output/, but in fact does its dirty deed in tmpdir/).

Note in the recipe for tmpdir/sentinel, that $? is correctly set to the list of output files that are out of date. This might be useful if you can pass a bunch of files to saxon rather than a folder.

I think one issue here is that 'saxon' supports either one file or all files in a directory, so isn't suitable for batch processing without copying to temporary directories.

Otherwise, this is quite simple to do by using a timestamp marker file as a proxy target. For example:

output/.timestamp : $(FILES)
    mkdir -p $(@D)
    $(COMMAND) -outputdir=output $?
    touch $@

The three commands are:

  1. Ensure that the output directory exists.
  2. Run the batch command on files newer than the timestamp file.
  3. Update the timestamp file (creating it if necessary).

Remembering that each line of a command is executed in its own subshell, and that if any command line fails, then subsequent lines are not invoked.

This approach is useful with Java builds.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!