Is there any way to get the version and vendor of the compiler used by the user through qmake? What I need is to disable building some targets of my project when g++ 3.x is used and enable them when g++ 4.x is used.
Update: Most answers targeted the preprocessor. This is something that I want to avoid. I don't want a target to be build for a specific compiler version and I want this decision to be made by the build system.
In addition to ashcatch's answer, qmake allows you to query the command line and get the response back as a variable. So you could to something like this:
linux-g++ {
system( g++ --version | grep -e "\<4.[0-9]" ) {
message( "g++ version 4.x found" )
CONFIG += g++4
}
else system( g++ --version | grep -e "\<3.[0-9]" ) {
message( "g++ version 3.x found" )
CONFIG += g++3
}
else {
error( "Unknown system/compiler configuration" )
}
}
Then later, when you want to use it to specify targets, you can use the config scoping rules:
SOURCES += blah blah2 blah3
g++4: SOURCES += blah4 blah5
My answer based on Caleb Huitt - cjhuitt's. But his approach does not work for me.
*-g++ {
GCC_VERSION = $$system("g++ -dumpversion")
contains(GCC_VERSION, 6.[0-9]) {
message( "g++ version 6.x found" )
CONFIG += g++6
} else {
contains(GCC_VERSION, 5.[0-9]) {
message( "g++ version 5.x found" )
CONFIG += g++5
} else {
contains(GCC_VERSION, 4.[0-9]) {
message( "g++ version 4.x found" )
CONFIG += g++4
} else {
message( "Unknown GCC configuration" )
}
}
}
}
As you see you can get version from GCC and then compare it with regex expression.
The way how to use is the same:
SOURCES += blah blah2 blah3
g++4: SOURCES += blah4 blah5
As a start, I would look at the scoping feature that qmake supports:
Scopes and Conditions
But while I read about it, it seems that by default you can use general platform conditions like win32 or unix or you can use the name of the qmake spec like linux-g++. You could test the Visual Studio version like this (since the different Visual Studio versions use different qmake specs), but I don't think that you can test the gcc version like this (at least I don't know how).
My answer is based on dismine's answer
We can simply extract the major version number using $$str_member
gcc | clang {
COMPILER_VERSION = $$system($$QMAKE_CXX " -dumpversion")
COMPILER_MAJOR_VERSION = $$str_member($$COMPILER_VERSION)
greaterThan(COMPILER_MAJOR_VERSION, 3): message("gcc 4 or later")
greaterThan(COMPILER_MAJOR_VERSION, 4): message("gcc 5 or later")
greaterThan(COMPILER_MAJOR_VERSION, 5): message("gcc 6 or later")
greaterThan(COMPILER_MAJOR_VERSION, 6): message("gcc 7 or later")
}
I do
isEmpty(MGWVER) {
MGW_MAJ = $$system(echo | gcc -dM -E - | fgrep __GNUC__ | cut -d\" \" -f 3)
MGW_MIN = $$system(echo | gcc -dM -E - | fgrep __GNUC_MINOR__ | cut -d\" \" -f 3)
MGWVER =$$MGW_MAJ$$MGW_MIN
message(MGWVER $$MGWVER)
}
It returns "48".
I use it for linking proper boost libraries:
USER_BOOST_CFG=mgw$${MGWVER}-mt-s-$$(BOOST_VER)
message($$USER_BOOST_CFG)
LIBS *= -L$$(BOOST_ROOT)/lib
LIBS *= -L$$(BOOST_ROOT)/stage/lib
LIBS *= -lboost_system-$$USER_BOOST_CFG
LIBS *= -lboost_filesystem-$$USER_BOOST_CFG
LIBS *= -lboost_date_time-$$USER_BOOST_CFG
effectively giving:
-lboost_system-mgw48-mt-s-1_54
I am on mingw.
Another idea is to look at QMAKESPEC vaariable and parse from it, hint:
message(QMAKESPEC $$QMAKESPEC)
SPLITED=$$section(QMAKESPEC, "/", 0, -3)
message(SPLITED $$SPLITED)
Each compiler vendor use to define some specific symbols that identify the compiler and version. You could make the check using those symbols.
I know, for example, that _MSC_VER gives the version of Microsoft C++ Compiler.
What I also know is that Boost Libraries use this kind of feature selection and adaptation.
You can take a look to Boost Config headers, found in include folder, at path: boost/config/* , specially at select_compiler_config.hpp.
By using those compiler specific symbols, you can make feature selection at preprocessing phase of building the code.
The following macros are defined in my version of gcc and g++
#define __GNUC__ 4
#define __GNUC_MINOR__ 0
#define __GNUC_PATCHLEVEL__ 1
Additionaly the g++ defines:
#define __GNUG__ 4
Related
I am trying to compile a project that includes the eigen library and I get this error:
In file included from /home/--/--/--/Eigen/Core:19,
from /home/--/--/--/Eigen/Geometry:11,
from /usr/include/rl-0.7.0/rl/math/Transform.h:34,
from /home/--/--/--/example.cpp:2:
/home/--/--/--/Eigen/src/Core/util/Macros.h:674:2: error: #error This compiler appears to be too old to be supported by Eigen
674 | #error This compiler appears to be too old to be supported by Eigen
| ^~~~~
I am using:
Ubuntu 20.04
Cmake 3.16.3
VSCode Compiler GCC 10.3.1
Eigen 3.4.90
The problem seems to be related to these lines in Macros.h file:
// The macros EIGEN_HAS_CXX?? defines a rough estimate of available c++ features
// but in practice we should not rely on them but rather on the availability of
// individual features as defined later.
// This is why there is no EIGEN_HAS_CXX17.
#if EIGEN_MAX_CPP_VER<14 || EIGEN_COMP_CXXVER<14 || (EIGEN_COMP_MSVC && EIGEN_COMP_MSVC < 1900) || \
(EIGEN_COMP_ICC && EIGEN_COMP_ICC < 1500) || (EIGEN_COMP_NVCC && EIGEN_COMP_NVCC < 80000) || \
(EIGEN_COMP_CLANG && ((EIGEN_COMP_CLANG<309) || (defined(__apple_build_version__) && (__apple_build_version__ < 9000000)))) || \
(EIGEN_COMP_GNUC_STRICT && EIGEN_COMP_GNUC<51)
#error This compiler appears to be too old to be supported by Eigen
#endif
Do you know how to fix this error?
As #Lala5th suggested, by changing the C++ standard the problem is solved.
I have modified the CMakeLists.txt:
From:
set(CMAKE_CXX_STANDARD 11)
To:
set(CMAKE_CXX_STANDARD 17)
(It also works with 14)
As you've noted, Macros.h file tells us the problem is with compiler version.
VSCode compiler
GCC 10 definitely has support for c++17. It means that you should change it's starting flags. In settings.json file add this lines:
"code-runner.executorMap": {
"cpp": "cd $dir && g++ -std=c++17 $fileName -o $fileNameWithoutExt && $dir$fileNameWithoutExt",
},
according to this answer.
Standard Bash's g++
Use g++ with -std=c++17 flag.
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
I'm just getting started on a project with wxWidgets, and I'm trying to set up a Bakefile for cross-platform compilation. I need to pass the output of wx-config --libs and wx-config --cxxflags to the compiler.
How can I accomplish this? I cannot find anything in the Bakefile docs about getting the output of a command into a variable. Backticks don't seem to work:
myvar = `wx-config --libs`
#=> bakefile.bkl:2:12: error: no viable alternative at character u'`'
You need to use quotes here, i.e.
myvar = "`wx-config --libs`"
For the reference, here is what I do in my own bakefiles:
if ( $toolset == gnu || $toolset == gnu-osx ) {
setting WX_CONFIG {
default = wx-config;
help = "Path to the wx-config script";
}
compiler-options += "`$(WX_CONFIG) --cppflags`";
link-options += "`$(WX_CONFIG) --libs`";
}
This allows to do things like make WX_CONFIG=/full/path/to/wx-config which is handy when using an uninstalled version of wxWidgets.
I am using qmake on OSX with clang. I try to use c++11 with the following flags in the .pro file
QMAKE_CXXFLAGS += -std=c++11 -stdlib=libc++
However qmake generates the follow flag in the makefile
CXXFLAGS = ... -mmacosx-version-min=10.5 ...
This flag causes clang to raise an error
invalid deployment target for -stdlib=libc++ (requires OS X 10.7 or later)
Changing the flag to 10.7 fixed the problem
CXXFLAGS = ... -mmacosx-version-min=10.7 ...
Is there any way to stop qmake from emitting this flag in the makefile?
you can install other compiler for example gcc4.7.
There are few easy ways macports:
1. http://www.macports.org/install.php
2. Applications > Utilities > Terminal
3. In terminal: sudo port selfupdate
4. sudo port install gcc47
5. Now add new compiler in Qt (Projects tab)
6. In profile change QMAKE_CXXFLAGS += -std=c++0x
Other way brew:
1. Applications > Utilities > Terminal
2. In terminal: ruby -e "$(curl -fsSkL raw.github.com/mxcl/homebrew/go)"
3. In terminal: brew doctor
4. In terminal: brew install gcc
5. Now add new compiler in Qt (Projects tab)
6. In profile change QMAKE_CXXFLAGS += -std=c++0x
Specify the target version via QMAKE_MACOSX_DEPLOYMENT_TARGET, e.g.:
QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.7
If you would totally get rid of the flag, you would get some message like:
ld: warning: -macosx_version_min not specified, assuming 10.8
So, your compiler will automatically add it anyway.
That flag is there for a reason. It's written into your binary. And when you try to load that binary on an older system, it will abort.
Now, if you really want MacOSX 10.5 compatibility, you cannot use -stdlib=libc++ because that libc++ is simply not available before MacOSX 10.7.
If you need libc++ (e.g. some C++11 features) + you want to make it work on <10.7, that's not so easy. See here for a related question.
Is there any way to get the version and vendor of the compiler used by the user through qmake? What I need is to disable building some targets of my project when g++ 3.x is used and enable them when g++ 4.x is used.
Update: Most answers targeted the preprocessor. This is something that I want to avoid. I don't want a target to be build for a specific compiler version and I want this decision to be made by the build system.
In addition to ashcatch's answer, qmake allows you to query the command line and get the response back as a variable. So you could to something like this:
linux-g++ {
system( g++ --version | grep -e "\<4.[0-9]" ) {
message( "g++ version 4.x found" )
CONFIG += g++4
}
else system( g++ --version | grep -e "\<3.[0-9]" ) {
message( "g++ version 3.x found" )
CONFIG += g++3
}
else {
error( "Unknown system/compiler configuration" )
}
}
Then later, when you want to use it to specify targets, you can use the config scoping rules:
SOURCES += blah blah2 blah3
g++4: SOURCES += blah4 blah5
My answer based on Caleb Huitt - cjhuitt's. But his approach does not work for me.
*-g++ {
GCC_VERSION = $$system("g++ -dumpversion")
contains(GCC_VERSION, 6.[0-9]) {
message( "g++ version 6.x found" )
CONFIG += g++6
} else {
contains(GCC_VERSION, 5.[0-9]) {
message( "g++ version 5.x found" )
CONFIG += g++5
} else {
contains(GCC_VERSION, 4.[0-9]) {
message( "g++ version 4.x found" )
CONFIG += g++4
} else {
message( "Unknown GCC configuration" )
}
}
}
}
As you see you can get version from GCC and then compare it with regex expression.
The way how to use is the same:
SOURCES += blah blah2 blah3
g++4: SOURCES += blah4 blah5
As a start, I would look at the scoping feature that qmake supports:
Scopes and Conditions
But while I read about it, it seems that by default you can use general platform conditions like win32 or unix or you can use the name of the qmake spec like linux-g++. You could test the Visual Studio version like this (since the different Visual Studio versions use different qmake specs), but I don't think that you can test the gcc version like this (at least I don't know how).
My answer is based on dismine's answer
We can simply extract the major version number using $$str_member
gcc | clang {
COMPILER_VERSION = $$system($$QMAKE_CXX " -dumpversion")
COMPILER_MAJOR_VERSION = $$str_member($$COMPILER_VERSION)
greaterThan(COMPILER_MAJOR_VERSION, 3): message("gcc 4 or later")
greaterThan(COMPILER_MAJOR_VERSION, 4): message("gcc 5 or later")
greaterThan(COMPILER_MAJOR_VERSION, 5): message("gcc 6 or later")
greaterThan(COMPILER_MAJOR_VERSION, 6): message("gcc 7 or later")
}
I do
isEmpty(MGWVER) {
MGW_MAJ = $$system(echo | gcc -dM -E - | fgrep __GNUC__ | cut -d\" \" -f 3)
MGW_MIN = $$system(echo | gcc -dM -E - | fgrep __GNUC_MINOR__ | cut -d\" \" -f 3)
MGWVER =$$MGW_MAJ$$MGW_MIN
message(MGWVER $$MGWVER)
}
It returns "48".
I use it for linking proper boost libraries:
USER_BOOST_CFG=mgw$${MGWVER}-mt-s-$$(BOOST_VER)
message($$USER_BOOST_CFG)
LIBS *= -L$$(BOOST_ROOT)/lib
LIBS *= -L$$(BOOST_ROOT)/stage/lib
LIBS *= -lboost_system-$$USER_BOOST_CFG
LIBS *= -lboost_filesystem-$$USER_BOOST_CFG
LIBS *= -lboost_date_time-$$USER_BOOST_CFG
effectively giving:
-lboost_system-mgw48-mt-s-1_54
I am on mingw.
Another idea is to look at QMAKESPEC vaariable and parse from it, hint:
message(QMAKESPEC $$QMAKESPEC)
SPLITED=$$section(QMAKESPEC, "/", 0, -3)
message(SPLITED $$SPLITED)
Each compiler vendor use to define some specific symbols that identify the compiler and version. You could make the check using those symbols.
I know, for example, that _MSC_VER gives the version of Microsoft C++ Compiler.
What I also know is that Boost Libraries use this kind of feature selection and adaptation.
You can take a look to Boost Config headers, found in include folder, at path: boost/config/* , specially at select_compiler_config.hpp.
By using those compiler specific symbols, you can make feature selection at preprocessing phase of building the code.
The following macros are defined in my version of gcc and g++
#define __GNUC__ 4
#define __GNUC_MINOR__ 0
#define __GNUC_PATCHLEVEL__ 1
Additionaly the g++ defines:
#define __GNUG__ 4