I'm working on Solaris with SunCC. Autoconf's AC_COMPILE_IFELSE and AC_LINK_IFELSE are misdetecting compiler features. Autoconf is reporting features are available even though the compiler rejects them with messages such as illegal option.
$ echo 'int main(int argc, char* argv[]) {}' > test.C
$ /opt/solarisstudio12.4/bin/CC test.C
$ /opt/solarisstudio12.4/bin/CC -msse4.2 -msha test.C
CC: Warning: Option -msse4.2 passed to ld, if ld is invoked, ignored otherwise
CC: Warning: Option -msha passed to ld, if ld is invoked, ignored otherwise
ld: fatal: option '-h a' is incompatible with building a dynamic executable
$ /opt/solarisstudio12.4/bin/CC -xarch=sha test.C
CC: Warning: illegal use of -xarch option, illegal value ignored: sha
I'd like to try to workaround the misdetections, but I need to know the compiler to do it. Autoconf has some macros that provide canonicalized names for CPU, Vendor and OS, but they do not appear to include the compiler or its vendor.
How do we detect or determine compiler name or vendor in Autoconf?
Adding the following is not really helpful since it does not identify the compiler.
AC_MSG_NOTICE(["Build: $build"])
AC_MSG_NOTICE(["Compiler: $compiler"])
Then:
CXX=/opt/solarisstudio12.4/bin/CC ./configure
...
configure: "Build: i386-pc-solaris2.11"
configure: "Compiler: /opt/solarisstudio12.4/bin/CC"
I don't think there is a standard way to do this.
We manually check for the existence of compiler macros according to predef.sourceforge.net and perhaps more sources like cc --version, the cc's command name, the operating system name, ...).
I.e. you compile a program, and check for defines.
If it doesn't exist / the programm #errors out -> not SunCC.
It looks messy, but here is an example straight from the Score-P source (vendor/common/build-config/m4/ax_compiler_vendor.m4). Maybe you can take some inspiration from it:
AC_DEFUN([AX_COMPILER_VENDOR],
[AC_CACHE_CHECK([for _AC_LANG compiler vendor], ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor,
dnl Please add if possible support to ax_compiler_version.m4
[# note: don't check for gcc first since some other compilers define __GNUC__
vendors="intel: __ICC,__ECC,__INTEL_COMPILER
ibm: __xlc__,__xlC__,__IBMC__,__IBMCPP__
pathscale: __PATHCC__,__PATHSCALE__
clang: __clang__
cray: _CRAYC
fujitsu: __FUJITSU
gnu: __GNUC__
sun: __SUNPRO_C,__SUNPRO_CC
hp: __HP_cc,__HP_aCC
dec: __DECC,__DECCXX,__DECC_VER,__DECCXX_VER
borland: __BORLANDC__,__CODEGEARC__,__TURBOC__
comeau: __COMO__
kai: __KCC
lcc: __LCC__
sgi: __sgi,sgi
microsoft: _MSC_VER
metrowerks: __MWERKS__
watcom: __WATCOMC__
portland: __PGI
tcc: __TINYC__
unknown: UNKNOWN"
for ventest in $vendors; do
case $ventest in
*:) vendor=$ventest; continue ;;
*) vencpp="defined("`echo $ventest | sed 's/,/) || defined(/g'`")" ;;
esac
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,[
#if !($vencpp)
thisisanerror;
#endif
])], [break])
done
ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor=`echo $vendor | cut -d: -f1`
])
])
As #Ronny stated, there does not appear to be a standard way to determine the compiler vendor. Detecting a vendor is important during configure for tasks like working around Autoconf bugs during misdetection: CC: Warning: illegal use of -xarch option, illegal value ignored: sha.
#Ronny showed how to do it with preprocessor macros. We avoided that because of the way compilers pretend to be GCC. Both Clang and Intel's compiler defines __GNUC__, and probably others do it, too.
Here's how to do it with version strings in configure.ac:
## Determine the compiler's vendor.
COMPILER_VERSION=`"$CXX" --version 2>/dev/null`
## IBM xlC test if COMPILER_VERSION is empty
if test x"$COMPILER_VERSION" = "x"; then
COMPILER_VERSION=`"$CXX" -qversion 2>/dev/null`
fi
## SunCC test if COMPILER_VERSION is empty
if test x"$COMPILER_VERSION" = "x"; then
COMPILER_VERSION=`"$CXX" -V 2>&1`
fi
Then, the vendor can be used like:
IS_SUN_COMPILER=`echo $COMPILER_VERSION | $EGREP -i -c -E 'Sun C\+\+'`
echo "IS_SUN_COMPILER: $IS_SUN_COMPILER"
...
## This block handles SunCC.
if test "$IS_SUN_COMPILER" -ne "0"; then
...
fi
Related
I have a GNUmakefile that respects CXX and CXXFLAGS. It also performs some platform and architecture tests. Currently, the makefile assumes the host and target are the same:
IS_X86 = $(shell uname -m | $(EGREP) -c "i.86|x86|i86|amd64")
In an effort to improve robustness, I want to ask the tools what it is compiling for. I've come up with the following, but I'm not sure it is correct.
$ export CXX=clang++
$ export CXXFLAGS="-DNDEBUG -g2 -O3 -m32"
$ $CXX $CXXFLAGS -dM -E - < /dev/null | egrep "(i386|x86_64)"
#define __i386 1
#define __i386__ 1
#define i386 1
$ export CXX=clang++
$ export CXXFLAGS="-DNDEBUG -g2 -O3"
$ $CXX $CXXFLAGS -dM -E - < /dev/null | egrep "(i386|x86_64)"
#define __x86_64 1
#define __x86_64__ 1
My question is, will the above - with CXX and CXXFLAGS - work reliably to detect a target? Or do I need something else?
Here's the two reasons I ask. First, my experience with Autotools indicates something different. When Autotools performs a test like above, they test CPP, and sometimes CPP or CXX needs to include --isysroot (or other hacks) to get things configured properly.
Second, some toolchains, like Clang, integrate other components (like a preprocessor or assembler), so I can't use CPP directly under all circumstances.
In fact, doing something as simple as $CXX -Wa,-v - </dev/null (ask assembler for its version) results in an "unsupported option" error under Clang when using its integrated assembler. (Cf., With integrated assembler enabled, fail to fetch version string of assembler).
And just in case: this is not an Autools or Cmake project. It does not use Boost or any other libraries. Its a stand alone C++03 project.
My question is, will the above - with CXX and CXXFLAGS - work reliably to detect a target?
The answer is Yes, it will. The preprocessor or compielr driver (passing down to preprocessor) will mostly yield expected target defines with all else being equal. Notable exception is GCC and ARMv8/Aarch64, which is missing a slew of expected defines.
The thing to avoid is uname -m (and friends). Uname reports information on the host, and not the target.
I am trying to run an autotools configure script for the bson-cpp project, and it fails because it cannot determine what flags it needs to compile with boost_filesystem. A quick look at confg.log shows:
g++ -o conftest -g -O2 -pthread -L/usr/local/lib -R/usr/local/lib -L/usr/local/libexec conftest.o -lboost_filesystem-mt -lboost_system-mt >&5
g++: error: unrecognized option '-R'
So, naturally, I tried to find out what the R option does, but I can't seem to find it documented anywhere. I've checked here and here to no avail. What does the option do and how do I tell autotools not to use it?
-R does not seem to be an option for g++ or gcc anywhere. -R may be a linker option on some platforms that is equivalent of -rpath to gnu ld, ... This seems to be a known bug in boost builds ... have a look at Use -Wl to pass arguments to the linker.
It actually has the patch available there
I am re-posting it for convenience, however PLEASE PLEASE look at the original URL linked above for official patch!
--- ../gnote/m4/boost.m4 2011-01-25 14:30:18.000000000 +0200
+++ m4/boost.m4 2011-02-27 20:57:11.686221539 +0200
## -403,7 +403,7 ##
LDFLAGS=$boost_save_LDFLAGS
LIBS=$boost_save_LIBS
if test x"$Boost_lib" = xyes; then
- Boost_lib_LDFLAGS="-L$boost_ldpath -R$boost_ldpath"
+ Boost_lib_LDFLAGS="-L$boost_ldpath -Wl,-R$boost_ldpath"
Boost_lib_LDPATH="$boost_ldpath"
break 6
else
It's an option similar to -rpath, but available only on some platforms. The script is maybe failing detecting your platform ?
It is not a valid option for GCC, so it does not do anything.
It is possibly a valid option for other compilers though, which could be why autoconf gives it a shot.
Not all errors in the config.log files are a problem. autoconf figures out a lot of things by "guessing", i.e. trying something and keeping that if it worked.
If I compile with -fPIC on x86 Linux with gcc 4.1, then the definition __PIC__ is set to 1 and the preprocessor can act on that at compile time. However, on OS/X under gcc 4.01 that is not the case. Is there some other way to determine the setting of -fPIC at compile time on OS/X?
A general facility for querying compilation flags at the preprocessor level under OS/X would be even more helpful, but I wasn't able to find anything like that.
-fPIC is the default on OS X. gcc 4.0.1 on my crufty old OS X 10.4 machine does define __PIC__; or, when it is explicitly turned off with -fno-PIC, it does not.
The settings of compilation flags are not in general exported to the preprocessor, except for certain special cases, which may vary across different GCC targets.
But you can see the effects of changing flags on the predefined preprocessor definitions, on any platform, using the -dM option to gcc, which dumps the preprocessor definitions after preprocessing is complete.
e.g. from a terminal window:
$ gcc -xc++ -dM -E /dev/null | sort > /tmp/defaults.txt
$ gcc -fno-PIC -xc++ -dM -E /dev/null | sort > /tmp/nopic.txt
$ diff /tmp/defaults.txt /tmp/nopic.txt
65d64
< #define __PIC__ 1
$
(I've specified -xc++ there because I'm preprocessing /dev/null rather than a file with an extension that indicates the language variant. That could also be -xc, -xobjective-c or -xobjective-c++.)
My system compiler (gcc42) works fine with the TR1 features that I want, but trying to support newer compiler versions other than the systems, trying to accessing TR1 headers an #error demanding the -std=c++0x option because of how it interfaces with library or some hub bub like that.
/usr/local/lib/gcc45/include/c++/bits/c++0x_warning.h:31:2: error: #error This file requires compiler and library support for the upcoming ISO C++ standard, C++0x. This support is currently experimental, and must be enabled with the -std=c++0x or -std=gnu++0x compiler options.
Having to supply an extra switch is no problem, to support GCC 4.4 and 4.5 under this system (FreeBSD), but obviously it changes the picture!
Using my system compiler (g++ 4.2 default dialect):
#include <tr1/foo>
using std::tr1::foo;
Using newer (4.5) versions of the compiler with -std=c++0x:
#include <foo>
using std::foo;
Is there anyway using the pre processor, that I can tell if g++ is running with C++0x features enabled?
Something like this is what I'm looking for:
#ifdef __CXX0X_MODE__
#endif
but I have not found anything in the manual or off the web.
At this rate, I'm starting to think that life would just be easier, to use Boost as a dependency, and not worry about a new language standard arriving before TR4... hehe.
There seems, with gcc 4.4.4, to be only one predefined macro hinting that -std=c++0x is in effect:
#define __GXX_EXPERIMENTAL_CXX0X__ 1
I don't have access to gcc 4.5.0 , but you can check that one yourself:
[16:13:41 0 ~] $ g++ -E -dM -std=c++0x -x c++ /dev/null >b
[16:13:44 0 ~] $ g++ -E -dM -std=c++98 -x c++ /dev/null >a
[16:13:50 0 ~] $ diff -u a b
--- a 2010-06-02 16:13:50.200787591 +0200
+++ b 2010-06-02 16:13:44.456912378 +0200
## -20,6 +20,7 ##
#define __linux 1
#define __DEC32_EPSILON__ 1E-6DF
#define __unix 1
+#define __GXX_EXPERIMENTAL_CXX0X__ 1
#define __LDBL_MAX_EXP__ 16384
#define __linux__ 1
#define __SCHAR_MAX__ 127
For one-line command do,
g++ -E -dM -std=c++98 -x c++ /dev/null > std1 && g++ -E -dM -std=c++0x -x c++ /dev/null > std2 && diff -u std1 std2 | grep '[+|-]^*#define' && rm std1 std2
gives you something like:
+#define __GXX_EXPERIMENTAL_CXX0X__ 1
If you compile with -std=c++0x, then __GXX_EXPERIMENTAL_CXX0X__ will be defined.
Well, from gcc-4.7 onwards you'll be able to check __cplusplus:
"G++ now sets the predefined macro __cplusplus to the correct value, 199711L for C++98/03, and 201103L for C++11"
This should be the correct, standard-compliant way to do it. Unfortunately, it doesn't work for most gcc installed in the wild.
Whatever I try to compile in Cygwin I get the following output:
checking for mingw32 environment... no
checking for EMX OS/2 environment... no
checking how to run the C preprocessor... gcc -E
checking for gcc... gcc
checking whether the C compiler (gcc ) works... no
configure: error: installation or configuration problem: C compiler cannot creat
e executables.
The last few lines of the logfile look like this:
configure:2810: checking for EMX OS/2 environment
configure:2822: gcc -c conftest.c 1>&5
configure: In function `main':
configure:2818: error: `__EMX__' undeclared (first use in this function)
configure:2818: error: (Each undeclared identifier is reported only once
configure:2818: error: for each function it appears in.)
configure: failed program was:
#line 2815 "configure"
#include "confdefs.h"
int main() {
return __EMX__;
; return 0; }
configure:2838: checking how to run the C preprocessor
configure:2859: gcc -E conftest.c >/dev/null 2>conftest.out
configure:2943: checking for gcc
configure:3056: checking whether the C compiler (gcc ) works
configure:3072: gcc -o conftest conftest.c -llib 1>&5
/usr/lib/gcc/i686-pc-cygwin/3.4.4/../../../../i686-pc-cygwin/bin/ld: cannot find
-llib
collect2: ld returned 1 exit status
configure: failed program was:
#line 3067 "configure"
#include "confdefs.h"
main(){return(0);}
This is a fresh Cygwin install with G++ and a bunch of other devtools added. Any idea what I need to do to get this thing working?
Update 0: Nick, your link to http://www.geektimes.com/linux/troubleshooting/c-cant-create-executables.html was tried already - unfortunately this instructions are for redhat and do not seem to apply to cygwin.
Your Configure is wrong.
Usually autoreconf -f helps. If not you need to check the failing rule and fix it.
The '-llib' seems a bit unusual to me, but I'm far from an expert. Just out of curiosity is autoconf installed? I had some problems similar to this until I installed autoconf. It seems like the configure script is incorrectly generating a '-llib' value but it's hard to say why based on just the snippets posted.
When I've had this problem, it has been a link error caused by Cygwin looking for "library.o" instead of "library.obj" or "library.so" instead of "library.dll".