CheckStructHasMember: Add support for C++
Previously if headers required to check if a struct has a member can be compiled with C++ compiler only, the check would fail because the C compiler fails. As a consequence, the result variable would be set to false, even if the struct has that particular member. Teach CHECK_STRUCT_HAS_MEMBER to accept a new optional argument LANGUAGE that allows one to explicitly set the compiler to use. The new signature is therefore: CHECK_STRUCT_HAS_MEMBER (<struct> <member> <header> <variable> [LANGUAGE <language>])
This commit is contained in:
parent
951a158c8a
commit
73d28d2177
|
@ -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 (<struct> <member> <header> <variable>
|
||||
# [LANGUAGE <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
|
||||
# <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
|
||||
# <language> - 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 ()
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 ()
|
|
@ -0,0 +1,9 @@
|
|||
#ifndef _CSHM_DUMMY_H
|
||||
#define _CSHM_DUMMY_H
|
||||
|
||||
struct non_existent_struct;
|
||||
struct struct_with_member{
|
||||
int member;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -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
|
|
@ -119,3 +119,4 @@ endif()
|
|||
add_RunCMake_test(File_Generate)
|
||||
add_RunCMake_test(ExportWithoutLanguage)
|
||||
add_RunCMake_test(target_link_libraries)
|
||||
add_RunCMake_test(CheckModules)
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
cmake_minimum_required(VERSION 2.8.11)
|
||||
project(${RunCMake_TEST})
|
||||
include(${RunCMake_TEST}.cmake)
|
|
@ -0,0 +1 @@
|
|||
1
|
|
@ -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\)
|
|
@ -0,0 +1,2 @@
|
|||
include(CheckStructHasMember)
|
||||
check_struct_has_member("struct timeval" tv_sec sys/select.h HAVE_TIMEVAL_TV_SEC_K C)
|
|
@ -0,0 +1 @@
|
|||
1
|
|
@ -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\)
|
|
@ -0,0 +1,2 @@
|
|||
include(CheckStructHasMember)
|
||||
check_struct_has_member("struct timeval" tv_sec sys/select.h HAVE_TIMEVAL_TV_SEC_K LANGUAGE)
|
|
@ -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)
|
|
@ -0,0 +1 @@
|
|||
1
|
|
@ -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\)
|
|
@ -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)
|
|
@ -0,0 +1 @@
|
|||
1
|
|
@ -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\)
|
|
@ -0,0 +1,2 @@
|
|||
include(CheckStructHasMember)
|
||||
check_struct_has_member("struct timeval" tv_sec sys/select.h HAVE_TIMEVAL_TV_SEC_K LANGUAGE FORTRAN)
|
|
@ -0,0 +1 @@
|
|||
1
|
|
@ -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\)
|
|
@ -0,0 +1,2 @@
|
|||
include(CheckStructHasMember)
|
||||
check_struct_has_member("struct timeval" tv_sec sys/select.h HAVE_TIMEVAL_TV_SEC_K LANGUAG C)
|
|
@ -0,0 +1,8 @@
|
|||
include(RunCMake)
|
||||
|
||||
run_cmake(CheckStructHasMemberOk)
|
||||
run_cmake(CheckStructHasMemberUnknownLanguage)
|
||||
run_cmake(CheckStructHasMemberMissingLanguage)
|
||||
run_cmake(CheckStructHasMemberMissingKey)
|
||||
run_cmake(CheckStructHasMemberTooManyArguments)
|
||||
run_cmake(CheckStructHasMemberWrongKey)
|
Loading…
Reference in New Issue