1# Distributed under the OSI-approved BSD 3-Clause License. See accompanying 2# file Copyright.txt or https://cmake.org/licensing for details. 3 4#[=======================================================================[.rst: 5CheckSymbolExists 6----------------- 7 8Provides a macro to check if a symbol exists as a function, variable, 9or macro in ``C``. 10 11.. command:: check_symbol_exists 12 13 .. code-block:: cmake 14 15 check_symbol_exists(<symbol> <files> <variable>) 16 17 Check that the ``<symbol>`` is available after including given header 18 ``<files>`` and store the result in a ``<variable>``. Specify the list 19 of files in one argument as a semicolon-separated list. 20 ``<variable>`` will be created as an internal cache variable. 21 22If the header files define the symbol as a macro it is considered 23available and assumed to work. If the header files declare the symbol 24as a function or variable then the symbol must also be available for 25linking (so intrinsics may not be detected). 26If the symbol is a type, enum value, or intrinsic it will not be recognized 27(consider using :module:`CheckTypeSize` or :module:`CheckSourceCompiles`). 28If the check needs to be done in C++, consider using 29:module:`CheckCXXSymbolExists` instead. 30 31The following variables may be set before calling this macro to modify 32the way the check is run: 33 34``CMAKE_REQUIRED_FLAGS`` 35 string of compile command line flags. 36``CMAKE_REQUIRED_DEFINITIONS`` 37 a :ref:`;-list <CMake Language Lists>` of macros to define (-DFOO=bar). 38``CMAKE_REQUIRED_INCLUDES`` 39 a :ref:`;-list <CMake Language Lists>` of header search paths to pass to 40 the compiler. 41``CMAKE_REQUIRED_LINK_OPTIONS`` 42 .. versionadded:: 3.14 43 a :ref:`;-list <CMake Language Lists>` of options to add to the link command. 44``CMAKE_REQUIRED_LIBRARIES`` 45 a :ref:`;-list <CMake Language Lists>` of libraries to add to the link 46 command. See policy :policy:`CMP0075`. 47``CMAKE_REQUIRED_QUIET`` 48 .. versionadded:: 3.1 49 execute quietly without messages. 50 51For example: 52 53.. code-block:: cmake 54 55 include(CheckSymbolExists) 56 57 # Check for macro SEEK_SET 58 check_symbol_exists(SEEK_SET "stdio.h" HAVE_SEEK_SET) 59 # Check for function fopen 60 check_symbol_exists(fopen "stdio.h" HAVE_FOPEN) 61#]=======================================================================] 62 63include_guard(GLOBAL) 64 65cmake_policy(PUSH) 66cmake_policy(SET CMP0054 NEW) # if() quoted variables not dereferenced 67 68macro(CHECK_SYMBOL_EXISTS SYMBOL FILES VARIABLE) 69 if(CMAKE_C_COMPILER_LOADED) 70 __CHECK_SYMBOL_EXISTS_IMPL("${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckSymbolExists.c" "${SYMBOL}" "${FILES}" "${VARIABLE}" ) 71 elseif(CMAKE_CXX_COMPILER_LOADED) 72 __CHECK_SYMBOL_EXISTS_IMPL("${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckSymbolExists.cxx" "${SYMBOL}" "${FILES}" "${VARIABLE}" ) 73 else() 74 message(FATAL_ERROR "CHECK_SYMBOL_EXISTS needs either C or CXX language enabled") 75 endif() 76endmacro() 77 78macro(__CHECK_SYMBOL_EXISTS_IMPL SOURCEFILE SYMBOL FILES VARIABLE) 79 if(NOT DEFINED "${VARIABLE}" OR "x${${VARIABLE}}" STREQUAL "x${VARIABLE}") 80 set(CMAKE_CONFIGURABLE_FILE_CONTENT "/* */\n") 81 set(MACRO_CHECK_SYMBOL_EXISTS_FLAGS ${CMAKE_REQUIRED_FLAGS}) 82 if(CMAKE_REQUIRED_LINK_OPTIONS) 83 set(CHECK_SYMBOL_EXISTS_LINK_OPTIONS 84 LINK_OPTIONS ${CMAKE_REQUIRED_LINK_OPTIONS}) 85 else() 86 set(CHECK_SYMBOL_EXISTS_LINK_OPTIONS) 87 endif() 88 if(CMAKE_REQUIRED_LIBRARIES) 89 set(CHECK_SYMBOL_EXISTS_LIBS 90 LINK_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES}) 91 else() 92 set(CHECK_SYMBOL_EXISTS_LIBS) 93 endif() 94 if(CMAKE_REQUIRED_INCLUDES) 95 set(CMAKE_SYMBOL_EXISTS_INCLUDES 96 "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}") 97 else() 98 set(CMAKE_SYMBOL_EXISTS_INCLUDES) 99 endif() 100 foreach(FILE ${FILES}) 101 string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT 102 "#include <${FILE}>\n") 103 endforeach() 104 string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT " 105int main(int argc, char** argv) 106{ 107 (void)argv;") 108 set(_CSE_CHECK_NON_MACRO "return ((int*)(&${SYMBOL}))[argc];") 109 if("${SYMBOL}" MATCHES "^[a-zA-Z_][a-zA-Z0-9_]*$") 110 # The SYMBOL has a legal macro name. Test whether it exists as a macro. 111 string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT " 112#ifndef ${SYMBOL} 113 ${_CSE_CHECK_NON_MACRO} 114#else 115 (void)argc; 116 return 0; 117#endif") 118 else() 119 # The SYMBOL cannot be a macro (e.g., a template function). 120 string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT " 121 ${_CSE_CHECK_NON_MACRO}") 122 endif() 123 string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT " 124}") 125 unset(_CSE_CHECK_NON_MACRO) 126 127 configure_file("${CMAKE_ROOT}/Modules/CMakeConfigurableFile.in" 128 "${SOURCEFILE}" @ONLY) 129 130 if(NOT CMAKE_REQUIRED_QUIET) 131 message(CHECK_START "Looking for ${SYMBOL}") 132 endif() 133 try_compile(${VARIABLE} 134 ${CMAKE_BINARY_DIR} 135 "${SOURCEFILE}" 136 COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} 137 ${CHECK_SYMBOL_EXISTS_LINK_OPTIONS} 138 ${CHECK_SYMBOL_EXISTS_LIBS} 139 CMAKE_FLAGS 140 -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_SYMBOL_EXISTS_FLAGS} 141 "${CMAKE_SYMBOL_EXISTS_INCLUDES}" 142 OUTPUT_VARIABLE OUTPUT) 143 if(${VARIABLE}) 144 if(NOT CMAKE_REQUIRED_QUIET) 145 message(CHECK_PASS "found") 146 endif() 147 set(${VARIABLE} 1 CACHE INTERNAL "Have symbol ${SYMBOL}") 148 file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log 149 "Determining if the ${SYMBOL} " 150 "exist passed with the following output:\n" 151 "${OUTPUT}\nFile ${SOURCEFILE}:\n" 152 "${CMAKE_CONFIGURABLE_FILE_CONTENT}\n") 153 else() 154 if(NOT CMAKE_REQUIRED_QUIET) 155 message(CHECK_FAIL "not found") 156 endif() 157 set(${VARIABLE} "" CACHE INTERNAL "Have symbol ${SYMBOL}") 158 file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log 159 "Determining if the ${SYMBOL} " 160 "exist failed with the following output:\n" 161 "${OUTPUT}\nFile ${SOURCEFILE}:\n" 162 "${CMAKE_CONFIGURABLE_FILE_CONTENT}\n") 163 endif() 164 unset(CMAKE_CONFIGURABLE_FILE_CONTENT) 165 endif() 166endmacro() 167 168cmake_policy(POP) 169