1 # In general, a flag is a string provided for supported functions under the
2 # multi-valued option `FLAGS`. It should be one of the following forms:
6 # A target will inherit all the flags of its upstream dependency.
8 # When we create a target `TARGET_NAME` with a flag using (add_header_library,
9 # add_object_library, ...), its behavior will depend on the flag form as follow:
10 # - FLAG_NAME: The following 2 targets will be generated:
11 # `TARGET_NAME` that has `FLAG_NAME` in its `FLAGS` property.
12 # `TARGET_NAME.__NO_FLAG_NAME` that depends on `DEP.__NO_FLAG_NAME` if
13 # `TARGET_NAME` depends on `DEP` and `DEP` has `FLAG_NAME` in its `FLAGS`
15 # - FLAG_NAME__ONLY: Only generate 1 target `TARGET_NAME` that has `FLAG_NAME`
16 # in its `FLAGS` property.
17 # - FLAG_NAME__NO: Only generate 1 target `TARGET_NAME` that depends on
18 # `DEP.__NO_FLAG_NAME` if `DEP` is in its DEPENDS list and `DEP` has `FLAG_NAME`
19 # in its `FLAGS` property.
21 # To show all the targets generated, pass SHOW_INTERMEDIATE_OBJECTS=ON to cmake.
22 # To show all the targets' dependency and flags, pass
23 # SHOW_INTERMEDIATE_OBJECTS=DEPS to cmake.
25 # To completely disable a flag FLAG_NAME expansion, set the variable
26 # SKIP_FLAG_EXPANSION_FLAG_NAME=TRUE in this file.
29 function(extract_flag_modifier input_flag output_flag modifier)
30 if(${input_flag} MATCHES "__NO$")
31 string(REGEX REPLACE "__NO$" "" flag "${input_flag}")
32 set(${output_flag} ${flag} PARENT_SCOPE)
33 set(${modifier} "NO" PARENT_SCOPE)
34 elseif(${input_flag} MATCHES "__ONLY$")
35 string(REGEX REPLACE "__ONLY$" "" flag "${input_flag}")
36 set(${output_flag} ${flag} PARENT_SCOPE)
37 set(${modifier} "ONLY" PARENT_SCOPE)
39 set(${output_flag} ${input_flag} PARENT_SCOPE)
40 set(${modifier} "" PARENT_SCOPE)
42 endfunction(extract_flag_modifier)
44 function(remove_duplicated_flags input_flags output_flags)
46 foreach(input_flag IN LISTS input_flags)
51 extract_flag_modifier(${input_flag} flag modifier)
53 # Check if the flag is skipped.
54 if(${SKIP_FLAG_EXPANSION_${flag}})
55 if("${SHOW_INTERMEDIATE_OBJECTS}" STREQUAL "DEPS")
56 message(STATUS " Flag ${flag} is ignored.")
62 foreach(out_flag IN LISTS out_flags)
63 extract_flag_modifier(${out_flag} o_flag o_modifier)
64 if("${flag}" STREQUAL "${o_flag}")
70 list(APPEND out_flags ${input_flag})
74 set(${output_flags} "${out_flags}" PARENT_SCOPE)
75 endfunction(remove_duplicated_flags)
77 # Collect flags from dependency list. To see which flags come with each
78 # dependence, pass `SHOW_INTERMEDIATE_OBJECTS=DEPS` to cmake.
79 function(get_flags_from_dep_list output_list)
81 foreach(dep IN LISTS ARGN)
86 get_fq_dep_name(fq_dep_name ${dep})
88 if(NOT TARGET ${fq_dep_name})
92 get_target_property(flags ${fq_dep_name} "FLAGS")
94 if(flags AND "${SHOW_INTERMEDIATE_OBJECTS}" STREQUAL "DEPS")
95 message(STATUS " FLAGS from dependency ${fq_dep_name} are ${flags}")
98 foreach(flag IN LISTS flags)
100 list(APPEND flag_list ${flag})
105 list(REMOVE_DUPLICATES flag_list)
107 set(${output_list} ${flag_list} PARENT_SCOPE)
108 endfunction(get_flags_from_dep_list)
110 # Given a `flag` without modifier, scan through the list of dependency, append
111 # `.__NO_flag` to any target that has `flag` in its FLAGS property.
112 function(get_fq_dep_list_without_flag output_list flag)
113 set(fq_dep_no_flag_list "")
114 foreach(dep IN LISTS ARGN)
115 get_fq_dep_name(fq_dep_name ${dep})
116 if(TARGET ${fq_dep_name})
117 get_target_property(dep_flags ${fq_dep_name} "FLAGS")
118 # Only target with `flag` has `.__NO_flag` target, `flag__NO` and
119 # `flag__ONLY` do not.
120 if(${flag} IN_LIST dep_flags)
121 list(APPEND fq_dep_no_flag_list "${fq_dep_name}.__NO_${flag}")
123 list(APPEND fq_dep_no_flag_list ${fq_dep_name})
126 list(APPEND fq_dep_no_flag_list ${fq_dep_name})
129 set(${output_list} ${fq_dep_no_flag_list} PARENT_SCOPE)
130 endfunction(get_fq_dep_list_without_flag)
133 set(FMA_OPT_FLAG "FMA_OPT")
134 set(ROUND_OPT_FLAG "ROUND_OPT")
136 # Skip FMA_OPT flag for targets that don't support fma.
137 if(NOT((LIBC_TARGET_ARCHITECTURE_IS_X86 AND (LIBC_CPU_FEATURES MATCHES "FMA")) OR
138 LIBC_TARGET_ARCHITECTURE_IS_RISCV64))
139 set(SKIP_FLAG_EXPANSION_FMA_OPT TRUE)
142 # Skip ROUND_OPT flag for targets that don't support SSE 4.2.
143 if(NOT(LIBC_TARGET_ARCHITECTURE_IS_X86 AND (LIBC_CPU_FEATURES MATCHES "SSE4_2")))
144 set(SKIP_FLAG_EXPANSION_ROUND_OPT TRUE)