Index: llvm/CMakeLists.txt =================================================================== --- llvm/CMakeLists.txt +++ llvm/CMakeLists.txt @@ -931,6 +931,8 @@ include(AddLLVM) include(TableGen) +include(LLVMDistributionSupport) + if( MINGW AND NOT "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" ) # People report that -O3 is unreliable on MinGW. The traditional # build also uses -O2 for that reason: @@ -1119,7 +1121,6 @@ # This must be at the end of the LLVM root CMakeLists file because it must run # after all targets are created. -include(LLVMDistributionSupport) llvm_distribution_add_targets() process_llvm_pass_plugins(GEN_CONFIG) Index: llvm/cmake/modules/AddLLVM.cmake =================================================================== --- llvm/cmake/modules/AddLLVM.cmake +++ llvm/cmake/modules/AddLLVM.cmake @@ -218,13 +218,30 @@ endif() function(add_link_opts target_name) + get_llvm_distribution(${target_name} in_distribution in_distribution_var) + if(NOT in_distribution) + # Don't LTO optimize targets that aren't part of any distribution. + if (LLVM_ENABLE_LTO) + # We may consider avoiding LTO altogether by using -fembed-bitcode + # and teaching the linker to select machine code from .o files, see + # https://lists.llvm.org/pipermail/llvm-dev/2021-April/149843.html + if((UNIX OR MINGW) AND LLVM_USE_LINKER STREQUAL "lld") + set_property(TARGET ${target_name} APPEND_STRING PROPERTY + LINK_FLAGS " -Wl,--lto-O0") + elseif(LINKER_IS_LLD_LINK) + set_property(TARGET ${target_name} APPEND_STRING PROPERTY + LINK_FLAGS " /opt:lldlto=0") + endif() + endif() + endif() + # Don't use linker optimizations in debug builds since it slows down the # linker in a context where the optimizations are not important. if (NOT uppercase_CMAKE_BUILD_TYPE STREQUAL "DEBUG") # Pass -O3 to the linker. This enabled different optimizations on different # linkers. - if(NOT (CMAKE_SYSTEM_NAME MATCHES "Darwin|SunOS|AIX|OS390" OR WIN32)) + if(NOT (CMAKE_SYSTEM_NAME MATCHES "Darwin|SunOS|AIX|OS390" OR WIN32) AND in_distribution) set_property(TARGET ${target_name} APPEND_STRING PROPERTY LINK_FLAGS " -Wl,-O3") endif() Index: llvm/cmake/modules/LLVMDistributionSupport.cmake =================================================================== --- llvm/cmake/modules/LLVMDistributionSupport.cmake +++ llvm/cmake/modules/LLVMDistributionSupport.cmake @@ -56,6 +56,49 @@ # only defines other functions (i.e. it doesn't execute any more code directly). llvm_distribution_build_target_map() +# Look up the distribution a particular target belongs to. By convention, the +# project calling this should set the ${PROJECT}${distribution}_HAS_EXPORTS +# global property to true if the target is in ${distribution} (${PROJECT} is the +# project name in uppercase). +# - target: The target to look up. +# - in_distribution_var: The variable with this name is set in the caller's +# scope to indicate if the target is in any distribution. If no distributions +# have been configured, this will always be set to true. +# - distribution_var: The variable with this name is set in the caller's scope +# to indicate the distribution name for the target. If the target belongs to +# the default (unnamed) distribution, or if no distributions have been +# configured, it's set to the empty string. +# - 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_llvm_distribution target in_distribution_var distribution_var) + if(NOT LLVM_DISTRIBUTION_COMPONENTS AND NOT LLVM_DISTRIBUTIONS) + set(${in_distribution_var} YES PARENT_SCOPE) + set(${distribution_var} "" PARENT_SCOPE) + 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) + set(${in_distribution_var} YES PARENT_SCOPE) + if(distribution STREQUAL "") + set(distribution "") + endif() + set(${distribution_var} "${distribution}" PARENT_SCOPE) + else() + set(${in_distribution_var} NO PARENT_SCOPE) + endif() +endfunction() + # 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 @@ -79,29 +122,11 @@ 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() + get_llvm_distribution(${target} in_distribution distribution ${ARGN}) - 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 "") - 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) + if(in_distribution) + set(${export_arg_var} EXPORT ${project}${distribution}${suffix} PARENT_SCOPE) + if(distribution) string(TOUPPER "${distribution}" distribution_upper) set_property(GLOBAL PROPERTY ${project_upper}_${distribution_upper}_HAS_EXPORTS True) endif()