即使没有任何改变,makefile 也会重建静态库

Posted

技术标签:

【中文标题】即使没有任何改变,makefile 也会重建静态库【英文标题】:makefile rebuilds static library even if nothing changed 【发布时间】:2014-06-08 10:06:36 【问题描述】:

我正在做一个基于递归(有毒但无关紧要)的构建系统。我遇到的主要问题是,即使对 *o 文件没有任何更改,make 也会重新创建我指示它执行的库。

这是我的 makefile 中处理静态库创建的部分。

all: $(DEPS) $(OBJS) $(LIB_TARGET)

### Archive into a library file (.a)
%.a: $(OBJS)
    @echo $(MSG_L)
    @echo 'Adding $< to library $@'
    $(AR) $(ARFLAGS) $(LIB_DIR)/$@ $^
    @echo $(MSG_L)

在它们各自的makefile中的某些目录下,$(LIB_TARGET)是用库名定义的,每个子目录使用前缀makefile来知道如何创建它的共享。 现在我最大的问题是,第一次运行创建所有内容是正常的,但在第二次运行时,或者每次后续运行都没有对代码中的任何内容进行任何更改,重新创建库(但不是 *d 或 *o 文件,它们不是重新创建,它们没有被删除,它们的时间戳没有改变,这是正常的)。

make -C modules all
make[3]: Entering directory `F:/automata/tmp/remake/src/modules'
make -C interface all
make[4]: Entering directory `F:/automata/tmp/remake/src/modules/interface'
make -C cli all
make[5]: Entering directory `F:/automata/tmp/remake/src/modules/interface/cli'
------- make Lib -------
Adding cli.o to library libInterface.a
avr-ar rcs F:/automata/tmp/remake//tmp/app/brick/lib/atmega328p/libInterface.a c
li.o
------- make Lib -------

注意:这是第二次/第三次运行,这里可以看出 *d 和 *o 没有重新创建

我创建了使用文件的规则,我能看到的唯一问题是我将库放在一个特殊的目录中,而不是与它从中获取源的目录相同。 关于如何解决这个问题而不让系统也重新创建库的任何想法?

谢谢。

【问题讨论】:

【参考方案1】:

任何时候你看到一个配方创建的目标文件不是完全 $@,你知道这是错误的,你会遇到这个问题。

在这里,您告诉 make 您将创建一个与模式 %.a 匹配的目标。 make 将该模式匹配到 libInterface.a 并将 $@ 设置为 libInterface.a 并调用您的配方。

但是你的食谱没有构建$@,它构建了$(LIBDIR)/$@,这是一个完全不同的文件。所以下次你运行make时,它会寻找libInterface.a作为all的先决条件,看到它不存在,然后重新运行你提供的规则......这又不会创建你告诉 make 它会的目标,$@,而是创建一些其他文件,make 对此一无所知。

你需要使用:

LIB_TARGET = $(LIB_DIR)/libInterface.a

....

### Archive into a library file (.a)
$(LIB_DIR)/%.a: $(OBJS)
        @echo $(MSG_L)
        @echo 'Adding $< to library $@'
        $(AR) $(ARFLAGS) $@ $^
        @echo $(MSG_L)

【讨论】:

谢谢你的回答和教训。我对make的理解增加了很多逻辑。 另外,虽然它可能有效,但它有点......不寻常......根据我的经验,看到一个模式匹配规则 ($(LIB_DIR)/%.a) 在某处没有引用相应的模式: 的右侧...该规则可能只是$(LIB_TARGET): $(OBJS),我认为这会更清楚... 显然有一个问题我无法理解。除了需要从子目录中添加更多一个 *.o 文件的库之外,它工作正常。第一个 obj 文件添加正常,但有时会错过第二个。这很奇怪,因为它有时会添加,有时不会。 @weaz 你确定它在做什么?我注意到在上面的配方中,@echo 行引用了$&lt; 自动变量,而$(AR) 行使用了$^。所以也许,它是在报道一件事,做另一件事…… @twalberg 这些*.o 文件的主要问题是它们似乎比要制作的库本身更旧,因此没有添加和忽略它们。根据速度的微小差异以及我使用 Windows 的事实,这可能是导致有时行为正常而有时不正常的原因。 Prerequisite 'uart.o' is older than target 'F:/automata/tmp/remake//tmp/app/brick/lib/atmega328p/libHw.a'.

以上是关于即使没有任何改变,makefile 也会重建静态库的主要内容,如果未能解决你的问题,请参考以下文章

即使没有任何更改,Makefile也会编译文件

怎么编写Makefile生成静态库

如何防止 FutureBuilder 的重建,即使其潜在的未来没有改变

重建后的Makefile重新编译代码需要很多时间

如何强制生成文件重建目标?

为不同的架构重建静态库