From ffa6f057b4ae07c9dc7b9e1d12ecc0a2e19333a1 Mon Sep 17 00:00:00 2001 From: Raphael Kubo da Costa Date: Tue, 15 Sep 2015 16:31:12 +0200 Subject: [PATCH] Avoid using C11 to build CMake if _Thread_local support is broken Support for C11's _Thread_local was introduced in GCC in the 4.9 series, even though we make the C11 compiler flags available in CMake with GCC >= 4.6. FreeBSD's runetype.h uses _Thread_local, which causes CMake's own build to fail when using GCC < 4.9 and -std=gnu11: /usr/include/runetype.h:92:22: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'const' extern _Thread_local const _RuneLocale *_ThreadRuneLocale; Add a test for _Thread_local support and only build CMake itself with C11 support if it works. Bug: http://www.cmake.org/Bug/view.php?id=15741 --- CMakeLists.txt | 7 +++++- Source/Checks/cm_c11_thread_local.c | 2 ++ Source/Checks/cm_c11_thread_local.cmake | 33 +++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 Source/Checks/cm_c11_thread_local.c create mode 100644 Source/Checks/cm_c11_thread_local.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 5e13a7e0f..94d138c3b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -38,7 +38,12 @@ endif() # Use most-recent available language dialects with GNU and Clang if(NOT DEFINED CMAKE_C_STANDARD AND NOT CMake_NO_C_STANDARD) - set(CMAKE_C_STANDARD 11) + include(${CMake_SOURCE_DIR}/Source/Checks/cm_c11_thread_local.cmake) + if(NOT CMake_C11_THREAD_LOCAL_BROKEN) + set(CMAKE_C_STANDARD 11) + else() + set(CMAKE_C_STANDARD 99) + endif() endif() if(NOT DEFINED CMAKE_CXX_STANDARD AND NOT CMake_NO_CXX_STANDARD) include(${CMake_SOURCE_DIR}/Source/Checks/cm_cxx14_cstdio.cmake) diff --git a/Source/Checks/cm_c11_thread_local.c b/Source/Checks/cm_c11_thread_local.c new file mode 100644 index 000000000..ab780f284 --- /dev/null +++ b/Source/Checks/cm_c11_thread_local.c @@ -0,0 +1,2 @@ +_Thread_local int i = 42; +int main(void) { return 0; } diff --git a/Source/Checks/cm_c11_thread_local.cmake b/Source/Checks/cm_c11_thread_local.cmake new file mode 100644 index 000000000..6b8d10b2b --- /dev/null +++ b/Source/Checks/cm_c11_thread_local.cmake @@ -0,0 +1,33 @@ +set(CMake_C11_THREAD_LOCAL_BROKEN 0) +if(CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND CMAKE_C11_STANDARD_COMPILE_OPTION) + if(NOT DEFINED CMake_C11_THREAD_LOCAL_WORKS) + message(STATUS "Checking if compiler supports C11 _Thread_local") + try_compile(CMake_C11_THREAD_LOCAL_WORKS + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_LIST_DIR}/cm_c11_thread_local.c + CMAKE_FLAGS -DCMAKE_C_STANDARD=11 + OUTPUT_VARIABLE OUTPUT + ) + if(CMake_C11_THREAD_LOCAL_WORKS AND "${OUTPUT}" MATCHES "error: expected '=', ',', ';', 'asm' or '__attribute__' before 'int'") + set_property(CACHE CMake_C11_THREAD_LOCAL_WORKS PROPERTY VALUE 0) + endif() + if(CMake_C11_THREAD_LOCAL_WORKS) + message(STATUS "Checking if compiler supports C11 _Thread_local - yes") + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log + "Determining if compiler supports C11 _Thread_local passed with the following output:\n" + "${OUTPUT}\n" + "\n" + ) + else() + message(STATUS "Checking if compiler supports C11 _Thread_local - no") + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log + "Determining if compiler supports C11 _Thread_local failed with the following output:\n" + "${OUTPUT}\n" + "\n" + ) + endif() + endif() + if(NOT CMake_C11_THREAD_LOCAL_WORKS) + set(CMake_C11_THREAD_LOCAL_BROKEN 1) + endif() +endif()