26.5 Flag Variables Ordering

What is the difference between AM_CFLAGS, CFLAGS, and
mumble_CFLAGS?
Why does automake output CPPFLAGS after
AM_CPPFLAGS on compile lines?  Shouldn’t it be the converse?
My configure adds some warning flags into CXXFLAGS.  In
one Makefile.am I would like to append a new flag, however if I
put the flag into AM_CXXFLAGS it is prepended to the other
flags, not appended.

Compile Flag Variables

This section attempts to answer all the above questions. We will mostly discuss CPPFLAGS in our examples, but 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 ( these variables are also used for other languages like C++ or preprocessed Fortran). CPPFLAGS is the user variable (see Variables reserved for the user), 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, while debugging a C++ project, if 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 have the last say. In the example above, the desire is for the ‘CXXFLAGS=-O0’ to supersede any other switch from AM_CXXFLAGS or mumble_CXXFLAGS.

It’s true that not all options to all programs can be overridden. So in general, users could conceivably want to place options at arbitrary places in the command line, but Automake does not support this. It would be difficult to make such generality comprehensible. Being able to specify the final options commonly suffices.

Thus, 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 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 a per-target variable (like mumble_LDFLAGS) for some non-declared LIBFOO target.

Other Variables

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 RUNTESTFLAGS and AM_RUNTESTFLAGS. The tags and ctags rules (see Interfacing to etags) use ETAGSFLAGS, AM_ETAGSFLAGS, CTAGSFLAGS, and AM_CTAGSFLAGS. Java rules (see Java bytecode compilation (deprecated)) use JAVACFLAGS and AM_JAVACFLAGS. None of these rules support per-target flags (yet).

To some extent, even AM_MAKEFLAGS (see Recursing subdirectories) obeys this naming scheme. The slight difference is that MAKEFLAGS is passed to sub-makes implicitly by make itself.

ARFLAGS (see Building a library) is usually defined by Automake and has neither an AM_ nor a 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.