how to use macro __GNUC__ and __GNUC_MINOR__ in configure.ac - c

I need to test the version of gcc in configure.ac, then I do this:
    
#if defined(__GNUC__) && (__GNUC__ > 3)
CFLAGS = xxxx  
#else
CFLAGS = xxxx
#endif 
but this failed, the CFLAGS in if expression is never used, and the gcc i'm using now is 4.1.2.
Then I wrote a simple c program to print out the __GNUC__ __GNUC_MINOR__, it works very well.
did I miss something? how can I use the two macros in configure.ac?     

That's not how autoconf works. autoconf.ac is not a C file that gets processed by the C preprocessor. Autoconf macros are something entirely different. You should look for a tutorial. If I remember correctly, this is a decent one. (Somebody will surely comment if it isn't :)
To check whether the compiler supports a particular flag, you should use the AX_CHECK_COMPILE_FLAG macro from the Autoconf Archive.

CFLAGS is reserved as an environment variable by the autotools. ./configure --help lists some others. Ideally, the user should supply the appropriate compiler flags, e.g.,
CC="gcc -std=c99" CFLAGS="-pipe -Wall -pedantic -O2" ./configure
and it's entirely reasonable to have a README file with the package if there are issues with different compilers. The best modern tutorial I'm aware of is the Autotools Mythbuster.
Now, if you want to proceed with this anyway as an interim solution, it is possible to modify CFLAGS...
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
[[#if defined (__GNUC__) && (__GNUC__ > 3)
#error "GCC4" /* not an actual error - just using the fail condition. */
#endif]])],
[CFLAGS=<your non-GCC4 flags here>], [CFLAGS=<your GCC4 flags here>])
If adding options to CFLAGS, this can be done with automake's CFLAGS primary - but that's another answer in itself.

Related

Compile with Clang and use GETTEXT

I have a automake enabled project which I would like to compile with clang. I have added a configure option to enable clang:
AC_ARG_ENABLE([clang],
[AS_HELP_STRING([--enable-clang],[use clang instead of gcc as C compiler.])])
#Use C99 compilation mode
if test "x$enable_clang" = "xyes"; then
# clang uses c99 mode by default, so we just set CC to clang and we are done
CC="clang";
else
# We do not need to set CC as the default is gcc, but we need to set it to
# use C99 compilation mode
CFLAGS="$CFLAGS -std=c99";
fi
Further up in the file I have also the following two macros, to enable gettext functionality:
AM_GNU_GETTEXT_VERSION([0.18.1])
AM_GNU_GETTEXT([external])
If these two macros are present then configure ignores that the CC variable is set to clang and falls back to gcc. I have to comment out the gettext macros and then clang is used.
Obviously there is some problem with GETTEXT and clang. Am I using the wrong macro, or is clang not able to use the gnu gettext library? How can I fix this?
Have you tried to set CC to clang before you check for libraries (like gettext)? – Some programmer dude
Nice that worked. – lanoxx

Program needs CFLAGS=-D_GNU_SOURCE added to compile, where should this go?

I have a project that uses autotools. I want to add -D_GNU_SOURCE when I compile the project. I could just hack this into the Makefile or configure script, but they get overwritten by configure.am and Makefile.am when I generate new ones before release.
Where is the right place to define this and what is the correct syntax, is there a macro I should be using?
You can can modify CFLAGS by adding a line like this to your configure.ac file:
CFLAGS="$CFLAGS -D_GNU_SOURCE"
then regenerate your configure script (this adds to the existing CFLAGS rather than replacing it, which it what you should do - so users can specify their own CFLAGS options when compiling and your script won't overwrite them).
However, for the specific case of _GNU_SOURCE, you should instead use the builtin autoconf macro:
AC_GNU_SOURCE
Place this early in your configure.ac file, before any rules that invoke the C compiler. Note that this doesn't add -D_GNU_SOURCE to CFLAGS, though - if you're using a configuration header (set with AC_CONFIG_HEADER) then it adds a definition for _GNU_SOURCE to that, and if you're not then it adds -D_GNU_SOURCE=1 to DEFS, which you can add to CFLAGS in your Makefile.
If you're using a configuration header (which for any non-trivial autoconf project, you probably should be) then it should be included before any system headers.

Where to add a CFLAG, such as -std=gnu99, into an autotools project

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'
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'.
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
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.

Is it possible to test whether a C define is declared in a gnu Makefile?

I want to include different directories in my build based on whether a #define is declared in a .h file in my project. Is this possible or am I going about this completely wrong?
Yes you are. The build system is supposed to configure the code, not vice-versa. You should use a configure script for this kind of options (or probably switch to a higher build system: autotools, CMake, QMake...).
The other answers have explained why this is a bad idea. Nonetheless, one way to do it is by preprocessing a makefile fragment:
In foo.mk.in:
#ifdef FOO
FOO_DEFINED := y
#else
FOO_DEFINED := n
#endif
In Makefile:
foo.mk: foo.mk.in
$(CPP) $(CPPFLAGS) -o $# $<
include foo.mk
ifeq ($(FOO_DEFINED),y)
$(warning FOO is defined)
else
$(warning FOO is not defined)
endif
It is possible, but you are going about this the wrong way. The way to include different directories is with different make targets. If your code has to know about them, use -D in your compiler switches. Alternatively, if your build needs to be able to run on other people's systems, something like autoconf is the way to go.

Why can't gcc find the random() interface when -std=c99 is set?

I do "#include <stdlib.h>" at the top of the source.
Example compilation:
/usr/bin/colorgcc -std=c99 -fgnu89-inline -g -Wall -I/usr/include -I./ -I../ -I../../ -I../../../ -I../../../../ -O3 -o f8 f8.c
In file included from f8.c:7:
ctype-cmp.c: In function ‘randomized’:
ctype-cmp.c:48: warning: implicit declaration of function ‘random’
ctype-cmp.c: In function ‘main’:
ctype-cmp.c:153: warning: implicit declaration of function ‘srandom’
ais#xcalibur:t$
When I turn off -std=c99, the function isfinite() can not be found. So I do want to use -std=c99 for this and other reasons. Is there some trick I'm missing?
man srandom says that the function is not part of C99 but part of POSIX.
Activate _BSD_SOURCE or _XOPEN_SOURCE >= 500 or any other suitable feature test macro that declares the srandom/random function (see man feature_test_macros and man srandom).
This one has good chances, but you need to figure out the macros that are defined/not defined implicitly thereby too by reading the manpages above.
/usr/bin/colorgcc -std=c99 -D_XOPEN_SOURCE=600 -fgnu89-inline -g -Wall
-I/usr/include -I./ -I../ -I../../ -I../../../ -I../../../../ -O3 -o f8 f8.c
Yes, there is a trick you are missing: you can use -std=gnu99 instead of -std=c99.
-std=c99 #defines __STRICT_ANSI__, which /usr/include/features.h interprets as "do not enable anything outside the C standard by default" (without it, you get at least both _SVID_SOURCE and _BSD_SOURCE). -std=gnu99, on the other hand, means "C99 plus GNU extensions" (the gcc default is currently -std=gnu89, its C89 equivalent, which is why you needed to specify something to get the new C99 features).
As an alternative, you can enable the feature test macros (as mentioned in #litb's answer). Looking at /usr/include/stdlib.h in my system, it expects one of __USE_SVID, __USE_XOPEN_EXTENDED, or __USE_BSD. /usr/include/features.h tells me that the feature test macros which would enable these are:
_SVID_SOURCE (enables __USE_SVID)
_BSD_SOURCE (enables __USE_BSD)
_XOPEN_SOURCE with a value of at least 500 (enables __USE_XOPEN_EXTENDED)
_XOPEN_SOURCE_EXTENDED (also enables __USE_XOPEN_EXTENDED)
_GNU_SOURCE (enables everything, including the four feature test macros above)
For new programs where you are not too concerned about potential name collisions with new functions from future standards, using both -std=gnu99 and -D_GNU_SOURCE is a good idea. It allows you to use all the new standard features and GNU extensions, which combined with some sort of fallback (for instance, autoconf-style feature tests) gives the most flexibility.
References:
Options Controlling C Dialect
Feature Test Macros
I've created random numbers using gcc in CodeBlocks under Ubuntu 9.10 (with compiler options: -std=gnu99 -D_GNU_SOURCE) So this worked for me:
This is my code I had played with:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
enum computer {keyboard, CPU, screen, printer};
int main(void)
{
enum computer comp;
time_t casovac;
comp = CPU;
srand(&casovac);
printf("%d", rand());
return 0;
}
This was only idea, of course you can accomplish it by other ways ;-) [To install CodeBlocks use: sudo apt-get install build-essential and then sudo apt-get install codeblocks]
I use rand() and srand(). BTW: Did you forget a header or two? At least the second warning tells me so.
Try including math.h. (Just remembered we always had issues with math library and had to actually force link it with -lm).

Resources