GNU从单个依赖项生成许多输出文件,可能与其他人匹配

时间:2017-06-06 08:14:55

标签: makefile gnu-make

我试着寻找这个问题的答案,所以如果这是我没有找到的问题的重复,我会提前道歉。也很抱歉,我不能直接提供我正在使用的代码(无论如何都需要很多环境依赖)。

我有一系列的行动,这些行动都取决于先前行动的成功,除非它们已经过时,否则不需要重复。 make解决方案似乎是正确的解决方案。我想出了一个几乎所有的解决方案。以下是我尝试复制的步骤序列,每个步骤的输出列在其输入下面:

  • ZIP文件
    • 摘录至package/
  • package/directory/*.comp
    • 执行uncomp.py以从.uncomp文件创建.comp文件
  • 到目前为止一切正常
  • package/directory/*.uncomp
    • 对于*.uncomp个文件,执行script1以生成.html个文件
    • 对于*_ext.uncomp个文件,执行script2以生成编号为*_ext.##.png个文件的文件
      • 可以使用多个编号的文件(_ext.0.png_ext.1.png_ext.2.png),并且在make运行时可能不存在。但是,make应该知道它们是上一步的输出,并且只有当这些文件(a)不存在或者(b)任何旧文件时,才会运行配方*_ext.uncomp档案。

我已经整理了一个Makefile,它几乎我正在寻找的东西,除了它将所有最后部分(编号文件)委托给我可以<的shell脚本/ em>程序来查看文件时间,但在我看来,这首先违背了使用make的目的。

环境

Debian 8.8(x86)

GNU Make 4.0
Built for x86_64-pc-linux-gnu

我的问题

我可以使用哪些规则和配方来告知GNU make *_ext.uncomp文件和_ext.##.png文件之间的关系,以便这些配方只在必要时执行(并说'Target is up-至今“如果所有.png文件至少与_ext.uncomp文件一样新”,那么这些文件也不会适用于*.uncomp文件,并且仍然可以使用输出中没有.png个文件?

我还需要指出 - _ext文件与其对应的HTML对应文件之间的关系。这样script1仅在HTML文件过期或不存在时执行。此配方/规则不应该关注_ext.uncomp个文件。

我的Makefile上的任何其他建议也会受到赞赏,因为我对它不太熟悉。

我当前Makefile

的广义内容
.PHONY : all
all : package package/directory/*.uncomp
    ./process $^

%.comp.uncomp : %.comp package
    python uncomp.py $<

package : *.zip
    rm -rf package/
    unzip *.zip -d package/

process脚本

的内容

如果满足问题的所有目标(make将处理所有内容),则此脚本将不再存在。它工作得很好,但它总是处理.uncomp文件,无论它们是什么,即使它们的输出已经存在并且比源更新。

#!/bin/bash

if [ $# -lt 2 ]; then
    echo "$0 expects at least 2 arguments"
    exit 1
fi

# Discard the first agrument, it's always 'package'
shift

# Iterate over each of the remaining arguments
while [ $# -gt 0 ]; do
    if [[ $1 == *_ext.uncomp ]] ; then
        python script2 $1
    elif [[ $1 == *.uncomp ]] ; then
        python script1 $1
    else
        echo "Warning: Unknown file type: $1"
    fi
    shift
done

1 个答案:

答案 0 :(得分:1)

我学到了很多关于GNU make试图让它发挥作用的知识。我发现解决我的问题的方法是不要过度思考它。

最重要的实现是我不需要make来跟踪编号输出文件的所有,而只需要第一个<(如果第一个是过时的或缺少,他们都将,并且他们都被脚本重新提取,所以我需要一个1:1的关系来指示那里。)

我发现当匹配模式规则时,GNU make 3.82及更高版本使用“最短词干优先”顺序而不是定义顺序。为了使我的文件与这两个版本兼容,我确保首先定义最具体的词干。

之后,这是一个建立一些隐含规则的问题,只是告诉make期待能够找到什么 - 这个概念有点落后于我的思维方式,这就是为什么我有一些麻烦一开始(寻找这个尚不存在的文件;现在,这是一种从 存在的文件中制作它的方法)。最终结果,功能齐全:

PACKAGE      := package
COMP         := .comp
UNCOMP       := .comp.uncomp
PNG0         := .comp.0.png
TXT          := .comp.txt
SUFFIX       := _ext

COMPFILES     = $(wildcard $(PACKAGE)/subdir/*$(COMP))
UNCOMPFILES   = $(COMPFILES:$(COMP)=$(UNCOMP))
SUFFIXFILES   = $(filter %$(SUFFIX)$(UNCOMP),$(UNCOMPFILES))
PNGFILES      = $(SUFFIXFILES:$(UNCOMP)=$(PNG0))
NOSUFFIXFILES = $(filter-out %$(SUFFIX)$(UNCOMP),$(UNCOMPFILES))
TXTFILES      = $(NOSUFFIXFILES:$(UNCOMP)=$(TXT))

.PHONY : all
all : pngs txts htaccess

.PHONY : txts
txts : $(TXTFILES)

.PHONY : pngs
pngs : $(PNGFILES)

.PHONY : uncomp
uncomp : $(UNCOMPFILES)
    make pngs
    make txts

.PHONY : htaccess
htaccess : $(PACKAGE)/.htaccess

%$(SUFFIX)$(PNG0) : %$(SUFFIX)$(UNCOMP)
    @# Ignore failures when extracting PNG files
    -python script1.py $<

%$(TXT) : %$(UNCOMP)
    @# Ignore failures when dumping TXT files
    -python script2.py $< > $@

%$(UNCOMP) : %$(COMP)
    @# Ignore decompression failure
    -python uncomp.py $<

$(PACKAGE)/.htaccess : .htaccess | $(PACKAGE)
    cp .htaccess $(PACKAGE)/

$(PACKAGE) : *.zip
    rm -rf $(PACKAGE)/
    unzip *.zip -d $(PACKAGE)/
    make uncomp

.PHONY : clean
clean :
    rm -rf $(PACKAGE)/