1 # Distributed under the OSI-approved BSD 3-Clause License. See accompanying
2 # file Copyright.txt or https://cmake.org/licensing for details.
4 #[=======================================================================[.rst:
8 Provides a macro to check if a symbol exists as a function, variable,
11 .. command:: check_symbol_exists
15 check_symbol_exists(<symbol> <files> <variable>)
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.
22 If the header files define the symbol as a macro it is considered
23 available and assumed to work. If the header files declare the symbol
24 as a function or variable then the symbol must also be available for
25 linking (so intrinsics may not be detected).
26 If the symbol is a type, enum value, or intrinsic it will not be recognized
27 (consider using :module:`CheckTypeSize` or :module:`CheckSourceCompiles`).
28 If the check needs to be done in C++, consider using
29 :module:`CheckCXXSymbolExists` instead.
31 The following variables may be set before calling this macro to modify
32 the way the check is run:
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
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``
49 execute quietly without messages.
55 include(CheckSymbolExists)
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 #]=======================================================================]
66 cmake_policy(SET CMP0054 NEW) # if() quoted variables not dereferenced
68 macro(CHECK_SYMBOL_EXISTS SYMBOL FILES VARIABLE)
69 if(CMAKE_C_COMPILER_LOADED)
70 __CHECK_SYMBOL_EXISTS_FILTER_FLAGS(C)
71 __CHECK_SYMBOL_EXISTS_IMPL("${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckSymbolExists.c" "${SYMBOL}" "${FILES}" "${VARIABLE}" )
72 __CHECK_SYMBOL_EXISTS_RESTORE_FLAGS(C)
73 elseif(CMAKE_CXX_COMPILER_LOADED)
74 __CHECK_SYMBOL_EXISTS_FILTER_FLAGS(CXX)
75 __CHECK_SYMBOL_EXISTS_IMPL("${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckSymbolExists.cxx" "${SYMBOL}" "${FILES}" "${VARIABLE}" )
76 __CHECK_SYMBOL_EXISTS_RESTORE_FLAGS(CXX)
78 message(FATAL_ERROR "CHECK_SYMBOL_EXISTS needs either C or CXX language enabled")
82 macro(__CHECK_SYMBOL_EXISTS_FILTER_FLAGS LANG)
83 set(__CMAKE_${LANG}_FLAGS_SAVED "${CMAKE_${LANG}_FLAGS}")
84 string(REGEX REPLACE "(^| )-Werror([= ][^ ]*)?( |$)" " " CMAKE_${LANG}_FLAGS "${CMAKE_${LANG}_FLAGS}")
85 string(REGEX REPLACE "(^| )-pedantic-errors( |$)" " " CMAKE_${LANG}_FLAGS "${CMAKE_${LANG}_FLAGS}")
88 macro(__CHECK_SYMBOL_EXISTS_RESTORE_FLAGS LANG)
89 set(CMAKE_${LANG}_FLAGS "${__CMAKE_${LANG}_FLAGS_SAVED}")
90 unset(__CMAKE_${LANG}_FLAGS_SAVED)
93 macro(__CHECK_SYMBOL_EXISTS_IMPL SOURCEFILE SYMBOL FILES VARIABLE)
94 if(NOT DEFINED "${VARIABLE}" OR "x${${VARIABLE}}" STREQUAL "x${VARIABLE}")
95 set(CMAKE_CONFIGURABLE_FILE_CONTENT "/* */\n")
96 set(MACRO_CHECK_SYMBOL_EXISTS_FLAGS ${CMAKE_REQUIRED_FLAGS})
97 if(CMAKE_REQUIRED_LINK_OPTIONS)
98 set(CHECK_SYMBOL_EXISTS_LINK_OPTIONS
99 LINK_OPTIONS ${CMAKE_REQUIRED_LINK_OPTIONS})
101 set(CHECK_SYMBOL_EXISTS_LINK_OPTIONS)
103 if(CMAKE_REQUIRED_LIBRARIES)
104 set(CHECK_SYMBOL_EXISTS_LIBS
105 LINK_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES})
107 set(CHECK_SYMBOL_EXISTS_LIBS)
109 if(CMAKE_REQUIRED_INCLUDES)
110 set(CMAKE_SYMBOL_EXISTS_INCLUDES
111 "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}")
113 set(CMAKE_SYMBOL_EXISTS_INCLUDES)
115 foreach(FILE ${FILES})
116 string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT
117 "#include <${FILE}>\n")
119 string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT "
120 int main(int argc, char** argv)
123 set(_CSE_CHECK_NON_MACRO "return ((int*)(&${SYMBOL}))[argc];")
124 if("${SYMBOL}" MATCHES "^[a-zA-Z_][a-zA-Z0-9_]*$")
125 # The SYMBOL has a legal macro name. Test whether it exists as a macro.
126 string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT "
128 ${_CSE_CHECK_NON_MACRO}
134 # The SYMBOL cannot be a macro (e.g., a template function).
135 string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT "
136 ${_CSE_CHECK_NON_MACRO}")
138 string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT "
140 unset(_CSE_CHECK_NON_MACRO)
142 configure_file("${CMAKE_ROOT}/Modules/CMakeConfigurableFile.in"
143 "${SOURCEFILE}" @ONLY)
145 if(NOT CMAKE_REQUIRED_QUIET)
146 message(CHECK_START "Looking for ${SYMBOL}")
148 try_compile(${VARIABLE}
151 COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
152 ${CHECK_SYMBOL_EXISTS_LINK_OPTIONS}
153 ${CHECK_SYMBOL_EXISTS_LIBS}
155 -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_SYMBOL_EXISTS_FLAGS}
156 "${CMAKE_SYMBOL_EXISTS_INCLUDES}"
157 OUTPUT_VARIABLE OUTPUT)
159 if(NOT CMAKE_REQUIRED_QUIET)
160 message(CHECK_PASS "found")
162 set(${VARIABLE} 1 CACHE INTERNAL "Have symbol ${SYMBOL}")
163 file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
164 "Determining if the ${SYMBOL} "
165 "exist passed with the following output:\n"
166 "${OUTPUT}\nFile ${SOURCEFILE}:\n"
167 "${CMAKE_CONFIGURABLE_FILE_CONTENT}\n")
169 if(NOT CMAKE_REQUIRED_QUIET)
170 message(CHECK_FAIL "not found")
172 set(${VARIABLE} "" CACHE INTERNAL "Have symbol ${SYMBOL}")
173 file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
174 "Determining if the ${SYMBOL} "
175 "exist failed with the following output:\n"
176 "${OUTPUT}\nFile ${SOURCEFILE}:\n"
177 "${CMAKE_CONFIGURABLE_FILE_CONTENT}\n")
179 unset(CMAKE_CONFIGURABLE_FILE_CONTENT)