2

There are plenty of examples of using cmake to set a preprocessor value. I'm having the reverse problem -- I want to find the value of __GLIBCXX__ and then perform other cmake commands conditionally based on the result.

Up until now, I had been using the GCC version as a surrogate for libstdc++ functionality, like this:

if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
    if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.6)
        ....
    # other gcc versions
        ....
    endif()
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
    # and so on
endif()

The problem I'm now having is the fallout from a known issue with libstdc++ and gcc-4.8 c++11 regex support, and the fact on many setups clang reuses the system libstdc++, therefore inheriting the same problem. Under these circumstances, there's no version test for clang that will help, since it's specifically related to libstdc++, and my surrogate method of using the compiler version no longer works.

In order to fallback on Boost.Regex or PCRE if either clang or gcc are using the libstdc++ distributed with gcc-4.8 or earlier, the best way I can think of is to check if __GLIBCXX__ <= 20140404, but I can't see how to get cmake to do it in a straight-forward way, since clang might not always be using libstdc++, e.g. most OS X systems.

CheckVariableExists doesn't seem to help, I suppose for at least two reasons; firstly, a preprocessor macro isn't a variable, and secondly, it doesn't give the value, only indicates its presence.

Community
  • 1
  • 1
Rich L
  • 1,905
  • 2
  • 19
  • 30
  • 1
    The value of `__GLIBCXX__` is not monotonous and is almost unusable. Boost instead tests which headers are available to guess the version of libstdc++. If you are going to compile a program, you might as well make it a program that demonstrates the lack of support in old versions, so you don't need to test `__GLIBCXX__`. – Marc Glisse Apr 17 '15 at 21:24

2 Answers2

1

You could use CHECK_CXX_SOURCE_COMPILES to compile a specific test which fails when your condition is not met:

INCLUDE (CheckCXXSourceCompiles)
CHECK_CXX_SOURCE_COMPILES(
"
#include <cstdio>
#ifdef __GLIBCXX__
#if __GLIBCXX__ <= 20140404
#error test failed
#endif
#endif
int main() { return 0;} 
" GLIBCXX_TEST) 

IF(NOT GLIBCXX_TEST)
MESSAGE(STATUS "__GLIBCXX__ test failed")
ENDIF()
m.s.
  • 16,063
  • 7
  • 53
  • 88
1

Based on m.s.'s idea and taking Marc Glisse's observation about __GLIBCXX__ not being a reliable way to test for this, I wrote a CMake module to test for broken implementations of regex support. In order for this test to pass, the compiler will need to be targetting C++11 or higher.

Gist is here: https://gist.github.com/anonymous/7520ce6f64c63e2f8e79

Sample use:

include(CheckForRegex)
check_cxx_native_regex_works(USE_NATIVE_REGEX)
add_definitions("-DUSE_NATIVE_REGEX=${USE_NATIVE_REGEX}")

if (NOT USE_NATIVE_REGEX)
    find_package(Boost REQUIRED COMPONENTS regex)
endif()
Rich L
  • 1,905
  • 2
  • 19
  • 30