28

I have a simple Autotools C project (not C++).

CFLAGs (by inspection) seem to be -g -O2.

I want all of the generated make files to also have -std=gnu99 appended to the CFLAGs, because I use for (int i = 0; i < MAX; i++) and similar.

I can obviously hack the Makefile, but this gets overwritten on ./configure.

Where is the correct place to add (or change) CFLAGs which are required by the code (as opposed to those CFLAGs which the user might want to change)?

(Note this is partial duplicate of Where to add a CFLAG, such as -std=gnu99, into an (Eclipse CDT) autotools project as I was getting Eclipse-specific answers which I didn't want.)


@DevSolar's answer has not helped yet. A configure.ac file (below) generates the configure script (also below).

configure.ac:

dnl Process this file with autoconf to produce a configure script.

CFLAGS="$CFLAGS -std=gnu99"
AC_PREREQ(2.59)
AC_INIT(tuntest, 1.0)


AC_CANONICAL_SYSTEM
AM_INIT_AUTOMAKE()

AC_PROG_CC

AC_CONFIG_FILES(Makefile src/Makefile)
AC_OUTPUT

$ grep CFLAGS configure

CFLAGS
CFLAGS
To assign environment variables (e.g., CC, CFLAGS...), specify them as
  CFLAGS      C compiler flags
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_test_CFLAGS=${CFLAGS+set}
ac_save_CFLAGS=$CFLAGS
   CFLAGS="-g"
  CFLAGS=""
     CFLAGS="-g"
if test "$ac_test_CFLAGS" = set; then
  CFLAGS=$ac_save_CFLAGS
    CFLAGS="-g -O2"
    CFLAGS="-g"
    CFLAGS="-O2"
    CFLAGS=
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
Community
  • 1
  • 1
fadedbee
  • 42,671
  • 44
  • 178
  • 308
  • 3
    Maybe you want to set `CFLAGS` when do configure, for example: `./configure CFLAGS="-g -O2 -std=gnu99"`. – Jinghao Shi Jul 25 '12 at 10:30
  • 1
    Yes, that's what I'm currently doing. The CFLAG I wish to add `-std=gnu99` is essential, therefore I want it not be be something that the user has to configure. The code will not compile without it, so it must always be there, hence the question. – fadedbee Jul 25 '12 at 10:32
  • Then how about `./configure CC="gcc -std=gnu99"`? – Jinghao Shi Jul 25 '12 at 10:34
  • 3
    I want the **user** to not have to add `-std=gnu99` anywhere. It needs to be added as a result of configuration somewhere in one of the autotools files. My objective is for the user to do `./configure` `make` `sudo make install` as normal. – fadedbee Jul 25 '12 at 11:00
  • 2
    How about adding `CFLAGS` (or updating if it exists) in `configure.ac` or `configure.in`? – another.anon.coward Jul 25 '12 at 11:17
  • @another.anon.coward - This is what I'm looking for and I have tried various variants, but haven't made it work yet (I don't know autotools well and the syntax/semantics of these files are a mystery to me). Could you answer with a working example? – fadedbee Jul 25 '12 at 11:21
  • Do you have `configure.in` or `configure.ac` file in the project? Is it a particular open source project or something of your own? – another.anon.coward Jul 25 '12 at 11:24
  • @another.anon.coward It's something of my own. Yes, there are both `configure.in` and `configure.ac` files. I think autotools may generate one from the other, so I must be careful to use the 'upstream' file. I don't know which this is. Could you post an example of the syntax needed? – fadedbee Jul 25 '12 at 11:54
  • Note that I deleted my answer as the alternatives are much better. – DevSolar Jul 25 '12 at 13:19

3 Answers3

26

autoconf has a macro for this:

Just put:

AC_PROG_CC_STDC

after your AC_PROG_CC and everything will be right.

Especially when you use other compilers that do not have -std=gnu99 but operate in C99 mode by default (or have a different option hpcc's -AC99 springs to mind).

I would NOT use CFLAGS for that kind of thing.

From the docs:

-- Macro: AC_PROG_CC_STDC
If the C compiler cannot compile ISO Standard C (currently C99),
try to add an option to output variable `CC' to make it work.  If
the compiler does not support C99, fall back to supporting ANSI
C89 (ISO C90).

After calling this macro you can check whether the C compiler has
been set to accept Standard C; if not, the shell variable
`ac_cv_prog_cc_stdc' is set to `no'.
pevik
  • 4,523
  • 3
  • 33
  • 44
hroptatyr
  • 4,702
  • 1
  • 35
  • 38
  • 2
    How does this cooperate with GCC's `-std=c99` vs. `-std=gnu99`? – DevSolar Jul 25 '12 at 13:18
  • it will automatically use `-std=gnu99` if the compiler is gcc or supports it. – hroptatyr Jul 25 '12 at 13:19
  • 4
    Any chance of asking for *non-extended* behaviour (`-std=c99`) explicitly? (Not what OP asked for, just out of interest - I don't care for GNU extensions, personally.) – DevSolar Jul 25 '12 at 13:21
  • if you want gcc's `-std=c99` explicitly, just use `./configure CC="gcc -std=c99"` or put it in a profile. The macro will detect that and report compliancy. – hroptatyr Jul 25 '12 at 13:22
  • @DevSolar: Looking at the macro definition it is just a tiny hack to support a different default list – hroptatyr Jul 25 '12 at 13:27
  • 11
    If you want the latest standard, then `AC_PROG_CC_STDC` is the way to go. If you want C99 explicitly, then you want the `AC_PROG_CC_C99` macro instead. See here: http://www.gnu.org/savannah-checkouts/gnu/autoconf/manual/autoconf-2.69/html_node/C-Compiler.html#C-Compiler – Jack Kelly Jul 26 '12 at 09:14
4

Although using a macro like AC_PROG_CC_STDC is preferable to adding compiler options to CFLAGS, autoconf currently has no macros enabling C11 compiler support -- there is no AC_PROG_CC_C11 yet, and AC_PROG_CC_STDC only adds the -std=gnu99 option for gcc instead of -std=gnu11 or -std=c11.

You can add compiler flags simply by putting

CFLAGS="$CFLAGS -std=c11"

in the configure.ac.

Alternatively, it might be better to check first if the compiler supports the added option, and print a warning otherwise, telling the user to manually add an equivalent option to CFLAGS that works for their compiler:

AX_CHECK_COMPILE_FLAG([-std=c11],
  [AX_APPEND_FLAG([-std=c11])],
  [AC_MSG_WARN([-std=c11 not supported, you may have to set CFLAGS to enable C11 support.])
])

This uses the AX_CHECK_COMPILE_FLAG and AX_APPEND_FLAG macros found in the GNU Autoconf Archive. To use them, put them into an m4 subdirectory and add AC_CONFIG_MACRO_DIR([m4]) to configure.ac

kelvin
  • 1,421
  • 13
  • 28
dpi
  • 1,919
  • 17
  • 17
  • 1
    A slightly simpler way, although without the option to customize the warning message, is to use: AX_APPEND_COMPILE_FLAGS([-std=c11 -foo -bar]) – Eric Oct 16 '15 at 16:48
  • 2
    `CFLAGS+=" -std=c11"` - You should not be changing `CFLAGS`. The user owns them, not Autoconf or Automake. The answer lies in `AM_CFLAGS` and its per-target variants, but no one has provided an answer for it. @Arjun came close, but the answer was deleted. – jww Nov 04 '17 at 14:39
1

This topic is covered in the Automake manual, 27.6 Flag Variables Ordering. There an interaction between configure.ac and Makefile.am, and its more than just setting a well known shell variable used in implicit make rules.

The short of it is, you should set it in a new variable called something like mumble_CFLAGS discussed in the Automake manual. mumble is just the name of your program, and it is often foo or bar in other examples. Later, when your makefile is created, the recipe for your program (mumble or foo or bar) will use $(mumble_CFLAGS) $(CFLAGS) to build the target.

Here is an example of how it might look. Instead of using mumble or foo or bar, it uses my_prog as a artifact name.

configure.ac:

# Perform a compile test using -std=gnu99, set has_gnu99
if test "$has_gnu99" -eq "1"; then
  AC_SUBST([MY_GNU99], [-std=gnu99])
fi

Makefile.am:

bin_PROGRAMS = my_prog
my_prog_CFLAGS = $(MY_GNU99) $(MY_ANOTHER_FLAG) $(MY_YET_ANOTHER_FLAG) ...

Later, when the makefile is generated, it will have a recipe similar to the following, where $(MY_PROG_CFLAGS) is applied to all the objects that build my_prog:

my_prog :
    $(CC) $(CPPFLAGS) $(MY_PROG_CFLAGS) $(CFLAGS) -c $< -o $@

The extra indirections of my_prog_CFLAGS allows you to have multiple flags for different targets. For example, you could have a my_prog_CFLAGS, a my_archive_CFLAGS and a my_sharedobj_CFLAGS.

And its not limited to my_prog_CFLAGS. You could also have my_prog_CPPFLAGS, my_prog_CXXFLAGS and other variables used implicitly in makefiles.


This is from the Automake manual:

Compile Flag Variables

This section attempts to answer all the above 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, 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 (actually these variables are also used for other languages like C++ or preprocessed Fortran). CPPFLAGS is the user variable (see 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, 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.

jww
  • 97,681
  • 90
  • 411
  • 885