diff --git a/Modules/CheckStructHasMember.cmake b/Modules/CheckStructHasMember.cmake index ea2891c8b..d28cc2a1e 100644 --- a/Modules/CheckStructHasMember.cmake +++ b/Modules/CheckStructHasMember.cmake @@ -1,10 +1,12 @@ # - Check if the given struct or class has the specified member variable -# CHECK_STRUCT_HAS_MEMBER (STRUCT MEMBER HEADER VARIABLE) +# CHECK_STRUCT_HAS_MEMBER (
+# [LANGUAGE ]) # -# STRUCT - the name of the struct or class you are interested in -# MEMBER - the member which existence you want to check -# HEADER - the header(s) where the prototype should be declared -# VARIABLE - variable to store the result +# - the name of the struct or class you are interested in +# - the member which existence you want to check +#
- the header(s) where the prototype should be declared +# - variable to store the result +# - the compiler to use (C or CXX) # # The following variables may be set before calling this macro to # modify the way the check is run: @@ -12,8 +14,9 @@ # CMAKE_REQUIRED_FLAGS = string of compile command line flags # CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar) # CMAKE_REQUIRED_INCLUDES = list of include directories +# CMAKE_REQUIRED_LIBRARIES = list of libraries to link # -# Example: CHECK_STRUCT_HAS_MEMBER("struct timeval" tv_sec sys/select.h HAVE_TIMEVAL_TV_SEC) +# Example: CHECK_STRUCT_HAS_MEMBER("struct timeval" tv_sec sys/select.h HAVE_TIMEVAL_TV_SEC LANGUAGE C) #============================================================================= # Copyright 2007-2009 Kitware, Inc. @@ -29,6 +32,7 @@ # License text for the above reference.) include(CheckCSourceCompiles) +include(CheckCXXSourceCompiles) macro (CHECK_STRUCT_HAS_MEMBER _STRUCT _MEMBER _HEADER _RESULT) set(_INCLUDE_FILES) @@ -36,16 +40,29 @@ macro (CHECK_STRUCT_HAS_MEMBER _STRUCT _MEMBER _HEADER _RESULT) set(_INCLUDE_FILES "${_INCLUDE_FILES}#include <${it}>\n") endforeach () + if("x${ARGN}" STREQUAL "x") + set(_lang C) + elseif("x${ARGN}" MATCHES "^xLANGUAGE;([a-zA-Z]+)$") + set(_lang "${CMAKE_MATCH_1}") + else() + message(FATAL_ERROR "Unknown arguments:\n ${ARGN}\n") + endif() + set(_CHECK_STRUCT_MEMBER_SOURCE_CODE " ${_INCLUDE_FILES} int main() { ${_STRUCT}* tmp; tmp->${_MEMBER}; - return 0; + return 0; } ") - CHECK_C_SOURCE_COMPILES("${_CHECK_STRUCT_MEMBER_SOURCE_CODE}" ${_RESULT}) + if("${_lang}" STREQUAL "C") + CHECK_C_SOURCE_COMPILES("${_CHECK_STRUCT_MEMBER_SOURCE_CODE}" ${_RESULT}) + elseif("${_lang}" STREQUAL "CXX") + CHECK_CXX_SOURCE_COMPILES("${_CHECK_STRUCT_MEMBER_SOURCE_CODE}" ${_RESULT}) + else() + message(FATAL_ERROR "Unknown language:\n ${_lang}\nSupported languages: C, CXX.\n") + endif() endmacro () - diff --git a/Tests/CMakeOnly/CMakeLists.txt b/Tests/CMakeOnly/CMakeLists.txt index be7ddbc21..7586de6b2 100644 --- a/Tests/CMakeOnly/CMakeLists.txt +++ b/Tests/CMakeOnly/CMakeLists.txt @@ -19,6 +19,8 @@ add_CMakeOnly_test(CheckCXXCompilerFlag) add_CMakeOnly_test(CheckLanguage) +add_CMakeOnly_test(CheckStructHasMember) + add_CMakeOnly_test(CompilerIdC) add_CMakeOnly_test(CompilerIdCXX) if(CMAKE_Fortran_COMPILER) diff --git a/Tests/CMakeOnly/CheckStructHasMember/CMakeLists.txt b/Tests/CMakeOnly/CheckStructHasMember/CMakeLists.txt new file mode 100644 index 000000000..f06d5c34d --- /dev/null +++ b/Tests/CMakeOnly/CheckStructHasMember/CMakeLists.txt @@ -0,0 +1,93 @@ +cmake_minimum_required(VERSION 2.8) + +project(CheckStructHasMember) + +set(CMAKE_REQUIRED_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}") + +include(CheckStructHasMember) + +foreach(_config_type Release RelWithDebInfo MinSizeRel Debug) + set(CMAKE_TRY_COMPILE_CONFIGURATION ${_config_type}) + unset(CSHM_RESULT_S1_${_config_type} CACHE) + unset(CSHM_RESULT_S2_${_config_type} CACHE) + unset(CSHM_RESULT_S3_${_config_type} CACHE) + message(STATUS "Testing configuration ${_config_type}") + + check_struct_has_member("struct non_existent_struct" "foo" "cm_cshm.h" CSHM_RESULT_S1_${_config_type}) + check_struct_has_member("struct struct_with_member" "non_existent_member" "cm_cshm.h" CSHM_RESULT_S2_${_config_type}) + check_struct_has_member("struct struct_with_member" "member" "cm_cshm.h" CSHM_RESULT_S3_${_config_type}) + + if(CSHM_RESULT_S1_${_config_type} OR CSHM_RESULT_S2_${_config_type}) + message(SEND_ERROR "CheckStructHasMember reported a nonexistent member as existing in configuration ${_config_type}") + endif() + + if(NOT CSHM_RESULT_S3_${_config_type}) + message(SEND_ERROR "CheckStructHasMember did not report an existent member as existing in configuration ${_config_type}") + endif() +endforeach() + +foreach(_config_type Release RelWithDebInfo MinSizeRel Debug) + set(CMAKE_TRY_COMPILE_CONFIGURATION ${_config_type}) + unset(CSHM_RESULT_S1_${_config_type}_C CACHE) + unset(CSHM_RESULT_S2_${_config_type}_C CACHE) + unset(CSHM_RESULT_S3_${_config_type}_C CACHE) + message(STATUS "Testing configuration ${_config_type}") + + check_struct_has_member("struct non_existent_struct" "foo" "cm_cshm.h" CSHM_RESULT_S1_${_config_type}_C LANGUAGE C) + check_struct_has_member("struct struct_with_member" "non_existent_member" "cm_cshm.h" CSHM_RESULT_S2_${_config_type}_C LANGUAGE C) + check_struct_has_member("struct struct_with_member" "member" "cm_cshm.h" CSHM_RESULT_S3_${_config_type}_C LANGUAGE C) + + if(CSHM_RESULT_S1_${_config_type}_C OR CSHM_RESULT_S2_${_config_type}_C) + message(SEND_ERROR "CheckStructHasMember reported a nonexistent member as existing in configuration ${_config_type}") + endif() + + if(NOT CSHM_RESULT_S3_${_config_type}_C) + message(SEND_ERROR "CheckStructHasMember did not report an existent member as existing in configuration ${_config_type}") + endif() +endforeach() + +foreach(_config_type Release RelWithDebInfo MinSizeRel Debug) + set(CMAKE_TRY_COMPILE_CONFIGURATION ${_config_type}) + unset(CSHM_RESULT_S1_${_config_type}_CXX CACHE) + unset(CSHM_RESULT_S2_${_config_type}_CXX CACHE) + unset(CSHM_RESULT_S3_${_config_type}_CXX CACHE) + unset(CSHM_RESULT_C1_${_config_type}_CXX CACHE) + unset(CSHM_RESULT_C2_${_config_type}_CXX CACHE) + unset(CSHM_RESULT_C3_${_config_type}_CXX CACHE) + + message(STATUS "Testing configuration ${_config_type}") + + check_struct_has_member("non_existent_struct" "foo" "cm_cshm.h" CSHM_RESULT_S1_${_config_type}_CXX LANGUAGE CXX) + check_struct_has_member("struct_with_non_existent_members" "non_existent_member" "cm_cshm.h" CSHM_RESULT_S2_${_config_type}_CXX LANGUAGE CXX) + check_struct_has_member("struct struct_with_member" "member" "cm_cshm.h" CSHM_RESULT_S3_${_config_type}_CXX LANGUAGE CXX) + check_struct_has_member("ns::non_existent_class" "foo" "cm_cshm.hxx" CSHM_RESULT_C1_${_config_type}_CXX LANGUAGE CXX) + check_struct_has_member("ns::class_with_non_existent_members" "foo" "cm_cshm.hxx" CSHM_RESULT_C2_${_config_type}_CXX LANGUAGE CXX) + check_struct_has_member("ns::class_with_member" "foo" "cm_cshm.hxx" CSHM_RESULT_C3_${_config_type}_CXX LANGUAGE CXX) + + if(CSHM_RESULT_S1_${_config_type}_CXX OR CSHM_RESULT_S2_${_config_type}_CXX OR CSHM_RESULT_C1_${_config_type}_CXX OR CSHM_RESULT_C2_${_config_type}_CXX) + message(SEND_ERROR "CheckStructHasMember reported a nonexistent member as existing in configuration ${_config_type}") + endif() + + if(NOT CSHM_RESULT_S3_${_config_type}_CXX OR NOT CSHM_RESULT_C3_${_config_type}_CXX) + message(SEND_ERROR "CheckStructHasMember did not report an existent member as existing in configuration ${_config_type}") + endif() +endforeach() + + +set(CMAKE_TRY_COMPILE_CONFIGURATION ${CMAKE_BUILD_TYPE}) + +if (CMAKE_COMPILER_IS_GNUCC) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3") + unset(CSHM_RESULT_O3 CACHE) + unset(CSHM_RESULT_O3_C CACHE) + unset(CSHM_RESULT_O3_CXX CACHE) + message(STATUS "Testing with optimization -O3") + + check_struct_has_member("class_with_non_existent_members" foo "cm_cshm.h" CSHM_RESULT_O3) + check_struct_has_member("class_with_non_existent_members" foo "cm_cshm.h" CSHM_RESULT_O3_C LANGUAGE C) + check_struct_has_member("class_with_non_existent_members" foo "cm_cshm.h" CSHM_RESULT_O3_CXX LANGUAGE CXX) + + if (CSE_RESULT_O3 OR CSHM_RESULT_O3_C OR CSHM_RESULT_O3_CXX) + message(SEND_ERROR "CheckSymbolExists reported a nonexistent symbol as existing with optimization -O3") + endif () +endif () diff --git a/Tests/CMakeOnly/CheckStructHasMember/cm_cshm.h b/Tests/CMakeOnly/CheckStructHasMember/cm_cshm.h new file mode 100644 index 000000000..82bb0498c --- /dev/null +++ b/Tests/CMakeOnly/CheckStructHasMember/cm_cshm.h @@ -0,0 +1,9 @@ +#ifndef _CSHM_DUMMY_H +#define _CSHM_DUMMY_H + +struct non_existent_struct; +struct struct_with_member{ + int member; +}; + +#endif diff --git a/Tests/CMakeOnly/CheckStructHasMember/cm_cshm.hxx b/Tests/CMakeOnly/CheckStructHasMember/cm_cshm.hxx new file mode 100644 index 000000000..458a99b46 --- /dev/null +++ b/Tests/CMakeOnly/CheckStructHasMember/cm_cshm.hxx @@ -0,0 +1,16 @@ +#ifndef _CSHM_DUMMY_HXX +#define _CSHM_DUMMY_HXX + +namespace ns { + +class non_existent_class; +class class_with_non_existent_members { +}; +class class_with_member { +public: + int foo; +}; + +} + +#endif diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index e45aba378..35c8e132e 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -119,3 +119,4 @@ endif() add_RunCMake_test(File_Generate) add_RunCMake_test(ExportWithoutLanguage) add_RunCMake_test(target_link_libraries) +add_RunCMake_test(CheckModules) diff --git a/Tests/RunCMake/CheckModules/CMakeLists.txt b/Tests/RunCMake/CheckModules/CMakeLists.txt new file mode 100644 index 000000000..65ac8e8db --- /dev/null +++ b/Tests/RunCMake/CheckModules/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 2.8.11) +project(${RunCMake_TEST}) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/CheckModules/CheckStructHasMemberMissingKey-result.txt b/Tests/RunCMake/CheckModules/CheckStructHasMemberMissingKey-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/CheckModules/CheckStructHasMemberMissingKey-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CheckModules/CheckStructHasMemberMissingKey-stderr.txt b/Tests/RunCMake/CheckModules/CheckStructHasMemberMissingKey-stderr.txt new file mode 100644 index 000000000..1b8603a83 --- /dev/null +++ b/Tests/RunCMake/CheckModules/CheckStructHasMemberMissingKey-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at .*/Modules/CheckStructHasMember.cmake:[0-9]+. \(message\): + Unknown arguments: + + C + +Call Stack \(most recent call first\): + CheckStructHasMemberMissingKey.cmake:[0-9]+ \(check_struct_has_member\) + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/CheckModules/CheckStructHasMemberMissingKey.cmake b/Tests/RunCMake/CheckModules/CheckStructHasMemberMissingKey.cmake new file mode 100644 index 000000000..49f51ceca --- /dev/null +++ b/Tests/RunCMake/CheckModules/CheckStructHasMemberMissingKey.cmake @@ -0,0 +1,2 @@ +include(CheckStructHasMember) +check_struct_has_member("struct timeval" tv_sec sys/select.h HAVE_TIMEVAL_TV_SEC_K C) diff --git a/Tests/RunCMake/CheckModules/CheckStructHasMemberMissingLanguage-result.txt b/Tests/RunCMake/CheckModules/CheckStructHasMemberMissingLanguage-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/CheckModules/CheckStructHasMemberMissingLanguage-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CheckModules/CheckStructHasMemberMissingLanguage-stderr.txt b/Tests/RunCMake/CheckModules/CheckStructHasMemberMissingLanguage-stderr.txt new file mode 100644 index 000000000..8fceab0df --- /dev/null +++ b/Tests/RunCMake/CheckModules/CheckStructHasMemberMissingLanguage-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at .*/Modules/CheckStructHasMember.cmake:[0-9]+. \(message\): + Unknown arguments: + + LANGUAGE + +Call Stack \(most recent call first\): + CheckStructHasMemberMissingLanguage.cmake:[0-9]+ \(check_struct_has_member\) + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/CheckModules/CheckStructHasMemberMissingLanguage.cmake b/Tests/RunCMake/CheckModules/CheckStructHasMemberMissingLanguage.cmake new file mode 100644 index 000000000..b404d665b --- /dev/null +++ b/Tests/RunCMake/CheckModules/CheckStructHasMemberMissingLanguage.cmake @@ -0,0 +1,2 @@ +include(CheckStructHasMember) +check_struct_has_member("struct timeval" tv_sec sys/select.h HAVE_TIMEVAL_TV_SEC_K LANGUAGE) diff --git a/Tests/RunCMake/CheckModules/CheckStructHasMemberOk.cmake b/Tests/RunCMake/CheckModules/CheckStructHasMemberOk.cmake new file mode 100644 index 000000000..b319e18f2 --- /dev/null +++ b/Tests/RunCMake/CheckModules/CheckStructHasMemberOk.cmake @@ -0,0 +1,4 @@ +include(CheckStructHasMember) +check_struct_has_member("struct timeval" tv_sec sys/select.h HAVE_TIMEVAL_TV_SEC) +check_struct_has_member("struct timeval" tv_sec sys/select.h HAVE_TIMEVAL_TV_SEC_C LANGUAGE C) +check_struct_has_member("struct timeval" tv_sec sys/select.h HAVE_TIMEVAL_TV_SEC_CXX LANGUAGE CXX) diff --git a/Tests/RunCMake/CheckModules/CheckStructHasMemberTooManyArguments-result.txt b/Tests/RunCMake/CheckModules/CheckStructHasMemberTooManyArguments-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/CheckModules/CheckStructHasMemberTooManyArguments-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CheckModules/CheckStructHasMemberTooManyArguments-stderr.txt b/Tests/RunCMake/CheckModules/CheckStructHasMemberTooManyArguments-stderr.txt new file mode 100644 index 000000000..459886744 --- /dev/null +++ b/Tests/RunCMake/CheckModules/CheckStructHasMemberTooManyArguments-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at .*/Modules/CheckStructHasMember.cmake:[0-9]+. \(message\): + Unknown arguments: + + LANGUAGE;C;CXX + +Call Stack \(most recent call first\): + CheckStructHasMemberTooManyArguments.cmake:[0-9]+ \(check_struct_has_member\) + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/CheckModules/CheckStructHasMemberTooManyArguments.cmake b/Tests/RunCMake/CheckModules/CheckStructHasMemberTooManyArguments.cmake new file mode 100644 index 000000000..12f81582d --- /dev/null +++ b/Tests/RunCMake/CheckModules/CheckStructHasMemberTooManyArguments.cmake @@ -0,0 +1,2 @@ +include(CheckStructHasMember) +check_struct_has_member("struct timeval" tv_sec sys/select.h HAVE_TIMEVAL_TV_SEC_K LANGUAGE C CXX) diff --git a/Tests/RunCMake/CheckModules/CheckStructHasMemberUnknownLanguage-result.txt b/Tests/RunCMake/CheckModules/CheckStructHasMemberUnknownLanguage-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/CheckModules/CheckStructHasMemberUnknownLanguage-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CheckModules/CheckStructHasMemberUnknownLanguage-stderr.txt b/Tests/RunCMake/CheckModules/CheckStructHasMemberUnknownLanguage-stderr.txt new file mode 100644 index 000000000..ba9e31312 --- /dev/null +++ b/Tests/RunCMake/CheckModules/CheckStructHasMemberUnknownLanguage-stderr.txt @@ -0,0 +1,10 @@ +CMake Error at .*/Modules/CheckStructHasMember.cmake:[0-9]+. \(message\): + Unknown language: + + FORTRAN + + Supported languages: C, CXX. + +Call Stack \(most recent call first\): + CheckStructHasMemberUnknownLanguage.cmake:[0-9]+ \(check_struct_has_member\) + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/CheckModules/CheckStructHasMemberUnknownLanguage.cmake b/Tests/RunCMake/CheckModules/CheckStructHasMemberUnknownLanguage.cmake new file mode 100644 index 000000000..183058ddc --- /dev/null +++ b/Tests/RunCMake/CheckModules/CheckStructHasMemberUnknownLanguage.cmake @@ -0,0 +1,2 @@ +include(CheckStructHasMember) +check_struct_has_member("struct timeval" tv_sec sys/select.h HAVE_TIMEVAL_TV_SEC_K LANGUAGE FORTRAN) diff --git a/Tests/RunCMake/CheckModules/CheckStructHasMemberWrongKey-result.txt b/Tests/RunCMake/CheckModules/CheckStructHasMemberWrongKey-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/CheckModules/CheckStructHasMemberWrongKey-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CheckModules/CheckStructHasMemberWrongKey-stderr.txt b/Tests/RunCMake/CheckModules/CheckStructHasMemberWrongKey-stderr.txt new file mode 100644 index 000000000..b9fbd38cf --- /dev/null +++ b/Tests/RunCMake/CheckModules/CheckStructHasMemberWrongKey-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at .*/Modules/CheckStructHasMember.cmake:[0-9]+. \(message\): + Unknown arguments: + + LANGUAG;C + +Call Stack \(most recent call first\): + CheckStructHasMemberWrongKey.cmake:[0-9]+ \(check_struct_has_member\) + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/CheckModules/CheckStructHasMemberWrongKey.cmake b/Tests/RunCMake/CheckModules/CheckStructHasMemberWrongKey.cmake new file mode 100644 index 000000000..900eb0a75 --- /dev/null +++ b/Tests/RunCMake/CheckModules/CheckStructHasMemberWrongKey.cmake @@ -0,0 +1,2 @@ +include(CheckStructHasMember) +check_struct_has_member("struct timeval" tv_sec sys/select.h HAVE_TIMEVAL_TV_SEC_K LANGUAG C) diff --git a/Tests/RunCMake/CheckModules/RunCMakeTest.cmake b/Tests/RunCMake/CheckModules/RunCMakeTest.cmake new file mode 100644 index 000000000..6a6b36eaf --- /dev/null +++ b/Tests/RunCMake/CheckModules/RunCMakeTest.cmake @@ -0,0 +1,8 @@ +include(RunCMake) + +run_cmake(CheckStructHasMemberOk) +run_cmake(CheckStructHasMemberUnknownLanguage) +run_cmake(CheckStructHasMemberMissingLanguage) +run_cmake(CheckStructHasMemberMissingKey) +run_cmake(CheckStructHasMemberTooManyArguments) +run_cmake(CheckStructHasMemberWrongKey)