What is the difference betweenAM_CFLAGS
,CFLAGS
, andmumble_CFLAGS
?
Why does automake outputCPPFLAGS
afterAM_CPPFLAGS
on compile lines? Shouldn't it be the converse?
My configure adds some warning flags intoCXXFLAGS
. In one Makefile.am I would like to append a new flag, however if I put the flag intoAM_CXXFLAGS
it is prepended to the other flags, not appended.
This section attempts to answer all the above questions. We will
mostly discuss CPPFLAGS
in our examples, but actually the
answer holds for all the compile flags used in Automake:
CCASFLAGS
, CFLAGS
, CPPFLAGS
, CXXFLAGS
,
FCFLAGS
, FFLAGS
, GCJFLAGS
, LDFLAGS
,
LFLAGS
, LIBTOOLFLAGS
, OBJCFLAGS
, OBJCXXFLAGS
,
RFLAGS
, UPCFLAGS
, and YFLAGS
.
CPPFLAGS
, AM_CPPFLAGS
, and mumble_CPPFLAGS
are
three variables that can be used to pass flags to the C preprocessor
(actually these variables are also used for other languages like C++
or preprocessed Fortran). CPPFLAGS
is the user variable
(see User Variables), AM_CPPFLAGS
is the Automake variable,
and mumble_CPPFLAGS
is the variable specific to the
mumble
target (we call this a per-target variable,
see Program and Library Variables).
Automake always uses two of these variables when compiling C sources
files. When compiling an object file for the mumble
target,
the first variable will be mumble_CPPFLAGS
if it is defined, or
AM_CPPFLAGS
otherwise. The second variable is always
CPPFLAGS
.
In the following example,
bin_PROGRAMS = foo bar foo_SOURCES = xyz.c bar_SOURCES = main.c foo_CPPFLAGS = -DFOO AM_CPPFLAGS = -DBAZ
xyz.o will be compiled with ‘$(foo_CPPFLAGS) $(CPPFLAGS)’,
(because xyz.o is part of the foo
target), while
main.o will be compiled with ‘$(AM_CPPFLAGS) $(CPPFLAGS)’
(because there is no per-target variable for target bar
).
The difference between mumble_CPPFLAGS
and AM_CPPFLAGS
being clear enough, let's focus on CPPFLAGS
. CPPFLAGS
is a user variable, i.e., a variable that users are entitled to modify
in order to compile the package. This variable, like many others,
is documented at the end of the output of ‘configure --help’.
For instance, someone who needs to add /home/my/usr/include to the C compiler's search path would configure a package with
./configure CPPFLAGS='-I /home/my/usr/include'
and this flag would be propagated to the compile rules of all Makefiles.
It is also not uncommon to override a user variable at
make-time. Many installers do this with prefix
, but
this can be useful with compiler flags too. For instance, if, while
debugging a C++ project, you need to disable optimization in one
specific object file, you can run something like
rm file.o make CXXFLAGS=-O0 file.o make
The reason ‘$(CPPFLAGS)’ appears after ‘$(AM_CPPFLAGS)’ or
‘$(mumble_CPPFLAGS)’ in the compile command is that users
should always have the last say. It probably makes more sense if you
think about it while looking at the ‘CXXFLAGS=-O0’ above, which
should supersede any other switch from AM_CXXFLAGS
or
mumble_CXXFLAGS
(and this of course replaces the previous value
of CXXFLAGS
).
You should never redefine a user variable such as CPPFLAGS
in
Makefile.am. Use ‘automake -Woverride’ to diagnose such
mistakes. Even something like
CPPFLAGS = -DDATADIR=\"$(datadir)\" @CPPFLAGS@
is erroneous. Although this preserves configure's value of
CPPFLAGS
, the definition of DATADIR
will disappear if a
user attempts to override CPPFLAGS
from the make
command line.
AM_CPPFLAGS = -DDATADIR=\"$(datadir)\"
is all that is needed here if no per-target flags are used.
You should not add options to these user variables within
configure either, for the same reason. Occasionally you need
to modify these variables to perform a test, but you should reset
their values afterwards. In contrast, it is OK to modify the
‘AM_’ variables within configure if you AC_SUBST
them, but it is rather rare that you need to do this, unless you
really want to change the default definitions of the ‘AM_’
variables in all Makefiles.
What we recommend is that you define extra flags in separate
variables. For instance, you may write an Autoconf macro that computes
a set of warning options for the C compiler, and AC_SUBST
them
in WARNINGCFLAGS
; you may also have an Autoconf macro that
determines which compiler and which linker flags should be used to
link with library libfoo, and AC_SUBST
these in
LIBFOOCFLAGS
and LIBFOOLDFLAGS
. Then, a
Makefile.am could use these variables as follows:
AM_CFLAGS = $(WARNINGCFLAGS) bin_PROGRAMS = prog1 prog2 prog1_SOURCES = ... prog2_SOURCES = ... prog2_CFLAGS = $(LIBFOOCFLAGS) $(AM_CFLAGS) prog2_LDFLAGS = $(LIBFOOLDFLAGS)
In this example both programs will be compiled with the flags
substituted into ‘$(WARNINGCFLAGS)’, and prog2
will
additionally be compiled with the flags required to link with
libfoo.
Note that listing AM_CFLAGS
in a per-target CFLAGS
variable is a common idiom to ensure that AM_CFLAGS
applies to
every target in a Makefile.in.
Using variables like this gives you full control over the ordering of
the flags. For instance, if there is a flag in $(WARNINGCFLAGS) that
you want to negate for a particular target, you can use something like
‘prog1_CFLAGS = $(AM_CFLAGS) -no-flag’. If all of these flags had
been forcefully appended to CFLAGS
, there would be no way to
disable one flag. Yet another reason to leave user variables to
users.
Finally, we have avoided naming the variable of the example
LIBFOO_LDFLAGS
(with an underscore) because that would cause
Automake to think that this is actually a per-target variable (like
mumble_LDFLAGS
) for some non-declared LIBFOO
target.
There are other variables in Automake that follow similar principles
to allow user options. For instance, Texinfo rules (see Texinfo)
use MAKEINFOFLAGS
and AM_MAKEINFOFLAGS
. Similarly,
DejaGnu tests (see DejaGnu Tests) use RUNTESTDEFAULTFLAGS
and
AM_RUNTESTDEFAULTFLAGS
. The tags and ctags rules
(see Tags) use ETAGSFLAGS
, AM_ETAGSFLAGS
,
CTAGSFLAGS
, and AM_CTAGSFLAGS
. Java rules
(see Java) use JAVACFLAGS
and AM_JAVACFLAGS
. None
of these rules support per-target flags (yet).
To some extent, even AM_MAKEFLAGS
(see Subdirectories)
obeys this naming scheme. The slight difference is that
MAKEFLAGS
is passed to sub-makes implicitly by
make itself.
However you should not think that all variables ending with
FLAGS
follow this convention. For instance,
DISTCHECK_CONFIGURE_FLAGS
(see Checking the Distribution) and
ACLOCAL_AMFLAGS
(see Rebuilding and Local Macros),
are two variables that are only useful to the maintainer and have no
user counterpart.
ARFLAGS
(see A Library) is usually defined by Automake and
has neither AM_
nor per-target cousin.
Finally you should not think that the existence of a per-target
variable implies the existence of an AM_
variable or of a user
variable. For instance, the mumble_LDADD
per-target variable
overrides the makefile-wide LDADD
variable (which is not a user
variable), and mumble_LIBADD
exists only as a per-target
variable. See Program and Library Variables.