--- /dev/null
+# 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 "")
+include(LLVMDistributionSupport)
+
function(clang_tablegen)
# Syntax:
# clang_tablegen output-file [tablegen-arg ...] SOURCE source-file
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}
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
+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.
# 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"
@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 "
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"
)
@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
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
+include(LLVMDistributionSupport)
+
macro(set_flang_windows_version_resource_properties name)
if (DEFINED windows_resource_file)
set_windows_version_resource_properties(${name} ${windows_resource_file}
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}
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
# 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"
@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 "
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(
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
set(FLANG_INCLUDE_DIRS "@FLANG_CONFIG_INCLUDE_DIRS@")
# Provide all our library targets to users.
-include("@FLANG_CONFIG_EXPORTS_FILE@")
+@FLANG_CONFIG_INCLUDE_EXPORTS@
+include(LLVMDistributionSupport)
+
macro(add_lld_library name)
cmake_parse_arguments(ARG
"SHARED"
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}
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
# 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"
@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 "
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
@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
set(LLD_INCLUDE_DIRS "@LLD_CONFIG_INCLUDE_DIRS@")
# Provide all our library targets to users.
-include("@LLD_CONFIG_EXPORTS_FILE@")
+@LLD_CONFIG_INCLUDE_EXPORTS@
+include(LLVMDistributionSupport)
include(LLVMProcessSources)
include(LLVM-Config)
include(DetermineGCCCompatible)
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}
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}
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}
+include(LLVMDistributionSupport)
+
set(LLVM_INSTALL_PACKAGE_DIR lib${LLVM_LIBDIR_SUFFIX}/cmake/llvm)
set(llvm_cmake_builddir "${LLVM_BINARY_DIR}/${LLVM_INSTALL_PACKAGE_DIR}")
# 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(
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
@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
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()
+# 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()
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
--------------------------------------------
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
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
-------------------
+include(LLVMDistributionSupport)
+
function(mlir_tablegen ofn)
tablegen(MLIR ${ARGV})
set(TABLEGEN_OUTPUT ${TABLEGEN_OUTPUT} ${CMAKE_CURRENT_BINARY_DIR}/${ofn}
# 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}
+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.
# 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"
@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)
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"
)
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
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