Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / llvm / cmake / modules / LLVMDistributionSupport.cmake
blob0b78f8f9137c5abb852ac3261483862c0e622967
1 # Utility functions for packaging an LLVM distribution. See the
2 # BuildingADistribution documentation for more details.
4 # These functions assume a number of conventions that are common across all LLVM
5 # subprojects:
6 # - The generated CMake exports file for ${project} is called ${project}Targets
7 #   (except for LLVM where it's called ${project}Exports for legacy reasons).
8 # - The build target for the CMake exports is called ${project}-cmake-exports
9 #   (except LLVM where it's just cmake-exports).
10 # - The ${PROJECT}${distribution}_HAS_EXPORTS global property holds whether a
11 #   project has any exports for a particular ${distribution} (where ${PROJECT}
12 #   is the project name in uppercase).
13 # - The ${PROJECT}_CMAKE_DIR variable is computed by ${project}Config.cmake to
14 #   hold the path of the installed CMake modules directory.
15 # - The ${PROJECT}_INSTALL_PACKAGE_DIR variable contains the install destination
16 #   for the project's CMake modules.
18 include_guard(GLOBAL)
20 if(LLVM_DISTRIBUTION_COMPONENTS AND LLVM_DISTRIBUTIONS)
21   message(FATAL_ERROR "LLVM_DISTRIBUTION_COMPONENTS and LLVM_DISTRIBUTIONS cannot be specified together")
22 endif()
24 if(LLVM_DISTRIBUTION_COMPONENTS OR LLVM_DISTRIBUTIONS)
25   if(LLVM_ENABLE_IDE)
26     message(FATAL_ERROR "LLVM_DISTRIBUTION_COMPONENTS cannot be specified with multi-configuration generators (i.e. Xcode or Visual Studio)")
27   endif()
28 endif()
30 # Build the map of targets to distributions that's used to look up the
31 # distribution for a target later. The distribution for ${target} is stored in
32 # the global property LLVM_DISTRIBUTION_FOR_${target}.
33 function(llvm_distribution_build_target_map)
34   foreach(target ${LLVM_DISTRIBUTION_COMPONENTS})
35     # CMake doesn't easily distinguish between properties that are unset and
36     # properties that are empty (you have to do a second get_property call with
37     # the SET option, which is unergonomic), so just use a special marker to
38     # denote the default (unnamed) distribution.
39     set_property(GLOBAL PROPERTY LLVM_DISTRIBUTION_FOR_${target} "<DEFAULT>")
40   endforeach()
42   foreach(distribution ${LLVM_DISTRIBUTIONS})
43     foreach(target ${LLVM_${distribution}_DISTRIBUTION_COMPONENTS})
44       # By default, we allow a target to be in multiple distributions, and use
45       # the last one to determine its export set. We disallow this in strict
46       # mode, emitting a single error at the end for readability.
47       if(LLVM_STRICT_DISTRIBUTIONS)
48         get_property(current_distribution GLOBAL PROPERTY LLVM_DISTRIBUTION_FOR_${target})
49         if(current_distribution AND NOT current_distribution STREQUAL distribution)
50           set_property(GLOBAL APPEND_STRING PROPERTY LLVM_DISTRIBUTION_ERRORS
51             "Target ${target} cannot be in multiple distributions \
52              ${distribution} and ${current_distribution}\n"
53             )
54         endif()
55       endif()
56       set_property(GLOBAL PROPERTY LLVM_DISTRIBUTION_FOR_${target} ${distribution})
57     endforeach()
58   endforeach()
59 endfunction()
61 # The include guard ensures this will only be called once. The rest of this file
62 # only defines other functions (i.e. it doesn't execute any more code directly).
63 llvm_distribution_build_target_map()
65 # Look up the distribution a particular target belongs to.
66 # - target: The target to look up.
67 # - in_distribution_var: The variable with this name is set in the caller's
68 #   scope to indicate if the target is in any distribution. If no distributions
69 #   have been configured, this will always be set to true.
70 # - distribution_var: The variable with this name is set in the caller's scope
71 #   to indicate the distribution name for the target. If the target belongs to
72 #   the default (unnamed) distribution, or if no distributions have been
73 #   configured, it's set to the empty string.
74 # - UMBRELLA: The (optional) umbrella target that the target is a part of. For
75 #   example, all LLVM libraries have the umbrella target llvm-libraries.
76 function(get_llvm_distribution target in_distribution_var distribution_var)
77   if(NOT LLVM_DISTRIBUTION_COMPONENTS AND NOT LLVM_DISTRIBUTIONS)
78     set(${in_distribution_var} YES PARENT_SCOPE)
79     set(${distribution_var} "" PARENT_SCOPE)
80     return()
81   endif()
83   cmake_parse_arguments(ARG "" UMBRELLA "" ${ARGN})
84   get_property(distribution GLOBAL PROPERTY LLVM_DISTRIBUTION_FOR_${target})
85   if(ARG_UMBRELLA)
86     get_property(umbrella_distribution GLOBAL PROPERTY LLVM_DISTRIBUTION_FOR_${ARG_UMBRELLA})
87     if(LLVM_STRICT_DISTRIBUTIONS AND distribution AND umbrella_distribution AND
88         NOT distribution STREQUAL umbrella_distribution)
89       set_property(GLOBAL APPEND_STRING PROPERTY LLVM_DISTRIBUTION_ERRORS
90         "Target ${target} has different distribution ${distribution} from its \
91          umbrella target's (${ARG_UMBRELLA}) distribution ${umbrella_distribution}\n"
92         )
93     endif()
94     if(NOT distribution)
95       set(distribution ${umbrella_distribution})
96     endif()
97   endif()
99   if(distribution)
100     set(${in_distribution_var} YES PARENT_SCOPE)
101     if(distribution STREQUAL "<DEFAULT>")
102       set(distribution "")
103     endif()
104     set(${distribution_var} "${distribution}" PARENT_SCOPE)
105   else()
106     set(${in_distribution_var} NO PARENT_SCOPE)
107   endif()
108 endfunction()
110 # Get the EXPORT argument to use for an install command for a target in a
111 # project. As explained at the top of the file, the project export set for a
112 # distribution is named ${project}{distribution}Targets (except for LLVM where
113 # it's named ${project}{distribution}Exports for legacy reasons). Also set the
114 # ${PROJECT}_${DISTRIBUTION}_HAS_EXPORTS global property to mark the project as
115 # having exports for the distribution.
116 # - target: The target to get the EXPORT argument for.
117 # - project: The project to produce the argument for. IMPORTANT: The casing of
118 #   this argument should match the casing used by the project's Config.cmake
119 #   file. The correct casing for the LLVM projects is Clang, Flang, LLD, LLVM,
120 #   and MLIR.
121 # - export_arg_var The variable with this name is set in the caller's scope to
122 #   the EXPORT argument for the target for the project.
123 # - UMBRELLA: The (optional) umbrella target that the target is a part of. For
124 #   example, all LLVM libraries have the umbrella target llvm-libraries.
125 function(get_target_export_arg target project export_arg_var)
126   string(TOUPPER "${project}" project_upper)
127   if(project STREQUAL "LLVM")
128     set(suffix "Exports") # legacy
129   else()
130     set(suffix "Targets")
131   endif()
133   get_llvm_distribution(${target} in_distribution distribution ${ARGN})
135   if(in_distribution)
136     set(${export_arg_var} EXPORT ${project}${distribution}${suffix} PARENT_SCOPE)
137     if(distribution)
138       string(TOUPPER "${distribution}" distribution_upper)
139       set_property(GLOBAL PROPERTY ${project_upper}_${distribution_upper}_HAS_EXPORTS True)
140     else()
141       set_property(GLOBAL PROPERTY ${project_upper}_HAS_EXPORTS True)
142     endif()
143   else()
144     set(${export_arg_var} "" PARENT_SCOPE)
145   endif()
146 endfunction()
148 # Produce a string of CMake include() commands to include the exported targets
149 # files for all distributions. See the comment at the top of this file for
150 # various assumptions made.
151 # - project: The project to produce the commands for. IMPORTANT: See the comment
152 #   for get_target_export_arg above for the correct casing of this argument.
153 # - includes_var: The variable with this name is set in the caller's scope to
154 #   the string of include commands.
155 function(get_config_exports_includes project includes_var)
156   string(TOUPPER "${project}" project_upper)
157   set(prefix "\${${project_upper}_CMAKE_DIR}/${project}")
158   if(project STREQUAL "LLVM")
159     set(suffix "Exports.cmake") # legacy
160   else()
161     set(suffix "Targets.cmake")
162   endif()
164   if(NOT LLVM_DISTRIBUTIONS)
165     set(${includes_var} "include(\"${prefix}${suffix}\")" PARENT_SCOPE)
166   else()
167     set(includes)
168     foreach(distribution ${LLVM_DISTRIBUTIONS})
169       list(APPEND includes "include(\"${prefix}${distribution}${suffix}\" OPTIONAL)")
170     endforeach()
171     string(REPLACE ";" "\n" includes "${includes}")
172     set(${includes_var} "${includes}" PARENT_SCOPE)
173   endif()
174 endfunction()
176 # Create the install commands and targets for the distributions' CMake exports.
177 # The target to install ${distribution} for a project is called
178 # ${project}-${distribution}-cmake-exports, where ${project} is the project name
179 # in lowercase and ${distribution} is the distribution name in lowercase, except
180 # for LLVM, where the target is just called ${distribution}-cmake-exports. See
181 # the comment at the top of this file for various assumptions made.
182 # - project: The project. IMPORTANT: See the comment for get_target_export_arg
183 #   above for the correct casing of this argument.
184 function(install_distribution_exports project)
185   string(TOUPPER "${project}" project_upper)
186   string(TOLOWER "${project}" project_lower)
187   if(project STREQUAL "LLVM")
188     set(prefix "")
189     set(suffix "Exports") # legacy
190   else()
191     set(prefix "${project_lower}-")
192     set(suffix "Targets")
193   endif()
194   set(destination "${${project_upper}_INSTALL_PACKAGE_DIR}")
196   if(NOT LLVM_DISTRIBUTIONS)
197     get_property(has_exports GLOBAL PROPERTY ${project_upper}_HAS_EXPORTS)
198     if(has_exports)
199       install(EXPORT ${project}${suffix} DESTINATION "${destination}"
200               COMPONENT ${prefix}cmake-exports)
201     endif()
202   else()
203     foreach(distribution ${LLVM_DISTRIBUTIONS})
204       string(TOUPPER "${distribution}" distribution_upper)
205       get_property(has_exports GLOBAL PROPERTY ${project_upper}_${distribution_upper}_HAS_EXPORTS)
206       if(has_exports)
207         string(TOLOWER "${distribution}" distribution_lower)
208         set(target ${prefix}${distribution_lower}-cmake-exports)
209         install(EXPORT ${project}${distribution}${suffix} DESTINATION "${destination}"
210                 COMPONENT ${target})
211         if(NOT LLVM_ENABLE_IDE)
212           add_custom_target(${target})
213           add_llvm_install_targets(install-${target} COMPONENT ${target})
214         endif()
215       endif()
216     endforeach()
217   endif()
218 endfunction()
220 # Create the targets for installing the configured distributions. The
221 # ${distribution} target builds the distribution, install-${distribution}
222 # installs it, and install-${distribution}-stripped installs a stripped version,
223 # where ${distribution} is the distribution name in lowercase, or "distribution"
224 # for the default distribution.
225 function(llvm_distribution_add_targets)
226   # This function is called towards the end of LLVM's CMakeLists.txt, so all
227   # errors will have been seen by now.
228   if(LLVM_STRICT_DISTRIBUTIONS)
229     get_property(errors GLOBAL PROPERTY LLVM_DISTRIBUTION_ERRORS)
230     if(errors)
231       string(PREPEND errors
232         "Strict distribution errors (turn off LLVM_STRICT_DISTRIBUTIONS to bypass):\n"
233         )
234       message(FATAL_ERROR "${errors}")
235     endif()
236   endif()
238   set(distributions "${LLVM_DISTRIBUTIONS}")
239   if(NOT distributions)
240     # CMake seemingly doesn't distinguish between an empty list and a list
241     # containing one element which is the empty string, so just use a special
242     # marker to denote the default (unnamed) distribution and fix it in the
243     # loop.
244     set(distributions "<DEFAULT>")
245   endif()
247   get_property(LLVM_DRIVER_TOOL_SYMLINKS GLOBAL PROPERTY LLVM_DRIVER_TOOL_SYMLINKS)
249   foreach(distribution ${distributions})
250     if(distribution STREQUAL "<DEFAULT>")
251       set(distribution_target distribution)
252       # Preserve legacy behavior for LLVM_DISTRIBUTION_COMPONENTS.
253       set(distribution_components ${LLVM_DISTRIBUTION_COMPONENTS} ${LLVM_RUNTIME_DISTRIBUTION_COMPONENTS})
254     else()
255       string(TOLOWER "${distribution}" distribution_lower)
256       set(distribution_target ${distribution_lower}-distribution)
257       set(distribution_components ${LLVM_${distribution}_DISTRIBUTION_COMPONENTS})
258     endif()
260     add_custom_target(${distribution_target})
261     add_custom_target(install-${distribution_target})
262     add_custom_target(install-${distribution_target}-stripped)
264     foreach(target ${distribution_components})
265       # Note that some distribution components may not have an actual target, but only an install-FOO target.
266       # This happens for example if a target is an INTERFACE target.
267       if(TARGET ${target})
268         add_dependencies(${distribution_target} ${target})
269       endif()
271       if(TARGET install-${target})
272         add_dependencies(install-${distribution_target} install-${target})
273       elseif(TARGET install-llvm-driver AND ${target} IN_LIST LLVM_DRIVER_TOOL_SYMLINKS)
274         add_dependencies(install-${distribution_target} install-llvm-driver)
275       else()
276         message(SEND_ERROR "Specified distribution component '${target}' doesn't have an install target")
277       endif()
279       if(TARGET install-${target}-stripped)
280         add_dependencies(install-${distribution_target}-stripped install-${target}-stripped)
281       elseif(TARGET install-llvm-driver-stripped AND ${target} IN_LIST LLVM_DRIVER_TOOL_SYMLINKS)
282         add_dependencies(install-${distribution_target}-stripped install-llvm-driver-stripped)
283       else()
284         message(SEND_ERROR
285                 "Specified distribution component '${target}' doesn't have an install-stripped target."
286                 " Its installation target creation should be changed to use add_llvm_install_targets,"
287                 " or you should manually create the 'install-${target}-stripped' target.")
288       endif()
289     endforeach()
290   endforeach()
291 endfunction()