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 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
|
# <struct> - the name of the struct or class you are interested in
|
||||||
# MEMBER - the member which existence you want to check
|
# <member> - the member which existence you want to check
|
||||||
# HEADER - the header(s) where the prototype should be declared
|
# <header> - the header(s) where the prototype should be declared
|
||||||
# VARIABLE - variable to store the result
|
# <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
|
# The following variables may be set before calling this macro to
|
||||||
# modify the way the check is run:
|
# modify the way the check is run:
|
||||||
|
@ -12,8 +14,9 @@
|
||||||
# CMAKE_REQUIRED_FLAGS = string of compile command line flags
|
# CMAKE_REQUIRED_FLAGS = string of compile command line flags
|
||||||
# CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar)
|
# CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar)
|
||||||
# CMAKE_REQUIRED_INCLUDES = list of include directories
|
# 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.
|
# Copyright 2007-2009 Kitware, Inc.
|
||||||
|
@ -29,6 +32,7 @@
|
||||||
# License text for the above reference.)
|
# License text for the above reference.)
|
||||||
|
|
||||||
include(CheckCSourceCompiles)
|
include(CheckCSourceCompiles)
|
||||||
|
include(CheckCXXSourceCompiles)
|
||||||
|
|
||||||
macro (CHECK_STRUCT_HAS_MEMBER _STRUCT _MEMBER _HEADER _RESULT)
|
macro (CHECK_STRUCT_HAS_MEMBER _STRUCT _MEMBER _HEADER _RESULT)
|
||||||
set(_INCLUDE_FILES)
|
set(_INCLUDE_FILES)
|
||||||
|
@ -36,16 +40,29 @@ macro (CHECK_STRUCT_HAS_MEMBER _STRUCT _MEMBER _HEADER _RESULT)
|
||||||
set(_INCLUDE_FILES "${_INCLUDE_FILES}#include <${it}>\n")
|
set(_INCLUDE_FILES "${_INCLUDE_FILES}#include <${it}>\n")
|
||||||
endforeach ()
|
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 "
|
set(_CHECK_STRUCT_MEMBER_SOURCE_CODE "
|
||||||
${_INCLUDE_FILES}
|
${_INCLUDE_FILES}
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
${_STRUCT}* tmp;
|
${_STRUCT}* tmp;
|
||||||
tmp->${_MEMBER};
|
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 ()
|
endmacro ()
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,8 @@ add_CMakeOnly_test(CheckCXXCompilerFlag)
|
||||||
|
|
||||||
add_CMakeOnly_test(CheckLanguage)
|
add_CMakeOnly_test(CheckLanguage)
|
||||||
|
|
||||||
|
add_CMakeOnly_test(CheckStructHasMember)
|
||||||
|
|
||||||
add_CMakeOnly_test(CompilerIdC)
|
add_CMakeOnly_test(CompilerIdC)
|
||||||
add_CMakeOnly_test(CompilerIdCXX)
|
add_CMakeOnly_test(CompilerIdCXX)
|
||||||
if(CMAKE_Fortran_COMPILER)
|
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(File_Generate)
|
||||||
add_RunCMake_test(ExportWithoutLanguage)
|
add_RunCMake_test(ExportWithoutLanguage)
|
||||||
add_RunCMake_test(target_link_libraries)
|
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