< 上一个 | 内容 | 下一个 >

Recording Dependencies manually

Usually people are happy enough with BUILT_SOURCES because they never build targets such as ‘make foo’ before ‘make all’, as in the previous example. However if this matters to you, you can avoid BUILT_SOURCES and record such dependencies explicitly in the ‘Makefile.am’.

bin_PROGRAMS = foo foo_SOURCES = foo.c nodist_foo_SOURCES = bindir.h foo.$(OBJEXT): bindir.h CLEANFILES = bindir.h bindir.h: Makefile

echo ’#define bindir "$(bindir)"’ >$@

You don’t have to list all the dependencies of ‘foo.o’ explicitly, only those that might need to be built. If a dependency already exists, it will not hinder the first compilation and will be recorded by the normal dependency tracking code. (Note that after this first compilation the dependency tracking code will also have recorded the dependency between ‘foo.o’ and ‘bindir.h’; so our explicit dependency is really useful to the first build only.)

Adding explicit dependencies like this can be a bit dangerous if you are not careful enough. This is due to the way Automake tries not to overwrite your rules (it assumes you know better than it). ‘foo.$(OBJEXT): bindir.h’ supersedes any rule Automake may want to output to build ‘foo.$(OBJEXT)’. It happens to work in this case because Automake doesn’t have to output any ‘foo.$(OBJEXT):’ target: it relies on a suffix rule instead (i.e., ‘.c.$(OBJEXT):’). Always check the generated ‘Makefile.in’ if you do this.

Build ‘bindir.h’ from ‘configure

It’s possible to define this preprocessor macro from ‘configure’, either in ‘config.h’ (see Section “Defining Directories” in The Autoconf Manual), or by processing a ‘bindir.h.in’ file using AC_CONFIG_FILES (see Section “Configuration Actions” in The Autoconf Manual).

At this point it should be clear that building ‘bindir.h’ from ‘configure’ works well for this example. ‘bindir.h’ will exist before you build any target, hence will not cause any dependency issue.

The Makefile can be shrunk as follows. We do not even have to mention ‘bindir.h’.

bin_PROGRAMS = foo foo_SOURCES = foo.c

However, it’s not always possible to build sources from ‘configure’, especially when these sources are generated by a tool that needs to be built first.


Build ‘bindir.c’, not ‘bindir.h’.

Another attractive idea is to define bindir as a variable or function exported from ‘bindir.o’, and build ‘bindir.c’ instead of ‘bindir.h’.

noinst_PROGRAMS = foo foo_SOURCES = foo.c bindir.h nodist_foo_SOURCES = bindir.c CLEANFILES = bindir.c bindir.c: Makefile

echo ’const char bindir[] = "$(bindir)";’ >$@

bindir.h’ contains just the variable’s declaration and doesn’t need to be built, so it won’t cause any trouble. ‘bindir.o’ is always dependent on ‘bindir.c’, so ‘bindir.c’ will get built first.