automake-1.16: Flag Variables Ordering

 
 26.6 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 (⇒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, ⇒
 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
 ‘Makefile’s.
 
    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 ‘Makefile’s.
 
    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 (⇒Texinfo) use
 ‘MAKEINFOFLAGS’ and ‘AM_MAKEINFOFLAGS’.  Similarly, DejaGnu tests (⇒
 DejaGnu Tests) use ‘RUNTESTFLAGS’ and ‘AM_RUNTESTFLAGS’.  The tags and
 ctags rules (⇒Tags) use ‘ETAGSFLAGS’, ‘AM_ETAGSFLAGS’,
 ‘CTAGSFLAGS’, and ‘AM_CTAGSFLAGS’.  Java rules (⇒Java) use
 ‘JAVACFLAGS’ and ‘AM_JAVACFLAGS’.  None of these rules support
 per-target flags (yet).
 
    To some extent, even ‘AM_MAKEFLAGS’ (⇒Subdirectories) obeys
 this naming scheme.  The slight difference is that ‘MAKEFLAGS’ is passed
 to sub-‘make’s implicitly by ‘make’ itself.
 
    ‘ARFLAGS’ (⇒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.
 ⇒Program and Library Variables.