Makefile自动变量由先决条件更改

时间:2014-12-21 08:52:55

标签: makefile prerequisites

第一次来这里。我对makefile很新。这是我当前的makefile:

    # Closure compiler php script path
    closure = ../../cli/scripts/Compilers/closure.php

    # Destination directory
    dest = ../../static/js/

    # Build directory
    build = build/

    # Tell "make" to search build and destination dirs
    vpath %.o $(build)
    vpath %.js $(dest)

    all: main.js
        @echo "Done.";

    main.js: \
            date.o \
            jquery.autocomplete.o \
            jquery.bullseye.o \
            jquery.clickopen.o \
            jquery.fbmodal.o \
            jquery.helpers.o \
            jquery.pulljson.o \
            jquery.thumbrotate.o \
            jquery.timefmt.o \
            jquery.tools.o \
            layout.main.o
        cat  $^ > $(dest)$@

    %.o: %.js
        php  $(closure)  $*.js  $(build)$@

    clean:
        rm -rf  $(build)*.o
        rm -rf  $(dest)*.js 

问题在于以下行: cat $^ > $(dest)$@

应该将所有必备对象(缩小的javascript)捕获到一个最终的js库中。根据makefile文档,$^是一个自动变量,它包含一系列先决条件及其所在的目录。根据我的经验,它的行为有所不同,具体取决于是否需要编译的先决条件。

如果先决条件是最新的,则此代码可以正常运行,$^包含如下列表:

build/date.o build/jquery.autocomplete.o build/jquery.bullseye.o....

但是,如果先决条件需要全新编译,那么$^会删除目录部分,如下所示:

date.o jquery.autocomplete.o jquery.bullseye.o

只有需要重新编译的文件才会删除目录部分。

我设法通过替换

来解决这个问题

cat $^ > $(dest)$@

cat $(addprefix $(build), $(^F) ) > $(dest)$@

我不喜欢它,因为:

  1. 这是一个黑客
  2. $(^F)已被半弃用
  3. 我想了解为什么make会像这样。
  4. 感谢

1 个答案:

答案 0 :(得分:1)

看这里:

# Tell "make" to search build and destination dirs
vpath %.o $(build)

如果Make正在寻找foo.o,它将首先查看本地目录。如果在那里找不到foo.o,它会在$(build)中查找(即build/,您可能会重新考虑您的变量名称。)

如果Make foo.o无法在任何地方找到它,那该怎么办?有了这条规则:

%.o: %.js
    php  $(closure)  $*.js  $(build)$@

此规则违反了makefile的重要指南,因为目标(foo.o)不是实际构建的内容的名称(build/foo.o)。

现在考虑Make尝试执行此规则时会发生什么:

main.js: date.o ...
    cat  $^ > $(dest)$@

因此,如果date.o是最新的,那么它就在build/中。 Make在那里找到它,自动变量$^扩展为build/date.o ...

但是如果必须重建date.o,那么Make会查看%.o规则,该规则承诺构建date.o build/date.o) ,因此Make将该规则用于其中,$^扩展为date.o ...

有几种方法可以解决这个问题。我做这样的事情:

OBJS := date.o jquery.autocomplete.o jquery.bullseye.o ...
OBJS := $(addprefix $(build),$(OBJS))

$(dest)main.js: $(OBJS)
    cat  $^ > $@

# you might have to tinker with this rule a little
$(build)%.o: %.js
    php  $(closure)  $<  $@