GNU Make 忘记了先决条件?

发布于 2024-09-08 11:44:07 字数 1954 浏览 3 评论 0原文

这有点复杂,所以我在此处上传了一个示例。

如何测试它:

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

weird.sh odd.sh 所做的只是简单地触摸一个源文件,重新制作,触摸另一个源文件,重新制作,几次。

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

$ ./weird.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

$

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

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

This is a bit complex so I have uploaded an example here.

How to test it:

  • Download the tarball and unpack it
  • cd make_problem/make
  • make aclean (forgot to remove the archive from the archive ;))
  • make alib (will re-create the simple and silly archive you just removed)
  • ./weird.sh

What weird.sh does is simply to touch a source file, re-make, touch another source file, re-make, a few times.

This is what the output looks like on my Linux system using GNU Make 3.81:

$ ./weird.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

$

Now I expected the archive be re-built every time a source was touched, but that evidently did not happen.

Can anyone explain this?
And explain how to make sure it always works as expected?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

穿越时光隧道 2024-09-15 11:44:07

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

具体来说,weird.sh 将:

  1. touch foo1.c
  2. run make,这
    1. 重建foo1.o
    2. 重建libmine.a
  3. touch bar1.c
  4. run make,其中
    1. 重建bar1.o
    2. 也许(见下文)重建libmine.a

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

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

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

The problem here is the relatively low resolution of file modification timestamps, which causes make to get confused when you run it twice in a row really quickly, like your weird.sh does.

Specifically, weird.sh will:

  1. touch foo1.c
  2. run make, which
    1. rebuilds foo1.o and
    2. rebuilds libmine.a
  3. touch bar1.c
  4. run make, which
    1. rebuilds bar1.o
    2. maybe(see below) rebuilds libmine.a

If the time between step 2.2 and step 4.2 is less than the timestamp resolution of your filesystem, then make sees libmine.a as already having the same timestamp as bar1.o, and so doesn't rebuild it.

The timestamp resolution for the Linux ext3 file system is 1 second. This explanation from the maintainer of make describes the problem in more detail, and also mentions that Solaris has better timestamp resolution, which probably explains why your example works as expected there.

If this is a problem for you in a real application, you might try the ext4 filesystem, which has nanosecond resolution timestamps. Otherwise, just put a sleep 1 after each make command in weird.sh, and the problem goes away :-)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文