automake
[Top][All Lists]
Advanced

[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





reply via email to

[Prev in Thread] Current Thread [Next in Thread]