[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
RFC for new FAQ entry: Flag Variables Ordering
From: |
Alexandre Duret-Lutz |
Subject: |
RFC for new FAQ entry: Flag Variables Ordering |
Date: |
Tue, 30 Nov 2004 01:49:07 +0100 |
User-agent: |
Gnus/5.1003 (Gnus v5.10.3) Emacs/21.3.50 (gnu/linux) |
There have been questions and even bug reports about this
lately. So here is an attempt to document the difference
between CFLAGS, AM_CFLAGS, and mumble_CFLAGS, how they are
ordered, and how they should be (or not be) used.
Suggestions, clarifications, and corrections most welcome.
26.5 Flag Variables Ordering
============================
What is the difference between `AM_CFLAGS', `CFLAGS', and
`mumble_CFLAGS'?
Why does `automake' outputs `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.
This section attempts to answer all these 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', `RFLAGS', 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, `AM_CPPFLAGS' is the
default Automake variable, and `mumble_CPPFLAGS' is the variable
specific to the `mumble' target (we call this a per-target variable).
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 always is `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 other, 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
`Makefile's.
It is also not uncommon to override a user variable at `make'-time.
Many installers to 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)' on 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, that 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 the configure 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 what is needed here if no per-target flags are used.
You should also not add options to these variables from inside
`configure', for the same reason. Occasionally you need to modify
these variables to perform a test, but you should reset their value
afterward.
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', abd `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 be additionally
compiled with the flags required to link with `libfoo'.
Note that listing `AM_CFLAGS' into 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 on 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 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 calling the variable `LIBFOO_LDFLAGS' (with
an underscore), because that would cause Automake thinking that this is
actually a per-target variable (like `mumble_LDFLAGS') for some
non-declared `LIBFOO' target.
--
Alexandre Duret-Lutz
- RFC for new FAQ entry: Flag Variables Ordering,
Alexandre Duret-Lutz <=