brintos

brintos / llvm-project-archived public Read only

0
0
Text · 13.5 KiB · 03c6773 Raw
302 lines · plain
1# Utility functions for packaging an LLVM distribution. See the2# BuildingADistribution documentation for more details.3 4# These functions assume a number of conventions that are common across all LLVM5# subprojects:6# - The generated CMake exports file for ${project} is called ${project}Targets7#   (except for LLVM where it's called ${project}Exports for legacy reasons).8# - The build target for the CMake exports is called ${project}-cmake-exports9#   (except LLVM where it's just cmake-exports).10# - The ${PROJECT}${distribution}_HAS_EXPORTS global property holds whether a11#   project has any exports for a particular ${distribution} (where ${PROJECT}12#   is the project name in uppercase).13# - The ${PROJECT}_CMAKE_DIR variable is computed by ${project}Config.cmake to14#   hold the path of the installed CMake modules directory.15# - The ${PROJECT}_INSTALL_PACKAGE_DIR variable contains the install destination16#   for the project's CMake modules.17 18include_guard(GLOBAL)19 20if(LLVM_DISTRIBUTION_COMPONENTS AND LLVM_DISTRIBUTIONS)21  message(FATAL_ERROR "LLVM_DISTRIBUTION_COMPONENTS and LLVM_DISTRIBUTIONS cannot be specified together")22endif()23 24if(LLVM_DISTRIBUTION_COMPONENTS OR LLVM_DISTRIBUTIONS)25  if(LLVM_ENABLE_IDE)26    message(FATAL_ERROR "LLVM_DISTRIBUTION_COMPONENTS cannot be specified with multi-configuration generators (i.e. Xcode or Visual Studio)")27  endif()28endif()29 30# Build the map of targets to distributions that's used to look up the31# distribution for a target later. The distribution for ${target} is stored in32# the global property LLVM_DISTRIBUTION_FOR_${target}.33function(llvm_distribution_build_target_map)34  foreach(target ${LLVM_DISTRIBUTION_COMPONENTS})35    # CMake doesn't easily distinguish between properties that are unset and36    # properties that are empty (you have to do a second get_property call with37    # the SET option, which is unergonomic), so just use a special marker to38    # denote the default (unnamed) distribution.39    set_property(GLOBAL PROPERTY LLVM_DISTRIBUTION_FOR_${target} "<DEFAULT>")40  endforeach()41 42  foreach(distribution ${LLVM_DISTRIBUTIONS})43    foreach(target ${LLVM_${distribution}_DISTRIBUTION_COMPONENTS})44      # By default, we allow a target to be in multiple distributions, and use45      # the last one to determine its export set. We disallow this in strict46      # mode, emitting a single error at the end for readability.47      if(LLVM_STRICT_DISTRIBUTIONS)48        get_property(current_distribution GLOBAL PROPERTY LLVM_DISTRIBUTION_FOR_${target})49        if(current_distribution AND NOT current_distribution STREQUAL distribution)50          set_property(GLOBAL APPEND_STRING PROPERTY LLVM_DISTRIBUTION_ERRORS51            "Target ${target} cannot be in multiple distributions \52             ${distribution} and ${current_distribution}\n"53            )54        endif()55      endif()56      set_property(GLOBAL PROPERTY LLVM_DISTRIBUTION_FOR_${target} ${distribution})57    endforeach()58  endforeach()59endfunction()60 61# The include guard ensures this will only be called once. The rest of this file62# only defines other functions (i.e. it doesn't execute any more code directly).63llvm_distribution_build_target_map()64 65# Look up the distribution a particular target belongs to.66# - target: The target to look up.67# - in_distribution_var: The variable with this name is set in the caller's68#   scope to indicate if the target is in any distribution. If no distributions69#   have been configured, this will always be set to true.70# - distribution_var: The variable with this name is set in the caller's scope71#   to indicate the distribution name for the target. If the target belongs to72#   the default (unnamed) distribution, or if no distributions have been73#   configured, it's set to the empty string.74# - UMBRELLA: The (optional) umbrella target that the target is a part of. For75#   example, all LLVM libraries have the umbrella target llvm-libraries.76function(get_llvm_distribution target in_distribution_var distribution_var)77  if(NOT LLVM_DISTRIBUTION_COMPONENTS AND NOT LLVM_DISTRIBUTIONS)78    set(${in_distribution_var} YES PARENT_SCOPE)79    set(${distribution_var} "" PARENT_SCOPE)80    return()81  endif()82 83  cmake_parse_arguments(ARG "" UMBRELLA "" ${ARGN})84  get_property(distribution GLOBAL PROPERTY LLVM_DISTRIBUTION_FOR_${target})85  if(ARG_UMBRELLA)86    get_property(umbrella_distribution GLOBAL PROPERTY LLVM_DISTRIBUTION_FOR_${ARG_UMBRELLA})87    if(LLVM_STRICT_DISTRIBUTIONS AND distribution AND umbrella_distribution AND88        NOT distribution STREQUAL umbrella_distribution)89      set_property(GLOBAL APPEND_STRING PROPERTY LLVM_DISTRIBUTION_ERRORS90        "Target ${target} has different distribution ${distribution} from its \91         umbrella target's (${ARG_UMBRELLA}) distribution ${umbrella_distribution}\n"92        )93    endif()94    if(NOT distribution)95      set(distribution ${umbrella_distribution})96    endif()97  endif()98 99  if(distribution)100    set(${in_distribution_var} YES PARENT_SCOPE)101    if(distribution STREQUAL "<DEFAULT>")102      set(distribution "")103    endif()104    set(${distribution_var} "${distribution}" PARENT_SCOPE)105  else()106    set(${in_distribution_var} NO PARENT_SCOPE)107  endif()108endfunction()109 110# Get the EXPORT argument to use for an install command for a target in a111# project. As explained at the top of the file, the project export set for a112# distribution is named ${project}{distribution}Targets (except for LLVM where113# it's named ${project}{distribution}Exports for legacy reasons). Also set the114# ${PROJECT}_${DISTRIBUTION}_HAS_EXPORTS global property to mark the project as115# having exports for the distribution.116# - target: The target to get the EXPORT argument for.117# - project: The project to produce the argument for. IMPORTANT: The casing of118#   this argument should match the casing used by the project's Config.cmake119#   file. The correct casing for the LLVM projects is Clang, Flang, LLD, LLVM,120#   and MLIR.121# - export_arg_var The variable with this name is set in the caller's scope to122#   the EXPORT argument for the target for the project.123# - UMBRELLA: The (optional) umbrella target that the target is a part of. For124#   example, all LLVM libraries have the umbrella target llvm-libraries.125function(get_target_export_arg target project export_arg_var)126  string(TOUPPER "${project}" project_upper)127  if(project STREQUAL "LLVM")128    set(suffix "Exports") # legacy129  else()130    set(suffix "Targets")131  endif()132 133  get_llvm_distribution(${target} in_distribution distribution ${ARGN})134 135  if(in_distribution)136    set(${export_arg_var} EXPORT ${project}${distribution}${suffix} PARENT_SCOPE)137    if(distribution)138      string(TOUPPER "${distribution}" distribution_upper)139      set_property(GLOBAL PROPERTY ${project_upper}_${distribution_upper}_HAS_EXPORTS True)140    else()141      set_property(GLOBAL PROPERTY ${project_upper}_HAS_EXPORTS True)142    endif()143  else()144    set(${export_arg_var} "" PARENT_SCOPE)145  endif()146endfunction()147 148# Produce a string of CMake include() commands to include the exported targets149# files for all distributions. See the comment at the top of this file for150# various assumptions made.151# - project: The project to produce the commands for. IMPORTANT: See the comment152#   for get_target_export_arg above for the correct casing of this argument.153# - includes_var: The variable with this name is set in the caller's scope to154#   the string of include commands.155function(get_config_exports_includes project includes_var)156  string(TOUPPER "${project}" project_upper)157  set(prefix "\${${project_upper}_CMAKE_DIR}/${project}")158  if(project STREQUAL "LLVM")159    set(suffix "Exports.cmake") # legacy160  else()161    set(suffix "Targets.cmake")162  endif()163 164  if(NOT LLVM_DISTRIBUTIONS)165    set(${includes_var} "include(\"${prefix}${suffix}\")" PARENT_SCOPE)166  else()167    set(includes)168    foreach(distribution ${LLVM_DISTRIBUTIONS})169      list(APPEND includes "include(\"${prefix}${distribution}${suffix}\" OPTIONAL)")170    endforeach()171    string(REPLACE ";" "\n" includes "${includes}")172    set(${includes_var} "${includes}" PARENT_SCOPE)173  endif()174endfunction()175 176# Create the install commands and targets for the distributions' CMake exports.177# The target to install ${distribution} for a project is called178# ${project}-${distribution}-cmake-exports, where ${project} is the project name179# in lowercase and ${distribution} is the distribution name in lowercase, except180# for LLVM, where the target is just called ${distribution}-cmake-exports. See181# the comment at the top of this file for various assumptions made.182# - project: The project. IMPORTANT: See the comment for get_target_export_arg183#   above for the correct casing of this argument.184function(install_distribution_exports project)185  string(TOUPPER "${project}" project_upper)186  string(TOLOWER "${project}" project_lower)187  if(project STREQUAL "LLVM")188    set(prefix "")189    set(suffix "Exports") # legacy190  else()191    set(prefix "${project_lower}-")192    set(suffix "Targets")193  endif()194  set(destination "${${project_upper}_INSTALL_PACKAGE_DIR}")195 196  if(NOT LLVM_DISTRIBUTIONS)197    get_property(has_exports GLOBAL PROPERTY ${project_upper}_HAS_EXPORTS)198    if(has_exports)199      install(EXPORT ${project}${suffix} DESTINATION "${destination}"200              COMPONENT ${prefix}cmake-exports)201    endif()202  else()203    foreach(distribution ${LLVM_DISTRIBUTIONS})204      string(TOUPPER "${distribution}" distribution_upper)205      get_property(has_exports GLOBAL PROPERTY ${project_upper}_${distribution_upper}_HAS_EXPORTS)206      if(has_exports)207        string(TOLOWER "${distribution}" distribution_lower)208        set(target ${prefix}${distribution_lower}-cmake-exports)209        install(EXPORT ${project}${distribution}${suffix} DESTINATION "${destination}"210                COMPONENT ${target})211        if(NOT LLVM_ENABLE_IDE)212          add_custom_target(${target})213          get_subproject_title(subproject_title)214          set_target_properties(${target} PROPERTIES FOLDER "${subproject_title}/Distribution")215          add_llvm_install_targets(install-${target} COMPONENT ${target})216        endif()217      endif()218    endforeach()219  endif()220endfunction()221 222# Create the targets for installing the configured distributions. The223# ${distribution} target builds the distribution, install-${distribution}224# installs it, and install-${distribution}-stripped installs a stripped version,225# where ${distribution} is the distribution name in lowercase, or "distribution"226# for the default distribution.227function(llvm_distribution_add_targets)228  # This function is called towards the end of LLVM's CMakeLists.txt, so all229  # errors will have been seen by now.230  if(LLVM_STRICT_DISTRIBUTIONS)231    get_property(errors GLOBAL PROPERTY LLVM_DISTRIBUTION_ERRORS)232    if(errors)233      string(PREPEND errors234        "Strict distribution errors (turn off LLVM_STRICT_DISTRIBUTIONS to bypass):\n"235        )236      message(FATAL_ERROR "${errors}")237    endif()238  endif()239 240  set(distributions "${LLVM_DISTRIBUTIONS}")241  if(NOT distributions)242    # CMake seemingly doesn't distinguish between an empty list and a list243    # containing one element which is the empty string, so just use a special244    # marker to denote the default (unnamed) distribution and fix it in the245    # loop.246    set(distributions "<DEFAULT>")247  endif()248 249  get_property(LLVM_DRIVER_TOOL_SYMLINKS GLOBAL PROPERTY LLVM_DRIVER_TOOL_SYMLINKS)250 251  foreach(distribution ${distributions})252    if(distribution STREQUAL "<DEFAULT>")253      set(distribution_target distribution)254      # Preserve legacy behavior for LLVM_DISTRIBUTION_COMPONENTS.255      set(distribution_components ${LLVM_DISTRIBUTION_COMPONENTS} ${LLVM_RUNTIME_DISTRIBUTION_COMPONENTS})256    else()257      string(TOLOWER "${distribution}" distribution_lower)258      set(distribution_target ${distribution_lower}-distribution)259      set(distribution_components ${LLVM_${distribution}_DISTRIBUTION_COMPONENTS})260    endif()261 262    add_custom_target(${distribution_target})263    add_custom_target(install-${distribution_target})264    add_custom_target(install-${distribution_target}-stripped)265    get_subproject_title(subproject_title)266    set_target_properties(267        ${distribution_target} 268        install-${distribution_target}269        install-${distribution_target}-stripped270      PROPERTIES 271        FOLDER "${subproject_title}/Distribution"272    )273 274    foreach(target ${distribution_components})275      # Note that some distribution components may not have an actual target, but only an install-FOO target.276      # This happens for example if a target is an INTERFACE target.277      if(TARGET ${target})278        add_dependencies(${distribution_target} ${target})279      endif()280 281      if(TARGET install-${target})282        add_dependencies(install-${distribution_target} install-${target})283      elseif(TARGET install-llvm-driver AND ${target} IN_LIST LLVM_DRIVER_TOOL_SYMLINKS)284        add_dependencies(install-${distribution_target} install-llvm-driver)285      else()286        message(SEND_ERROR "Specified distribution component '${target}' doesn't have an install target")287      endif()288 289      if(TARGET install-${target}-stripped)290        add_dependencies(install-${distribution_target}-stripped install-${target}-stripped)291      elseif(TARGET install-llvm-driver-stripped AND ${target} IN_LIST LLVM_DRIVER_TOOL_SYMLINKS)292        add_dependencies(install-${distribution_target}-stripped install-llvm-driver-stripped)293      else()294        message(SEND_ERROR295                "Specified distribution component '${target}' doesn't have an install-stripped target."296                " Its installation target creation should be changed to use add_llvm_install_targets,"297                " or you should manually create the 'install-${target}-stripped' target.")298      endif()299    endforeach()300  endforeach()301endfunction()302