Adding a dependency for a target in automake - automake

I've run into a problem with automake that I can't seem to find a clean solution for, which seem like it should be possible (even simple), but nothing simple works.
Basically the problem I have is with a source file that includes an autogenerated header file. I can add the dependencies to generate the header file just file, and once the header exists, everything works, as automake's auto dependency generation takes care of everything. The problem is the first time you run make in a clean tree, the dependency files don't exist, so automake doesn't know to generate the header file, which makes the compile of the file including the header fail without generating any dependencies. Its a chicken-and-egg problem -- you need to manually tell (auto)make to build the header file.
The obvious solution is just to add a dependency to the Makefile.am file for the header, but that doesn't work, since having a dependency for a target override automake's automatic rule generation, as the docs say:
Note that Automake does not make any distinction between rules with commands and rules that only specify dependencies. So it is not possible to append new dependencies to an automake-defined target without redefining the entire rule.
For now I've hacked around the problem by 'hiding' the dependency from automake, but this only works for GNU-make:
Makefile.am:
bin_PROGRAMS = foo
foo_SOURCES = main.c foobar.c baz.c
gen.h: system.spec
...command to regen gen.h
# foobar.c #includes gen.h, so it needs to exist prior to compiling foobar.c
$(eval foo-foobar.o: gen.h)
This does the trick, but seems ugly. Is there a better automake-safe way of doing this?

Automake supplies BUILT_SOURCES to solve this problem. Files added to this are built before ordinary compilations are done -- it is specifically intended for generated headers and sources.
In your case this should suffice:
BUILT_SOURCES = gen.h

sample Makefile.am should be like
bin_PROGRAMS = foo
foo_SOURCES = main.c foobar.c baz.c
nodist_foo_SOURCES = gen.h
BUILT_SOURCES = gen.h
CLEANFILES = gen.h
gen.h: Makefile system.spec
command to regen gen.h
#above line should begin with a <TAB>

Related

Include Makerules from sub.mk with Makefile.am

is it possible to not generate the Makerules from Makefile.am, but include the Makerules from a predefined sub.mk?
Well, I have a big Makefile-Project i want to build a custom App for.
Building an App for this project is done with a Makefile in the following structure:
PROJDIR ?= ../..
TARGET = myApp
SRC_C = main.c
include $(PROJDIR)/prog.mk
The actual makerules are hidden somewhere in prog.mk which requires the variables TARGET, SRC_C etc.
Now, i want to use an independent Automake project to generate the Makefile of my App.
Is it even possible to let Makefile.am generate a Makefile like the one above?
Can someone provide an example for this?
No, automake by design is not going to generate anything close to that, since it's a full stack to define your targets and it'll take care of building them.
You can use autoconf alone, by writing a template Makefile.in and have it substitute the variables you figure out at ./configure time, but that means you're essentially on your own to write the structure.

Configure automake to install extra programs

My project is a library and automake is configured to build it and test it. There is also additional target which builds demo application for my library. It's defined in Makefile.am as EXTRA_PROGRAMS. I'd like to be able to install with make install or similar. Is there a way to do it but still keep optionality of this target (i.e. simply defining this target in bin_PROGRAMS will make this target required)?
The usual way to do this sort of thing is to have configure substitute the value into bin_PROGRAMS conditionally. In your Makefile.am this would look like:
bin_PROGRAMS = main-program $(test_program)
EXTRA_PROGRAMS = test-program
Then in configure.in you'd do something like:
if mumble; then
test_program=test-program
fi
AC_SUBST(test_program)

Compile subdir-objects multiple times

Automake 1.14 is causing us a few issues. At first, automake errored with the complaint:
warning: source file 'X' is in a subdirectory but option 'subdir-objects' is disabled
So I enabled subdir-objects, but now it isn't recompiling some files. For example, lets say
src/a/foo.c is compiled in SUBDIR a but in src/b, I would like to compile it again with different preprocessor flags, however since ../a/foo.o already exists, make doesn't rebuild it. This is because subdir-objects changes am_b_OBJECTS to look for ../a/foo.o instead of foo.o. Is there a way I can get around the original complaint and instruct make to build the file a second time with the appropriate preprocessor flags? This all worked on previous versions of automake.
I would settle for executing rm ../a/foo.o before compiling src/b but I don't know how to edit the Makefile.am to make that happen.
This happens if you're using subdir-objects under the same tree from different Makefile.am files. As automake can't see you're using the same source file with different parameters it'll assume it was rebuilt correctly.
The proper solution to this is to not use separate Makefile.am files and instead rephrase the build system as non-recursive automake and so in that case it would then build foo.c as foo-a.o and foo-b.o.

How to create a non-transitive dependency list (GCC)

Is there a way to generate dependencies of a C(++) source file similar to using the -MM option of GCC that only include the direct dependencies of said file, i.e. only the files directly included by this source file?
More context on why I'm looking for this functionality - maybe there is a completely different solution to my problem: I have a generic makefile with auto-detection of dependencies that suffices my needs but is slow. The basic structure is as follows:
Full dependencies of main.cpp are retrieved with gcc -MM
All *.h dependencies for which a corresonding *.cpp exists are changed to *.o dependencies
the altered dependencies are included in the makefile
All *.o targets are built, dependencies are retrieved with gcc -MM and included
All *.o targets are linked to create the executable
So far, this makefile has worked fine but -as said before- it is slow. I analyzed its execution path for one project and included all the generated dependencies by hand to try and optimize its speed. The result was by removing all transitive dependencies, the makefile retained its functionality but got much faster (also reflected in the number of lines of the debug output of make -d).
First of all, the method you are using is slightly confusing. All .h files used in the compilation of one .cpp file must be kept in its dependencies, and the automatic collection of *.o files shouldn't be that slow. I'd advise to go with classic -MM and to build the list of cpp files that are to be compiled by hand. automake does it that way, and if there was a really reliable way of figuring out the list of compilation units automatically, these guys would have found it :-).
Nevertheless, the -H option of the gcc helps you. It prints the names of all used files to stderr, with . prefixed for the level of inclusion. So,
cpp -I $< >/dev/null | sed -n -e 's/^\. //p'
should do the trick. Caveat: If a header file is included deeper in the hierarchy first and then later in the main file, it is not found. However, your dependency system should be able to handle that if you keep the 1-to-1 of .h and .cpp files.

How to create dependencies in automake?

I have a Makefile.am file right now that looks like this:
lib_LIBRARIES = foo.a
foo_a_SOURCES = bar.F90 baz.F90
When compiled, bar.F90 gives bar.o. However, bar.F90 depends on several other Fortran files (cat.F90, dog.F90, pig.F90). I want to set up Automake to rebuild bar.o if the source of one of these dependencies change.
I've been reading the GNU manuals for automake/autoconf and was unable to find a solution to this. Thanks for reading.
Automake tracks most source-level dependencies automatically as described in the Dependencies section of its manual. If you already knew that and experimentation has shown that it isn't working you will likely have to override the bar.o target to add dependencies as described in the Extending section.

Resources