소스 검색

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.
Hong Xu 6 년 전
부모
커밋
72fcadb007
3개의 변경된 파일48개의 추가작업 그리고 2개의 파일을 삭제
  1. 11 0
      Modules/CheckCXXSymbolExists.cmake
  2. 23 2
      Modules/CheckSymbolExists.cmake
  3. 14 0
      Tests/CMakeOnly/CheckCXXSymbolExists/CMakeLists.txt

+ 11 - 0
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:
 

+ 23 - 2
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()
 

+ 14 - 0
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()