【问题标题】:GNU Make forgets prerequisites?GNU Make 忘记了先决条件?
【发布时间】:2010-07-12 07:42:54
【问题描述】:

这有点复杂,所以我上传了一个例子here

如何测试:

  • 下载压缩包并解压
  • cd make_problem/make
  • make aclean(忘记从存档中删除存档;))
  • make alib(将重新创建您刚刚删除的简单而愚蠢的存档)
  • ./weird.sh

奇怪的.sh 所做的只是触摸一个源文件,重新制作,触摸另一个源文件,重新制作,几次。

这是我使用 GNU Make 3.81 的 Linux 系统上的输出:

$ ./奇怪的.sh #### 1 #### gcc -c -g -Wall -Wextra -o ../swu/1/src/foo1.o ../swu/1/src/foo1.c ar cr ../make/libmine.a ../swu/1/src/foo1.o ==== 1 ==== gcc -c -g -Wall -Wextra -o ../swu/1/src/bar1.o ../swu/1/src/bar1.c ar cr ../make/libmine.a ../swu/1/src/bar1.o #### 2 #### gcc -c -g -Wall -Wextra -o ../swu/1/src/foo2.o ../swu/1/src/foo2.c ==== 2 ==== gcc -c -g -Wall -Wextra -o ../swu/1/src/bar2.o ../swu/1/src/bar2.c #### 3 #### gcc -c -g -Wall -Wextra -o ../swu/1/src/foo3.o ../swu/1/src/foo3.c ==== 3 ==== gcc -c -g -Wall -Wextra -o ../swu/1/src/bar3.o ../swu/1/src/bar3.c #### 4 #### gcc -c -g -Wall -Wextra -o ../swu/1/src/foo4.o ../swu/1/src/foo4.c ==== 4 ==== gcc -c -g -Wall -Wextra -o ../swu/1/src/bar4.o ../swu/1/src/bar4.c #### 5 #### gcc -c -g -Wall -Wextra -o ../swu/1/src/foo5.o ../swu/1/src/foo5.c ==== 5 ==== gcc -c -g -Wall -Wextra -o ../swu/1/src/bar5.o ../swu/1/src/bar5.c #### 6 #### gcc -c -g -Wall -Wextra -o ../swu/1/src/foo6.o ../swu/1/src/foo6.c ==== 6 ==== gcc -c -g -Wall -Wextra -o ../swu/1/src/bar6.o ../swu/1/src/bar6.c #### 7 #### gcc -c -g -Wall -Wextra -o ../swu/1/src/foo7.o ../swu/1/src/foo7.c ==== 7 ==== gcc -c -g -Wall -Wextra -o ../swu/1/src/bar7.o ../swu/1/src/bar7.c ar cr ../make/libmine.a ../swu/1/src/bar7.o #### 8 #### gcc -c -g -Wall -Wextra -o ../swu/1/src/foo8.o ../swu/1/src/foo8.c ==== 8 ==== gcc -c -g -Wall -Wextra -o ../swu/1/src/bar8.o ../swu/1/src/bar8.c $

现在我希望每次触及源时都会重新构建存档,但这显然没有发生。

谁能解释一下? 并解释如何确保它始终按预期工作?

【问题讨论】:

  • 使用 Solaris 10 和 GNU Make 3.80,它实际上似乎可以按预期工作。在 Linux 下,使用 GNU Make 3.80,我得到与上面相同的行为。有人知道 GNU Make 的平台相关问题吗?
  • 抱歉,上传的示例乱七八糟。它现在被更干净的版本取代(并且不需要最初的“make aclean”)
  • 如果问题被简化为问题中包含的一个小的 makefile 片段,我会赞成这个问题。

标签: gnu-make


【解决方案1】:

这里的问题是文件修改时间戳的分辨率相对较低,这会导致 make 在您非常快速地连续运行两次时感到困惑,就像您的 weird.sh 一样。

具体来说,weird.sh 将:

  1. 触摸foo1.c
  2. 运行 make,其中
    1. 重建foo1.o
    2. 重建libmine.a
  3. 触摸bar1.c
  4. 运行 make,其中
    1. 重建bar1.o
    2. 也许(见下文)重建libmine.a

如果步骤 2.2 和步骤 4.2 之间的时间小于文件系统的时间戳分辨率,则 make 会将 libmine.a 视为已经具有与 bar1.o 相同的时间戳,因此不会重建它。

Linux ext3 文件系统的时间戳分辨率为 1 秒。这个explanation from the maintainer of make 更详细地描述了这个问题,并且还提到了 Solaris 具有更好的时间戳分辨率,这可能解释了为什么您的示例在那里按预期工作。

如果在实际应用中这对您来说是个问题,您可以尝试使用具有纳秒分辨率时间戳的 ext4 文件系统。否则,只需在 weird.sh 中的每个 make 命令后加上 sleep 1,问题就会消失 :-)

【讨论】:

  • 谢谢,这让我对如何读取高分辨率时间戳有点好奇,因为它们不能位于正常的统计结构中。但这是一条支线。如果可以的话,我会在问题本身中给出一个简短的例子,但由于有很多文字,我认为这会更好。对不起,如果我想错了。
  • 在 stat 结构中添加了额外的字段来保存每个时间戳的纳秒部分。
猜你喜欢
  • 2016-01-03
  • 1970-01-01
  • 1970-01-01
  • 2012-02-21
  • 2021-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-04
相关资源
最近更新 更多