CheckCXXSymbolExists: Make C++-syntax symbols work on more compilers

On some compilers the syntax `#ifndef std::fopen` will always lead to
compilation error.  Avoid generating it in the check.
This commit is contained in:
Hong Xu 2019-07-07 15:47:06 -07:00 committed by Brad King
parent 93f10f06b3
commit 72fcadb007
3 changed files with 48 additions and 2 deletions

View File

@ -27,6 +27,17 @@ Check if a symbol exists as a function, variable, or macro in ``C++``.
not be recognized: consider using the :module:`CheckTypeSize` not be recognized: consider using the :module:`CheckTypeSize`
or :module:`CheckCXXSourceCompiles` module instead. or :module:`CheckCXXSourceCompiles` module instead.
.. note::
This command is unreliable when ``<symbol>`` is (potentially) an overloaded
function. Since there is no reliable way to predict whether a given function
in the system environment may be defined as an overloaded function or may be
an overloaded function on other systems or will become so in the future, it
is generally advised to use the :module:`CheckCXXSourceCompiles` module for
checking any function symbol (unless somehow you surely know the checked
function is not overloaded on other systems or will not be so in the
future).
The following variables may be set before calling this macro to modify The following variables may be set before calling this macro to modify
the way the check is run: the way the check is run:

View File

@ -99,8 +99,28 @@ macro(__CHECK_SYMBOL_EXISTS_IMPL SOURCEFILE SYMBOL FILES VARIABLE)
string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT
"#include <${FILE}>\n") "#include <${FILE}>\n")
endforeach() endforeach()
string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT "
"\nint main(int argc, char** argv)\n{\n (void)argv;\n#ifndef ${SYMBOL}\n return ((int*)(&${SYMBOL}))[argc];\n#else\n (void)argc;\n return 0;\n#endif\n}\n") int main(int argc, char** argv)
{
(void)argv;")
set(_CSE_CHECK_NON_MACRO "return ((int*)(&${SYMBOL}))[argc];")
if("${SYMBOL}" MATCHES "^[a-zA-Z_][a-zA-Z0-9_]*$")
# The SYMBOL has a legal macro name. Test whether it exists as a macro.
string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT "
#ifndef ${SYMBOL}
${_CSE_CHECK_NON_MACRO}
#else
(void)argc;
return 0;
#endif")
else()
# The SYMBOL cannot be a macro (e.g., a template function).
string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT "
${_CSE_CHECK_NON_MACRO}")
endif()
string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT "
}")
unset(_CSE_CHECK_NON_MACRO)
configure_file("${CMAKE_ROOT}/Modules/CMakeConfigurableFile.in" configure_file("${CMAKE_ROOT}/Modules/CMakeConfigurableFile.in"
"${SOURCEFILE}" @ONLY) "${SOURCEFILE}" @ONLY)
@ -139,6 +159,7 @@ macro(__CHECK_SYMBOL_EXISTS_IMPL SOURCEFILE SYMBOL FILES VARIABLE)
"${OUTPUT}\nFile ${SOURCEFILE}:\n" "${OUTPUT}\nFile ${SOURCEFILE}:\n"
"${CMAKE_CONFIGURABLE_FILE_CONTENT}\n") "${CMAKE_CONFIGURABLE_FILE_CONTENT}\n")
endif() endif()
unset(CMAKE_CONFIGURABLE_FILE_CONTENT)
endif() endif()
endmacro() endmacro()

View File

@ -49,6 +49,15 @@ else ()
message(STATUS "errno found in <cerrno>") message(STATUS "errno found in <cerrno>")
endif () endif ()
check_cxx_symbol_exists("std::fopen" "cstdio" CSE_RESULT_FOPEN)
if (NOT CSE_RESULT_FOPEN)
if(NOT ("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 13.10))
message(SEND_ERROR "CheckCXXSymbolExists did not find std::fopen in <cstdio>")
endif()
else()
message(STATUS "std::fopen found in <cstdio>")
endif()
if (CMAKE_COMPILER_IS_GNUCXX) if (CMAKE_COMPILER_IS_GNUCXX)
string(APPEND CMAKE_CXX_FLAGS " -O3") string(APPEND CMAKE_CXX_FLAGS " -O3")
unset(CSE_RESULT_O3 CACHE) unset(CSE_RESULT_O3 CACHE)
@ -60,3 +69,8 @@ if (CMAKE_COMPILER_IS_GNUCXX)
message(SEND_ERROR "CheckCXXSymbolExists reported a nonexistent symbol as existing with optimization -O3") message(SEND_ERROR "CheckCXXSymbolExists reported a nonexistent symbol as existing with optimization -O3")
endif () endif ()
endif () endif ()
check_cxx_symbol_exists("std::non_existent_function_for_symbol_test<int*>" "algorithm" CSE_RESULT_NON_SYMBOL)
if (CSE_RESULT_NON_SYMBOL)
message(SEND_ERROR "CheckCXXSymbolExists reported a nonexistent symbol.")
endif()