From 5a678b88f56f3f0c7ef37adcb4e6251b2630a004 Mon Sep 17 00:00:00 2001 From: Daniel Scharrer Date: Mon, 11 Mar 2013 13:59:33 +0100 Subject: [PATCH] Add C++11 feature checks --- CMakeLists.txt | 20 ++++------- cmake/CXX11Check.cmake | 32 +++++++++++++++++ cmake/CompileCheck.cmake | 38 ++++++++++++-------- cmake/check-cxx11-std-codecvt_utf8_utf16.cpp | 6 ++++ cmake/check-cxx11-std-unique_ptr.cpp | 6 ++++ src/configure.hpp.in | 1 - src/util/storedenum.hpp | 15 +++----- 7 files changed, 78 insertions(+), 40 deletions(-) create mode 100644 cmake/CXX11Check.cmake create mode 100644 cmake/check-cxx11-std-codecvt_utf8_utf16.cpp create mode 100644 cmake/check-cxx11-std-unique_ptr.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 7ae3f0b..2f7dbb1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -48,6 +48,7 @@ include(CheckSymbolExists) set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") # For custom cmake modules include(BuildType) include(CompileCheck) +include(CXX11Check) include(Doxygen) include(PrintConfiguration) include(StyleCheck) @@ -142,23 +143,14 @@ add_definitions(${iconv_DEFINITIONS}) # Set compiler flags -set(INNOEXTRACT_STD_BITSET_CONSTRUCT_TYPE "unsigned long") -if(MSVC) - if(NOT MSVC_VERSION LESS 1600) - # MSVC 10+ - set(INNOEXTRACT_STD_BITSET_CONSTRUCT_TYPE "unsigned long long") - set(INNOEXTRACT_HAVE_STD_CODECVT_UTF8_UTF16 ON) - set(INNOEXTRACT_HAVE_STD_UNIQUE_PTR ON) - endif() -elseif(${Boost_VERSION} LESS 104800) +if(${Boost_VERSION} LESS 104800) # Older Boost versions don't work with C++11 elseif(USE_CXX11) - add_cxxflag("-std=c++11") - if(FLAG_FOUND) - set(INNOEXTRACT_STD_BITSET_CONSTRUCT_TYPE "unsigned long long") - set(INNOEXTRACT_HAVE_STD_UNIQUE_PTR ON) + enable_cxx11() + check_cxx11("std::unique_ptr" INNOEXTRACT_HAVE_STD_UNIQUE_PTR) + if(WIN32) + check_cxx11("std::codecvt_utf8_utf16" INNOEXTRACT_HAVE_STD_CODECVT_UTF8_UTF16) endif() - # missing check for INNOEXTRACT_HAVE_STD_CODECVT_UTF8_UTF16 endif() # Don't expose internal symbols to the outside world by default diff --git a/cmake/CXX11Check.cmake b/cmake/CXX11Check.cmake new file mode 100644 index 0000000..b2411af --- /dev/null +++ b/cmake/CXX11Check.cmake @@ -0,0 +1,32 @@ + +include(CheckCXXSourceCompiles) +include(CompileCheck) + +set(_HAS_CXX11 0) + +function(enable_cxx11) + if(MSVC) + set(_HAS_CXX11 1 PARENT_SCOPE) + else() + add_cxxflag("-std=c++11") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" PARENT_SCOPE) + if(FLAG_FOUND OR NOT CMAKE_COMPILER_IS_GNUCXX) + set(_HAS_CXX11 1 PARENT_SCOPE) + endif() + endif() +endfunction(enable_cxx11) + +function(check_cxx11 CHECK RESULTVAR) + if(${_HAS_CXX11}) + string(REGEX REPLACE "[^a-zA-Z0-9_][^a-zA-Z0-9_]*" "-" check "${CHECK}") + set(file "${CMAKE_MODULE_PATH}/check-cxx11-${check}.cpp") + check_compile(result "${file}" "${CHECK}" "C++11 feature") + if("${result}" STREQUAL "") + set(${RESULTVAR} OFF PARENT_SCOPE) + else() + set(${RESULTVAR} ON PARENT_SCOPE) + endif() + else() + set(${RESULTVAR} OFF PARENT_SCOPE) + endif() +endfunction() \ No newline at end of file diff --git a/cmake/CompileCheck.cmake b/cmake/CompileCheck.cmake index f2c3078..f667985 100644 --- a/cmake/CompileCheck.cmake +++ b/cmake/CompileCheck.cmake @@ -17,10 +17,13 @@ # misrepresented as being the original software. # 3. This notice may not be removed or altered from any source distribution. -function(check_flag RESULT FLAG TYPE) +function(check_compile RESULT FILE FLAG TYPE) + + string(REGEX REPLACE "[^a-zA-Z0-9_][^a-zA-Z0-9_]*" "-" cachevar "${TYPE}-${FLAG}") + set(cahevar "CHECK_COMPILE_${cahevar}") - if(DEFINED CHECK_COMPILER_FLAG_${FLAG}) - if(CHECK_COMPILER_FLAG_${FLAG}) + if(DEFINED ${cachevar}) + if(${cachevar}) set(${RESULT} "${FLAG}" PARENT_SCOPE) else() set(${RESULT} "" PARENT_SCOPE) @@ -57,19 +60,17 @@ function(check_flag RESULT FLAG TYPE) set(old_CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}") set(old_CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}") set(old_CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS}") - if("${TYPE}" STREQUAL linker) + if("${TYPE}" STREQUAL "linker flag") set(CMAKE_EXE_LINKER_FLAGS "${old_CMAKE_EXE_LINKER_FLAGS} ${FLAG}") set(CMAKE_SHARED_LINKER_FLAGS "${old_CMAKE_SHARED_LINKER_FLAGS} ${FLAG}") set(CMAKE_MODULE_LINKER_FLAGS "${old_CMAKE_MODULE_LINKER_FLAGS} ${FLAG}") - else() + elseif("${TYPE}" STREQUAL "compiler flag") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FLAG}") endif() # Check if we can compile and link a simple file with the new flags - set(compile_test_file "${CMAKE_CURRENT_BINARY_DIR}/compile_flag_test.cpp") - file(WRITE ${compile_test_file} "__attribute__((const)) int main(){ return 0; }\n") try_compile( - CHECK_COMPILER_FLAG ${CMAKE_BINARY_DIR} ${compile_test_file} + check_compiler_flag ${CMAKE_BINARY_DIR} ${FILE} CMAKE_FLAGS "-DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS}" "-DCMAKE_EXE_LINKER_FLAGS=${CMAKE_EXE_LINKER_FLAGS}" "-DCMAKE_SHARED_LINKER_FLAGS=${CMAKE_SHARED_LINKER_FLAGS}" @@ -83,10 +84,10 @@ function(check_flag RESULT FLAG TYPE) set(CMAKE_SHARED_LINKER_FLAGS "${old_CMAKE_SHARED_LINKER_FLAGS}") set(CMAKE_MODULE_LINKER_FLAGS "${old_CMAKE_MODULE_LINKER_FLAGS}") - if(NOT CHECK_COMPILER_FLAG) - message(STATUS "Checking ${TYPE} flag: ${FLAG} - unsupported") + if(NOT check_compiler_flag) + message(STATUS "Checking ${TYPE}: ${FLAG} - unsupported") set(${RESULT} "" PARENT_SCOPE) - set("CHECK_COMPILER_FLAG_${FLAG}" 0 CACHE INTERNAL "...") + set("${cachevar}" 0 CACHE INTERNAL "...") else() set(has_warning 0) @@ -97,17 +98,24 @@ function(check_flag RESULT FLAG TYPE) endforeach() if(has_warning) - message(STATUS "Checking ${TYPE} flag: ${FLAG} - unsupported (warning)") + message(STATUS "Checking ${TYPE}: ${FLAG} - unsupported (warning)") set(${RESULT} "" PARENT_SCOPE) - set("CHECK_COMPILER_FLAG_${FLAG}" 0 CACHE INTERNAL "...") + set("${cachevar}" 0 CACHE INTERNAL "...") else() - message(STATUS "Checking ${TYPE} flag: ${FLAG}") + message(STATUS "Checking ${TYPE}: ${FLAG}") set(${RESULT} "${FLAG}" PARENT_SCOPE) - set("CHECK_COMPILER_FLAG_${FLAG}" 1 CACHE INTERNAL "...") + set("${cachevar}" 1 CACHE INTERNAL "...") endif() endif() +endfunction(check_compile) + +function(check_flag RESULT FLAG TYPE) + set(compile_test_file "${CMAKE_CURRENT_BINARY_DIR}/compile_flag_test.cpp") + file(WRITE ${compile_test_file} "__attribute__((const)) int main(){ return 0; }\n") + check_compile(result "${compile_test_file}" "${FLAG}" "${TYPE} flag") + set(${RESULT} "${result}" PARENT_SCOPE) endfunction(check_flag) function(check_compiler_flag RESULT FLAG) diff --git a/cmake/check-cxx11-std-codecvt_utf8_utf16.cpp b/cmake/check-cxx11-std-codecvt_utf8_utf16.cpp new file mode 100644 index 0000000..e49e08f --- /dev/null +++ b/cmake/check-cxx11-std-codecvt_utf8_utf16.cpp @@ -0,0 +1,6 @@ +#include + +int main() { + std::codecvt_utf8_utf16 codecvt; + return 0; +} \ No newline at end of file diff --git a/cmake/check-cxx11-std-unique_ptr.cpp b/cmake/check-cxx11-std-unique_ptr.cpp new file mode 100644 index 0000000..afd8772 --- /dev/null +++ b/cmake/check-cxx11-std-unique_ptr.cpp @@ -0,0 +1,6 @@ +#include + +int main() { + std::unique_ptr ptr(new char); + return !ptr; +} \ No newline at end of file diff --git a/src/configure.hpp.in b/src/configure.hpp.in index 4cb6853..e77f09a 100644 --- a/src/configure.hpp.in +++ b/src/configure.hpp.in @@ -26,7 +26,6 @@ #cmakedefine01 INNOEXTRACT_HAVE_BSWAP_64 // C++11 functionality -#define INNOEXTRACT_STD_BITSET_CONSTRUCT_TYPE ${INNOEXTRACT_STD_BITSET_CONSTRUCT_TYPE} #cmakedefine01 INNOEXTRACT_HAVE_STD_CODECVT_UTF8_UTF16 #cmakedefine01 INNOEXTRACT_HAVE_STD_UNIQUE_PTR diff --git a/src/util/storedenum.hpp b/src/util/storedenum.hpp index de8cc86..c3ea27a 100644 --- a/src/util/storedenum.hpp +++ b/src/util/storedenum.hpp @@ -23,6 +23,7 @@ #include #include +#include #include #include @@ -130,19 +131,13 @@ public: operator std::bitset() const { - // Make `make style` shut up since we really need unsigned long here. - typedef INNOEXTRACT_STD_BITSET_CONSTRUCT_TYPE construct_type; - - static const size_t construct_size = sizeof(construct_type) * 8; - - BOOST_STATIC_ASSERT(base_size % construct_size == 0 || base_size < construct_size); + #define concat(a, b) a##b + BOOST_STATIC_ASSERT(sizeof(base_type) <= sizeof(concat(unsi, gned) concat(lo, ng))); + #undef concat std::bitset result(0); for(size_t i = 0; i < count; i++) { - for(size_t j = 0; j < util::ceildiv(base_size, construct_size); j++) { - construct_type chunk = static_cast(bits[i] >> (j * construct_size)); - result |= std::bitset(chunk) << ((i * base_size) + (j * construct_size)); - } + result |= std::bitset(bits[i]) << (i * base_size); } return result; }