31

I want to know how to set default compiler/linker/etc. flags if I use Autoconf/Automake combo.

For example, the default compiler flag is "-O2 -g" if I don't set anything. I can just override it with something else, for example if I want to debug:

./configure 'CXXFLAGS=-O0 -g'

But I find the default configuration stupid because if I enable optimization, debugging will become impossible. So the default flags should either be "-O2" or "-O0 -g", if I run configure without arguments. How do I do it?

Edit: I tried the following solutions:

  • Put progname_CXXFLAGS=whatever to Makefile.am. It doesn't work, because it adds the flags to the default flags instead of replacing them.
  • Put CXXFLAGS=whatever into configure.ac. This works, but then I can't override it later.
petersohn
  • 11,292
  • 13
  • 61
  • 98
  • 1
    @users-not-understanding-why-this-doesn't-work-in-a-C-project: CXXFLAGS should be CFLAGS when passed as an arg. to ./configure – legends2k Jun 14 '12 at 06:46

7 Answers7

22

According to autoconf manual (about AC_PROG_CC):

If using the GNU C compiler, set shell variable GCC to ‘yes’. If output variable CFLAGS was not already set, set it to -g -O2 for the GNU C compiler (-O2 on systems where GCC does not accept -g), or -g for other compilers. If your package does not like this default, then it is acceptable to insert the line

: ${CFLAGS=""}

after AC_INIT and before AC_PROG_CC to select an empty default instead.

Similarly, according to autoconf manual (about AC_PROG_CXX):

If using the GNU C++ compiler, set shell variable GXX to ‘yes’. If output variable CXXFLAGS was not already set, set it to -g -O2 for the GNU C++ compiler (-O2 on systems where G++ does not accept -g), or -g for other compilers. If your package does not like this default, then it is acceptable to insert the line

: ${CXXFLAGS=""}

after AC_INIT and before AC_PROG_CXX to select an empty default instead.

malex984
  • 329
  • 2
  • 5
9

If you merely want to have the default flags set for yourself whenever you run configure, there are (at least) 3 good ways to do it. Either set CXXFLAGS in your environment (eg in .login or .bashrc), use a CONFIG_SITE environment variable to specify a config file, or set the value you want for CXXFLAGS in $prefix/share/config.site. If you want to set the default flags to something other than '-O2 -g' for all users of your package, then you need to change what you want because doing so violates the principal of least surprise. Anyone familiar with autoconf expects the default flags to be -O2 -g and you should not change that.

Go with the 3rd option given above, and just do

$ echo 'CXXFLAGS="-O0 -g"' > /usr/local/share/config.site

(or redirect to wherever you typically set $prefix, eg $HOME/share/config.site) As an added bonus, this will set CXXFLAGS for all autoconfiscated projects that you configure, not just your own. (Assuming you set prefix appropriately. If you want a config.site to be valid for all projects regardless of prefix, then use a CONFIG_SITE setting)

William Pursell
  • 204,365
  • 48
  • 270
  • 300
7

Meanwhile I figured out how to do it. I will give an explanation to this.

The basic thing is that Autoconf substitutes shell variables in Makefile.in. The question is how do I get the value of these variables? The answer is that the initialization command substitutes variables that are told them at command line (like ./configure 'CXXFLAGS=-O0 -g'), and otherwise they are substituted by whatever command defines the default (for example, CXXFLAGS is set by AC_PROG_CXX) if they are not empty. So the solution is to set our new default before AC_PROG_CXX but after substitutions from the command lines are made. For example:

if test -z $CXXFLAGS; then
    CXXFLAGS='-O2'
fi
AC_PROG_CXX
petersohn
  • 11,292
  • 13
  • 61
  • 98
  • 11
    This solution completely violates the principal of least surprise. When running configure without explicitly setting CXXFLAGS, people expect CXXFLAGS to be set to '-g -O2'. If you want to change it for yourself, do so with a config.site. Do not make the change in configure.ac. It is the wrong place to do it. – William Pursell Jul 19 '10 at 07:06
  • 3
    Also (although this seems like an unusual use case), if a user explicitly sets CXXFLAGS to be empty (configure CXXFLAGS= --prefix ...), this code will override the user. Instead of testing that CXXFLAGS is empty, you should check if it is undefined with ": ${CXXFLAGS=-O2}' – William Pursell Jul 05 '11 at 15:08
  • 1
    Thanks. This is the solution I want too. I want to change the default optimization from -O2 to -O3 but allow people to make their own changes. – vy32 Jul 07 '12 at 14:05
  • 1
    What about `AM_CXXFLAGS`? – S.S. Anne Oct 06 '19 at 22:01
3

You can set target-specific defaults in the Makefile.am, or you can set the default in the configure.ac, and that'll apply to everything you build in the project.

See section 4.8.1 (and 5.10.4) in the autoconf manual.

Note the remarks in 4.8.1 about not second-guessing the eventual package user: if you do want to set flags that the user shouldn't be concerned with then set them using AM_CXXFLAGS, flags such as this that the user should be able to override should be set in CXXFLAGS.

But... do you really want to do this?

  1. You say 'debugging will become impossible'. Have you tried this and seen something go wrong? The compiler/debugger is possibly cleverer than you give it credit for.
  2. What's a good default for you at development time is not necessarily a good default for the eventual user at build time. If it really is necessary to turn off optimisation during development, then just configure your development system with ./configure CXXFLAGS='-O0 -g', exactly as you described. If your configure.ac is written correctly, that'll configure your build without optimisation whilst leaving the (good) default unchanged.

Short version: the way you're doing now is the right way.

Edited to add:

In general, if a shell variable appears as an argument to AC_SUBST (either explicitly or, as in the case of things like CXXFLAGS, implicitly within some other command), then it is substituted into the output files. That is, after AC_SUBST(foo), the value of the $foo variable in the ./configure script will be substituted into @foo@ instances.

Norman Gray
  • 11,978
  • 2
  • 33
  • 56
  • 2
    First, you didn't answer my question. You commented on why do I want to do it, and this is something I don't want to argue about, because it is not the point. The point is that I want to change default compiler flags. – petersohn Jun 25 '10 at 10:39
  • Fair enough. I hadn't really realised that your question was about the sh-mechanics of setting the variable, and I've edited in a possibly-useful extra remark about that. – Norman Gray Jun 27 '10 at 19:45
  • @NormanGray -O2 optimizes out a lot of variables, so yes, the debugger is not cleverer than the petersohn gives it credit for. – John Perry Oct 20 '17 at 22:30
  • You can of course outsmart the rules, but it's best not to. – Edward Hartnett Jun 23 '19 at 19:38
1

Building on the answers above, I added this to configure.ac:

AC_ARG_WITH(debug, [  --with-debug            add the debugging module], [AC_DEFINE(WITH_DEBUG,1,0)
AC_SUBST(WITH_DEBUG,1)
CXXFLAGS="-O0 -ggdb"])

It also defines WITH_DEBUG in the AC_CONFIG_HEADERS(config.h) and adds it to the Makefile with AC_SUBST().

0

On your Makefile.am you can define them with

programname_CXXFLAGS=-O0 -g

Updated: 20100628

You should try and add the CXXFLAGS in configure.in before calling AC_PROG_CXX. I did not test it, but your configure.in should look something like

AC_INIT
...
CXXFLAGS=-MY -FLAGS
...
AC_PROG_CXX

Please, let me know if this works since I am curious :-)

krico
  • 5,723
  • 2
  • 25
  • 28
  • 1
    I tried that one first. It doesn't work. It adds the flags to the default flags, so it produces "-O2 -g -O0 -g" or something similar. – petersohn Jun 25 '10 at 09:14
  • 3
    All configure.in files should be blank or non-existent. The name 'configure.in' has been obsolete for several years. 'configure.ac' is the correct name. – William Pursell Jul 01 '10 at 03:34
0

The points regarding not surprising the user are valid, but some flags are reasonable to turn on by default (e.g. -Wall -Wextra), and other flags are code base specific and are sometimes needed (e.g. -std=gnu99).

The question then becomes how to do this portably. I personally steal the flag check macros from the libuv project. To do this I add libuv-check-flags.m4 to the m4 directory of my project. I can then do the following in my configure.ac:

m4_include([m4/libuv-check-flags.m4])
AM_INIT_AUTOMAKE([-Wall -Werror foreign 1.11.2])

# Checks for programs.
AC_PROG_CC
CC_CHECK_CFLAGS_APPEND([-std=gnu99])
CC_CHECK_CFLAGS_APPEND([-Wall])
CC_CHECK_CFLAGS_APPEND([-Wextra])
AC_PROG_LIBTOOL

My generated configure file then produces a compiler command line of:

gcc -g -O2 -std=gnu99 -Wall -Wextra

I can still override the -g -O2 default using the solutions above, e.g.:

./configure CFLAGS='-O0 -g'

Produces a command line of:

gcc -O0 -g -std=gnu99 -Wall -Wextra

And leveraging gcc semantics I can still disable base flags if necessary. For example I can disable warnings if I really really want to with:

./configure CFLAGS='-Wno-all -Wno-extra'

You may say, "well what if the compiler doesn't support those flags?" That's why these macros are so useful and great, since they ensure compiler features are checked first, so -Wall and -Wextra wouldn't be added in the first place if they weren't supported.

libuv is one of the most portable and widely used C libraries on the planet, so I think following their lead is reasonable. And while these macros are pure C specific, adapting them for use with CXXFLAGS would be trivial.

References:

Dylan Cali
  • 1,463
  • 1
  • 13
  • 17