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?
$@ is the name of the target being generated, and $< the first prerequisite (usually a source file). You can find a list of all these special variables in the GNU Make manual.
A Makefile.am has the same syntax as an ordinary Makefile . When automake processes a Makefile.am it copies the entire file into the output Makefile.in (that will be later turned into Makefile by configure ) but will react to certain variable definitions by generating some build rules and other variables.
$(CC) $(CFLAGS) -I$(LIB_PATH) -L$(LIB_PATH) -o $(PROGRAM) main. c -l$(LIB) `pkg-config ...` Basically, you need set the include path to the . h file with -I, then -L for the lib path and -l to set the lib name.
It should be CFLAGS := -Wall -Wextra $(CFLAGS) , the difference is that CFLAGS is explicitly appended. So for example, you may set -Og , but user don't want optimization and passes CFLAGS=-O0 on command line. By using CFLAGS += -Og your -Og will take over the user provided value.
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.cppNote 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.cppand in
src/Makefile.am
, link your executable to the library:bin_PROGRAMS = foo foo_SOURCES = main.c foo_LDADD = crtnn/libcrtnn.a SUBDIRS = crtnnIt'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.cppand
src/Makefile.am
as follows:bin_PROGRAMS = foo foo_SOURCES = main.c foo_LDADD = crtnn/libcrtnn.la SUBDIRS = crtnnWhat 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.
You could simply specify source files in project/src/Makefile.am and not have a Makefile.am in ctrnn:
maude_SOURCES = ctrnn/network.cpp ctrnn/neuron.cpp
or you can use a libtool convenience library. In ctrnn/Makefile.am, put:
noinst_LTLIBRARIES = libctrnn.la libctrnn_la_SOURCES = network.cpp neuron.cpp
and in src/Makefile.am, put
LDADD = ctrnn/libmylib.la
If you aren't already using libtool, you'll also need to add LT_INIT to configure.ac.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With