可以'make'检查依赖项的mtime是否在运行之间*不同*,而不仅仅是它是否比目标更新?

时间:2009-11-09 21:33:53

标签: build-process header makefile symlink

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

如果您对这种情况的出现感到好奇:foo.h驻留在符号链接文件夹中。符号链接可能指向foolib-1.0文件夹,foolib-2.0文件夹等。当符号链接指向库的不同版本时,即使是旧版本,也应该重建foo_user.cpp。如果我只是将symlinkfolder / foo.h指定为foo_user.cpp的依赖项,那么make只关注foo.h的时间戳,而不是注意访问foo.h的符号链接目录的时间戳。我不能将符号链接本身添加为依赖项,因为make规则是由编译器生成的(GCC有一个特殊的标志,当给定它时会导致它为源文件所依赖的所有标题输出一个make规则)。 p>

4 个答案:

答案 0 :(得分: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

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

clean:
    echo cleaned

realtarget:
    echo made

答案 1 :(得分:2)

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

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

  
      
  • 使用MD5签名可靠地检测构建更改;可选的,可配置的传统时间戳支持。
  •   

答案 2 :(得分: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,其中有时将包含对符号链接触发器的依赖。 Trigger是一个特殊的中间版本,所有有意义的信息都是它的时间戳。当符号链接发生更改时,触发器的时间戳会更新为当前时间(请参阅touch),从而使foo_user过时并且重建时间。

在计算上述依赖关系后,需要

includeMAKE_RESTARTS重启make。如果包含的makefile是目标本身,则认为目标是重建的,重建目标然后重新启动并重新读取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 ;\ 
     ...

答案 3 :(得分:0)

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

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