How do I specify in a Makefile.am script that I only want to compile object .o files?

automake, gnu-make, makefile

Solution

Automake cannot build objects without an explicit target (program, library) that will use these objects. One reason is that compilation options are specified per-target. If two targets, e.g. two binaries use the same object but have different compilation option, the same object may have to be compiled twice.

You have three ways to do what you want, they all involve tying your source files to some target.

Do not use a `src/ctrnn/Makefile.am`, just make reference to the subdirectory source files from your `src/Makefile.am`:

bin_PROGRAMS = foo
foo_SOURCES = main.c crtnn/network.cpp crtnn/neuron.cpp

Note that this will build `network.o` and `neuron.o` in the same directory as `main.o`. If you want objects in subdirectories, use `AUTOMAKE_OPTIONS = subdir-objects`.

Use a convenience library. In `src/crtnn/Makefile.am` make a library of your two objects:

noinst_LIBRARIES = libcrtnn.a
libcrtnn_a_SOURCES = network.cpp neuron.cpp

and in `src/Makefile.am`, link your executable to the library:

bin_PROGRAMS = foo
foo_SOURCES = main.c
foo_LDADD = crtnn/libcrtnn.a
SUBDIRS = crtnn

It's called "convenience" when it is not going to be installed (you can tell because of the `noinst_` prefix): it is just used during the build. And this is a static library, so the result is the same as if you had replaced `crtnn/libcrtnn.a` by `crtnn/network.o` and `crtn/neuro.o` when linking `foo`.

Use a Libtool convenience library. This requires more setup if you are not using Libtool already. You should add a call `LT_INIT` in `configure.ac` and rerun `autoreconf` to install the libtool files. Then you can update `src/crtnn/Makefile.am` to make a library of your two objects as follows:

noinst_LTLIBRARIES = libcrtnn.la
libcrtnn_la_SOURCES = network.cpp neuron.cpp

and `src/Makefile.am` as follows:

bin_PROGRAMS = foo
foo_SOURCES = main.c
foo_LDADD = crtnn/libcrtnn.la
SUBDIRS = crtnn

What is the difference? you may ask, almost none. One advantage of using Libtool convenience libraries is that they can be nested: a Libtool library can include another Libtool library (this is convenient when you have a deep hierarchy of source code and you are building a library at each level). Also Libtool convenience libraries can be used to build a shared library if you want. Automake's static libraries cannot.

Problem

I have a `Makefile.am` which will be responsible for building a final application binary: ``` project/src/Makefile.am ``` Also in the src directory is a sub-directory called `ctrnn` which contains an additional `Makefile.am`: ``` project/src/ctrnn/Makefile.am ``` Now, `ctrnn/Makefile.am` should only generate object `.o` files with the idea being that the top-level `Makefile.am` should use the object files generated in subdirectory `ctrnn` to build the binary. This is the `ctrnn/Makefile.am`: ``` SOURCES = network.cpp\ neuron.cpp AM_CPPFLAGS= @CXXFLAGS@ ``` Based on this `Makefile.am` file, I want to end up with network.o and neuron.o. I am generating the according `Makefile` using Automake etc, yet when I try and then execute the make file, it doesn't do anything and just says: ``` make: Nothing to be done for `all' ``` I know why this is, I need to specify the build target. But how do I do this in the `ctrnn/Makefile.am` script given that I don't want to build a binary which would require `bin_PROGRAMS` but actual object files `network.o` and `neuron.o`? (Note if I do specify a bin_PROGRAMS name, it rightly ends up complaining of an undefined reference to main). What am I do wrong?

Original source