[cmake] Add support for multiple distributions

LLVM's build system contains support for configuring a distribution, but
it can often be useful to be able to configure multiple distributions
(e.g. if you want separate distributions for the tools and the
libraries). Add this support to the build system, along with
documentation and usage examples.

Reviewed By: phosek

Differential Revision: https://reviews.llvm.org/D89177
This commit is contained in:
Shoaib Meenai 2020-10-01 14:35:28 -07:00
parent 7b57517507
commit 56f7e5a822
19 changed files with 395 additions and 146 deletions

View File

@ -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 "")

View File

@ -1,3 +1,5 @@
include(LLVMDistributionSupport)
function(clang_tablegen)
# Syntax:
# clang_tablegen output-file [tablegen-arg ...] SOURCE source-file
@ -112,14 +114,7 @@ macro(add_clang_library name)
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 @@ macro(add_clang_tool name)
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

View File

@ -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 @@ export(TARGETS ${CLANG_EXPORTS} FILE ${clang_cmake_builddir}/ClangTargets.cmake)
# 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 @@ configure_file(
@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 @@ get_filename_component(CLANG_INSTALL_PREFIX \"\${CLANG_INSTALL_PREFIX}\" PATH)")
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 @@ configure_file(
@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

View File

@ -11,7 +11,7 @@ set(CLANG_INCLUDE_DIRS "@CLANG_CONFIG_INCLUDE_DIRS@")
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

View File

@ -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 @@ macro(add_flang_library name)
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 @@ macro(add_flang_tool name)
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

View File

@ -14,7 +14,7 @@ export(TARGETS ${FLANG_EXPORTS} FILE ${flang_cmake_builddir}/FlangTargets.cmake)
# 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 @@ configure_file(
@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 @@ endforeach(p)
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_CMAKE_DIR)
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

View File

@ -10,4 +10,4 @@ set(FLANG_CMAKE_DIR "@FLANG_CONFIG_CMAKE_DIR@")
set(FLANG_INCLUDE_DIRS "@FLANG_CONFIG_INCLUDE_DIRS@")
# Provide all our library targets to users.
include("@FLANG_CONFIG_EXPORTS_FILE@")
@FLANG_CONFIG_INCLUDE_EXPORTS@

View File

@ -1,3 +1,5 @@
include(LLVMDistributionSupport)
macro(add_lld_library name)
cmake_parse_arguments(ARG
"SHARED"
@ -11,12 +13,7 @@ macro(add_lld_library name)
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 @@ macro(add_lld_tool name)
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

View File

@ -14,7 +14,7 @@ export(TARGETS ${LLD_EXPORTS} FILE ${lld_cmake_builddir}/LLDTargets.cmake)
# 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 @@ configure_file(
@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 @@ get_filename_component(LLD_INSTALL_PREFIX \"\${LLD_INSTALL_PREFIX}\" PATH)")
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 @@ configure_file(
@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

View File

@ -10,4 +10,4 @@ set(LLD_CMAKE_DIR "@LLD_CONFIG_CMAKE_DIR@")
set(LLD_INCLUDE_DIRS "@LLD_CONFIG_INCLUDE_DIRS@")
# Provide all our library targets to users.
include("@LLD_CONFIG_EXPORTS_FILE@")
@LLD_CONFIG_INCLUDE_EXPORTS@

View File

@ -1,3 +1,4 @@
include(LLVMDistributionSupport)
include(LLVMProcessSources)
include(LLVM-Config)
include(DetermineGCCCompatible)
@ -791,15 +792,13 @@ macro(add_llvm_library name)
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 @@ macro(add_llvm_tool name)
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 @@ macro(add_llvm_utility name)
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}

View File

@ -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 @@ endif()
# 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 @@ if (LLVM_INSTALL_UTILS AND LLVM_BUILD_UTILS)
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 @@ configure_file(
@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

View File

@ -112,8 +112,7 @@ set(LLVM_DEFAULT_EXTERNAL_LIT "@LLVM_CONFIG_DEFAULT_EXTERNAL_LIT@")
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()

View File

@ -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)
# 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(target ${LLVM_DISTRIBUTION_COMPONENTS}
${LLVM_RUNTIME_DISTRIBUTION_COMPONENTS})
if(TARGET ${target})
add_dependencies(distribution ${target})
else()
message(SEND_ERROR "Specified distribution component '${target}' doesn't have a target")
endif()
if(TARGET install-${target})
add_dependencies(install-distribution 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-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()
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()
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()
# 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()
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()
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()

View File

@ -87,6 +87,40 @@ generates a ``distribution`` target which builds all the components specified in
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 @@ that are already documented include: *LLVM_TARGETS_TO_BUILD*,
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

View File

@ -64,6 +64,10 @@ Changes to the LLVM IR
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
-------------------

View File

@ -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 @@ endfunction(add_mlir_library)
# 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}

View File

@ -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 @@ get_property(MLIR_TRANSLATION_LIBS GLOBAL PROPERTY MLIR_TRANSLATION_LIBS)
# 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 @@ configure_file(
@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 @@ get_filename_component(MLIR_INSTALL_PREFIX \"\${MLIR_INSTALL_PREFIX}\" PATH)")
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 @@ configure_file(
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

View File

@ -20,7 +20,7 @@ set_property(GLOBAL PROPERTY MLIR_CONVERSION_LIBS "@MLIR_CONVERSION_LIBS@")
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