-
Notifications
You must be signed in to change notification settings - Fork 10.7k
/
LLVMLibCFlagRules.cmake
152 lines (132 loc) · 5.21 KB
/
LLVMLibCFlagRules.cmake
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# In general, a flag is a string provided for supported functions under the
# multi-valued option `FLAGS`. It should be one of the following forms:
# FLAG_NAME
# FLAG_NAME__NO
# FLAG_NAME__ONLY
# A target will inherit all the flags of its upstream dependency.
#
# When we create a target `TARGET_NAME` with a flag using (add_header_library,
# add_object_library, ...), its behavior will depend on the flag form as follow:
# - FLAG_NAME: The following 2 targets will be generated:
# `TARGET_NAME` that has `FLAG_NAME` in its `FLAGS` property.
# `TARGET_NAME.__NO_FLAG_NAME` that depends on `DEP.__NO_FLAG_NAME` if
# `TARGET_NAME` depends on `DEP` and `DEP` has `FLAG_NAME` in its `FLAGS`
# property.
# - FLAG_NAME__ONLY: Only generate 1 target `TARGET_NAME` that has `FLAG_NAME`
# in its `FLAGS` property.
# - FLAG_NAME__NO: Only generate 1 target `TARGET_NAME` that depends on
# `DEP.__NO_FLAG_NAME` if `DEP` is in its DEPENDS list and `DEP` has `FLAG_NAME`
# in its `FLAGS` property.
#
# To show all the targets generated, pass SHOW_INTERMEDIATE_OBJECTS=ON to cmake.
# To show all the targets' dependency and flags, pass
# SHOW_INTERMEDIATE_OBJECTS=DEPS to cmake.
#
# To completely disable a flag FLAG_NAME expansion, set the variable
# SKIP_FLAG_EXPANSION_FLAG_NAME=TRUE in this file.
function(extract_flag_modifier input_flag output_flag modifier)
if(${input_flag} MATCHES "__NO$")
string(REGEX REPLACE "__NO$" "" flag "${input_flag}")
set(${output_flag} ${flag} PARENT_SCOPE)
set(${modifier} "NO" PARENT_SCOPE)
elseif(${input_flag} MATCHES "__ONLY$")
string(REGEX REPLACE "__ONLY$" "" flag "${input_flag}")
set(${output_flag} ${flag} PARENT_SCOPE)
set(${modifier} "ONLY" PARENT_SCOPE)
else()
set(${output_flag} ${input_flag} PARENT_SCOPE)
set(${modifier} "" PARENT_SCOPE)
endif()
endfunction(extract_flag_modifier)
function(remove_duplicated_flags input_flags output_flags)
set(out_flags "")
foreach(input_flag IN LISTS input_flags)
if(NOT input_flag)
continue()
endif()
extract_flag_modifier(${input_flag} flag modifier)
# Check if the flag is skipped.
if(${SKIP_FLAG_EXPANSION_${flag}})
if("${SHOW_INTERMEDIATE_OBJECTS}" STREQUAL "DEPS")
message(STATUS " Flag ${flag} is ignored.")
endif()
continue()
endif()
set(found FALSE)
foreach(out_flag IN LISTS out_flags)
extract_flag_modifier(${out_flag} o_flag o_modifier)
if("${flag}" STREQUAL "${o_flag}")
set(found TRUE)
break()
endif()
endforeach()
if(NOT found)
list(APPEND out_flags ${input_flag})
endif()
endforeach()
set(${output_flags} "${out_flags}" PARENT_SCOPE)
endfunction(remove_duplicated_flags)
# Collect flags from dependency list. To see which flags come with each
# dependence, pass `SHOW_INTERMEDIATE_OBJECTS=DEPS` to cmake.
function(get_flags_from_dep_list output_list)
set(flag_list "")
foreach(dep IN LISTS ARGN)
if(NOT dep)
continue()
endif()
get_fq_dep_name(fq_dep_name ${dep})
if(NOT TARGET ${fq_dep_name})
continue()
endif()
get_target_property(flags ${fq_dep_name} "FLAGS")
if(flags AND "${SHOW_INTERMEDIATE_OBJECTS}" STREQUAL "DEPS")
message(STATUS " FLAGS from dependency ${fq_dep_name} are ${flags}")
endif()
foreach(flag IN LISTS flags)
if(flag)
list(APPEND flag_list ${flag})
endif()
endforeach()
endforeach(dep)
list(REMOVE_DUPLICATES flag_list)
set(${output_list} ${flag_list} PARENT_SCOPE)
endfunction(get_flags_from_dep_list)
# Given a `flag` without modifier, scan through the list of dependency, append
# `.__NO_flag` to any target that has `flag` in its FLAGS property.
function(get_fq_dep_list_without_flag output_list flag)
set(fq_dep_no_flag_list "")
foreach(dep IN LISTS ARGN)
get_fq_dep_name(fq_dep_name ${dep})
if(TARGET ${fq_dep_name})
get_target_property(dep_flags ${fq_dep_name} "FLAGS")
# Only target with `flag` has `.__NO_flag` target, `flag__NO` and
# `flag__ONLY` do not.
if(${flag} IN_LIST dep_flags)
list(APPEND fq_dep_no_flag_list "${fq_dep_name}.__NO_${flag}")
else()
list(APPEND fq_dep_no_flag_list ${fq_dep_name})
endif()
else()
list(APPEND fq_dep_no_flag_list ${fq_dep_name})
endif()
endforeach(dep)
set(${output_list} ${fq_dep_no_flag_list} PARENT_SCOPE)
endfunction(get_fq_dep_list_without_flag)
# Special flags
set(FMA_OPT_FLAG "FMA_OPT")
set(ROUND_OPT_FLAG "ROUND_OPT")
# SSE2 is the baseline for x86_64, so we add a negative flag to disable it if needed.
set(DISABLE_SSE2_OPT_FLAG "DISABLE_SSE2_OPT")
# Skip FMA_OPT flag for targets that don't support fma.
if(NOT((LIBC_TARGET_ARCHITECTURE_IS_X86 AND (LIBC_CPU_FEATURES MATCHES "FMA")) OR
LIBC_TARGET_ARCHITECTURE_IS_RISCV64))
set(SKIP_FLAG_EXPANSION_FMA_OPT TRUE)
endif()
# Skip ROUND_OPT flag for targets that don't support SSE 4.2.
if(NOT(LIBC_TARGET_ARCHITECTURE_IS_X86 AND (LIBC_CPU_FEATURES MATCHES "SSE4_2")))
set(SKIP_FLAG_EXPANSION_ROUND_OPT TRUE)
endif()
# Skip DISABLE_SSE2_OPT flag for targets that don't support SSE2.
if(NOT(LIBC_TARGET_ARCHITECTURE_IS_X86 AND (LIBC_CPU_FEATURES MATCHES "SSE2")))
set(SKIP_FLAG_EXPANSION_DISABLE_SSE2_OPT TRUE)
endif()