@@ -23,6 +23,104 @@ if (NOT COMMAND "fail_in_source_build")
2323 endfunction ()
2424endif ()
2525
26+ if (NOT COMMAND "extract_value" )
27+
28+ #! extract_value : Extracts variable value
29+ #
30+ # If given key is a value, then the value will be assigned
31+ # to the output variable.
32+ #
33+ # @param <variable> output The variable to assign extracted value to
34+ # @param <mixed> key The target key
35+ #
36+ # @return
37+ # output The extracted value
38+ #
39+ function (extract_value output key)
40+
41+ set ("${output} " "${key} " )
42+
43+ if (DEFINED ${key} )
44+ set ("${output} " "${${key} }" )
45+ endif ()
46+
47+ return (PROPAGATE "${output} " )
48+ endfunction ()
49+ endif ()
50+
51+ if (NOT COMMAND "safeguard_properties" )
52+
53+ #! safeguard_properties : Invoke a "risky" callback whilst "safeguarding" properties
54+ #
55+ # Function copies the values of the specified properties, invokes the callback, and
56+ # restores the properties' values.
57+ #
58+ # Caution: This function does NOT prevent properties from being force-cached.
59+ # Environment variables are NOT prevented changed.
60+ #
61+ # Alternatively, consider using cmake's `block()`.
62+ #
63+ # @see https://cmake.org/cmake/help/latest/manual/cmake-language.7.html#variables
64+ # @see https://cmake.org/cmake/help/latest/manual/cmake-language.7.html#environment-variables
65+ # @see https://cmake.org/cmake/help/latest/command/block.html#block
66+ #
67+ # @param [CALLBACK <command>] Risky command or macro to be invoked.
68+ # @param [PROPERTIES <variable>...] One or more properties to safeguard.
69+ #
70+ # @return
71+ # [PROPERTIES <variable>...] Restored properties
72+ #
73+ function (safeguard_properties)
74+ set (options "" ) # N/A
75+ set (oneValueArgs CALLBACK)
76+ set (multiValueArgs PROPERTIES)
77+
78+ cmake_parse_arguments (INPUT "${options} " "${oneValueArgs} " "${multiValueArgs} " ${ARGN} )
79+
80+ # Ensure required arguments are defined
81+ set (requiredArgs "CALLBACK;PROPERTIES" )
82+ foreach (arg ${requiredArgs} )
83+ if (NOT DEFINED INPUT_${arg} )
84+ message (FATAL_ERROR "${arg} argument is missing, for ${CMAKE_CURRENT_FUNCTION} ()" )
85+ endif ()
86+ endforeach ()
87+
88+ # ---------------------------------------------------------------------------------------------- #
89+
90+ # Abort if callback not defined
91+ if (NOT COMMAND "${INPUT_CALLBACK} " )
92+ message (FATAL_ERROR "Callback \" ${INPUT_CALLBACK} ()\" does not exist" )
93+ endif ()
94+
95+ # ---------------------------------------------------------------------------------------------- #
96+
97+ set (prefix "original_" )
98+
99+ # Copy each provided property
100+ foreach (prop ${INPUT_PROPERTIES} )
101+ message (VERBOSE "Safeguarding: ${prop} , original value: ${${prop} }" )
102+
103+ set ("${prefix}${prop} " "${${prop} }" )
104+ endforeach ()
105+
106+ # ---------------------------------------------------------------------------------------------- #
107+
108+ # Invoke the risky callback
109+ message (VERBOSE "Invoking risky callback: ${INPUT_CALLBACK} " )
110+ cmake_language(CALL "${INPUT_CALLBACK} " )
111+
112+ # ---------------------------------------------------------------------------------------------- #
113+
114+ # Restore each provided property
115+ foreach (prop ${INPUT_PROPERTIES} )
116+ message (VERBOSE "Restoring: ${prop} from: ${${prop} }, to original value: ${${prefix}${prop} }" )
117+
118+ # Ensure that property is set on parent scope
119+ set ("${prop} " "${${prefix}${prop} }" PARENT_SCOPE)
120+ endforeach ()
121+ endfunction ()
122+ endif ()
123+
26124if (NOT COMMAND "dump" )
27125
28126 #! dump : Outputs given variables' name and value
0 commit comments