a7139af5fe55ab2ade224076bb9f598b66996f2b
[platform/upstream/cmake.git] / Modules / CheckSymbolExists.cmake
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:
5 CheckSymbolExists
6 -----------------
7
8 Provides a macro to check if a symbol exists as a function, variable,
9 or 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
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.
30
31 The following variables may be set before calling this macro to modify
32 the 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
51 For 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
63 include_guard(GLOBAL)
64
65 cmake_policy(PUSH)
66 cmake_policy(SET CMP0054 NEW) # if() quoted variables not dereferenced
67
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)
77   else()
78     message(FATAL_ERROR "CHECK_SYMBOL_EXISTS needs either C or CXX language enabled")
79   endif()
80 endmacro()
81
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}")
86 endmacro()
87
88 macro(__CHECK_SYMBOL_EXISTS_RESTORE_FLAGS LANG)
89     set(CMAKE_${LANG}_FLAGS "${__CMAKE_${LANG}_FLAGS_SAVED}")
90     unset(__CMAKE_${LANG}_FLAGS_SAVED)
91 endmacro()
92
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})
100     else()
101       set(CHECK_SYMBOL_EXISTS_LINK_OPTIONS)
102     endif()
103     if(CMAKE_REQUIRED_LIBRARIES)
104       set(CHECK_SYMBOL_EXISTS_LIBS
105         LINK_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES})
106     else()
107       set(CHECK_SYMBOL_EXISTS_LIBS)
108     endif()
109     if(CMAKE_REQUIRED_INCLUDES)
110       set(CMAKE_SYMBOL_EXISTS_INCLUDES
111         "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}")
112     else()
113       set(CMAKE_SYMBOL_EXISTS_INCLUDES)
114     endif()
115     foreach(FILE ${FILES})
116       string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT
117         "#include <${FILE}>\n")
118     endforeach()
119     string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT "
120 int main(int argc, char** argv)
121 {
122   (void)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 "
127 #ifndef ${SYMBOL}
128   ${_CSE_CHECK_NON_MACRO}
129 #else
130   (void)argc;
131   return 0;
132 #endif")
133     else()
134       # The SYMBOL cannot be a macro (e.g., a template function).
135       string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT "
136   ${_CSE_CHECK_NON_MACRO}")
137     endif()
138     string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT "
139 }")
140     unset(_CSE_CHECK_NON_MACRO)
141
142     configure_file("${CMAKE_ROOT}/Modules/CMakeConfigurableFile.in"
143       "${SOURCEFILE}" @ONLY)
144
145     if(NOT CMAKE_REQUIRED_QUIET)
146       message(CHECK_START "Looking for ${SYMBOL}")
147     endif()
148     try_compile(${VARIABLE}
149       ${CMAKE_BINARY_DIR}
150       "${SOURCEFILE}"
151       COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
152       ${CHECK_SYMBOL_EXISTS_LINK_OPTIONS}
153       ${CHECK_SYMBOL_EXISTS_LIBS}
154       CMAKE_FLAGS
155       -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_SYMBOL_EXISTS_FLAGS}
156       "${CMAKE_SYMBOL_EXISTS_INCLUDES}"
157       OUTPUT_VARIABLE OUTPUT)
158     if(${VARIABLE})
159       if(NOT CMAKE_REQUIRED_QUIET)
160         message(CHECK_PASS "found")
161       endif()
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")
168     else()
169       if(NOT CMAKE_REQUIRED_QUIET)
170         message(CHECK_FAIL "not found")
171       endif()
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")
178     endif()
179     unset(CMAKE_CONFIGURABLE_FILE_CONTENT)
180   endif()
181 endmacro()
182
183 cmake_policy(POP)