我有一个autotools管理的项目(sscce tar.gz package here),具有以下结构:
我的configure.ac
是:
AC_INIT([foo], [1.0], [foo@bar.ba])
AM_INIT_AUTOMAKE([foreign -Wall -Werror])
AC_PROG_CC
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
我的Makefile.am
是:
bin_PROGRAMS = main
main_SOURCES = main.c foo.c foo.h
它编译并完美运行......但后来我注意到我的Makefile.am
不正确。它声明我的主要代码取决于foo.h
,但实际文件是foo/foo.h
。我改变了它,编译按预期工作,就像以前一样:
bin_PROGRAMS = main
main_SOURCES = main.c foo.c foo/foo.h
然而,它让我想知道:当依赖关系错误时它是如何工作的?它工作得很好,我甚至可以编辑foo/foo.h
,make
将重新编译相关文件。实际上,我甚至可以从依赖项中删除头文件......
bin_PROGRAMS = main
main_SOURCES = main.c foo.c
...它仍会被扫描,会触发重新编译相关文件。
所以,我的问题是:
Makefile
如何知道foo/foo.h
是make
调用期间要分析的依赖项?main_SOURCES
变量吗?make
不应该失败,因为我声明一个不存在的文件是依赖项?答案 0 :(得分:5)
查看automake manual。依赖计算在构建时完成,作为编译的副作用。 history of dependency tracking也可能对您有意义。请注意,这里的手册中有一个错误:它听起来像depcomp
被无条件调用,但事实并非如此(configure
时的测试检查编译器是否可以不使用它:参见@am__fastdepCC_TRUE@
中的Makefile.in
行。
所以会发生的事情是列出每个对象的依赖关系的文件存储在一个名为.deps
的隐藏子目录中。这些文件初始为空,并在编译相应的源文件时被覆盖。 (对于gcc
,这是通过-MD
和相关标志完成的。)
您绝对应该在main_SOURCES
变量中列出标题,这样Makefile
会在您运行make dist
(或者更好,make distcheck
)时对其进行打包。
make
将不会失败,因为您实际上并未列出main_SOURCES
行中的依赖项。 automake
将处理该分配,然后写出构建main
(仅依赖于目标文件)和各种目标文件(通过后缀规则)的规则。标题不是构建过程中任何内容的直接输入文件,因此您可以滑行。在示例项目上运行make dist
会出现错误:
make: *** No rule to make target `foo.h', needed by `distdir'. Stop.