From b944bad7adc70999ee4f604c30b719c99891e8a3 Mon Sep 17 00:00:00 2001 From: Matthias Maier Date: Thu, 2 Jul 2015 12:27:28 +0200 Subject: [PATCH] CMake: Restructure logic in check_01_cxx_features --- cmake/checks/check_01_cxx_features.cmake | 561 +++++++++++------------ 1 file changed, 270 insertions(+), 291 deletions(-) diff --git a/cmake/checks/check_01_cxx_features.cmake b/cmake/checks/check_01_cxx_features.cmake index c6997f9c5e..1bb9f98169 100644 --- a/cmake/checks/check_01_cxx_features.cmake +++ b/cmake/checks/check_01_cxx_features.cmake @@ -1,6 +1,6 @@ ## --------------------------------------------------------------------- ## -## Copyright (C) 2012 - 2014 by the deal.II authors +## Copyright (C) 2012 - 2015 by the deal.II authors ## ## This file is part of the deal.II library. ## @@ -21,6 +21,7 @@ # DEAL_II_WITH_CXX11 # DEAL_II_WITH_CXX14 # +# DEAL_II_HAVE_CXX11_IS_TRIVIALLY_COPYABLE # DEAL_II_HAVE_ISNAN # DEAL_II_HAVE_UNDERSCORE_ISNAN # DEAL_II_HAVE_ISFINITE @@ -36,254 +37,276 @@ # # backwards compatibility with the old DEAL_II_CXX11_FLAG option # - -IF(DEFINED DEAL_II_CXX11_FLAG AND NOT DEFINED DEAL_II_CXX_VERSION_FLAG) - SET(DEAL_II_CXX_VERSION_FLAG ${DEAL_II_CXX11_FLAG}) -ENDIF() - -IF(DEAL_II_WITH_CXX11 AND DEAL_II_WITH_CXX14) - MESSAGE(STATUS - "Since DEAL_II_WITH_CXX11 and DEAL_II_WITH_CXX14 were both specified,\n" - "DEAL_II_WITH_CXX14 is chosen as the standard.") -ENDIF() +SET_IF_EMPTY(DEAL_II_CXX_VERSION_FLAG "${DEAL_II_CXX11_FLAG}") IF(DEAL_II_WITH_CXX14 AND DEFINED DEAL_II_WITH_CXX11 AND NOT DEAL_II_WITH_CXX11) MESSAGE(FATAL_ERROR "Compiling deal.II with C++14 support (i.e., DEAL_II_WITH_CXX14=ON) requires" " that C++11 support not be explicitly disabled (i.e., DEAL_II_WITH_CXX11 may" - " not be set to a logically false value).") + " not be set to a logically false value)." + ) ENDIF() +IF(DEFINED DEAL_II_WITH_CXX11 AND NOT DEAL_II_WITH_CXX11) + SET(DEAL_II_WITH_CXX14 OFF) +ENDIF() + + # -# Test for C++11 flag support if the compiler supports a C++11 flag and C++11 -# support is not explicitly disabled. +# Check the user supplied DEAL_II_CXX_VERSION_FLAG # -IF((NOT DEFINED DEAL_II_WITH_CXX11 OR DEAL_II_WITH_CXX11) - AND NOT DEFINED DEAL_II_CXX_VERSION_FLAG) - CHECK_CXX_COMPILER_FLAG("-std=c++0x" DEAL_II_HAVE_FLAG_stdcxx0x) - CHECK_CXX_COMPILER_FLAG("-std=c++11" DEAL_II_HAVE_FLAG_stdcxx11) - IF(DEAL_II_HAVE_FLAG_stdcxx11) - SET(DEAL_II_CXX11_FLAG "-std=c++11") - ELSEIF(DEAL_II_HAVE_FLAG_stdcxx0x) - SET(DEAL_II_CXX11_FLAG "-std=c++0x") - ELSE() - IF(DEAL_II_WITH_CXX11) - MESSAGE(FATAL_ERROR - "C++11 support was requested but CMake was not able to find a valid C++11" - " flag. Try manually specifying DEAL_II_CXX_VERSION_FLAG and reruning CMake.") - ENDIF() +IF(NOT "${DEAL_II_CXX_VERSION_FLAG}" STREQUAL "") + CHECK_CXX_COMPILER_FLAG(${DEAL_II_CXX_VERSION_FLAG} DEAL_II_CXX_VERSION_FLAG_VALID) + IF(NOT DEAL_II_CXX_VERSION_FLAG_VALID) + MESSAGE(FATAL_ERROR + "The supplied flag \"${DEAL_II_CXX_VERSION_FLAG}\" was not recognized " + "by the compiler." + ) ENDIF() - # - # C++11 support must not be explicitly disabled for C++14 support to be - # enabled. - # - - IF(NOT DEFINED DEAL_II_WITH_CXX14 OR DEAL_II_WITH_CXX14) - CHECK_CXX_COMPILER_FLAG("-std=c++1y" DEAL_II_HAVE_FLAG_stdcxx1y) - CHECK_CXX_COMPILER_FLAG("-std=c++14" DEAL_II_HAVE_FLAG_stdcxx14) - IF(DEAL_II_HAVE_FLAG_stdcxx14) - SET(DEAL_II_CXX14_FLAG "-std=c++14") - ELSEIF(DEAL_II_HAVE_FLAG_stdcxx1y) - SET(DEAL_II_CXX14_FLAG "-std=c++1y") - ELSE() - IF(DEAL_II_WITH_CXX14) - MESSAGE(FATAL_ERROR - "C++14 support was requested but CMake was not able to find a valid C++14" - " flag. Try manually specifying DEAL_II_CXX_VERSION_FLAG and reruning CMake.") - ENDIF() - ENDIF() - ENDIF() + SET(_user_provided_cxx_version_flag TRUE) ENDIF() # -# Only run these tests if CMake should attempt to set up C++11 (or newer) -# support. +# A macro to check for various C++11 and C++14 flags # -IF(DEFINED DEAL_II_CXX11_FLAG OR DEFINED DEAL_II_CXX14_FLAG - OR DEFINED DEAL_II_CXX_VERSION_FLAG) - IF(NOT DEFINED DEAL_II_CXX_VERSION_FLAG) - IF(DEFINED DEAL_II_CXX14_FLAG) - SET(DEAL_II_CXX_VERSION_FLAG ${DEAL_II_CXX14_FLAG}) - ELSEIF(DEFINED DEAL_II_CXX11_FLAG) - SET(DEAL_II_CXX_VERSION_FLAG ${DEAL_II_CXX11_FLAG}) - ELSE() - SET(DEAL_II_CXX_VERSION_FLAG " ") + +MACRO(_check_cxx_flag _suffix) + IF("${DEAL_II_CXX_VERSION_FLAG}" STREQUAL "") + CHECK_CXX_COMPILER_FLAG("-std=c++${_suffix}" DEAL_II_HAVE_FLAG_stdcxx${_suffix}) + IF(DEAL_II_HAVE_FLAG_stdcxx${_suffix}) + SET(DEAL_II_CXX_VERSION_FLAG "-std=c++${_suffix}") ENDIF() + ENDIF() +ENDMACRO() + +MACRO(_check_version _version _symbolic) + _check_cxx_flag("${_version}") + _check_cxx_flag("${_symbolic}") + IF(DEAL_II_WITH_CXX${_version} AND "${DEAL_II_CXX_VERSION_FLAG}" STREQUAL "") + MESSAGE(FATAL_ERROR + "C++${_version} support was requested but CMake was not able to find a valid C++${_version}" + " flag. Try to manually specify DEAL_II_CXX_VERSION_FLAG and rerun CMake." + ) + ENDIF() +ENDMACRO() + +# +# Check for proper C++14 support and set up DEAL_II_HAVE_CXX14: +# +IF(NOT DEFINED DEAL_II_WITH_CXX14 OR DEAL_II_WITH_CXX14) + _check_version("14" "1y") + + IF(NOT "${DEAL_II_CXX_VERSION_FLAG}" STREQUAL "") + # Set CMAKE_REQUIRED_FLAGS for the unit tests + MESSAGE(STATUS "Using C++ version flag \"${DEAL_II_CXX_VERSION_FLAG}\"") + PUSH_CMAKE_REQUIRED("${DEAL_II_CXX_VERSION_FLAG}") + + # + # This test does not guarantee full C++14 support, but virtually every + # compiler with some C++14 support implements this. + # + CHECK_CXX_SOURCE_COMPILES( + " + #include + int main() + { + auto ptr = std::make_unique(42); + return 0; + } + " + DEAL_II_HAVE_CXX14_MAKE_UNIQUE) + + RESET_CMAKE_REQUIRED() + ENDIF() + + IF(DEAL_II_HAVE_CXX14_MAKE_UNIQUE) + SET(DEAL_II_HAVE_CXX14 TRUE) ELSE() - CHECK_CXX_COMPILER_FLAG(${DEAL_II_CXX_VERSION_FLAG} DEAL_II_CXX_VERSION_FLAG_VALID) - IF(NOT DEAL_II_CXX_VERSION_FLAG_VALID) - MESSAGE(FATAL_ERROR - "The supplied flag \"${DEAL_II_CXX_VERSION_FLAG}\" was not recognized " - "by the detected compiler.") + IF(NOT _user_provided_cxx_version_flag) + SET(DEAL_II_CXX_VERSION_FLAG "") ENDIF() ENDIF() +ENDIF() - # Set CMAKE_REQUIRED_FLAGS for the unit tests - MESSAGE(STATUS "Using C++ version flag \"${DEAL_II_CXX_VERSION_FLAG}\"") - PUSH_CMAKE_REQUIRED("${DEAL_II_CXX_VERSION_FLAG}") - CHECK_CXX_SOURCE_COMPILES( - " - #include - std::array p; - int main(){ p[0]; return 0; } - " - DEAL_II_HAVE_CXX11_ARRAY) +# +# Check for proper C++11 support and set up DEAL_II_HAVE_CXX11: +# +IF(NOT DEFINED DEAL_II_WITH_CXX11 OR DEAL_II_WITH_CXX11) - CHECK_CXX_SOURCE_COMPILES( - " - #include - std::condition_variable c; - int main(){ c.notify_all(); return 0; } - " - DEAL_II_HAVE_CXX11_CONDITION_VARIABLE) + IF("${DEAL_II_CXX_VERSION_FLAG}" STREQUAL "") + _check_version("11" "0x") + ENDIF() - CHECK_CXX_SOURCE_COMPILES( - " - #include - void f(int, double){} - std::function g = std::bind (f, std::placeholders::_1,1.1); - int main(){ return 0; } - " - DEAL_II_HAVE_CXX11_FUNCTIONAL) + IF(NOT "${DEAL_II_CXX_VERSION_FLAG}" STREQUAL "") + # Set CMAKE_REQUIRED_FLAGS for the unit tests + MESSAGE(STATUS "Using C++ version flag \"${DEAL_II_CXX_VERSION_FLAG}\"") + PUSH_CMAKE_REQUIRED("${DEAL_II_CXX_VERSION_FLAG}") - # Make sure we don't run into GCC bug 35569 - CHECK_CXX_SOURCE_COMPILES( - " - #include - void f(int){} - using namespace std; - using namespace std::placeholders; - int main(){ bind(multiplies(),4,_1)(5); return 0; } - " - DEAL_II_HAVE_CXX11_FUNCTIONAL_GCCBUG35569_OK) + CHECK_CXX_SOURCE_COMPILES( + " + #include + std::array p; + int main(){ p[0]; return 0; } + " + DEAL_II_HAVE_CXX11_ARRAY) - CHECK_CXX_SOURCE_COMPILES( - " - #include - std::shared_ptr p(new int(3)); - int main(){ return 0; } - " - DEAL_II_HAVE_CXX11_SHARED_PTR) - - # - # On some systems with gcc 4.5.0, we can compile the code - # below but it will throw an exception when run. So test - # that as well. - # - IF(DEAL_II_ALLOW_PLATFORM_INTROSPECTION) - PUSH_CMAKE_REQUIRED("-pthread") - CHECK_CXX_SOURCE_RUNS( + CHECK_CXX_SOURCE_COMPILES( + " + #include + std::condition_variable c; + int main(){ c.notify_all(); return 0; } + " + DEAL_II_HAVE_CXX11_CONDITION_VARIABLE) + + CHECK_CXX_SOURCE_COMPILES( + " + #include + void f(int, double){} + std::function g = std::bind (f, std::placeholders::_1,1.1); + int main(){ return 0; } + " + DEAL_II_HAVE_CXX11_FUNCTIONAL) + + # Make sure we don't run into GCC bug 35569 + CHECK_CXX_SOURCE_COMPILES( " - #include + #include void f(int){} - int main(){ std::thread t(f,1); t.join(); return 0; } + using namespace std; + using namespace std::placeholders; + int main(){ bind(multiplies(),4,_1)(5); return 0; } " - DEAL_II_HAVE_CXX11_THREAD) - RESET_CMAKE_REQUIRED() - PUSH_CMAKE_REQUIRED("${DEAL_II_CXX_VERSION_FLAG}") - ELSE() - # Just export it ;-) - SET(DEAL_II_HAVE_CXX11_THREAD TRUE CACHE BOOL "") - ENDIF() + DEAL_II_HAVE_CXX11_FUNCTIONAL_GCCBUG35569_OK) - CHECK_CXX_SOURCE_COMPILES( - " - #include - std::mutex m; - int main(){ m.lock(); return 0; } - " - DEAL_II_HAVE_CXX11_MUTEX) + CHECK_CXX_SOURCE_COMPILES( + " + #include + std::shared_ptr p(new int(3)); + int main(){ return 0; } + " + DEAL_II_HAVE_CXX11_SHARED_PTR) - CHECK_CXX_SOURCE_COMPILES( - " - #include ], - std::tuple p(1,1.1,'a'); - int main(){ return 0; } - " - DEAL_II_HAVE_CXX11_TUPLE) + # + # On some systems with gcc 4.5.0, we can compile the code + # below but it will throw an exception when run. So test + # that as well. + # + IF(DEAL_II_ALLOW_PLATFORM_INTROSPECTION) + PUSH_CMAKE_REQUIRED("-pthread") + CHECK_CXX_SOURCE_RUNS( + " + #include + void f(int){} + int main(){ std::thread t(f,1); t.join(); return 0; } + " + DEAL_II_HAVE_CXX11_THREAD) + RESET_CMAKE_REQUIRED() + PUSH_CMAKE_REQUIRED("${DEAL_II_CXX_VERSION_FLAG}") + ELSE() + # Just export it ;-) + SET(DEAL_II_HAVE_CXX11_THREAD TRUE CACHE BOOL "") + ENDIF() - CHECK_CXX_SOURCE_COMPILES( - " - #include - const bool m0 = std::is_trivial::value; - const bool m1 = std::is_standard_layout::value; - const bool m2 = std::is_pod::value; - int main(){ return 0; } - " - DEAL_II_HAVE_CXX11_TYPE_TRAITS) - - # - # On Mac OS-X 10.9 with recent gcc compilers in C++11 mode linking to - # some standard C library functions, notably toupper and tolower, fail - # due to unresolved references to these functions. - # - # Thanks to Denis Davydov for the testcase. - # - # Matthias Maier, 2013 - # - CHECK_CXX_SOURCE_COMPILES( - " - #include - int main () - { - char c = toupper('a'); - } - " - DEAL_II_HAVE_CXX11_MACOSXC99BUG_OK) - - - # - # icc-13 triggers an internal compiler error when compiling - # std::numeric_limits<...>::min() with -std=c++0x [1]. - # - # Reported by Ted Kord. - # - # - Matthias Maier, 2013 - # - # [1] http://software.intel.com/en-us/forums/topic/328902 - # - CHECK_CXX_SOURCE_COMPILES( - " - #include - struct Integer - { - static const int min_int_value; - static const int max_int_value; - }; - const int Integer::min_int_value = std::numeric_limits::min(); - const int Integer::max_int_value = std::numeric_limits::max(); - int main() { return 0; } - " - DEAL_II_HAVE_CXX11_ICCNUMERICLIMITSBUG_OK) - - - # - # icc-14.0.0 has an astonishing bug [1] where it hits an internal compiler - # error when run in C++11 mode with libstdc++-4.7 (from gcc). - # - # We just disable C++11 mode in this case - # - # [1] http://software.intel.com/en-us/forums/topic/472385 - # - # - Matthias Maier, 2013 - # - CHECK_CXX_SOURCE_COMPILES( - " - #include - template void foo() - { - std::vector data(100); - } - int main() - { - foo(); - } - " - DEAL_II_HAVE_CXX11_ICCLIBSTDCPP47CXX11BUG_OK) + CHECK_CXX_SOURCE_COMPILES( + " + #include + std::mutex m; + int main(){ m.lock(); return 0; } + " + DEAL_II_HAVE_CXX11_MUTEX) + + CHECK_CXX_SOURCE_COMPILES( + " + #include ], + std::tuple p(1,1.1,'a'); + int main(){ return 0; } + " + DEAL_II_HAVE_CXX11_TUPLE) + + CHECK_CXX_SOURCE_COMPILES( + " + #include + const bool m0 = std::is_trivial::value; + const bool m1 = std::is_standard_layout::value; + const bool m2 = std::is_pod::value; + int main(){ return 0; } + " + DEAL_II_HAVE_CXX11_TYPE_TRAITS) + + # + # On Mac OS-X 10.9 with recent gcc compilers in C++11 mode linking to + # some standard C library functions, notably toupper and tolower, fail + # due to unresolved references to these functions. + # + # Thanks to Denis Davydov for the testcase. + # + # Matthias Maier, 2013 + # + CHECK_CXX_SOURCE_COMPILES( + " + #include + int main () + { + char c = toupper('a'); + } + " + DEAL_II_HAVE_CXX11_MACOSXC99BUG_OK) + + + # + # icc-13 triggers an internal compiler error when compiling + # std::numeric_limits<...>::min() with -std=c++0x [1]. + # + # Reported by Ted Kord. + # + # - Matthias Maier, 2013 + # + # [1] http://software.intel.com/en-us/forums/topic/328902 + # + CHECK_CXX_SOURCE_COMPILES( + " + #include + struct Integer + { + static const int min_int_value; + static const int max_int_value; + }; + const int Integer::min_int_value = std::numeric_limits::min(); + const int Integer::max_int_value = std::numeric_limits::max(); + int main() { return 0; } + " + DEAL_II_HAVE_CXX11_ICCNUMERICLIMITSBUG_OK) + + + # + # icc-14.0.0 has an astonishing bug [1] where it hits an internal compiler + # error when run in C++11 mode with libstdc++-4.7 (from gcc). + # + # We just disable C++11 mode in this case + # + # [1] http://software.intel.com/en-us/forums/topic/472385 + # + # - Matthias Maier, 2013 + # + CHECK_CXX_SOURCE_COMPILES( + " + #include + template void foo() + { + std::vector data(100); + } + int main() + { + foo(); + } + " + DEAL_II_HAVE_CXX11_ICCLIBSTDCPP47CXX11BUG_OK) + RESET_CMAKE_REQUIRED() + ENDIF() IF( DEAL_II_HAVE_CXX11_ARRAY AND DEAL_II_HAVE_CXX11_CONDITION_VARIABLE AND @@ -299,48 +322,10 @@ IF(DEFINED DEAL_II_CXX11_FLAG OR DEFINED DEAL_II_CXX14_FLAG DEAL_II_HAVE_CXX11_ICCLIBSTDCPP47CXX11BUG_OK ) SET(DEAL_II_HAVE_CXX11 TRUE) ENDIF() - - IF(DEAL_II_HAVE_CXX11) - # - # Some compilers (such as Intel 15.3 and GCC 4.9.2) support the flags - # "-std=c++11" and "-std=c++14" but do not support - # 'std::is_trivially_copyable', so check for support in C++11 or newer. - # - CHECK_CXX_SOURCE_COMPILES( - " - #include - int main(){ std::is_trivially_copyable bob; } - " - DEAL_II_HAVE_CXX11_IS_TRIVIALLY_COPYABLE) - ENDIF() - - # - # This test does not guarantee full C++14 support, but virtually every - # compiler with some C++14 support implements this. - # - CHECK_CXX_SOURCE_COMPILES( - " - #include - int main() - { - auto ptr = std::make_unique(42); - return 0; - } - " - DEAL_II_HAVE_CXX14_MAKE_UNIQUE) - IF( DEAL_II_HAVE_CXX11 AND - DEAL_II_HAVE_CXX14_MAKE_UNIQUE) - SET(DEAL_II_HAVE_CXX14 TRUE) - ENDIF() - - RESET_CMAKE_REQUIRED() -ELSE() - SET(DEAL_II_HAVE_CXX11 FALSE) - SET(DEAL_II_HAVE_CXX14 FALSE) ENDIF() # -# Set up a configuration option for C++11 support: +# Set up a configuration options for C++11 and C++14 support: # OPTION(DEAL_II_WITH_CXX11 @@ -348,10 +333,6 @@ OPTION(DEAL_II_WITH_CXX11 ${DEAL_II_HAVE_CXX11} ) -# -# Set up a configuration option for C++14 support: -# - OPTION(DEAL_II_WITH_CXX14 "Compile deal.II using C++14 language standard." ${DEAL_II_HAVE_CXX14} @@ -362,39 +343,23 @@ OPTION(DEAL_II_WITH_CXX14 # is not available due to above tests (DEAL_II_HAVE_CXX11): # -IF(DEAL_II_WITH_CXX11 AND NOT DEAL_II_HAVE_CXX11) - MESSAGE(FATAL_ERROR "\n" - "C++11 support was requested (DEAL_II_WITH_CXX11=TRUE) but is not " - "supported by the current compiler.\n" - "Please disable C++11 support, i.e. configure with\n" - " -DDEAL_II_WITH_CXX11=FALSE,\n" - "or use a different compiler, instead. (If the compiler flag for C++11 " - "support differs from \"-std=c++0x\" or \"-std=c++11\", a suitable " - "compiler flag has to be specified manually via\n" - " -DDEAL_II_CXX_VERSION_FLAG=\"...\"\n\n" - ) -ENDIF() - -# -# similar for C++14 -# - -IF(DEAL_II_WITH_CXX14 AND NOT DEAL_II_HAVE_CXX14) - MESSAGE(FATAL_ERROR "\n" - "C++14 support was requested (DEAL_II_WITH_CXX14=${DEAL_II_WITH_CXX14}) " - "but is not supported by the current compiler and flag combination.\n" - "Please disable C++14 support, i.e. configure with\n" - " -DDEAL_II_WITH_CXX14=FALSE,\n" - "or use a different compiler, instead. (If the compiler flag for C++14 " - "support differs from \"-std=c++14\" or \"-std=c++1y\", a suitable " - "compiler flag has to be specified manually via\n" - " -DDEAL_II_CXX_VERSION_FLAG=\"...\"\n\n" - ) -ENDIF() +MACRO(_bailout _version) + IF(DEAL_II_WITH_CXX${_version} AND NOT DEAL_II_HAVE_CXX${_version}) + MESSAGE(FATAL_ERROR "\n" + "C++${_version} support was requested (DEAL_II_WITH_CXX${_version}=${DEAL_II_WITH_CXX${_version}}) but is not " + "supported by the current compiler.\n" + "Please disable C++${_version} support, i.e. configure with\n" + " -DDEAL_II_WITH_CXX${_version}=FALSE,\n" + "or use a different compiler, instead. (If the compiler flag for C++${_version} " + "support differs from \"-std=c++0x\" or \"-std=c++${_version}\", a suitable " + "compiler flag has to be specified manually via\n" + " -DDEAL_II_CXX_VERSION_FLAG=\"...\"\n\n" + ) + ENDIF() +ENDMACRO() -# -# Set up support for newer versions of C++: -# +_bailout("11") +_bailout("14") IF (DEAL_II_WITH_CXX14) ADD_FLAGS(DEAL_II_CXX_FLAGS "${DEAL_II_CXX_VERSION_FLAG}") @@ -414,6 +379,20 @@ ENDIF() # # ######################################################################## +# +# Some compilers (such as Intel 15.3 and GCC 4.9.2) support the flags +# "-std=c++11" and "-std=c++14" but do not support +# 'std::is_trivially_copyable', so check for support in C++11 or newer. +# +IF(DEAL_II_HAVE_CXX11) + CHECK_CXX_SOURCE_COMPILES( + " + #include + int main(){ std::is_trivially_copyable bob; } + " + DEAL_II_HAVE_CXX11_IS_TRIVIALLY_COPYABLE) +ENDIF() + CHECK_CXX_SOURCE_COMPILES( " #include -- 2.39.5