gnumake和模式规则

Bri*_*and 4 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 $< $@
Run Code Online (Sandbox Code Playgroud)

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

Eld*_*mov 7

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

$(WWW_OUT_DIR)/%:   $(WWW_SRC_DIR)/%
    cp $< $@
Run Code Online (Sandbox Code Playgroud)

另请记住,自GNU Make 3.82模式搜索算法已经过一点修改(来自Changelog):

特定于模式的变量和模式规则现在应用于最短的第一顺序而不是定义顺序(具有相同主干长度的变量和规则仍然在定义顺序中应用).这产生了通常期望的行为,其中更优选更具体的图案.

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

UPD.

从一个很好的例子在这里:

在版本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 $*)."
Run Code Online (Sandbox Code Playgroud)

比较gmake 3.81和3.82的输出:

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