@@ -129,6 +129,135 @@ function(get_fq_dep_list_without_flag output_list flag)
129129 set (${output_list} ${fq_dep_no_flag_list} PARENT_SCOPE)
130130endfunction (get_fq_dep_list_without_flag)
131131
132+ # Check if a `flag` is set
133+ function (check_flag result flag_name)
134+ list (FIND ARGN ${flag_name} _FLAG has_flag)
135+ if (${has_flag} LESS 0)
136+ list (FIND ARGN "${flag_name} _FLAG__ONLY" has_flag)
137+ endif ()
138+ if (${has_flag} GREATER -1)
139+ set (${result} TRUE PARENT_SCOPE)
140+ else ()
141+ set (${result} FALSE PARENT_SCOPE)
142+ endif ()
143+ endfunction (check_flag)
144+
145+ # Generate all flags' combinations and call the corresponding function provided
146+ # by `CREATE_TARGET` to create a target for each combination.
147+ function (expand_flags_for_target target_name flags )
148+ cmake_parse_arguments (
149+ "EXPAND_FLAGS"
150+ "" # Optional arguments
151+ "CREATE_TARGET" # Single-value arguments
152+ "DEPENDS;FLAGS" # Multi-value arguments
153+ ${ARGN}
154+ )
155+
156+ list (LENGTH flags nflags)
157+ if (NOT ${nflags} )
158+ cmake_language(CALL ${EXPAND_FLAGS_CREATE_TARGET}
159+ ${target_name}
160+ ${EXPAND_FLAGS_UNPARSED_ARGUMENTS}
161+ DEPENDS ${EXPAND_FLAGS_DEPENDS}
162+ FLAGS ${EXPAND_FLAGS_FLAGS}
163+ )
164+ return ()
165+ endif ()
166+
167+ list (GET flags 0 flag)
168+ list (REMOVE_AT flags 0)
169+ extract_flag_modifier(${flag} real_flag modifier)
170+
171+ if (NOT "${modifier} " STREQUAL "NO" )
172+ expand_flags_for_target(
173+ ${target_name}
174+ "${flags} "
175+ DEPENDS ${EXPAND_FLAGS_DEPENDS}
176+ FLAGS ${EXPAND_FLAGS_FLAGS}
177+ CREATE_TARGET ${EXPAND_FLAGS_CREATE_TARGET}
178+ ${EXPAND_FLAGS_UNPARSED_ARGUMENTS}
179+ )
180+ endif ()
181+
182+ if ("${real_flag} " STREQUAL "" OR "${modifier} " STREQUAL "ONLY" )
183+ return ()
184+ endif ()
185+
186+ set (NEW_FLAGS ${EXPAND_FLAGS_FLAGS} )
187+ list (REMOVE_ITEM NEW_FLAGS ${flag} )
188+ get_fq_dep_list_without_flag(NEW_DEPS ${real_flag} ${EXPAND_FLAGS_DEPENDS} )
189+
190+ # Only target with `flag` has `.__NO_flag` target, `flag__NO` and
191+ # `flag__ONLY` do not.
192+ if ("${modifier} " STREQUAL "" )
193+ set (TARGET_NAME "${target_name} .__NO_${flag} " )
194+ else ()
195+ set (TARGET_NAME "${target_name} " )
196+ endif ()
197+
198+ expand_flags_for_target(
199+ ${TARGET_NAME}
200+ "${flags} "
201+ DEPENDS ${NEW_DEPS}
202+ FLAGS ${NEW_FLAGS}
203+ CREATE_TARGET ${EXPAND_FLAGS_CREATE_TARGET}
204+ ${EXPAND_FLAGS_UNPARSED_ARGUMENTS}
205+ )
206+ endfunction (expand_flags_for_target)
207+
208+ # Collect all flags from a target's dependency, and then forward to
209+ # `expand_flags_for_target to generate all flags' combinations and call
210+ # the corresponding function provided by `CREATE_TARGET` to create a target for
211+ # each combination.
212+ function (add_target_with_flags target_name)
213+ cmake_parse_arguments (
214+ "ADD_TO_EXPAND"
215+ "" # Optional arguments
216+ "CREATE_TARGET;" # Single value arguments
217+ "DEPENDS;FLAGS;ADD_FLAGS" # Multi-value arguments
218+ ${ARGN}
219+ )
220+
221+ if (NOT target_name)
222+ message (FATAL_ERROR "Bad target name" )
223+ endif ()
224+
225+ if (NOT ADD_TO_EXPAND_CREATE_TARGET)
226+ message (FATAL_ERROR "Missing function to create targets. Please specify "
227+ "`CREATE_TARGET <function>`" )
228+ endif ()
229+
230+ get_fq_target_name(${target_name} fq_target_name)
231+
232+ if (ADD_TO_EXPAND_DEPENDS AND ("${SHOW_INTERMEDIATE_OBJECTS} " STREQUAL "DEPS" ))
233+ message (STATUS "Gathering FLAGS from dependencies for ${fq_target_name} " )
234+ endif ()
235+
236+ get_fq_deps_list(fq_deps_list ${ADD_TO_EXPAND_DEPENDS} )
237+ get_flags_from_dep_list(deps_flag_list ${fq_deps_list} )
238+
239+ # Appending ADD_FLAGS before flags from dependency.
240+ if (ADD_TO_EXPAND_ADD_FLAGS)
241+ list (APPEND ADD_TO_EXPAND_FLAGS ${ADD_TO_EXPAND_ADD_FLAGS} )
242+ endif ()
243+ list (APPEND ADD_TO_EXPAND_FLAGS ${deps_flag_list} )
244+ remove_duplicated_flags("${ADD_TO_EXPAND_FLAGS} " flags )
245+ list (SORT flags )
246+
247+ if (SHOW_INTERMEDIATE_OBJECTS AND flags )
248+ message (STATUS "Target ${fq_target_name} has FLAGS: ${flags} " )
249+ endif ()
250+
251+ expand_flags_for_target(
252+ ${fq_target_name}
253+ "${flags} "
254+ DEPENDS "${fq_deps_list} "
255+ FLAGS "${flags} "
256+ CREATE_TARGET ${ADD_TO_EXPAND_CREATE_TARGET}
257+ ${ADD_TO_EXPAND_UNPARSED_ARGUMENTS}
258+ )
259+ endfunction (add_target_with_flags)
260+
132261# Special flags
133262set (FMA_OPT_FLAG "FMA_OPT" )
134263set (ROUND_OPT_FLAG "ROUND_OPT" )
0 commit comments