Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / libc / cmake / modules / LLVMLibCLibraryRules.cmake
blobe6cfd79e65a085ac84509434f32e30ef56554d7c
1 function(collect_object_file_deps target result)
2   # NOTE: This function does add entrypoint targets to |result|.
3   # It is expected that the caller adds them separately.
4   set(all_deps "")
5   get_target_property(target_type ${target} "TARGET_TYPE")
6   if(NOT target_type)
7     return()
8   endif()
10   if(${target_type} STREQUAL ${OBJECT_LIBRARY_TARGET_TYPE})
11     list(APPEND all_deps ${target})
12     get_target_property(deps ${target} "DEPS")
13     foreach(dep IN LISTS deps)
14       collect_object_file_deps(${dep} dep_targets)
15       list(APPEND all_deps ${dep_targets})
16     endforeach(dep)
17     list(REMOVE_DUPLICATES all_deps)
18     set(${result} ${all_deps} PARENT_SCOPE)
19     return()
20   endif()
22   if(${target_type} STREQUAL ${ENTRYPOINT_OBJ_TARGET_TYPE} OR
23      ${target_type} STREQUAL ${ENTRYPOINT_OBJ_VENDOR_TARGET_TYPE})
24     set(entrypoint_target ${target})
25     get_target_property(is_alias ${entrypoint_target} "IS_ALIAS")
26     if(is_alias)
27       get_target_property(aliasee ${entrypoint_target} "DEPS")
28       if(NOT aliasee)
29         message(FATAL_ERROR
30                 "Entrypoint alias ${entrypoint_target} does not have an aliasee.")
31       endif()
32       set(entrypoint_target ${aliasee})
33     endif()
34     get_target_property(deps ${target} "DEPS")
35     foreach(dep IN LISTS deps)
36       collect_object_file_deps(${dep} dep_targets)
37       list(APPEND all_deps ${dep_targets})
38     endforeach(dep)
39     list(REMOVE_DUPLICATES all_deps)
40     set(${result} ${all_deps} PARENT_SCOPE)
41     return()
42   endif()
44   if(${target_type} STREQUAL ${ENTRYPOINT_EXT_TARGET_TYPE})
45     # It is not possible to recursively extract deps of external dependencies.
46     # So, we just accumulate the direct dep and return.
47     get_target_property(deps ${target} "DEPS")
48     set(${result} ${deps} PARENT_SCOPE)
49     return()
50   endif()
51 endfunction(collect_object_file_deps)
53 # A rule to build a library from a collection of entrypoint objects.
54 # Usage:
55 #     add_entrypoint_library(
56 #       DEPENDS <list of add_entrypoint_object targets>
57 #     )
59 # NOTE: If one wants an entrypoint to be available in a library, then they will
60 # have to list the entrypoint target explicitly in the DEPENDS list. Implicit
61 # entrypoint dependencies will not be added to the library.
62 function(add_entrypoint_library target_name)
63   cmake_parse_arguments(
64     "ENTRYPOINT_LIBRARY"
65     "" # No optional arguments
66     "" # No single value arguments
67     "DEPENDS" # Multi-value arguments
68     ${ARGN}
69   )
70   if(NOT ENTRYPOINT_LIBRARY_DEPENDS)
71     message(FATAL_ERROR "'add_entrypoint_library' target requires a DEPENDS list "
72                         "of 'add_entrypoint_object' targets.")
73   endif()
75   get_fq_deps_list(fq_deps_list ${ENTRYPOINT_LIBRARY_DEPENDS})
76   set(all_deps "")
77   foreach(dep IN LISTS fq_deps_list)
78     get_target_property(dep_type ${dep} "TARGET_TYPE")
79     if(NOT ((${dep_type} STREQUAL ${ENTRYPOINT_OBJ_TARGET_TYPE}) OR
80             (${dep_type} STREQUAL ${ENTRYPOINT_EXT_TARGET_TYPE}) OR
81             (${dep_type} STREQUAL ${ENTRYPOINT_OBJ_VENDOR_TARGET_TYPE})))
82       message(FATAL_ERROR "Dependency '${dep}' of 'add_entrypoint_collection' is "
83                           "not an 'add_entrypoint_object' or 'add_entrypoint_external' target.")
84     endif()
85     collect_object_file_deps(${dep} recursive_deps)
86     list(APPEND all_deps ${recursive_deps})
87     # Add the entrypoint object target explicitly as collect_object_file_deps
88     # only collects object files from non-entrypoint targets.
89     if(${dep_type} STREQUAL ${ENTRYPOINT_OBJ_TARGET_TYPE} OR
90        ${dep_type} STREQUAL ${ENTRYPOINT_OBJ_VENDOR_TARGET_TYPE})
91       set(entrypoint_target ${dep})
92       get_target_property(is_alias ${entrypoint_target} "IS_ALIAS")
93       if(is_alias)
94         get_target_property(aliasee ${entrypoint_target} "DEPS")
95         if(NOT aliasee)
96           message(FATAL_ERROR
97                   "Entrypoint alias ${entrypoint_target} does not have an aliasee.")
98         endif()
99         set(entrypoint_target ${aliasee})
100       endif()
101     endif()
102     list(APPEND all_deps ${entrypoint_target})
103   endforeach(dep)
104   list(REMOVE_DUPLICATES all_deps)
105   set(objects "")
106   foreach(dep IN LISTS all_deps)
107     list(APPEND objects $<$<STREQUAL:$<TARGET_NAME_IF_EXISTS:${dep}>,${dep}>:$<TARGET_OBJECTS:${dep}>>)
108   endforeach(dep)
110   add_library(
111     ${target_name}
112     STATIC
113     ${objects}
114   )
115   set_target_properties(${target_name} PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${LIBC_LIBRARY_DIR})
116 endfunction(add_entrypoint_library)
118 # Rule to build a shared library of redirector objects.
119 function(add_redirector_library target_name)
120   cmake_parse_arguments(
121     "REDIRECTOR_LIBRARY"
122     ""
123     ""
124     "DEPENDS"
125     ${ARGN}
126   )
128   set(obj_files "")
129   foreach(dep IN LISTS REDIRECTOR_LIBRARY_DEPENDS)
130     # TODO: Ensure that each dep is actually a add_redirector_object target.
131     list(APPEND obj_files $<TARGET_OBJECTS:${dep}>)
132   endforeach(dep)
134   # TODO: Call the linker explicitly instead of calling the compiler driver to
135   # prevent DT_NEEDED on C++ runtime.
136   add_library(
137     ${target_name}
138     EXCLUDE_FROM_ALL
139     SHARED
140     ${obj_files}
141   )
142   set_target_properties(${target_name}  PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${LIBC_LIBRARY_DIR})
143   target_link_libraries(${target_name}  -nostdlib -lc -lm)
144   set_target_properties(${target_name}  PROPERTIES LINKER_LANGUAGE "C")
145 endfunction(add_redirector_library)
147 set(HDR_LIBRARY_TARGET_TYPE "HDR_LIBRARY")
149 # Internal function, used by `add_header_library`.
150 function(create_header_library fq_target_name)
151   cmake_parse_arguments(
152     "ADD_HEADER"
153     "" # Optional arguments
154     "" # Single value arguments
155     "HDRS;DEPENDS;FLAGS;COMPILE_OPTIONS" # Multi-value arguments
156     ${ARGN}
157   )
159   if(NOT ADD_HEADER_HDRS)
160     message(FATAL_ERROR "'add_header_library' target requires a HDRS list of .h files.")
161   endif()
163   if(SHOW_INTERMEDIATE_OBJECTS)
164     message(STATUS "Adding header library ${fq_target_name}")
165     if(${SHOW_INTERMEDIATE_OBJECTS} STREQUAL "DEPS")
166       foreach(dep IN LISTS ADD_HEADER_DEPENDS)
167         message(STATUS "  ${fq_target_name} depends on ${dep}")
168       endforeach()
169     endif()
170   endif()
172   add_library(${fq_target_name} INTERFACE)
173   target_sources(${fq_target_name} INTERFACE ${ADD_HEADER_HDRS})
174   if(ADD_HEADER_DEPENDS)
175     add_dependencies(${fq_target_name} ${ADD_HEADER_DEPENDS})
176     target_link_libraries(${fq_target_name} INTERFACE ${ADD_HEADER_DEPENDS})
177   endif()
178   if(ADD_HEADER_COMPILE_OPTIONS)
179     target_compile_options(${fq_target_name} INTERFACE ${ADD_HEADER_COMPILE_OPTIONS})
180   endif()
181   set_target_properties(
182     ${fq_target_name}
183     PROPERTIES
184       INTERFACE_FLAGS "${ADD_HEADER_FLAGS}"
185       TARGET_TYPE "${HDR_LIBRARY_TARGET_TYPE}"
186       DEPS "${ADD_HEADER_DEPENDS}"
187       FLAGS "${ADD_HEADER_FLAGS}"
188   )
189 endfunction(create_header_library)
191 # Rule to add header only libraries.
192 # Usage
193 #    add_header_library(
194 #      <target name>
195 #      HDRS  <list of .h files part of the library>
196 #      DEPENDS <list of dependencies>
197 #      FLAGS <list of flags>
198 #    )
200 # Internal function, used by `add_header_library`.
201 function(expand_flags_for_header_library target_name flags)
202   cmake_parse_arguments(
203     "EXPAND_FLAGS"
204     "IGNORE_MARKER" # Optional arguments
205     "" # Single-value arguments
206     "DEPENDS;FLAGS" # Multi-value arguments
207     ${ARGN}
208   )
210   list(LENGTH flags nflags)
211   if(NOT ${nflags})
212     create_header_library(
213       ${target_name}
214       DEPENDS ${EXPAND_FLAGS_DEPENDS}
215       FLAGS ${EXPAND_FLAGS_FLAGS}
216       ${EXPAND_FLAGS_UNPARSED_ARGUMENTS}
217     )
218     return()
219   endif()
221   list(GET flags 0 flag)
222   list(REMOVE_AT flags 0)
223   extract_flag_modifier(${flag} real_flag modifier)
225   if(NOT "${modifier}" STREQUAL "NO")
226     expand_flags_for_header_library(
227       ${target_name}
228       "${flags}"
229       DEPENDS ${EXPAND_FLAGS_DEPENDS} IGNORE_MARKER
230       FLAGS ${EXPAND_FLAGS_FLAGS} IGNORE_MARKER
231       ${EXPAND_FLAGS_UNPARSED_ARGUMENTS}
232     )
233   endif()
235   if("${real_flag}" STREQUAL "" OR "${modifier}" STREQUAL "ONLY")
236     return()
237   endif()
239   set(NEW_FLAGS ${EXPAND_FLAGS_FLAGS})
240   list(REMOVE_ITEM NEW_FLAGS ${flag})
241   get_fq_dep_list_without_flag(NEW_DEPS ${real_flag} ${EXPAND_FLAGS_DEPENDS})
243   # Only target with `flag` has `.__NO_flag` target, `flag__NO` and
244   # `flag__ONLY` do not.
245   if("${modifier}" STREQUAL "")
246     set(TARGET_NAME "${target_name}.__NO_${flag}")
247   else()
248     set(TARGET_NAME "${target_name}")
249   endif()
251   expand_flags_for_header_library(
252     ${TARGET_NAME}
253     "${flags}"
254     DEPENDS ${NEW_DEPS} IGNORE_MARKER
255     FLAGS ${NEW_FLAGS} IGNORE_MARKER
256     ${EXPAND_FLAGS_UNPARSED_ARGUMENTS}
257   )
258 endfunction(expand_flags_for_header_library)
260 function(add_header_library target_name)
261   cmake_parse_arguments(
262     "ADD_TO_EXPAND"
263     "" # Optional arguments
264     "" # Single value arguments
265     "DEPENDS;FLAGS" # Multi-value arguments
266     ${ARGN}
267   )
269   get_fq_target_name(${target_name} fq_target_name)
271   if(ADD_TO_EXPAND_DEPENDS AND ("${SHOW_INTERMEDIATE_OBJECTS}" STREQUAL "DEPS"))
272     message(STATUS "Gathering FLAGS from dependencies for ${fq_target_name}")
273   endif()
275   get_fq_deps_list(fq_deps_list ${ADD_TO_EXPAND_DEPENDS})
276   get_flags_from_dep_list(deps_flag_list ${fq_deps_list})
277   
278   list(APPEND ADD_TO_EXPAND_FLAGS ${deps_flag_list})
279   remove_duplicated_flags("${ADD_TO_EXPAND_FLAGS}" flags)
280   list(SORT flags)
282   if(SHOW_INTERMEDIATE_OBJECTS AND flags)
283     message(STATUS "Header library ${fq_target_name} has FLAGS: ${flags}")
284   endif()
286   expand_flags_for_header_library(
287     ${fq_target_name}
288     "${flags}"
289     DEPENDS ${fq_deps_list} IGNORE_MARKER
290     FLAGS ${flags} IGNORE_MARKER
291     ${ADD_TO_EXPAND_UNPARSED_ARGUMENTS}
292   )
293 endfunction(add_header_library)