2

如果 foo_user.cpp 依赖于 foo.h,则构建 foo_user.cpp,然后将 foo.h 的修改时间设置为更远的过去,make 不会重新构建 foo_user.cpp(因为 foo.cpp 是“较新的”)。如果 make 记录了依赖项的修改时间,并且如果它们完全改变(新的或旧的),我希望它认为该依赖项的目标已经过时。GNU 能做到这一点吗?如果没有,有没有简单的替代方案?

如果您好奇这种情况是如何产生的: foo.h 位于一个符号链接的文件夹中。符号链接可能指向傻瓜1.0 文件夹、傻瓜2.0 文件夹等。当符号链接指向不同版本的库时,即使是旧版本,也应该重建foo_user.cpp。如果我只是将 symlinkfolder/foo.h 指定为 foo_user.cpp 的依赖项,则 make 只关注 foo.h 的时间戳,而不是访问 foo.h 的符号链接目录的时间戳。我不能将符号链接本身添加为依赖项,因为 make 规则是由编译器生成的(GCC 有一个特殊的标志,当给定它时,它会为源文件所依赖的所有头文件输出一个 make 规则)。

4

4 回答 4

3

我试图理解为什么你不能只将符号链接添加为依赖项。我想您的自动依赖关系在一条线上,但您可以拥有任意数量的。

x.o: a.h b.h    
x.o: c.h    
x.o: d.h

但是话虽如此,似乎可能make会统计符号链接的目标,而不是符号链接本身,因此可能不是 DTRT。我想您可以在创建符号链接时在某处触摸文件,但我也想您已经想到了...

您可以运行一个规则,ls -id link/. > test它将链接目标目录的 inode 号放入test. 然后cmp test save,您可以save从上次运行的位置开始。make clean && make target然后,如果它们不同,则可以使用该 make 规则。

targetwrapper: 
    ls -id link/. > test
    cmp test save || make clean
    make realtarget
    cp test save

clean:
    echo cleaned

realtarget:
    echo made
于 2009-11-09T21:40:19.813 回答
2

不,Make 不支持这一点。您可能希望考虑使用另一个构建系统,例如SCons,它不仅仅依赖于时间戳,而是实际计算源文件的 MD5 哈希,并根据哈希做出决策。

来自“是什么让 SCons 变得更好?” 在其网站上:

  • 使用 MD5 签名可靠地检测构建更改;对传统时间戳的可选、可配置支持。
于 2009-11-09T21:35:54.847 回答
1

虽然make不支持开箱即用,但您可以对其进行编程。

include more_deps

ifneq ($(MAKE_RESTARTS),)

more_deps:
  if (foolink.old differs from what foolink points to) ; then \
    readlink foolink > foolink.old ; \
    echo "foo_user: foolink_trigger" > more_deps ; \
    touch foolink_trigger ; \
  else \
    echo "" > more_deps ;\
  fi

endif

foo_user: foo_user.cpp
  g++ $^ -o $@

在这里,您包含 makefile more_deps,它有时会包含对符号链接触发器的依赖关系。触发器是一种特殊的中间飞行,所有有意义的信息都是它的时间戳。当符号链接更改时,触发器的时间戳会更新为当前时间(请参阅touch参考资料),从而使 foo_user 过时并且它是重建的。

include并且MAKE_RESTARTS需要在计算上述依赖关系后重新启动make。如果包含的 makefile 本身是一个目标,则认为该目标被重新构建,被重新构建,然后 make 重新启动并重新读取 makefile。但是当它第二次读取 makefile 时,它​​并没有将more_deps其视为目标,因为MAKE_RESTARTS变量扩展为非空字符串。

事实上,if 语句听起来像这样:

more_deps:
  if (any condition you want with $(VARIABLES) possible!) ; then \
     update a file that holds the previous state ;\ 
     ...
于 2009-11-09T21:50:56.590 回答
0

您通过哪个过程更改符号链接?您可以向make clean更改符号链接的脚本添加一种操作。

您还可以设置一个“头文件工作文件夹”,让您复制头文件,其中复制的头文件取决于它们的原始文件和符号链接。GCC 生成的依赖项只考虑工作头文件,不会与您copy headers into the working folder的 Makefile 部分发生冲突。

于 2009-11-09T21:51:33.860 回答