I have an autotools-managed project (sscce tar.gz package here) with this structure:
My configure.ac is:
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
My Makefile.am were:
bin_PROGRAMS = main
main_SOURCES = main.c foo.c foo.h
It compiled and ran perfectly… but then I note my Makefile.am was not correct. It stated that my main code depended upon foo.h, but the real file was foo/foo.h. I changed it, and the compilation was working as expected, as it was before:
bin_PROGRAMS = main
main_SOURCES = main.c foo.c foo/foo.h
However, it made me wonder: how did it work when the dependencies were wrong? It worked so well that I could even edit foo/foo.h and make would recompile the dependent files. Actually, I could even remove the header file from the dependencies…
bin_PROGRAMS = main
main_SOURCES = main.c foo.c
…and it would be still scanned an would trigger the recompilation of dependent files.
So, my questions are:
- How does the autotools-generated
Makefileknow thatfoo/foo.his a dependency to be analyzed during themakeinvocation? - Should I add the header files to the
main_SOURCESvariable? - Shouldn’t
makefail in the first case, since I am declaring that a non-existent file is a dependency?
Have a look at the automake manual. Dependency computation is done at build time, as a side-effect of compilation. The history of dependency tracking might also be interesting to you. Note that there’s an error in the manual here: it makes it sound like
depcompis unconditionally invoked, which is not the case (a test atconfiguretime checks if your compiler can do without it: see the@am__fastdepCC_TRUE@lines inMakefile.in.So what happens is that files listing the dependencies of each object are stored in a hidden subdirectory called
.deps. These files are initally empty and get overwritten as their corresponding source file is compiled. (Forgcc, this is done via-MDand related flags.)You should absolutely list your headers in the
main_SOURCESvariable, so that yourMakefilewill package them up when you runmake dist(or better yet,make distcheck).makewon’t fail if you list a non-existent header, because you’re not actually listing the dependencies in yourmain_SOURCESline.automakewill process that assignment and then write out the rules for buildingmain(which will depend on object files only) and the various object files (via a suffix rule). The headers aren’t the direct input file to anything in the build process, so you skate by. Runningmake diston your sample project gives the error: