5

I have an autotools-managed project (sscce tar.gz package here) with this structure:

./main.c
./foo.c
./foo/foo.h

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 Makefile know that foo/foo.h is a dependency to be analyzed during the make invocation?
  • Should I add the header files to the main_SOURCES variable?
  • Shouldn't make fail in the first case, since I am declaring that a non-existent file is a dependency?
brandizzi
  • 26,083
  • 8
  • 103
  • 158
  • Out of curiosity, are you omitting some details? How is `-I$(srcdir)/foo` getting into `CPPFLAGS`? – William Pursell Jul 24 '12 at 14:54
  • @WilliamPursell Well, I am omitting some details of my *real* scenario, but the example below compiles as expected. In this case, there is no need for `-I$(srcdir)/foo` because both `foo.c` and `main.c` includes the file with the dir name: `#include "foo/foo.h"` as seen [here](http://pastebin.com/p9d1XNcU). – brandizzi Jul 24 '12 at 18:02

1 Answers1

6

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 depcomp is unconditionally invoked, which is not the case (a test at configure time checks if your compiler can do without it: see the @am__fastdepCC_TRUE@ lines in Makefile.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. (For gcc, this is done via -MD and related flags.)

You should absolutely list your headers in the main_SOURCES variable, so that your Makefile will package them up when you run make dist (or better yet, make distcheck).

make won't fail if you list a non-existent header, because you're not actually listing the dependencies in your main_SOURCES line. automake will process that assignment and then write out the rules for building main (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. Running make dist on your sample project gives the error:

make: *** No rule to make target `foo.h', needed by `distdir'.  Stop.
Jack Kelly
  • 18,264
  • 2
  • 56
  • 81