1 # Distributed under the OSI-approved BSD 3-Clause License. See accompanying
2 # file Copyright.txt or https://cmake.org/licensing for details.
6 #[=======================================================================[.rst:
10 This module provides macros for managing the state of variables that influence
11 how various CMake check commands (e.g., ``check_symbol_exists()``, etc.) are
12 performed. These macros save, reset, and restore the following variables:
14 * ``CMAKE_REQUIRED_FLAGS``
15 * ``CMAKE_REQUIRED_DEFINITIONS``
16 * ``CMAKE_REQUIRED_INCLUDES``
17 * ``CMAKE_REQUIRED_LINK_OPTIONS``
18 * ``CMAKE_REQUIRED_LIBRARIES``
19 * ``CMAKE_REQUIRED_LINK_DIRECTORIES``
20 * ``CMAKE_REQUIRED_QUIET``
21 * ``CMAKE_EXTRA_INCLUDE_FILES``
26 .. command:: cmake_push_check_state
28 Saves (pushes) the current states of the above variables onto a stack. This
29 is typically used to preserve the current configuration before making
30 temporary modifications for specific checks.
34 cmake_push_check_state([RESET])
37 When this option is specified, the macro not only saves the current states
38 of the listed variables but also resets them to empty, allowing them to be
39 reconfigured from a clean state.
41 .. command:: cmake_reset_check_state
43 Resets (clears) the contents of the variables listed above to empty states.
47 cmake_reset_check_state()
49 This macro can be used, for example, when performing multiple sequential
50 checks that require entirely new configurations, ensuring no previous
51 configuration unintentionally carries over.
53 .. command:: cmake_pop_check_state
55 Restores the states of the variables listed above to their values at the time
56 of the most recent ``cmake_push_check_state()`` call.
60 cmake_pop_check_state()
62 This macro is used to revert temporary changes made during a check. To
63 prevent unexpected behavior, pair each ``cmake_push_check_state()`` with a
64 corresponding ``cmake_pop_check_state()``.
66 These macros are useful for scoped configuration, for example, in
67 :ref:`Find modules <Find Modules>` or when performing checks in a controlled
68 environment, ensuring that temporary modifications are isolated to the scope of
69 the check and do not propagate into other parts of the build system.
73 Other CMake variables, such as ``CMAKE_<LANG>_FLAGS``, propagate to all checks
74 regardless of these macros, as those fundamental variables are designed to
75 influence the global state of the build system.
82 include(CMakePushCheckState)
84 # Save and reset the current state
85 cmake_push_check_state(RESET)
87 # Perform check with specific compile definitions
88 set(CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE)
89 include(CheckSymbolExists)
90 check_symbol_exists(memfd_create "sys/mman.h" HAVE_MEMFD_CREATE)
92 # Restore the original state
93 cmake_pop_check_state()
95 Variable states can be pushed onto the stack multiple times, allowing for nested
96 or sequential configurations. Each ``cmake_pop_check_state()`` restores the
97 most recent pushed states.
101 include(CMakePushCheckState)
103 # Save and reset the current state
104 cmake_push_check_state(RESET)
106 # Perform the first check with additional libraries
107 set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_DL_LIBS})
108 include(CheckSymbolExists)
109 check_symbol_exists(dlopen "dlfcn.h" HAVE_DLOPEN)
112 cmake_push_check_state()
114 # Perform the second check with libraries and additional compile definitions
115 set(CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE)
116 check_symbol_exists(dladdr "dlfcn.h" HAVE_DLADDR)
118 message(STATUS "${CMAKE_REQUIRED_DEFINITIONS}")
119 # Output: -D_GNU_SOURCE
121 # Restore the previous state
122 cmake_pop_check_state()
124 message(STATUS "${CMAKE_REQUIRED_DEFINITIONS}")
125 # Output here is empty
127 # Reset variables to prepare for the next check
128 cmake_reset_check_state()
130 # Perform the next check only with additional compile definitions
131 set(CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE)
132 check_symbol_exists(dl_iterate_phdr "link.h" HAVE_DL_ITERATE_PHDR)
134 # Restore the original state
135 cmake_pop_check_state()
136 #]=======================================================================]
138 macro(CMAKE_RESET_CHECK_STATE)
140 set(CMAKE_EXTRA_INCLUDE_FILES)
141 set(CMAKE_REQUIRED_INCLUDES)
142 set(CMAKE_REQUIRED_DEFINITIONS)
143 set(CMAKE_REQUIRED_LINK_OPTIONS)
144 set(CMAKE_REQUIRED_LIBRARIES)
145 set(CMAKE_REQUIRED_LINK_DIRECTORIES)
146 set(CMAKE_REQUIRED_FLAGS)
147 set(CMAKE_REQUIRED_QUIET)
151 macro(CMAKE_PUSH_CHECK_STATE)
153 if(NOT DEFINED _CMAKE_PUSH_CHECK_STATE_COUNTER)
154 set(_CMAKE_PUSH_CHECK_STATE_COUNTER 0)
157 math(EXPR _CMAKE_PUSH_CHECK_STATE_COUNTER "${_CMAKE_PUSH_CHECK_STATE_COUNTER}+1")
159 set(_CMAKE_EXTRA_INCLUDE_FILES_SAVE_${_CMAKE_PUSH_CHECK_STATE_COUNTER} ${CMAKE_EXTRA_INCLUDE_FILES})
160 set(_CMAKE_REQUIRED_INCLUDES_SAVE_${_CMAKE_PUSH_CHECK_STATE_COUNTER} ${CMAKE_REQUIRED_INCLUDES})
161 set(_CMAKE_REQUIRED_DEFINITIONS_SAVE_${_CMAKE_PUSH_CHECK_STATE_COUNTER} ${CMAKE_REQUIRED_DEFINITIONS})
162 set(_CMAKE_REQUIRED_LINK_OPTIONS_SAVE_${_CMAKE_PUSH_CHECK_STATE_COUNTER} ${CMAKE_REQUIRED_LINK_OPTIONS})
163 set(_CMAKE_REQUIRED_LIBRARIES_SAVE_${_CMAKE_PUSH_CHECK_STATE_COUNTER} ${CMAKE_REQUIRED_LIBRARIES})
164 set(_CMAKE_REQUIRED_LINK_DIRECTORIES_SAVE_${_CMAKE_PUSH_CHECK_STATE_COUNTER} ${CMAKE_REQUIRED_LINK_DIRECTORIES})
165 set(_CMAKE_REQUIRED_FLAGS_SAVE_${_CMAKE_PUSH_CHECK_STATE_COUNTER} ${CMAKE_REQUIRED_FLAGS})
166 set(_CMAKE_REQUIRED_QUIET_SAVE_${_CMAKE_PUSH_CHECK_STATE_COUNTER} ${CMAKE_REQUIRED_QUIET})
168 if (${ARGC} GREATER 0 AND "${ARGV0}" STREQUAL "RESET")
169 cmake_reset_check_state()
174 macro(CMAKE_POP_CHECK_STATE)
176 # don't pop more than we pushed
177 if("${_CMAKE_PUSH_CHECK_STATE_COUNTER}" GREATER "0")
179 set(CMAKE_EXTRA_INCLUDE_FILES ${_CMAKE_EXTRA_INCLUDE_FILES_SAVE_${_CMAKE_PUSH_CHECK_STATE_COUNTER}})
180 set(CMAKE_REQUIRED_INCLUDES ${_CMAKE_REQUIRED_INCLUDES_SAVE_${_CMAKE_PUSH_CHECK_STATE_COUNTER}})
181 set(CMAKE_REQUIRED_DEFINITIONS ${_CMAKE_REQUIRED_DEFINITIONS_SAVE_${_CMAKE_PUSH_CHECK_STATE_COUNTER}})
182 set(CMAKE_REQUIRED_LINK_OPTIONS ${_CMAKE_REQUIRED_LINK_OPTIONS_SAVE_${_CMAKE_PUSH_CHECK_STATE_COUNTER}})
183 set(CMAKE_REQUIRED_LIBRARIES ${_CMAKE_REQUIRED_LIBRARIES_SAVE_${_CMAKE_PUSH_CHECK_STATE_COUNTER}})
184 set(CMAKE_REQUIRED_LINK_DIRECTORIES ${_CMAKE_REQUIRED_LINK_DIRECTORIES_SAVE_${_CMAKE_PUSH_CHECK_STATE_COUNTER}})
185 set(CMAKE_REQUIRED_FLAGS ${_CMAKE_REQUIRED_FLAGS_SAVE_${_CMAKE_PUSH_CHECK_STATE_COUNTER}})
186 set(CMAKE_REQUIRED_QUIET ${_CMAKE_REQUIRED_QUIET_SAVE_${_CMAKE_PUSH_CHECK_STATE_COUNTER}})
188 math(EXPR _CMAKE_PUSH_CHECK_STATE_COUNTER "${_CMAKE_PUSH_CHECK_STATE_COUNTER}-1")