This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG56f7e5a822b4: [cmake] Add support for multiple distributions 
(authored by smeenai).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D89177/new/

https://reviews.llvm.org/D89177

Files:
  clang/cmake/caches/MultiDistributionExample.cmake
  clang/cmake/modules/AddClang.cmake
  clang/cmake/modules/CMakeLists.txt
  clang/cmake/modules/ClangConfig.cmake.in
  flang/cmake/modules/AddFlang.cmake
  flang/cmake/modules/CMakeLists.txt
  flang/cmake/modules/FlangConfig.cmake.in
  lld/cmake/modules/AddLLD.cmake
  lld/cmake/modules/CMakeLists.txt
  lld/cmake/modules/LLDConfig.cmake.in
  llvm/cmake/modules/AddLLVM.cmake
  llvm/cmake/modules/CMakeLists.txt
  llvm/cmake/modules/LLVMConfig.cmake.in
  llvm/cmake/modules/LLVMDistributionSupport.cmake
  llvm/docs/BuildingADistribution.rst
  llvm/docs/ReleaseNotes.rst
  mlir/cmake/modules/AddMLIR.cmake
  mlir/cmake/modules/CMakeLists.txt
  mlir/cmake/modules/MLIRConfig.cmake.in

Index: mlir/cmake/modules/MLIRConfig.cmake.in
===================================================================
--- mlir/cmake/modules/MLIRConfig.cmake.in
+++ mlir/cmake/modules/MLIRConfig.cmake.in
@@ -20,7 +20,7 @@
 set_property(GLOBAL PROPERTY MLIR_TRANSLATION_LIBS "@MLIR_TRANSLATION_LIBS@")
 
 # Provide all our library targets to users.
-include("@MLIR_CONFIG_EXPORTS_FILE@")
+@MLIR_CONFIG_INCLUDE_EXPORTS@
 
 # By creating these targets here, subprojects that depend on MLIR's
 # tablegen-generated headers can always depend on these targets whether building
Index: mlir/cmake/modules/CMakeLists.txt
===================================================================
--- mlir/cmake/modules/CMakeLists.txt
+++ mlir/cmake/modules/CMakeLists.txt
@@ -1,3 +1,5 @@
+include(LLVMDistributionSupport)
+
 # Generate a list of CMake library targets so that other CMake projects can
 # link against them. LLVM calls its version of this file LLVMExports.cmake, but
 # the usual CMake convention seems to be ${Project}Targets.cmake.
@@ -19,7 +21,7 @@
 # Generate MlirConfig.cmake for the build tree.
 set(MLIR_CONFIG_CMAKE_DIR "${mlir_cmake_builddir}")
 set(MLIR_CONFIG_LLVM_CMAKE_DIR "${llvm_cmake_builddir}")
-set(MLIR_CONFIG_EXPORTS_FILE "\${MLIR_CMAKE_DIR}/MLIRTargets.cmake")
+set(MLIR_CONFIG_INCLUDE_EXPORTS "include(\"\${MLIR_CMAKE_DIR}/MLIRTargets.cmake\")")
 set(MLIR_CONFIG_INCLUDE_DIRS
   "${MLIR_SOURCE_DIR}/include"
   "${MLIR_BINARY_DIR}/include"
@@ -30,7 +32,6 @@
   @ONLY)
 set(MLIR_CONFIG_CMAKE_DIR)
 set(MLIR_CONFIG_LLVM_CMAKE_DIR)
-set(MLIR_CONFIG_EXPORTS_FILE)
 set(MLIR_CONFIG_INCLUDE_DIRS)
 
 # For compatibility with projects that include(MLIRConfig)
@@ -55,7 +56,7 @@
 endforeach(p)
 set(MLIR_CONFIG_CMAKE_DIR "\${MLIR_INSTALL_PREFIX}/${MLIR_INSTALL_PACKAGE_DIR}")
 set(MLIR_CONFIG_LLVM_CMAKE_DIR "\${MLIR_INSTALL_PREFIX}/${LLVM_INSTALL_PACKAGE_DIR}")
-set(MLIR_CONFIG_EXPORTS_FILE "\${MLIR_CMAKE_DIR}/MLIRTargets.cmake")
+get_config_exports_includes(MLIR MLIR_CONFIG_INCLUDE_EXPORTS)
 set(MLIR_CONFIG_INCLUDE_DIRS
   "\${MLIR_INSTALL_PREFIX}/include"
   )
@@ -66,17 +67,12 @@
 set(MLIR_CONFIG_CODE)
 set(MLIR_CONFIG_CMAKE_DIR)
 set(MLIR_CONFIG_LLVM_CMAKE_DIR)
-set(MLIR_CONFIG_EXPORTS_FILE)
 set(MLIR_CONFIG_INCLUDE_DIRS)
 
 if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY)
   # Not TOOLCHAIN ONLY, so install the MLIR parts as well
   # Include the cmake files so other tools can use mlir-tblgen, etc.
-  get_property(mlir_has_exports GLOBAL PROPERTY MLIR_HAS_EXPORTS)
-  if(mlir_has_exports)
-    install(EXPORT MLIRTargets DESTINATION ${MLIR_INSTALL_PACKAGE_DIR}
-            COMPONENT mlir-cmake-exports)
-  endif()
+  install_distribution_exports(MLIR)
 
   install(FILES
     ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/MLIRConfig.cmake
Index: mlir/cmake/modules/AddMLIR.cmake
===================================================================
--- mlir/cmake/modules/AddMLIR.cmake
+++ mlir/cmake/modules/AddMLIR.cmake
@@ -1,3 +1,5 @@
+include(LLVMDistributionSupport)
+
 function(mlir_tablegen ofn)
   tablegen(MLIR ${ARGV})
   set(TABLEGEN_OUTPUT ${TABLEGEN_OUTPUT} ${CMAKE_CURRENT_BINARY_DIR}/${ofn}
@@ -141,14 +143,7 @@
 # where non-standard library builds can be installed.
 function(add_mlir_library_install name)
   if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY)
-  set(export_to_mlirtargets)
-  if (${name} IN_LIST LLVM_DISTRIBUTION_COMPONENTS OR
-      "mlir-libraries" IN_LIST LLVM_DISTRIBUTION_COMPONENTS OR
-      NOT LLVM_DISTRIBUTION_COMPONENTS)
-      set(export_to_mlirtargets EXPORT MLIRTargets)
-    set_property(GLOBAL PROPERTY MLIR_HAS_EXPORTS True)
-  endif()
-
+  get_target_export_arg(${name} MLIR export_to_mlirtargets UMBRELLA mlir-libraries)
   install(TARGETS ${name}
     COMPONENT ${name}
     ${export_to_mlirtargets}
Index: llvm/docs/ReleaseNotes.rst
===================================================================
--- llvm/docs/ReleaseNotes.rst
+++ llvm/docs/ReleaseNotes.rst
@@ -64,6 +64,10 @@
 Changes to building LLVM
 ------------------------
 
+* The build system now supports building multiple distributions, so that you can
+  e.g. have one distribution containing just tools and another for libraries (to
+  enable development). See :ref:`Multi-distribution configurations` for details.
+
 Changes to TableGen
 -------------------
 
Index: llvm/docs/BuildingADistribution.rst
===================================================================
--- llvm/docs/BuildingADistribution.rst
+++ llvm/docs/BuildingADistribution.rst
@@ -87,6 +87,40 @@
 the list. This is a convenience build target to allow building just the
 distributed pieces without needing to build all configured targets.
 
+.. _Multi-distribution configurations:
+
+Multi-distribution configurations
+---------------------------------
+
+The ``install-distribution`` target described above is for building a single
+distribution. LLVM's build system also supports building multiple distributions,
+which can be used to e.g. have one distribution containing just tools and
+another for libraries (to enable development). These are configured by setting
+the *LLVM_DISTRIBUTIONS* variable to hold a list of all distribution names
+(which conventionally start with an uppercase letter, e.g. "Development"), and
+then setting the *LLVM_<distribution>_DISTRIBUTION_COMPONENTS* variable to the
+list of targets for that distribution. For each distribution, the build system
+generates an ``install-${distribution}-distribution`` target, where
+``${distribution}`` is the name of the distribution in lowercase, to install
+that distribution. Each target can only be in one distribution.
+
+Each distribution creates its own set of CMake exports, and the target to
+install the CMake exports for a particular distribution for a project is named
+``${project}-${distribution}-cmake-exports``, where ``${project}`` is the name
+of the project in lowercase and ``${distribution}`` is the name of the
+distribution in lowercase, unless the project is LLVM, in which case the target
+is just named ``${distribution}-cmake-exports``. These targets need to be
+explicitly included in the *LLVM_<distribution>_DISTRIBUTION_COMPONENTS*
+variable in order to be included as part of the distribution.
+
+Unlike with the single distribution setup, when building multiple distributions,
+any components specified in *LLVM_RUNTIME_DISTRIBUTION_COMPONENTS* are not
+automatically added to any distribution. Instead, you must include the targets
+explicitly in some *LLVM_<distribution>_DISTRIBUTION_COMPONENTS* list.
+
+We strongly encourage looking at ``clang/cmake/caches/MultiDistributionExample.cmake``
+as an example of configuring multiple distributions.
+
 Special Notes for Library-only Distributions
 --------------------------------------------
 
@@ -179,6 +213,11 @@
   of the libraries and runtimes. Component names match the names of the build
   system targets.
 
+**LLVM_DISTRIBUTIONS**:STRING
+  This variable can be set to a semi-colon separated list of distributions. See
+  the :ref:`Multi-distribution configurations` section above for details on this
+  and other CMake variables to configure multiple distributions.
+
 **LLVM_RUNTIME_DISTRIBUTION_COMPONENTS**:STRING
   This variable can be set to a semi-colon separated list of runtime library
   components. This is used in conjunction with *LLVM_ENABLE_RUNTIMES* to specify
Index: llvm/cmake/modules/LLVMDistributionSupport.cmake
===================================================================
--- llvm/cmake/modules/LLVMDistributionSupport.cmake
+++ llvm/cmake/modules/LLVMDistributionSupport.cmake
@@ -1,36 +1,238 @@
+# Utility functions for packaging an LLVM distribution. See the
+# BuildingADistribution documentation for more details.
 
-if(LLVM_DISTRIBUTION_COMPONENTS)
+# These functions assume a number of conventions that are common across all LLVM
+# subprojects:
+# - The generated CMake exports file for ${project} is called ${project}Targets
+#   (except for LLVM where it's called ${project}Exports for legacy reasons).
+# - The build target for the CMake exports is called ${project}-cmake-exports
+#   (except LLVM where it's just cmake-exports).
+# - The ${PROJECT}${distribution}_HAS_EXPORTS global property holds whether a
+#   project has any exports for a particular ${distribution} (where ${PROJECT}
+#   is the project name in uppercase).
+# - The ${PROJECT}_CMAKE_DIR variable is computed by ${project}Config.cmake to
+#   hold the path of the installed CMake modules directory.
+# - The ${PROJECT}_INSTALL_PACKAGE_DIR variable contains the install destination
+#   for the project's CMake modules.
+
+include_guard(GLOBAL)
+
+if(LLVM_DISTRIBUTION_COMPONENTS AND LLVM_DISTRIBUTIONS)
+  message(FATAL_ERROR "LLVM_DISTRIBUTION_COMPONENTS and LLVM_DISTRIBUTIONS cannot be specified together")
+endif()
+
+if(LLVM_DISTRIBUTION_COMPONENTS OR LLVM_DISTRIBUTIONS)
   if(LLVM_ENABLE_IDE)
     message(FATAL_ERROR "LLVM_DISTRIBUTION_COMPONENTS cannot be specified with multi-configuration generators (i.e. Xcode or Visual Studio)")
   endif()
 endif()
 
-function(llvm_distribution_add_targets)
-  add_custom_target(distribution)
-  add_custom_target(install-distribution)
-  add_custom_target(install-distribution-stripped)
-
-  foreach(target ${LLVM_DISTRIBUTION_COMPONENTS}
-      ${LLVM_RUNTIME_DISTRIBUTION_COMPONENTS})
-    if(TARGET ${target})
-      add_dependencies(distribution ${target})
+# Build the map of targets to distributions that's used to look up the
+# distribution for a target later. The distribution for ${target} is stored in
+# the global property LLVM_DISTRIBUTION_FOR_${target}.
+function(llvm_distribution_build_target_map)
+  foreach(target ${LLVM_DISTRIBUTION_COMPONENTS})
+    # CMake doesn't easily distinguish between properties that are unset and
+    # properties that are empty (you have to do a second get_property call with
+    # the SET option, which is unergonomic), so just use a special marker to
+    # denote the default (unnamed) distribution.
+    set_property(GLOBAL PROPERTY LLVM_DISTRIBUTION_FOR_${target} "<DEFAULT>")
+  endforeach()
+
+  foreach(distribution ${LLVM_DISTRIBUTIONS})
+    foreach(target ${LLVM_${distribution}_DISTRIBUTION_COMPONENTS})
+      # We don't allow a target to be in multiple distributions, because we
+      # wouldn't know which export set to place it in.
+      get_property(current_distribution GLOBAL PROPERTY LLVM_DISTRIBUTION_FOR_${target})
+      if(current_distribution AND NOT current_distribution STREQUAL distribution)
+        message(SEND_ERROR "Target ${target} cannot be in multiple distributions ${distribution} and ${current_distribution}")
+      endif()
+      set_property(GLOBAL PROPERTY LLVM_DISTRIBUTION_FOR_${target} ${distribution})
+    endforeach()
+  endforeach()
+endfunction()
+
+# The include guard ensures this will only be called once. The rest of this file
+# only defines other functions (i.e. it doesn't execute any more code directly).
+llvm_distribution_build_target_map()
+
+# Get the EXPORT argument to use for an install command for a target in a
+# project. As explained at the top of the file, the project export set for a
+# distribution is named ${project}{distribution}Targets (except for LLVM where
+# it's named ${project}{distribution}Exports for legacy reasons). Also set the
+# ${PROJECT}_${DISTRIBUTION}_HAS_EXPORTS global property to mark the project as
+# having exports for the distribution.
+# - target: The target to get the EXPORT argument for.
+# - project: The project to produce the argument for. IMPORTANT: The casing of
+#   this argument should match the casing used by the project's Config.cmake
+#   file. The correct casing for the LLVM projects is Clang, Flang, LLD, LLVM,
+#   and MLIR.
+# - export_arg_var The variable with this name is set in the caller's scope to
+#   the EXPORT argument for the target for the project.
+# - UMBRELLA: The (optional) umbrella target that the target is a part of. For
+#   example, all LLVM libraries have the umbrella target llvm-libraries.
+function(get_target_export_arg target project export_arg_var)
+  string(TOUPPER "${project}" project_upper)
+  if(project STREQUAL "LLVM")
+    set(suffix "Exports") # legacy
+  else()
+    set(suffix "Targets")
+  endif()
+
+  if(NOT LLVM_DISTRIBUTION_COMPONENTS AND NOT LLVM_DISTRIBUTIONS)
+    set(${export_arg_var} EXPORT ${project}${suffix} PARENT_SCOPE)
+    set_property(GLOBAL PROPERTY ${project_upper}_HAS_EXPORTS True)
+    return()
+  endif()
+
+  cmake_parse_arguments(ARG "" UMBRELLA "" ${ARGN})
+  get_property(distribution GLOBAL PROPERTY LLVM_DISTRIBUTION_FOR_${target})
+  if(ARG_UMBRELLA)
+    get_property(umbrella_distribution GLOBAL PROPERTY LLVM_DISTRIBUTION_FOR_${ARG_UMBRELLA})
+    if(distribution AND umbrella_distribution AND NOT distribution STREQUAL umbrella_distribution)
+      message(SEND_ERROR "Target ${target} has different distribution ${distribution} from its"
+                         " umbrella target ${ARG_UMBRELLA} distribution ${umbrella_distribution}")
+    elseif(NOT distribution)
+      set(distribution ${umbrella_distribution})
+    endif()
+  endif()
+  if(distribution)
+    if(distribution STREQUAL "<DEFAULT>")
+      set(${export_arg_var} EXPORT ${project}${suffix} PARENT_SCOPE)
+      set_property(GLOBAL PROPERTY ${project_upper}_HAS_EXPORTS True)
     else()
-      message(SEND_ERROR "Specified distribution component '${target}' doesn't have a target")
+      set(${export_arg_var} EXPORT ${project}${distribution}${suffix} PARENT_SCOPE)
+      string(TOUPPER "${distribution}" distribution_upper)
+      set_property(GLOBAL PROPERTY ${project_upper}_${distribution_upper}_HAS_EXPORTS True)
     endif()
+  else()
+    set(${export_arg_var} "" PARENT_SCOPE)
+  endif()
+endfunction()
 
-    if(TARGET install-${target})
-      add_dependencies(install-distribution install-${target})
-    else()
-      message(SEND_ERROR "Specified distribution component '${target}' doesn't have an install target")
+# Produce a string of CMake include() commands to include the exported targets
+# files for all distributions. See the comment at the top of this file for
+# various assumptions made.
+# - project: The project to produce the commands for. IMPORTANT: See the comment
+#   for get_target_export_arg above for the correct casing of this argument.
+# - includes_var: The variable with this name is set in the caller's scope to
+#   the string of include commands.
+function(get_config_exports_includes project includes_var)
+  string(TOUPPER "${project}" project_upper)
+  set(prefix "\${${project_upper}_CMAKE_DIR}/${project}")
+  if(project STREQUAL "LLVM")
+    set(suffix "Exports.cmake") # legacy
+  else()
+    set(suffix "Targets.cmake")
+  endif()
+
+  if(NOT LLVM_DISTRIBUTIONS)
+    set(${includes_var} "include(\"${prefix}${suffix}\")" PARENT_SCOPE)
+  else()
+    set(includes)
+    foreach(distribution ${LLVM_DISTRIBUTIONS})
+      list(APPEND includes "include(\"${prefix}${distribution}${suffix}\" OPTIONAL)")
+    endforeach()
+    string(REPLACE ";" "\n" includes "${includes}")
+    set(${includes_var} "${includes}" PARENT_SCOPE)
+  endif()
+endfunction()
+
+# Create the install commands and targets for the distributions' CMake exports.
+# The target to install ${distribution} for a project is called
+# ${project}-${distribution}-cmake-exports, where ${project} is the project name
+# in lowercase and ${distribution} is the distribution name in lowercase, except
+# for LLVM, where the target is just called ${distribution}-cmake-exports. See
+# the comment at the top of this file for various assumptions made.
+# - project: The project. IMPORTANT: See the comment for get_target_export_arg
+#   above for the correct casing of this argument.
+function(install_distribution_exports project)
+  string(TOUPPER "${project}" project_upper)
+  string(TOLOWER "${project}" project_lower)
+  if(project STREQUAL "LLVM")
+    set(prefix "")
+    set(suffix "Exports") # legacy
+  else()
+    set(prefix "${project_lower}-")
+    set(suffix "Targets")
+  endif()
+  set(destination "${${project_upper}_INSTALL_PACKAGE_DIR}")
+
+  if(NOT LLVM_DISTRIBUTIONS)
+    get_property(has_exports GLOBAL PROPERTY ${project_upper}_HAS_EXPORTS)
+    if(has_exports)
+      install(EXPORT ${project}${suffix} DESTINATION "${destination}"
+              COMPONENT ${prefix}cmake-exports)
     endif()
+  else()
+    foreach(distribution ${LLVM_DISTRIBUTIONS})
+      string(TOUPPER "${distribution}" distribution_upper)
+      get_property(has_exports GLOBAL PROPERTY ${project_upper}_${distribution_upper}_HAS_EXPORTS)
+      if(has_exports)
+        string(TOLOWER "${distribution}" distribution_lower)
+        set(target ${prefix}${distribution_lower}-cmake-exports)
+        install(EXPORT ${project}${distribution}${suffix} DESTINATION "${destination}"
+                COMPONENT ${target})
+        if(NOT LLVM_ENABLE_IDE)
+          add_custom_target(${target})
+          add_llvm_install_targets(install-${target} COMPONENT ${target})
+        endif()
+      endif()
+    endforeach()
+  endif()
+endfunction()
+
+# Create the targets for installing the configured distributions. The
+# ${distribution} target builds the distribution, install-${distribution}
+# installs it, and install-${distribution}-stripped installs a stripped version,
+# where ${distribution} is the distribution name in lowercase, or "distribution"
+# for the default distribution.
+function(llvm_distribution_add_targets)
+  set(distributions "${LLVM_DISTRIBUTIONS}")
+  if(NOT distributions)
+    # CMake seemingly doesn't distinguish between an empty list and a list
+    # containing one element which is the empty string, so just use a special
+    # marker to denote the default (unnamed) distribution and fix it in the
+    # loop.
+    set(distributions "<DEFAULT>")
+  endif()
 
-    if(TARGET install-${target}-stripped)
-      add_dependencies(install-distribution-stripped install-${target}-stripped)
+  foreach(distribution ${distributions})
+    if(distribution STREQUAL "<DEFAULT>")
+      set(distribution_target distribution)
+      # Preserve legacy behavior for LLVM_DISTRIBUTION_COMPONENTS.
+      set(distribution_components ${LLVM_DISTRIBUTION_COMPONENTS} ${LLVM_RUNTIME_DISTRIBUTION_COMPONENTS})
     else()
-      message(SEND_ERROR
-              "Specified distribution component '${target}' doesn't have an install-stripped target."
-              " Its installation target creation should be changed to use add_llvm_install_targets,"
-              " or you should manually create the 'install-${target}-stripped' target.")
+      string(TOLOWER "${distribution}" distribution_lower)
+      set(distribution_target ${distribution_lower}-distribution)
+      set(distribution_components ${LLVM_${distribution}_DISTRIBUTION_COMPONENTS})
     endif()
+
+    add_custom_target(${distribution_target})
+    add_custom_target(install-${distribution_target})
+    add_custom_target(install-${distribution_target}-stripped)
+
+    foreach(target ${distribution_components})
+      if(TARGET ${target})
+        add_dependencies(${distribution_target} ${target})
+      else()
+        message(SEND_ERROR "Specified distribution component '${target}' doesn't have a target")
+      endif()
+
+      if(TARGET install-${target})
+        add_dependencies(install-${distribution_target} install-${target})
+      else()
+        message(SEND_ERROR "Specified distribution component '${target}' doesn't have an install target")
+      endif()
+
+      if(TARGET install-${target}-stripped)
+        add_dependencies(install-${distribution_target}-stripped install-${target}-stripped)
+      else()
+        message(SEND_ERROR
+                "Specified distribution component '${target}' doesn't have an install-stripped target."
+                " Its installation target creation should be changed to use add_llvm_install_targets,"
+                " or you should manually create the 'install-${target}-stripped' target.")
+      endif()
+    endforeach()
   endforeach()
 endfunction()
Index: llvm/cmake/modules/LLVMConfig.cmake.in
===================================================================
--- llvm/cmake/modules/LLVMConfig.cmake.in
+++ llvm/cmake/modules/LLVMConfig.cmake.in
@@ -112,8 +112,7 @@
 set(LLVM_LIT_ARGS "@LLVM_LIT_ARGS@")
 
 if(NOT TARGET LLVMSupport)
-  set(LLVM_EXPORTED_TARGETS "@LLVM_CONFIG_EXPORTS@")
-  include("@LLVM_CONFIG_EXPORTS_FILE@")
+  @LLVM_CONFIG_INCLUDE_EXPORTS@
   @llvm_config_include_buildtree_only_exports@
 endif()
 
Index: llvm/cmake/modules/CMakeLists.txt
===================================================================
--- llvm/cmake/modules/CMakeLists.txt
+++ llvm/cmake/modules/CMakeLists.txt
@@ -1,3 +1,5 @@
+include(LLVMDistributionSupport)
+
 set(LLVM_INSTALL_PACKAGE_DIR lib${LLVM_LIBDIR_SUFFIX}/cmake/llvm)
 set(llvm_cmake_builddir "${LLVM_BINARY_DIR}/${LLVM_INSTALL_PACKAGE_DIR}")
 
@@ -77,8 +79,8 @@
 # LLVM_CONFIG_CMAKE_DIR being the source directory. In contrast in the install
 # tree, both the generated LLVMExports.cmake file and the rest of the cmake
 # source files are put in the same cmake directory.
-set(LLVM_CONFIG_EXPORTS_FILE "${LLVM_EXPORTS_FILE}")
 set(LLVM_CONFIG_EXPORTS "${LLVM_EXPORTS};${LLVM_EXPORTS_BUILDTREE_ONLY}")
+set(LLVM_CONFIG_INCLUDE_EXPORTS "include(\"${LLVM_EXPORTS_FILE}\")")
 set(llvm_config_include_buildtree_only_exports
 "include(\"${LLVM_BUILDTREEONLY_EXPORTS_FILE}\")")
 configure_file(
@@ -120,7 +122,7 @@
   set(LLVM_CONFIG_DEFAULT_EXTERNAL_LIT "${LLVM_CONFIG_TOOLS_BINARY_DIR}/llvm-lit")
 endif()
 
-set(LLVM_CONFIG_EXPORTS_FILE "\${LLVM_CMAKE_DIR}/LLVMExports.cmake")
+get_config_exports_includes(LLVM LLVM_CONFIG_INCLUDE_EXPORTS)
 set(LLVM_CONFIG_EXPORTS "${LLVM_EXPORTS}")
 configure_file(
   LLVMConfig.cmake.in
@@ -134,11 +136,7 @@
   @ONLY)
 
 if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY)
-  get_property(llvm_has_exports GLOBAL PROPERTY LLVM_HAS_EXPORTS)
-  if(llvm_has_exports)
-    install(EXPORT LLVMExports DESTINATION ${LLVM_INSTALL_PACKAGE_DIR}
-            COMPONENT cmake-exports)
-  endif()
+  install_distribution_exports(LLVM)
 
   install(FILES
     ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/LLVMConfig.cmake
Index: llvm/cmake/modules/AddLLVM.cmake
===================================================================
--- llvm/cmake/modules/AddLLVM.cmake
+++ llvm/cmake/modules/AddLLVM.cmake
@@ -1,3 +1,4 @@
+include(LLVMDistributionSupport)
 include(LLVMProcessSources)
 include(LLVM-Config)
 include(DetermineGCCCompatible)
@@ -791,15 +792,13 @@
     set_property(GLOBAL APPEND PROPERTY LLVM_EXPORTS_BUILDTREE_ONLY ${name})
   else()
     if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY OR ARG_INSTALL_WITH_TOOLCHAIN)
-
-      set(export_to_llvmexports)
-      if(${name} IN_LIST LLVM_DISTRIBUTION_COMPONENTS OR
-          (in_llvm_libs AND "llvm-libraries" IN_LIST LLVM_DISTRIBUTION_COMPONENTS) OR
-          NOT LLVM_DISTRIBUTION_COMPONENTS)
-        set(export_to_llvmexports EXPORT LLVMExports)
-        set_property(GLOBAL PROPERTY LLVM_HAS_EXPORTS True)
+      if(in_llvm_libs)
+        set(umbrella UMBRELLA llvm-libraries)
+      else()
+        set(umbrella)
       endif()
 
+      get_target_export_arg(${name} LLVM export_to_llvmexports ${umbrella})
       install(TARGETS ${name}
               ${export_to_llvmexports}
               LIBRARY DESTINATION lib${LLVM_LIBDIR_SUFFIX} COMPONENT ${name}
@@ -1208,13 +1207,7 @@
 
   if ( ${name} IN_LIST LLVM_TOOLCHAIN_TOOLS OR NOT LLVM_INSTALL_TOOLCHAIN_ONLY)
     if( LLVM_BUILD_TOOLS )
-      set(export_to_llvmexports)
-      if(${name} IN_LIST LLVM_DISTRIBUTION_COMPONENTS OR
-          NOT LLVM_DISTRIBUTION_COMPONENTS)
-        set(export_to_llvmexports EXPORT LLVMExports)
-        set_property(GLOBAL PROPERTY LLVM_HAS_EXPORTS True)
-      endif()
-
+      get_target_export_arg(${name} LLVM export_to_llvmexports)
       install(TARGETS ${name}
               ${export_to_llvmexports}
               RUNTIME DESTINATION ${LLVM_TOOLS_INSTALL_DIR}
@@ -1267,13 +1260,7 @@
   set_target_properties(${name} PROPERTIES FOLDER "Utils")
   if ( ${name} IN_LIST LLVM_TOOLCHAIN_UTILITIES OR NOT LLVM_INSTALL_TOOLCHAIN_ONLY)
     if (LLVM_INSTALL_UTILS AND LLVM_BUILD_UTILS)
-      set(export_to_llvmexports)
-      if (${name} IN_LIST LLVM_DISTRIBUTION_COMPONENTS OR
-          NOT LLVM_DISTRIBUTION_COMPONENTS)
-        set(export_to_llvmexports EXPORT LLVMExports)
-        set_property(GLOBAL PROPERTY LLVM_HAS_EXPORTS True)
-      endif()
-
+      get_target_install_arg(${name} LLVM export_to_llvmexports)
       install(TARGETS ${name}
               ${export_to_llvmexports}
               RUNTIME DESTINATION ${LLVM_UTILS_INSTALL_DIR}
Index: lld/cmake/modules/LLDConfig.cmake.in
===================================================================
--- lld/cmake/modules/LLDConfig.cmake.in
+++ lld/cmake/modules/LLDConfig.cmake.in
@@ -10,4 +10,4 @@
 set(LLD_INCLUDE_DIRS "@LLD_CONFIG_INCLUDE_DIRS@")
 
 # Provide all our library targets to users.
-include("@LLD_CONFIG_EXPORTS_FILE@")
+@LLD_CONFIG_INCLUDE_EXPORTS@
Index: lld/cmake/modules/CMakeLists.txt
===================================================================
--- lld/cmake/modules/CMakeLists.txt
+++ lld/cmake/modules/CMakeLists.txt
@@ -14,7 +14,7 @@
 # Generate LLDConfig.cmake for the build tree.
 set(LLD_CONFIG_CMAKE_DIR "${lld_cmake_builddir}")
 set(LLD_CONFIG_LLVM_CMAKE_DIR "${llvm_cmake_builddir}")
-set(LLD_CONFIG_EXPORTS_FILE "${lld_cmake_builddir}/LLDTargets.cmake")
+set(LLD_CONFIG_INCLUDE_EXPORTS "include(\"${lld_cmake_builddir}/LLDTargets.cmake\")")
 set(LLD_CONFIG_INCLUDE_DIRS
   "${LLD_SOURCE_DIR}/include"
   "${LLD_BINARY_DIR}/include"
@@ -25,7 +25,6 @@
   @ONLY)
 set(LLD_CONFIG_CMAKE_DIR)
 set(LLD_CONFIG_LLVM_CMAKE_DIR)
-set(LLD_CONFIG_EXPORTS_FILE)
 
 # Generate LLDConfig.cmake for the install tree.
 set(LLD_CONFIG_CODE "
@@ -40,7 +39,7 @@
 endforeach(p)
 set(LLD_CONFIG_CMAKE_DIR "\${LLD_INSTALL_PREFIX}/${LLD_INSTALL_PACKAGE_DIR}")
 set(LLD_CONFIG_LLVM_CMAKE_DIR "\${LLD_INSTALL_PREFIX}/${LLVM_INSTALL_PACKAGE_DIR}")
-set(LLD_CONFIG_EXPORTS_FILE "\${LLD_CMAKE_DIR}/LLDTargets.cmake")
+get_config_exports_includes(LLD LLD_CONFIG_INCLUDE_EXPORTS)
 set(LLD_CONFIG_INCLUDE_DIRS "\${LLD_INSTALL_PREFIX}/include")
 configure_file(
   ${CMAKE_CURRENT_SOURCE_DIR}/LLDConfig.cmake.in
@@ -48,14 +47,9 @@
   @ONLY)
 set(LLD_CONFIG_CODE)
 set(LLD_CONFIG_CMAKE_DIR)
-set(LLD_CONFIG_EXPORTS_FILE)
 
 if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY)
-  get_property(lld_has_exports GLOBAL PROPERTY LLD_HAS_EXPORTS)
-  if(lld_has_exports)
-    install(EXPORT LLDTargets DESTINATION ${LLD_INSTALL_PACKAGE_DIR}
-            COMPONENT lld-cmake-exports)
-  endif()
+  install_distribution_exports(LLD)
 
   install(FILES
     ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/LLDConfig.cmake
Index: lld/cmake/modules/AddLLD.cmake
===================================================================
--- lld/cmake/modules/AddLLD.cmake
+++ lld/cmake/modules/AddLLD.cmake
@@ -1,3 +1,5 @@
+include(LLVMDistributionSupport)
+
 macro(add_lld_library name)
   cmake_parse_arguments(ARG
     "SHARED"
@@ -11,12 +13,7 @@
   set_target_properties(${name} PROPERTIES FOLDER "lld libraries")
 
   if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY)
-    if(${name} IN_LIST LLVM_DISTRIBUTION_COMPONENTS OR
-        NOT LLVM_DISTRIBUTION_COMPONENTS)
-      set(export_to_lldtargets EXPORT LLDTargets)
-      set_property(GLOBAL PROPERTY LLD_HAS_EXPORTS True)
-    endif()
-
+    get_target_export_arg(${name} LLD export_to_lldtargets)
     install(TARGETS ${name}
       COMPONENT ${name}
       ${export_to_lldtargets}
@@ -46,12 +43,7 @@
   add_lld_executable(${name} ${ARGN})
 
   if (LLD_BUILD_TOOLS)
-    if(${name} IN_LIST LLVM_DISTRIBUTION_COMPONENTS OR
-        NOT LLVM_DISTRIBUTION_COMPONENTS)
-      set(export_to_lldtargets EXPORT LLDTargets)
-      set_property(GLOBAL PROPERTY LLD_HAS_EXPORTS True)
-    endif()
-
+    get_target_export_arg(${name} LLD export_to_lldtargets)
     install(TARGETS ${name}
       ${export_to_lldtargets}
       RUNTIME DESTINATION bin
Index: flang/cmake/modules/FlangConfig.cmake.in
===================================================================
--- flang/cmake/modules/FlangConfig.cmake.in
+++ flang/cmake/modules/FlangConfig.cmake.in
@@ -10,4 +10,4 @@
 set(FLANG_INCLUDE_DIRS "@FLANG_CONFIG_INCLUDE_DIRS@")
 
 # Provide all our library targets to users.
-include("@FLANG_CONFIG_EXPORTS_FILE@")
+@FLANG_CONFIG_INCLUDE_EXPORTS@
Index: flang/cmake/modules/CMakeLists.txt
===================================================================
--- flang/cmake/modules/CMakeLists.txt
+++ flang/cmake/modules/CMakeLists.txt
@@ -14,7 +14,7 @@
 # Generate FlangConfig.cmake for the build tree.
 set(FLANG_CONFIG_CMAKE_DIR "${flang_cmake_builddir}")
 set(FLANG_CONFIG_LLVM_CMAKE_DIR "${llvm_cmake_builddir}")
-set(FLANG_CONFIG_EXPORTS_FILE "${flang_cmake_builddir}/FlangTargets.cmake")
+set(FLANG_CONFIG_INCLUDE_EXPORTS "include(\"${flang_cmake_builddir}/FlangTargets.cmake\")")
 set(FLANG_CONFIG_INCLUDE_DIRS
   "${FLANG_SOURCE_DIR}/include"
   "${FLANG_BINARY_DIR}/include"
@@ -25,7 +25,6 @@
   @ONLY)
 set(FLANG_CONFIG_CMAKE_DIR)
 set(FLANG_CONFIG_LLVM_CMAKE_DIR)
-set(FLANG_CONFIG_EXPORTS_FILE)
 
 # Generate FlangConfig.cmake for the install tree.
 set(FLANG_CONFIG_CODE "
@@ -41,7 +40,7 @@
 
 set(FLANG_CONFIG_CMAKE_DIR "\${FLANG_INSTALL_PREFIX}/${FLANG_INSTALL_PACKAGE_DIR}")
 set(FLANG_CONFIG_LLVM_CMAKE_DIR "\${FLANG_INSTALL_PREFIX}/${LLVM_INSTALL_PACKAGE_DIR}")
-set(FLANG_CONFIG_EXPORTS_FILE "\${FLANG_CMAKE_DIR}/FlangTargets.cmake")
+get_config_exports_includes(Flang FLANG_CONFIG_INCLUDE_EXPORTS)
 set(FLANG_CONFIG_INCLUDE_DIRS "\${FLANG_INSTALL_PREFIX}/include")
 
 configure_file(
@@ -54,11 +53,7 @@
 set(FLANG_CONFIG_EXPORTS_FILE)
 
 if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY)
-  get_property(flang_has_exports GLOBAL PROPERTY FLANG_HAS_EXPORTS)
-  if(flang_has_exports)
-    install(EXPORT FlangTargets DESTINATION ${FLANG_INSTALL_PACKAGE_DIR}
-            COMPONENT flang-cmake-exports)
-  endif()
+  install_distribution_exports(Flang)
 
   install(FILES
     ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/FlangConfig.cmake
Index: flang/cmake/modules/AddFlang.cmake
===================================================================
--- flang/cmake/modules/AddFlang.cmake
+++ flang/cmake/modules/AddFlang.cmake
@@ -1,3 +1,5 @@
+include(LLVMDistributionSupport)
+
 macro(set_flang_windows_version_resource_properties name)
   if (DEFINED windows_resource_file)
     set_windows_version_resource_properties(${name} ${windows_resource_file}
@@ -63,14 +65,7 @@
   if (TARGET ${name})
 
     if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY OR ${name} STREQUAL "libflang")
-      set(export_to_flangtargets)
-      if (${name} IN_LIST LLVM_DISTRIBUTION_COMPONENTS OR
-          "flang-libraries" IN_LIST LLVM_DISTRIBUTION_COMPONENTS OR
-          NOT LLVM_DISTRIBUTION_COMPONENTS)
-        set(export_to_flangtargets EXPORT FlangTargets)
-        set_property(GLOBAL PROPERTY FLANG_HAS_EXPORTS True)
-      endif()
-
+      get_target_export_arg(${name} Flang export_to_flangtargets UMBRELLA flang-libraries)
       install(TARGETS ${name}
         COMPONENT ${name}
         ${export_to_flangtargets}
@@ -110,13 +105,7 @@
   add_flang_executable(${name} ${ARGN})
 
   if (FLANG_BUILD_TOOLS)
-    set(export_to_flangtargets)
-    if (${name} IN_LIST LLVM_DISTRIBUTION_COMPONENTS OR
-        NOT LLVM_DISTRIBUTION_COMPONENTS)
-      set(export_to_flangtargets EXPORT FlangTargets)
-      set_property(GLOBAL PROPERTY FLANG_HAS_EXPORTS True)
-    endif()
-
+    get_target_export_arg(${name} Flang export_to_flangtargets)
     install(TARGETS ${name}
       ${export_to_flangtargets}
       RUNTIME DESTINATION bin
Index: clang/cmake/modules/ClangConfig.cmake.in
===================================================================
--- clang/cmake/modules/ClangConfig.cmake.in
+++ clang/cmake/modules/ClangConfig.cmake.in
@@ -11,7 +11,7 @@
 set(CLANG_LINK_CLANG_DYLIB "@CLANG_LINK_CLANG_DYLIB@")
 
 # Provide all our library targets to users.
-include("@CLANG_CONFIG_EXPORTS_FILE@")
+@CLANG_CONFIG_INCLUDE_EXPORTS@
 
 # By creating clang-tablegen-targets here, subprojects that depend on Clang's
 # tablegen-generated headers can always depend on this target whether building
Index: clang/cmake/modules/CMakeLists.txt
===================================================================
--- clang/cmake/modules/CMakeLists.txt
+++ clang/cmake/modules/CMakeLists.txt
@@ -1,3 +1,5 @@
+include(LLVMDistributionSupport)
+
 # Generate a list of CMake library targets so that other CMake projects can
 # link against them. LLVM calls its version of this file LLVMExports.cmake, but
 # the usual CMake convention seems to be ${Project}Targets.cmake.
@@ -14,7 +16,7 @@
 # Generate ClangConfig.cmake for the build tree.
 set(CLANG_CONFIG_CMAKE_DIR "${clang_cmake_builddir}")
 set(CLANG_CONFIG_LLVM_CMAKE_DIR "${llvm_cmake_builddir}")
-set(CLANG_CONFIG_EXPORTS_FILE "${clang_cmake_builddir}/ClangTargets.cmake")
+set(CLANG_CONFIG_INCLUDE_EXPORTS "include(\"${clang_cmake_builddir}/ClangTargets.cmake\")")
 set(CLANG_CONFIG_INCLUDE_DIRS
   "${CLANG_SOURCE_DIR}/include"
   "${CLANG_BINARY_DIR}/include"
@@ -25,7 +27,6 @@
   @ONLY)
 set(CLANG_CONFIG_CMAKE_DIR)
 set(CLANG_CONFIG_LLVM_CMAKE_DIR)
-set(CLANG_CONFIG_EXPORTS_FILE)
 
 # Generate ClangConfig.cmake for the install tree.
 set(CLANG_CONFIG_CODE "
@@ -40,7 +41,7 @@
 endforeach(p)
 set(CLANG_CONFIG_CMAKE_DIR "\${CLANG_INSTALL_PREFIX}/${CLANG_INSTALL_PACKAGE_DIR}")
 set(CLANG_CONFIG_LLVM_CMAKE_DIR "\${CLANG_INSTALL_PREFIX}/${LLVM_INSTALL_PACKAGE_DIR}")
-set(CLANG_CONFIG_EXPORTS_FILE "\${CLANG_CMAKE_DIR}/ClangTargets.cmake")
+get_config_exports_includes(Clang CLANG_CONFIG_INCLUDE_EXPORTS)
 set(CLANG_CONFIG_INCLUDE_DIRS
   "\${CLANG_INSTALL_PREFIX}/include"
   )
@@ -50,14 +51,9 @@
   @ONLY)
 set(CLANG_CONFIG_CODE)
 set(CLANG_CONFIG_CMAKE_DIR)
-set(CLANG_CONFIG_EXPORTS_FILE)
 
 if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY)
-  get_property(clang_has_exports GLOBAL PROPERTY CLANG_HAS_EXPORTS)
-  if(clang_has_exports)
-    install(EXPORT ClangTargets DESTINATION ${CLANG_INSTALL_PACKAGE_DIR}
-            COMPONENT clang-cmake-exports)
-  endif()
+  install_distribution_exports(Clang)
 
   install(FILES
     ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/ClangConfig.cmake
Index: clang/cmake/modules/AddClang.cmake
===================================================================
--- clang/cmake/modules/AddClang.cmake
+++ clang/cmake/modules/AddClang.cmake
@@ -1,3 +1,5 @@
+include(LLVMDistributionSupport)
+
 function(clang_tablegen)
   # Syntax:
   # clang_tablegen output-file [tablegen-arg ...] SOURCE source-file
@@ -112,14 +114,7 @@
       target_link_libraries(${lib} INTERFACE ${LLVM_COMMON_LIBS})
 
       if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY OR ARG_INSTALL_WITH_TOOLCHAIN)
-        set(export_to_clangtargets)
-        if(${lib} IN_LIST LLVM_DISTRIBUTION_COMPONENTS OR
-            "clang-libraries" IN_LIST LLVM_DISTRIBUTION_COMPONENTS OR
-            NOT LLVM_DISTRIBUTION_COMPONENTS)
-          set(export_to_clangtargets EXPORT ClangTargets)
-          set_property(GLOBAL PROPERTY CLANG_HAS_EXPORTS True)
-        endif()
-
+        get_target_export_arg(${name} Clang export_to_clangtargets UMBRELLA clang-libraries)
         install(TARGETS ${lib}
           COMPONENT ${lib}
           ${export_to_clangtargets}
@@ -161,13 +156,7 @@
   add_dependencies(${name} clang-resource-headers)
 
   if (CLANG_BUILD_TOOLS)
-    set(export_to_clangtargets)
-    if(${name} IN_LIST LLVM_DISTRIBUTION_COMPONENTS OR
-        NOT LLVM_DISTRIBUTION_COMPONENTS)
-      set(export_to_clangtargets EXPORT ClangTargets)
-      set_property(GLOBAL PROPERTY CLANG_HAS_EXPORTS True)
-    endif()
-
+    get_target_export_arg(${name} Clang export_to_clangtargets)
     install(TARGETS ${name}
       ${export_to_clangtargets}
       RUNTIME DESTINATION bin
Index: clang/cmake/caches/MultiDistributionExample.cmake
===================================================================
--- /dev/null
+++ clang/cmake/caches/MultiDistributionExample.cmake
@@ -0,0 +1,74 @@
+# This file sets up a CMakeCache for a simple build with multiple distributions.
+# Note that for a real distribution, you likely want to perform a boostrap
+# build; see clang/cmake/caches/DistributionExample.cmake and the
+# BuildingADistribution documentation for details. This cache file doesn't
+# demonstrate bootstrapping so it can focus on the configuration details
+# specific to multiple distributions instead.
+
+# Build an optimized toolchain for an example set of targets.
+set(CMAKE_BUILD_TYPE Release CACHE STRING "")
+set(LLVM_TARGETS_TO_BUILD
+      AArch64
+      ARM
+      X86
+    CACHE STRING "")
+
+# Enable the LLVM projects and runtimes.
+set(LLVM_ENABLE_PROJECTS
+      clang
+      lld
+    CACHE STRING "")
+set(LLVM_ENABLE_RUNTIMES
+      compiler-rt
+      libcxx
+      libcxxabi
+    CACHE STRING "")
+
+# We'll build two distributions: Toolchain, which just holds the tools
+# (intended for most end users), and Development, which has libraries (for end
+# users who wish to develop their own tooling using those libraries). This will
+# produce the install-toolchain-distribution and install-development-distribution
+# targets to install the distributions.
+set(LLVM_DISTRIBUTIONS
+      Toolchain
+      Development
+    CACHE STRING "")
+
+# We want to include the C++ headers in our distribution.
+set(LLVM_RUNTIME_DISTRIBUTION_COMPONENTS
+      cxx-headers
+    CACHE STRING "")
+
+# You likely want more tools; this is just an example :) Note that we need to
+# include cxx-headers explicitly here (in addition to it being added to
+# LLVM_RUNTIME_DISTRIBUTION_COMPONENTS above).
+set(LLVM_Toolchain_DISTRIBUTION_COMPONENTS
+      builtins
+      clang
+      clang-resource-headers
+      cxx-headers
+      lld
+      llvm-objdump
+    CACHE STRING "")
+
+# Note that we need to include the CMake exports targets for the distribution
+# (development-cmake-exports and clang-development-cmake-exports), as well as
+# the general CMake exports target for each project (cmake-exports and
+# clang-cmake-exports), in our list of targets. The distribution CMake exports
+# targets just install the CMake exports file for the distribution's targets,
+# whereas the project CMake exports targets install the rest of the project's
+# CMake exports (which are needed in order to import the project from other
+# CMake_projects via find_package, and include the distribution's CMake exports
+# file to get the exported targets).
+set(LLVM_Development_DISTRIBUTION_COMPONENTS
+      # LLVM
+      cmake-exports
+      development-cmake-exports
+      llvm-headers
+      llvm-libraries
+      # Clang
+      clang-cmake-exports
+      clang-development-cmake-exports
+      clang-headers
+      clang-libraries
+    CACHE STRING "")
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to