summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHong Xu <hong@topbug.net>2019-07-07 15:47:06 -0700
committerBrad King <brad.king@kitware.com>2019-07-26 15:09:28 -0400
commit72fcadb007261f8e1883040d7dc5643e3555aa45 (patch)
tree0a7f2ab77a257930351375e04a61223149f74bdc
parent93f10f06b3b86085a180e5259f653646e1705baf (diff)
downloadcmake-72fcadb007261f8e1883040d7dc5643e3555aa45.tar.gz
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.
-rw-r--r--Modules/CheckCXXSymbolExists.cmake11
-rw-r--r--Modules/CheckSymbolExists.cmake25
-rw-r--r--Tests/CMakeOnly/CheckCXXSymbolExists/CMakeLists.txt14
3 files changed, 48 insertions, 2 deletions
diff --git a/Modules/CheckCXXSymbolExists.cmake b/Modules/CheckCXXSymbolExists.cmake
index b11209453d..5c9079dbf3 100644
--- a/Modules/CheckCXXSymbolExists.cmake
+++ b/Modules/CheckCXXSymbolExists.cmake
@@ -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`
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 way the check is run:
diff --git a/Modules/CheckSymbolExists.cmake b/Modules/CheckSymbolExists.cmake
index c2f488aee2..105338301a 100644
--- a/Modules/CheckSymbolExists.cmake
+++ b/Modules/CheckSymbolExists.cmake
@@ -99,8 +99,28 @@ macro(__CHECK_SYMBOL_EXISTS_IMPL SOURCEFILE SYMBOL FILES VARIABLE)
string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT
"#include <${FILE}>\n")
endforeach()
- 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")
+ string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT "
+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"
"${SOURCEFILE}" @ONLY)
@@ -139,6 +159,7 @@ macro(__CHECK_SYMBOL_EXISTS_IMPL SOURCEFILE SYMBOL FILES VARIABLE)
"${OUTPUT}\nFile ${SOURCEFILE}:\n"
"${CMAKE_CONFIGURABLE_FILE_CONTENT}\n")
endif()
+ unset(CMAKE_CONFIGURABLE_FILE_CONTENT)
endif()
endmacro()
diff --git a/Tests/CMakeOnly/CheckCXXSymbolExists/CMakeLists.txt b/Tests/CMakeOnly/CheckCXXSymbolExists/CMakeLists.txt
index f058c19fb6..2028a135cf 100644
--- a/Tests/CMakeOnly/CheckCXXSymbolExists/CMakeLists.txt
+++ b/Tests/CMakeOnly/CheckCXXSymbolExists/CMakeLists.txt
@@ -49,6 +49,15 @@ else ()
message(STATUS "errno found in <cerrno>")
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)
string(APPEND CMAKE_CXX_FLAGS " -O3")
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")
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()