我正在试着调试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,所以目标/path/to/foo.a会多次更新。我们没有并行运行make,所以我认为文件的更新不会互相踩踏。似乎make故意不更新.a文件,尽管.o文件更新。制作foo.a的方法如下:
$(OBJLIB): $(OBJS)
$(AR) $(ARFLAGS) $(OBJLIB) $?
其中ARFLAGS = rv且OBJLIB为/path/to/foo.a。
我是否认为.o文件被视为仅限订单依赖项?还有什么我在这里不见了吗?我使用$(info)输出OBJLIB和OBJS的内容,并且没有错误的管道('|')字符进入变量内容,这将导致仅依赖顺序的依赖。
答案 0 :(得分:1)
不幸的是,答案与make无关。据我所知,文件系统是真正的罪魁祸首。有几个人在构建中取得了成功,但事实并非如此。我们使用通用构建环境的系统之间的区别在于我在使用ext4文件系统时在ext3文件系统上构建。
由于ext3不支持sub-1s时间戳(ext4),在某些情况下,当仅使用少量CPP文件调用规则时,它们在同一秒内被编译,之前的调用更新了存档,一切都是以相同的时间戳结束。将目录复制到ext4文件系统修复了该问题。
真正的解决方法是编写一套合适的制作规则,但至少我们有一个答案,说明为什么除了我之外它对每个人都有效。
答案 1 :(得分:0)
您提到了.a文件的几个更新,因为make在不同的子目录中被调用。可能是消息
No need to remake target `/path/to/foo.a'
来自一个子目录,而is newer
来自另一个子目录。考虑在一个步骤中从所有对象构建lib。
答案 2 :(得分:0)
试试这个。
$(OBJLIB): $(OBJS)
$(AR) $(ARFLAGS) $(OBJLIB) $^
你的问题是变量$?是 newer 的依赖项列表而不是目标,而$ ^是所有依赖项的列表。
此外,您可以使用$ @来更加惯用。
$(OBJLIB): $(OBJS)
$(AR) $(ARFLAGS) $@ $^