0

我正在拔头发试图调试 make 的问题。似乎 make 将某些先决条件随机视为仅订单先决条件,导致它们被排除在依赖它们的静态库目标之外。大多数时候,构建工作会找到,但偶尔会构建一些 .cpp 文件,但不包含在 .a 中。当我使用 --debug 运行 Make 时,我看到了可疑先决条件的以下输出。

Prerequisite `blah.o' is newer than target `/path/to/foo.a`
Prerequisite `blah1.o' is newer than target `/path/to/foo.a`
Prerequisite `blah2.o' is newer than target `/path/to/foo.a`
No need to remake target `/path/to/foo.a'

对于确实进入.a的所有先决条件,最后一行是“必须重新匹配目标/path/to/foo.a”,正如我所期望的那样。

因为 make 在几个子目录中被调用,所以 target /path/to/foo.a 被更新了几次。我们没有并行运行 make,所以我认为文件的更新不会相互影响。尽管 .o 较新,但似乎 make 故意不更新 .a 文件。制作 foo.a 的配方如下:

$(OBJLIB): $(OBJS)
    $(AR)     $(ARFLAGS) $(OBJLIB) $?

其中 ARFLAGS=rv 和 OBJLIB 将是 /path/to/foo.a。

我认为 .o 文件被视为仅订单依赖项是否正确?还有什么我在这里想念的吗?我正在使用 $(info) 输出 OBJLIB 和 OBJS 的内容,并且没有错误的管道 ('|') 字符进入变量内容,这会导致仅顺序依赖。

4

3 回答 3

1

不幸的是,答案与make无关。据我所知,文件系统是真正的罪魁祸首。有几个人在构建过程中取得了成功,但我没有。我们使用通用构建环境的系统之间的区别在于,我是在 ext3 文件系统上构建的,而他们使用的是 ext4 文件系统。

由于 ext3 不支持 sub-1s 时间戳(ext4 支持),因此在某些情况下,当仅使用几个 CPP 文件调用规则时,它们会在之前的调用更新存档的同一秒内被编译,并且一切都以相同的时间戳。将目录复制到 ext4 文件系统解决了这个问题。

真正的解决办法是编写一套适当的 make 规则,但至少我们知道为什么它对除了我以外的所有人都有效。

于 2013-06-11T02:07:15.600 回答
0

试试这个。

$(OBJLIB): $(OBJS)
    $(AR)     $(ARFLAGS) $(OBJLIB) $^

你的问题是变量 $? 是比目标更新的依赖项列表,而 $^ 是所有依赖项的列表。

此外,您可以使用 $@ for 更加地道。

$(OBJLIB): $(OBJS)
    $(AR)     $(ARFLAGS) $@ $^
于 2013-06-10T20:17:38.427 回答
0

您提到了对 .a 文件的一些更新,因为在不同的子目录中调用了 make。应该是消息

No need to remake target `/path/to/foo.a'

来自一个子目录,并且is newer- 来自另一个。考虑一步构建所有对象的库。

于 2013-06-10T20:14:13.037 回答