[ORC] Add std::tuple support to SimplePackedSerialization.
[llvm-project.git] / llvm / cmake / modules / LLVMDistributionSupport.cmake
blobe1c9a6cce5e67d0efeb019734e1a8994993b454c
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       # We don't allow a target to be in multiple distributions, because we
45       # wouldn't know which export set to place it in.
46       get_property(current_distribution GLOBAL PROPERTY LLVM_DISTRIBUTION_FOR_${target})
47       if(current_distribution AND NOT current_distribution STREQUAL distribution)
48         message(SEND_ERROR "Target ${target} cannot be in multiple distributions ${distribution} and ${current_distribution}")
49       endif()
50       set_property(GLOBAL PROPERTY LLVM_DISTRIBUTION_FOR_${target} ${distribution})
51     endforeach()
52   endforeach()
53 endfunction()
55 # The include guard ensures this will only be called once. The rest of this file
56 # only defines other functions (i.e. it doesn't execute any more code directly).
57 llvm_distribution_build_target_map()
59 # Look up the distribution a particular target belongs to.
60 # - target: The target to look up.
61 # - in_distribution_var: The variable with this name is set in the caller's
62 #   scope to indicate if the target is in any distribution. If no distributions
63 #   have been configured, this will always be set to true.
64 # - distribution_var: The variable with this name is set in the caller's scope
65 #   to indicate the distribution name for the target. If the target belongs to
66 #   the default (unnamed) distribution, or if no distributions have been
67 #   configured, it's set to the empty string.
68 # - UMBRELLA: The (optional) umbrella target that the target is a part of. For
69 #   example, all LLVM libraries have the umbrella target llvm-libraries.
70 function(get_llvm_distribution target in_distribution_var distribution_var)
71   if(NOT LLVM_DISTRIBUTION_COMPONENTS AND NOT LLVM_DISTRIBUTIONS)
72     set(${in_distribution_var} YES PARENT_SCOPE)
73     set(${distribution_var} "" PARENT_SCOPE)
74     return()
75   endif()
77   cmake_parse_arguments(ARG "" UMBRELLA "" ${ARGN})
78   get_property(distribution GLOBAL PROPERTY LLVM_DISTRIBUTION_FOR_${target})
79   if(ARG_UMBRELLA)
80     get_property(umbrella_distribution GLOBAL PROPERTY LLVM_DISTRIBUTION_FOR_${ARG_UMBRELLA})
81     if(distribution AND umbrella_distribution AND NOT distribution STREQUAL umbrella_distribution)
82       message(SEND_ERROR "Target ${target} has different distribution ${distribution} from its"
83                          " umbrella target ${ARG_UMBRELLA} distribution ${umbrella_distribution}")
84     elseif(NOT distribution)
85       set(distribution ${umbrella_distribution})
86     endif()
87   endif()
88   if(distribution)
89     set(${in_distribution_var} YES PARENT_SCOPE)
90     if(distribution STREQUAL "<DEFAULT>")
91       set(distribution "")
92     endif()
93     set(${distribution_var} "${distribution}" PARENT_SCOPE)
94   else()
95     set(${in_distribution_var} NO PARENT_SCOPE)
96   endif()
97 endfunction()
99 # Get the EXPORT argument to use for an install command for a target in a
100 # project. As explained at the top of the file, the project export set for a
101 # distribution is named ${project}{distribution}Targets (except for LLVM where
102 # it's named ${project}{distribution}Exports for legacy reasons). Also set the
103 # ${PROJECT}_${DISTRIBUTION}_HAS_EXPORTS global property to mark the project as
104 # having exports for the distribution.
105 # - target: The target to get the EXPORT argument for.
106 # - project: The project to produce the argument for. IMPORTANT: The casing of
107 #   this argument should match the casing used by the project's Config.cmake
108 #   file. The correct casing for the LLVM projects is Clang, Flang, LLD, LLVM,
109 #   and MLIR.
110 # - export_arg_var The variable with this name is set in the caller's scope to
111 #   the EXPORT argument for the target for the project.
112 # - UMBRELLA: The (optional) umbrella target that the target is a part of. For
113 #   example, all LLVM libraries have the umbrella target llvm-libraries.
114 function(get_target_export_arg target project export_arg_var)
115   string(TOUPPER "${project}" project_upper)
116   if(project STREQUAL "LLVM")
117     set(suffix "Exports") # legacy
118   else()
119     set(suffix "Targets")
120   endif()
122   get_llvm_distribution(${target} in_distribution distribution ${ARGN})
124   if(in_distribution)
125     set(${export_arg_var} EXPORT ${project}${distribution}${suffix} PARENT_SCOPE)
126     if(distribution)
127       string(TOUPPER "${distribution}" distribution_upper)
128       set_property(GLOBAL PROPERTY ${project_upper}_${distribution_upper}_HAS_EXPORTS True)
129     else()
130       set_property(GLOBAL PROPERTY ${project_upper}_HAS_EXPORTS True)
131     endif()
132   else()
133     set(${export_arg_var} "" PARENT_SCOPE)
134   endif()
135 endfunction()
137 # Produce a string of CMake include() commands to include the exported targets
138 # files for all distributions. See the comment at the top of this file for
139 # various assumptions made.
140 # - project: The project to produce the commands for. IMPORTANT: See the comment
141 #   for get_target_export_arg above for the correct casing of this argument.
142 # - includes_var: The variable with this name is set in the caller's scope to
143 #   the string of include commands.
144 function(get_config_exports_includes project includes_var)
145   string(TOUPPER "${project}" project_upper)
146   set(prefix "\${${project_upper}_CMAKE_DIR}/${project}")
147   if(project STREQUAL "LLVM")
148     set(suffix "Exports.cmake") # legacy
149   else()
150     set(suffix "Targets.cmake")
151   endif()
153   if(NOT LLVM_DISTRIBUTIONS)
154     set(${includes_var} "include(\"${prefix}${suffix}\")" PARENT_SCOPE)
155   else()
156     set(includes)
157     foreach(distribution ${LLVM_DISTRIBUTIONS})
158       list(APPEND includes "include(\"${prefix}${distribution}${suffix}\" OPTIONAL)")
159     endforeach()
160     string(REPLACE ";" "\n" includes "${includes}")
161     set(${includes_var} "${includes}" PARENT_SCOPE)
162   endif()
163 endfunction()
165 # Create the install commands and targets for the distributions' CMake exports.
166 # The target to install ${distribution} for a project is called
167 # ${project}-${distribution}-cmake-exports, where ${project} is the project name
168 # in lowercase and ${distribution} is the distribution name in lowercase, except
169 # for LLVM, where the target is just called ${distribution}-cmake-exports. See
170 # the comment at the top of this file for various assumptions made.
171 # - project: The project. IMPORTANT: See the comment for get_target_export_arg
172 #   above for the correct casing of this argument.
173 function(install_distribution_exports project)
174   string(TOUPPER "${project}" project_upper)
175   string(TOLOWER "${project}" project_lower)
176   if(project STREQUAL "LLVM")
177     set(prefix "")
178     set(suffix "Exports") # legacy
179   else()
180     set(prefix "${project_lower}-")
181     set(suffix "Targets")
182   endif()
183   set(destination "${${project_upper}_INSTALL_PACKAGE_DIR}")
185   if(NOT LLVM_DISTRIBUTIONS)
186     get_property(has_exports GLOBAL PROPERTY ${project_upper}_HAS_EXPORTS)
187     if(has_exports)
188       install(EXPORT ${project}${suffix} DESTINATION "${destination}"
189               COMPONENT ${prefix}cmake-exports)
190     endif()
191   else()
192     foreach(distribution ${LLVM_DISTRIBUTIONS})
193       string(TOUPPER "${distribution}" distribution_upper)
194       get_property(has_exports GLOBAL PROPERTY ${project_upper}_${distribution_upper}_HAS_EXPORTS)
195       if(has_exports)
196         string(TOLOWER "${distribution}" distribution_lower)
197         set(target ${prefix}${distribution_lower}-cmake-exports)
198         install(EXPORT ${project}${distribution}${suffix} DESTINATION "${destination}"
199                 COMPONENT ${target})
200         if(NOT LLVM_ENABLE_IDE)
201           add_custom_target(${target})
202           add_llvm_install_targets(install-${target} COMPONENT ${target})
203         endif()
204       endif()
205     endforeach()
206   endif()
207 endfunction()
209 # Create the targets for installing the configured distributions. The
210 # ${distribution} target builds the distribution, install-${distribution}
211 # installs it, and install-${distribution}-stripped installs a stripped version,
212 # where ${distribution} is the distribution name in lowercase, or "distribution"
213 # for the default distribution.
214 function(llvm_distribution_add_targets)
215   set(distributions "${LLVM_DISTRIBUTIONS}")
216   if(NOT distributions)
217     # CMake seemingly doesn't distinguish between an empty list and a list
218     # containing one element which is the empty string, so just use a special
219     # marker to denote the default (unnamed) distribution and fix it in the
220     # loop.
221     set(distributions "<DEFAULT>")
222   endif()
224   foreach(distribution ${distributions})
225     if(distribution STREQUAL "<DEFAULT>")
226       set(distribution_target distribution)
227       # Preserve legacy behavior for LLVM_DISTRIBUTION_COMPONENTS.
228       set(distribution_components ${LLVM_DISTRIBUTION_COMPONENTS} ${LLVM_RUNTIME_DISTRIBUTION_COMPONENTS})
229     else()
230       string(TOLOWER "${distribution}" distribution_lower)
231       set(distribution_target ${distribution_lower}-distribution)
232       set(distribution_components ${LLVM_${distribution}_DISTRIBUTION_COMPONENTS})
233     endif()
235     add_custom_target(${distribution_target})
236     add_custom_target(install-${distribution_target})
237     add_custom_target(install-${distribution_target}-stripped)
239     foreach(target ${distribution_components})
240       if(TARGET ${target})
241         add_dependencies(${distribution_target} ${target})
242       else()
243         message(SEND_ERROR "Specified distribution component '${target}' doesn't have a target")
244       endif()
246       if(TARGET install-${target})
247         add_dependencies(install-${distribution_target} install-${target})
248       else()
249         message(SEND_ERROR "Specified distribution component '${target}' doesn't have an install target")
250       endif()
252       if(TARGET install-${target}-stripped)
253         add_dependencies(install-${distribution_target}-stripped install-${target}-stripped)
254       else()
255         message(SEND_ERROR
256                 "Specified distribution component '${target}' doesn't have an install-stripped target."
257                 " Its installation target creation should be changed to use add_llvm_install_targets,"
258                 " or you should manually create the 'install-${target}-stripped' target.")
259       endif()
260     endforeach()
261   endforeach()
262 endfunction()