gnumake和模式规则

时间:2012-02-15 21:26:38

标签: makefile gnu-make

我正在使用GNUmake从源目录生成某些Web内容的部署版本。我希望成为通过压缩工具(例如YUI压缩器)运行某些文件的规则,然后对于没有规则的任何内容,只需复制它。

例如:

# Rule with all the $(WWW_OUT_DIR)/*.* files as a prerequisite
all: $(WWW_OUT_FILES)

# Generic rule to perform compression on Javascript files.
$(WWW_OUT_DIR)/%.js:     $(WWW_SRC_DIR)/%.js
    $(YUI_COMP) $(YUI_COMP_OPTS) $< > $@

# Generic rule to perform compression on CSS files.
$(WWW_OUT_DIR)/%.css:    $(WWW_SRC_DIR)/%.css
    $(YUI_COMP) $(YUI_COMP_OPTS) $< > $@

# TDB Rule to magically handle everything else? (This doesn't work)
$(WWW_OUT_DIR)/%.%:   $(WWW_SRC_DIR)/%.%
    cp $< $@

如何完成最后一条规则的目标?即对于$(WWW_OUT_FILES)中不是.js或.css的所有内容,只需复制它?如果可能,我想保留对相应输入文件的依赖。

1 个答案:

答案 0 :(得分:7)

你几乎是对的,唯一要解决的是最后一个模式规则,只需删除多余的百分号:

$(WWW_OUT_DIR)/%:   $(WWW_SRC_DIR)/%
    cp $< $@

另请注意,自GNU Make 3.82模式搜索算法进行了一些修改(来自Changelog):

  

特定于模式的变量和模式规则现在应用于     最短的第一顺序而不是定义顺序(变量     具有相同茎长的规则仍然适用于定义     订购)。这产生了通常期望的行为,其中更具体     模式是首选。

如果您使用最新版本的Make,这正是您想要的。为了使您的Makefile与其他版本的GNU Make兼容(包括3.82之前的版本),必须在其他版本之后定义规则(如原始问题中所述)。

UPD。

来自here的一个很好的例子:

  

在版本3.82之前,当gmake在模式搜索期间发现多个匹配时,它更喜欢先前在makefile中声明的模式而不是稍后声明的模式。从3.82开始,gmake反而更喜欢导致最短茎的模式。由于行话,这听起来有点令人困惑,但我认为这实际上会使gmake更好地坚持最不惊讶的原则。这是一个例子:

all: sub/foo.x

%.x:
    @echo "Prefer first match (stem is $*)."

sub/%.x:
    @echo "Prefer most specific match (stem is $*)."
  

比较gmake 3.81和3.82的输出:

     
      
  • gmake 3.81

    Prefer first match (stem is sub/foo).
    
  •   
  • gmake 3.82

    Prefer most specific match (stem is foo).
    
  •   
     

gmake 3.82更喜欢第二种模式,因为它比第一种模式更具体。请注意,与之前版本的gmake相比,这是一个重要的向后兼容性。