You say you're interested in
how to create makefile.am files for each subdirectories so that autotool can build the project in the build directory
, but this is not an appropriate goal, as this example itself demonstrates. It is rarely useful or appropriate to have a Makefile.am
that does not define any targets to be built. You have stipulated that you don't want to build Pet as a library, so what target would a Makefile.am
in its directory define? Similar applies to Dog
if you want to avoid building it as a library. There is little or no point to using recursive make
in this situation.
I do note, however, that Automake has the concept of a "convenience library", which is an intermediate target that is never itself installed, but contains object code that can be linked into an executable or a larger library. I will demonstrate this later, as it's the most sensible way to set up the makefile-per-directory structure you are asking for in this particular case.
Additionally, with respect to directing the output to a specific directory in the source tree: this can be done, but it is probably a waste of effort. The Autotools already provide a convenient method for out-of-source building that more easily accomplishes the goal of separating the build results from the source in the event that the person building the project wishes to do that.
NEVERTHELESS, the basics of recursive builds with the Autotools are pretty simple. There are two main things to do:
each Makefile.am
that wants to express a recursion into one or more subdirectories does so by listing the relative paths to each of those subdirectories in the variable SUBDIRS
.
the project configure.ac
must designate of the Makefile
s to be built via its AC_CONFIG_FILES
macro.
That's all you need to do to set up the recursion generally, and the details of how to set up specific targets and options are project-specific.
- Is that possible we build the hello.exe at
build
directory instead of build/HelloWorld/
directory? To do this, do I have to put
the bin_PROGRAMS
at the ./Makefile.am
Yes, you can specify building into build/hello
rather than build/HelloWorld/hello
. You might not strictly have to put the corresponding bin_PROGRAMS
into the top-level Makefile.am
, but you definitely should put it there or in a build/Makefile.am
file. I urge you to avoid trying to have any makefile build targets outside the tree rooted at the directory where that particular makefile resides.
- I do not want to build Pet as librarys, I'm wondering whether there is a way I can just tell automake to find source codes in
different locations.
You can absolutely specify source files in a different directory from the Makefile.am
. Just provide the appropriate path, relative to the makefile's directory. This makes more sense for sources in the same tree as the makefile, but using sources located elsewhere is not as much of an issue as trying to build targets elsewhere.
- I know that using non-recursive makefile would be easier. But I just want to learn how to create recursive makefiles for multiple
directories.
Non-recursive makefiles are not necessarily easier than recursive ones, but they are generally better, because they express the whole target / prerequisite tree as a unit instead of chopping it up into pieces. make
can make better build decisions when it has all the information at once.
I just started learning automake things, and I know these codes do not
work at all.
My answer to your related question provides a recursive solution to a related problem. It demonstrates one of the key principles that you seem to be missing: the variables specifying a target's sources and other build properties need to appear in the same Makefile.am
file in which the target itself is defined. Each Makefile.am
corresponds to a separate makefile. To a first approximation, data are not shared between makefiles, so all the information needed to build a given target needs to appear in the same one.
The other thing that seems to distinguish this question from your other is that you want (however wrongheadedly) to specify a particular output directory in your makefile. Do remember that wherever the built files initially go, it is a staging area -- it doesn't much matter, because they get put in their final destination by make install
. Even so, you can specify a target residing in a different directory by giving the correct relative path to it. Of course, such a change to the target name needs to be reflected in the names of the variables derived from the target name.
Here, then, is a recursive Automake setup that should build your example project using one makefile per source directory:
Makefile.am
SUBDIRS = Pet HelloWorld
# Note: specifying output into a different directory
bin_PROGRAMS = build/hello
# Note the form of the following names:
build_hello_SOURCES = HelloWorld/main.cpp
build_hello_CPPFLAGS = -I$(srcdir)/Pet -I$(srcdir)/HelloWorld/Dog
# Note that library order matters
build_hello_LDADD = HelloWorld/Dog/libDog.a Pet/libPet.a
Pet/Makefile.am
noinst_LIBRARIES = libPet.a
libPet_a_SOURCES = \
Pet.cpp \
Pet.h
HelloWorld/Makefile.am
SUBDIRS = Dog
# No own targets defined here, just the recursion into Dog. This could have been
# skipped altogether, but I'm sticking to the letter of one Makefile.am per source
# directory.
HelloWorld/Dog/Makefile.am
noinst_LIBRARIES = libDog.a
libDog_a_SOURCES = \
Dog.cpp \
Dog.h
libDog_a_CPPFLAGS = -I$(top_srcdir)/Pet
Your configure.ac
ought to work with that as-is.
Note this does not rely on VPATH
; it builds specifically into the build/
subdirectory of the build tree, including when you build directly in the source tree.