diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt --- a/llvm/CMakeLists.txt +++ b/llvm/CMakeLists.txt @@ -921,6 +921,7 @@ set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") include(AddLLVM) +include(LLVMComponents) include(TableGen) if( MINGW AND NOT "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" ) diff --git a/llvm/cmake/modules/AddLLVM.cmake b/llvm/cmake/modules/AddLLVM.cmake --- a/llvm/cmake/modules/AddLLVM.cmake +++ b/llvm/cmake/modules/AddLLVM.cmake @@ -724,13 +724,32 @@ # to link extra component into an existing group. function(add_llvm_component_group name) cmake_parse_arguments(ARG "HAS_JIT" "" "LINK_COMPONENTS" ${ARGN}) - add_custom_target(${name}) - if(ARG_HAS_JIT) - set_property(TARGET ${name} PROPERTY COMPONENT_HAS_JIT ON) - endif() - if(ARG_LINK_COMPONENTS) - set_property(TARGET ${name} PROPERTY LLVM_LINK_COMPONENTS ${ARG_LINK_COMPONENTS}) - endif() + + set(_component_name ${name}) + llvm_component_create_dummy_source(_dummy_file ${name}_Group) + + # Map legacy component libs. + llvm_map_components_to_libnames(_component_libs + ${ARG_LINK_COMPONENTS}) + + llvm_component_add_library(${name} + ${ARG_UNPARSED_ARGUMENTS} + ${_dummy_file} + PARTIAL_SOURCES_INTENDED + ADD_TO_COMPONENT ${_component_name} + LINK_LIBS ${_component_libs} + DEPENDS ${LLVM_COMMON_DEPENDS}) + + # TODO: LLVM_LIBS here is actually components. + set_property( GLOBAL APPEND PROPERTY LLVM_LIBS ${_component_name} ) + + # add_custom_target(${name}) + # if(ARG_HAS_JIT) + # set_property(TARGET ${name} PROPERTY COMPONENT_HAS_JIT ON) + # endif() + # if(ARG_LINK_COMPONENTS) + # set_property(TARGET ${name} PROPERTY LLVM_LINK_COMPONENTS ${ARG_LINK_COMPONENTS}) + # endif() endfunction() # An LLVM component is a cmake target with the following cmake properties @@ -746,20 +765,49 @@ cmake_parse_arguments(ARG "" "COMPONENT_NAME;ADD_TO_COMPONENT" - "" + "LINK_LIBS;DEPENDS;LINK_COMPONENTS" ${ARGN}) - add_llvm_library(${name} COMPONENT_LIB ${ARG_UNPARSED_ARGUMENTS}) - string(REGEX REPLACE "^LLVM" "" component_name ${name}) - set_property(TARGET ${name} PROPERTY LLVM_COMPONENT_NAME ${component_name}) - + set(_component_name) if(ARG_COMPONENT_NAME) - set_property(GLOBAL PROPERTY LLVM_COMPONENT_NAME_${ARG_COMPONENT_NAME} ${component_name}) + # TODO: Why does it need the prefix? + set(_component_name LLVM${ARG_COMPONENT_NAME}) endif() - - if(ARG_ADD_TO_COMPONENT) - set_property(TARGET ${ARG_ADD_TO_COMPONENT} APPEND PROPERTY LLVM_LINK_COMPONENTS ${component_name}) + if(NOT _component_name) + set(_component_name ${ARG_ADD_TO_COMPONENT}) + endif() + if(NOT _component_name) + # Default to the library name for the component name (i.e LLVMDemangle). + set(_component_name ${name}) endif() + # Map legacy component libs. + llvm_map_components_to_libnames(_component_libs + ${ARG_LINK_COMPONENTS} + ${LLVM_LINK_COMPONENTS} + ) + + llvm_component_add_library(${name} + ${ARG_UNPARSED_ARGUMENTS} + ADD_TO_COMPONENT ${_component_name} + DEPENDS ${ARG_DEPENDS} ${LLVM_COMMON_DEPENDS} + LINK_LIBS ${_component_libs} ${ARG_LINK_LIBS}) + + # Usually done by add_llvm_library but managed separately here. + # Needed in order to map some component name forms. + # TODO: LLVM_LIBS here is actually components. + set_property(GLOBAL APPEND PROPERTY LLVM_LIBS ${_component_name}) + + # add_llvm_library(${name} COMPONENT_LIB ${ARG_UNPARSED_ARGUMENTS}) + # string(REGEX REPLACE "^LLVM" "" component_name ${name}) + # set_property(TARGET ${name} PROPERTY LLVM_COMPONENT_NAME ${component_name}) + + # if(ARG_COMPONENT_NAME) + # set_property(GLOBAL PROPERTY LLVM_COMPONENT_NAME_${ARG_COMPONENT_NAME} ${component_name}) + # endif() + + # if(ARG_ADD_TO_COMPONENT) + # set_property(TARGET ${ARG_ADD_TO_COMPONENT} APPEND PROPERTY LLVM_LINK_COMPONENTS ${component_name}) + # endif() endfunction() macro(add_llvm_library name) @@ -899,13 +947,20 @@ add_llvm_symbol_exports( ${name} ${LLVM_EXPORTED_SYMBOL_FILE} ) endif(LLVM_EXPORTED_SYMBOL_FILE) - if (LLVM_LINK_LLVM_DYLIB AND NOT ARG_DISABLE_LLVM_LINK_LLVM_DYLIB) - set(USE_SHARED USE_SHARED) - endif() - set(EXCLUDE_FROM_ALL OFF) set_output_directory(${name} BINARY_DIR ${LLVM_RUNTIME_OUTPUT_INTDIR} LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}) - llvm_config( ${name} ${USE_SHARED} ${LLVM_LINK_COMPONENTS} ) + + # Force static linkage. + if (ARG_DISABLE_LLVM_LINK_LLVM_DYLIB) + set_property(TARGET ${name} PROPERTY LLVM_LINK_STATIC ON) + endif() + + # Link components. + llvm_map_components_to_libnames(_llvm_component_libs + ${LLVM_LINK_COMPONENTS} + ) + target_link_libraries(${name} PRIVATE ${_llvm_component_libs}) + if( LLVM_COMMON_DEPENDS ) add_dependencies( ${name} ${LLVM_COMMON_DEPENDS} ) endif( LLVM_COMMON_DEPENDS ) @@ -1452,7 +1507,9 @@ set(LLVM_REQUIRES_RTTI OFF) list(APPEND LLVM_LINK_COMPONENTS Support) # gtest needs it for raw_ostream - add_llvm_executable(${test_name} IGNORE_EXTERNALIZE_DEBUGINFO NO_INSTALL_RPATH ${ARGN}) + add_llvm_executable(${test_name} + IGNORE_EXTERNALIZE_DEBUGINFO + NO_INSTALL_RPATH ${ARGN}) set(outdir ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}) set_output_directory(${test_name} BINARY_DIR ${outdir} LIBRARY_DIR ${outdir}) # libpthreads overrides some standard library symbols, so main diff --git a/llvm/cmake/modules/LLVM-Build.cmake b/llvm/cmake/modules/LLVM-Build.cmake --- a/llvm/cmake/modules/LLVM-Build.cmake +++ b/llvm/cmake/modules/LLVM-Build.cmake @@ -75,30 +75,3 @@ endforeach() file(APPEND ${ARG_OUTPUT} "};") endfunction() - -# Resolve cross-component dependencies, for each available component. -function(LLVMBuildResolveComponentsLink) - - # the native target may not be enabled when cross compiling - if(TARGET ${LLVM_NATIVE_ARCH}) - get_property(llvm_has_jit_native TARGET ${LLVM_NATIVE_ARCH} PROPERTY LLVM_HAS_JIT) - else() - set(llvm_has_jit_native OFF) - endif() - - if(llvm_has_jit_native) - set_property(TARGET Engine APPEND PROPERTY LLVM_LINK_COMPONENTS "MCJIT" "Native") - else() - set_property(TARGET Engine APPEND PROPERTY LLVM_LINK_COMPONENTS "Interpreter") - endif() - - get_property(llvm_components GLOBAL PROPERTY LLVM_COMPONENT_LIBS) - foreach(llvm_component ${llvm_components}) - get_property(link_components TARGET ${llvm_component} PROPERTY LLVM_LINK_COMPONENTS) - llvm_map_components_to_libnames(llvm_libs ${link_components}) - if(llvm_libs) - get_property(libtype TARGET ${llvm_component} PROPERTY LLVM_LIBTYPE) - target_link_libraries(${llvm_component} ${libtype} ${llvm_libs}) - endif() - endforeach() -endfunction() diff --git a/llvm/cmake/modules/LLVM-Config.cmake b/llvm/cmake/modules/LLVM-Config.cmake --- a/llvm/cmake/modules/LLVM-Config.cmake +++ b/llvm/cmake/modules/LLVM-Config.cmake @@ -66,36 +66,6 @@ endif() endfunction() -macro(llvm_config executable) - cmake_parse_arguments(ARG "USE_SHARED" "" "" ${ARGN}) - set(link_components ${ARG_UNPARSED_ARGUMENTS}) - - if(ARG_USE_SHARED) - # If USE_SHARED is specified, then we link against libLLVM, - # but also against the component libraries below. This is - # done in case libLLVM does not contain all of the components - # the target requires. - # - # Strip LLVM_DYLIB_COMPONENTS out of link_components. - # To do this, we need special handling for "all", since that - # may imply linking to libraries that are not included in - # libLLVM. - - if (DEFINED link_components AND DEFINED LLVM_DYLIB_COMPONENTS) - if("${LLVM_DYLIB_COMPONENTS}" STREQUAL "all") - set(link_components "") - else() - list(REMOVE_ITEM link_components ${LLVM_DYLIB_COMPONENTS}) - endif() - endif() - - target_link_libraries(${executable} PRIVATE LLVM) - endif() - - explicit_llvm_config(${executable} ${link_components}) -endmacro(llvm_config) - - function(explicit_llvm_config executable) set( link_components ${ARGN} ) @@ -124,83 +94,50 @@ # handling. Also does not cover 'all' as we only have a list of the libnames # available and not a list of the components. function(llvm_expand_pseudo_components out_components) + # Targets were originally much more fine-grained and we supported linking + # at that granularity. Now these all just alias to the target library. + set(_all_targets_aliases AllTargets AllTargetsCodeGens + AllTargetsAsmParsers AllTargetsDescs AllTargetsDisassemblers + AllTargetsInfos) + set( link_components ${ARGN} ) foreach(c ${link_components}) # add codegen, asmprinter, asmparser, disassembler list(FIND LLVM_TARGETS_TO_BUILD ${c} idx) if( NOT idx LESS 0 ) if( TARGET LLVM${c}CodeGen ) + # TODO: Still needed? Remove? list(APPEND expanded_components "${c}CodeGen") else() - if( TARGET LLVM${c} ) - list(APPEND expanded_components "${c}") + if( TARGET LLVMTarget${c} ) + list(APPEND expanded_components "Target${c}") else() message(FATAL_ERROR "Target ${c} is not in the set of libraries.") endif() endif() - if( TARGET LLVM${c}AsmPrinter ) - list(APPEND expanded_components "${c}AsmPrinter") - endif() - if( TARGET LLVM${c}AsmParser ) - list(APPEND expanded_components "${c}AsmParser") - endif() - if( TARGET LLVM${c}Desc ) - list(APPEND expanded_components "${c}Desc") - endif() - if( TARGET LLVM${c}Disassembler ) - list(APPEND expanded_components "${c}Disassembler") - endif() - if( TARGET LLVM${c}Info ) - list(APPEND expanded_components "${c}Info") - endif() - if( TARGET LLVM${c}Utils ) - list(APPEND expanded_components "${c}Utils") - endif() elseif( c STREQUAL "nativecodegen" ) - if( TARGET LLVM${LLVM_NATIVE_ARCH}CodeGen ) - list(APPEND expanded_components "${LLVM_NATIVE_ARCH}CodeGen") - endif() - if( TARGET LLVM${LLVM_NATIVE_ARCH}Desc ) - list(APPEND expanded_components "${LLVM_NATIVE_ARCH}Desc") + if( TARGET LLVMTarget${LLVM_NATIVE_ARCH} ) + list(APPEND expanded_components "Target${LLVM_NATIVE_ARCH}") endif() - if( TARGET LLVM${LLVM_NATIVE_ARCH}Info ) - list(APPEND expanded_components "${LLVM_NATIVE_ARCH}Info") - endif() - elseif( c STREQUAL "AllTargetsCodeGens" ) - # Link all the codegens from all the targets - foreach(t ${LLVM_TARGETS_TO_BUILD}) - if( TARGET LLVM${t}CodeGen) - list(APPEND expanded_components "${t}CodeGen") - endif() - endforeach(t) - elseif( c STREQUAL "AllTargetsAsmParsers" ) - # Link all the asm parsers from all the targets + elseif("${c}" IN_LIST _all_targets_aliases) + # Link all target libraries. foreach(t ${LLVM_TARGETS_TO_BUILD}) - if( TARGET LLVM${t}AsmParser ) - list(APPEND expanded_components "${t}AsmParser") - endif() - endforeach(t) - elseif( c STREQUAL "AllTargetsDescs" ) - # Link all the descs from all the targets - foreach(t ${LLVM_TARGETS_TO_BUILD}) - if( TARGET LLVM${t}Desc ) - list(APPEND expanded_components "${t}Desc") - endif() - endforeach(t) - elseif( c STREQUAL "AllTargetsDisassemblers" ) - # Link all the disassemblers from all the targets - foreach(t ${LLVM_TARGETS_TO_BUILD}) - if( TARGET LLVM${t}Disassembler ) - list(APPEND expanded_components "${t}Disassembler") - endif() - endforeach(t) - elseif( c STREQUAL "AllTargetsInfos" ) - # Link all the infos from all the targets - foreach(t ${LLVM_TARGETS_TO_BUILD}) - if( TARGET LLVM${t}Info ) - list(APPEND expanded_components "${t}Info") + if( TARGET LLVMTarget${t}) + list(APPEND expanded_components "Target${t}") + else() + message(WARNING "Target library LLVMTarget${t} not found. Skipping.") endif() - endforeach(t) + endforeach() + elseif("${c}" STREQUAL "ScalarOpts") + # TODO: Many things refer to a component named "ScalarOpts", but that + # is a library of the component. Replace these occurences and remove this + # exception. + list(APPEND expanded_components "Scalar") + elseif("${c}" STREQUAL "ObjCARCOpts") + # TODO: Many things refer to a component named "ObjCARCOpts", but that + # is a library of the component. Replace these occurences and remove this + # exception. + list(APPEND expanded_components "ObjCARC") else() list(APPEND expanded_components "${c}") endif() diff --git a/llvm/cmake/modules/LLVMComponents.cmake b/llvm/cmake/modules/LLVMComponents.cmake new file mode 100644 --- /dev/null +++ b/llvm/cmake/modules/LLVMComponents.cmake @@ -0,0 +1,420 @@ +# LLVMComponents.cmake +# +# In the LLVM build system, a "component" is essentially a public library that +# can either be statically or dynamically linked. In the latter case, the +# consumer of a component will be transparently directed to the appropriate +# shared library (or DLL) that houses the component (which may, and likely +# is different from how the library is physically defined in the build +# system). +# +# Using components: +# ================= +# +# Linking to components: +# ---------------------- +# Consumers link to a component in one of two ways: +# a) By linking to the interface library named the same as the component +# name. This will automatically link in the correct static or dynamic +# way, depending on the build configuration and settings of the final +# executable or shared library. +# b) For "classic" LLVM component aliases (such as "Support", "Core", etc), +# the following mechanisms will expand component aliases and add them to +# the target_link_libraries as above: +# - By listing is in `LINK_COMPONENTS` of an llvm_add_library derived macro. +# - By setting a variable `LLVM_LINK_COMPONENTS` in the scope prior to +# calling a macro/function that creates an LLVM library or executable. +# +# Static vs dynamic linkage: +# -------------------------- +# If the global `LLVM_BUILD_SHARED_COMPONENTS` option is enabled, then shared +# libraries (or DLLs) will be created for all components that support shared +# linkage on the platform, and by default, executables will link against these +# shared libraries. +# +# Individual executables can opt in to always link statically by setting +# a target property `LLVM_LINK_STATIC` to true. Example: +# `set_target_properties(FileCheck PROPERTIES LLVM_LINK_STATIC ON)` +# +# Per-component shared-libraries vs aggregate: +# -------------------------------------------- +# By default if `LLVM_BUILD_SHARED_COMPONENTS` is enabled, every component will +# be built into its own shared library. Various other groupings are possible. +# As an example, `LLVM_BUILD_LLVM_DYLIB` will redirect many of the core LLVM +# components into a libLLVM.so file instead of breaking them into individual +# libraries. This is implemented on top of the Component Redirection feature +# (see below). +# +# "Classic" LLVM components: +# -------------------------- +# The wrappers `add_llvm_component_group` and `add_llvm_component_library` +# exist for components under `llvm/lib` defined with classic naming (i.e. +# "Core", "Support", etc). The naming is transparently mapped to underlying +# calls to `llvm_component_add_library`. +# +# Visibility: +# ----------- +# When a library is added to a shared component, it is annotated as either +# "export all symbols" or "export explicit symbols". The former is the +# traditional default when building shared libraries on Unix-like systems and +# the latter is the default behavior when building Windows DLLs. We default +# all libraries to "export all symbols" mode and allow opt-in to explicit mode +# with the flag EXPORT_EXPLICIT_SYMBOLS. +# +# On Unix, in "export all symbols" mode when performing a shared build, +# libraries are built with their VISIBILITY_PRESET left as "default" (takes +# any cmake global configure default that may be defined). It will be set to +# "hidden" when in EXPORT_EXPLICIT_SYMBOLS mode. Note that if built with default +# visibility globally set to hidden, then shared library builds may not +# function. However, if this is being done, it is assumed that the user knows +# what they intend (there are cases where such things are useful, if not +# particularly well defined). +# +# On Windows, in EXPORT_ALL_SYMBOLS mode, special care is taken to generate +# appropriate def files to mimic the Unix-like EXPORT_ALL_SYMBOLS behavior to +# the extent possible. A number of caveats apply. +# +# By making this an explicit toggle, libraries can progressively opt-in to more +# granulary visibility controls in a portable way, which generally leads to +# smaller, better optimized shared libraries with less private-API leakage. +# +# Mapping to LLVM_LINK_COMPONENTS: +# -------------------------------- +# LLVM_LINK_COMPONENTS is implemented on top of this feature and is retained +# as-is within the llvm/lib tree for compatibility. There is a global (TODO) +# that switches between building a mondo libLLVM.so or emitting fine grained +# shared components that map to top-level link components. +# +# Implementing components: +# ======================== +# +# Internally, components are an abstraction disjoint from the libraries that +# make them up. Multiple libraries can contribute to a single, named component, +# although, in many common cases, there is a 1:1 correspondance between library +# and component. The namespace is laid out to accomodate this. +# +# Adding a library to a component is done by invoking +# `llvm_component_add_library` and specifying an `ADD_TO_COMPONENT ` +# parameter. As long as one such library is added to a given component name, +# then the `llvm_component::` alias will be available to link against it. +# +# Internally, a component consists of a number of targets, with a few available +# for external use: +# * Compilation targets: Can be used to set compilation flags. Obtain via +# `llvm_component_get_compile_targets` once a component has been +# instantiated. +# * Linkage targets: Can be used to set linkage flags. Obtain via +# `llvm_component_get_link_targets`. +# * Property target: Generic target that is safe to stash any properties on +# related to the component. Get via `llvm_component_get_props_target`. +# +# The library name specified in the `llvm_component_add_library` call should +# be considered an implementation detail and is generally only useful for +# setting compiler definitions directly on the objects that comprise this +# part of the component. Note that it is illegal to depend on one library that +# makes up a component from another in the same component (and unnecessary, +# since their objects will participate in the same shared or static library +# link at the component level). +# +# Internal layout: +# ---------------- +# Internally, a number of targets are created. In the below `${libname}` refers +# to the library `name` passed to `llvm_component_add_library` and +# `${componentname}` refers to the argument `ADD_TO_COMPONENT`. +# +# * `${libname}_impl`: An object library containing the objects that should be +# contributed to the component. +# * `${componentname}`: INTERFACE library that represents the component. +# * `${componentname}_props` : Custom property target for the component. +# * `${componentname}_shared` (on disk as `${componentname}`) : +# The shared library for the component (if not redirected to an aggregate +# library). +# * `${componentname}_static` (on disk as `${componentname}_static`) : +# The static library for the component. This library does not participate +# in shared library redirection and will be used by executables and +# libraries configured for static linking. +# +# These should all be considered implementation details and not depended on. + +# Adds a library that is part of a component. +function(llvm_component_add_library name) + cmake_parse_arguments(ARG + "EXPORT_EXPLICIT_SYBMOLS" + "ADD_TO_COMPONENT" + "ADDITIONAL_HEADERS;DEPENDS;LINK_LIBS" + ${ARGN}) + # Validate arguments. + if(ARG_ADD_TO_COMPONENT) + set(component_name ${ARG_ADD_TO_COMPONENT}) + else() + message(FATAL_ERROR "ADD_TO_COMPONENT is required for ${name}") + endif() + + # The main component implementation (object) library. + set(_impl_target ${name}_impl) + llvm_process_sources(_all_src_files + ${ARG_UNPARSED_ARGUMENTS} ${ARG_ADDITIONAL_HEADERS}) + add_library(${_impl_target} OBJECT EXCLUDE_FROM_ALL + ${_all_src_files} + ) + llvm_update_compile_flags(${_impl_target}) + set_target_properties(${_impl_target} PROPERTIES FOLDER "Object Libraries") + # Set a marker to indicate that the library is a component. This is used + # by some validity checks to enforce depending on it in the right way. + set_target_properties(${_impl_target} PROPERTIES + LLVM_LIBRARY_IS_NEWCOMPONENT_LIB TRUE) + + # Explicit depends. + if(ARG_DEPENDS) + # TODO: Object library deps are non transitive. + add_dependencies(${_impl_target} ${ARG_DEPENDS}) + endif() + if(ARG_LINK_LIBS) + # TODO: Object library deps are non transitive. + target_link_libraries(${_impl_target} PRIVATE ${ARG_LINK_LIBS}) + endif() + + # Set export visibility at the library level. + if(ARG_EXPORT_EXPLICIT_SYBMOLS) + set_property(TARGET ${_impl_target} CXX_VISIBILITY_PRESET "hidden") + set_property(TARGET ${_impl_target} C_VISIBILITY_PRESET "hidden") + endif() + + # Get or create the component. + set(component_props_target ${component_name}_props) + set(component_interface_target ${component_name}) + if(NOT TARGET ${component_interface_target}) + # Create the component. + llvm_component_create(${component_name}) + endif() + + # Resolve the static and shared library sub-targets from the component. + get_target_property(component_shared_target + ${component_props_target} LLVM_NEWCOMPONENT_SHARED_TARGET) + get_target_property(component_static_target + ${component_props_target} LLVM_NEWCOMPONENT_STATIC_TARGET) + + # Add the impl library to component static and link libraries as needed. + if(component_shared_target) + if(ARG_DEPENDS) + add_dependencies(${component_shared_target} ${ARG_DEPENDS}) + endif() + target_sources(${component_shared_target} PRIVATE $) + # NOTE: A generator such as $ + # can make this property "live" based on the object library, but formulating + # it properly requires more features than old versions of cmake have (and + # is tricky). + target_link_libraries(${component_shared_target} + PRIVATE ${ARG_LINK_LIBS}) + endif() + if(component_static_target) + if(ARG_DEPENDS) + add_dependencies(${component_static_target} ${ARG_DEPENDS}) + endif() + target_sources(${component_static_target} PRIVATE $) + target_link_libraries(${component_static_target} + PRIVATE ${ARG_LINK_LIBS}) + endif() + + # The compile targets are responsible for compiling the sources, and the + # link targets are what is ultimately performing the link. In degenerate + # cases, there can be multiples of each (i.e. on windows where libraries + # destined for a DLL are compiled differently from those that are not). + set_property(TARGET ${component_props_target} + APPEND PROPERTY LLVM_NEWCOMPONENT_COMPILE_TARGETS ${_impl_target} + ) + + # Extend the interface link libraries appropriately. + # Static linking just links directly against the static library. + target_link_libraries(${component_interface_target} INTERFACE + $<$>:${component_static_target}> + ) + + # Shared linking will either link against component shared library, if + # it exists, or the TODO + set(actual_shared_target ${component_shared_target}) + if(NOT component_shared_target) + set(actual_shared_target ${component_static_target}) + endif() + target_link_libraries(${component_interface_target} INTERFACE + $<$>>:${actual_shared_target}> + ) +endfunction() + +function(llvm_component_create component_name) + set(component_props_target ${component_name}_props) + set(component_interface_target ${component_name}) + + # Sanity check. + if(TARGET ${component_props_target} OR + TARGET ${component_interface_target}) + message(FATAL_ERROR "Attempted to create component ${component_name} multiple times") + endif() + + # Create the interface library for the component. + add_library(${component_interface_target} INTERFACE) + + # Add a dummy target that is just for holding component properties. + # This is because INTERFACE libraries cannot have custom properties, and + # we prefer to not randomly pollute the global namespace. + add_custom_target(${component_props_target}) + + # Set the interface target on the property target. + set_target_properties(${component_props_target} PROPERTIES + LLVM_NEWCOMPONENT_INTERFACE_TARGET ${component_interface_target} + ) + + # Locate the component shared library target that corresponds to this + # component name. + llvm_component_ensure_libraries(${_component_name}) + + # Exports and creates install targets for the component. + llvm_component_install(${_component_name}) +endfunction() + +# Finds the shared library target that corresponds to the requested +# `component_name`. +function(llvm_component_ensure_libraries component_name) + set(component_props_target ${component_name}_props) + llvm_component_create_dummy_source(_dummy_file ${component_name}) + + # Ensure the shared target. + get_target_property(_shared_taget + ${component_props_target} LLVM_NEWCOMPONENT_SHARED_TARGET) + if(NOT _shared_target) + # See if there is a redirection entry for the component (i.e. specifying + # that the component goes into a dedicated shared library). + get_property(_shared_target GLOBAL + PROPERTY LLVM_NEWCOMPONENT_${component_name}_REDIRECT_SHARED_TARGET) + + # Neither. Go ahead and create the default association now. + if(NOT _shared_target) + set(_shared_target "${component_name}_shared") + endif() + + # Memorialize the decision. + set_property(TARGET ${component_props_target} PROPERTY + LLVM_NEWCOMPONENT_SHARED_TARGET ${_shared_target}) + set_property(TARGET ${component_props_target} APPEND PROPERTY + LLVM_NEWCOMPONENT_LINK_TARGETS ${_shared_target}) + endif() + + if(NOT TARGET ${_shared_target}) + # Not yet created. Do so now. + # TODO: This doesn't quite work yet for redirection. Need to not set the + # OUTPUT_NAME in that case. + add_library(${_shared_target} SHARED + ${_dummy_file}) + set_property(TARGET ${_shared_target} PROPERTY OUTPUT_NAME ${component_name}) + endif() + + # Ensure the static target. Static targets are always per-component and do + # not participate in redirection. + get_target_property(_static_taget + ${component_props_target} LLVM_NEWCOMPONENT_STATIC_TARGET) + if(NOT _static_target) + # Latch it. + set(_static_target "${component_name}_static") + set_property(TARGET ${component_props_target} PROPERTY + LLVM_NEWCOMPONENT_STATIC_TARGET ${_static_target}) + set_property(TARGET ${component_props_target} APPEND PROPERTY + LLVM_NEWCOMPONENT_LINK_TARGETS ${_shared_target}) + endif() + + if(NOT TARGET ${_static_target}) + add_library(${_static_target} STATIC + ${_dummy_file}) + endif() +endfunction() + +function(llvm_component_install component_name) + set(component_props_target ${component_name}_props) + get_target_property(component_interface_target ${component_props_target} + LLVM_NEWCOMPONENT_INTERFACE_TARGET) + get_target_property(component_static_target ${component_props_target} + LLVM_NEWCOMPONENT_STATIC_TARGET) + get_target_property(component_shared_target ${component_props_target} + LLVM_NEWCOMPONENT_SHARED_TARGET) + + set(export_to_llvmexports EXPORT LLVMExports) + set_property(GLOBAL PROPERTY LLVM_HAS_EXPORTS True) + + # Create the main install target for the interface library. + install(TARGETS ${component_interface_target} + ${export_to_llvmexports} + LIBRARY DESTINATION lib${LLVM_LIBDIR_SUFFIX} COMPONENT ${component_name} + ARCHIVE DESTINATION lib${LLVM_LIBDIR_SUFFIX} COMPONENT ${component_name} + RUNTIME DESTINATION bin COMPONENT ${component_name}) + + if (NOT LLVM_ENABLE_IDE) + add_llvm_install_targets(install-${component_name} + DEPENDS + ${component_interface_target} + COMPONENT ${component_name}) + endif() + set_property(GLOBAL APPEND PROPERTY LLVM_EXPORTS ${component_interface_target}) + + # Generate install targets for each sub-library. + foreach(t ${component_shared_target} ${component_static_target}) + install(TARGETS ${t} + ${export_to_llvmexports} + LIBRARY DESTINATION lib${LLVM_LIBDIR_SUFFIX} COMPONENT ${t} + ARCHIVE DESTINATION lib${LLVM_LIBDIR_SUFFIX} COMPONENT ${t} + RUNTIME DESTINATION bin COMPONENT ${t}) + + if (NOT LLVM_ENABLE_IDE) + add_llvm_install_targets(install-${t} + DEPENDS + ${t} + COMPONENT ${t}) + add_dependencies(install-${component_name} install-${t}) + add_dependencies(install-${component_name}-stripped install-${t}-stripped) + endif() + set_property(GLOBAL APPEND PROPERTY LLVM_EXPORTS ${t}) + endforeach() +endfunction() + +# Gets a target in a component responsible for holding generic properites about +# the component. The components system does nothing with this target but +# ensures it is present and isolated from real library targets. +function(llvm_component_get_props_target out_target name) + set(${out_target} ${name}_props PARENT_SCOPE) +endfunction() + +# Gets the list of compilation targets that a component produces. Compilation +# affecting properties should be manipulated on these targets. +function(llvm_component_get_compile_targets out_targets name) + get_target_property(_compile_targets ${name}_props LLVM_NEWCOMPONENT_COMPILE_TARGETS) + if(NOT _compile_targets) + message(SEND_ERROR "Could not get component compile targets for ${name} (is it a component library?)") + endif() + set(${out_targets} "${_compile_targets}" PARENT_SCOPE) +endfunction() + +# Gets the list of linkable targets that a component produces. Link-affecting +# properties should be manipulated on these targets. +function(llvm_component_get_link_targets out_targets name) + get_target_property(_link_targets ${name}_props LLVM_NEWCOMPONENT_LINK_TARGETS) + if(NOT _link_targets) + message(SEND_ERROR "Could not get component link targets for ${name} (is it a component library?)") + endif() + set(${out_targets} "${_link_targets}" PARENT_SCOPE) +endfunction() + +# Short-cut to call 'target_include_dirs' for all compilation targets in a +# component. +function(llvm_component_include_dirs name) + llvm_component_get_compile_targets(_targets ${name}) + foreach(_target in ${_targets}) + target_include_directories(${_target} ${ARGN}) + endforeach() +endfunction() + +# Utility to create a dummy/empty source file. +# TODO: Just drop such a file somewhere in the source tree. +function(llvm_component_create_dummy_source out_name basename) + set(_dummy_file ${CMAKE_CURRENT_BINARY_DIR}/${basename}__DummyComponent.cpp) + file(WRITE ${_dummy_file} "// This file intentionally empty\n") + set_property(SOURCE ${_dummy_file} APPEND_STRING PROPERTY COMPILE_FLAGS + "-Wno-empty-translation-unit") + set(${out_name} ${_dummy_file} PARENT_SCOPE) +endfunction() diff --git a/llvm/lib/CMakeLists.txt b/llvm/lib/CMakeLists.txt --- a/llvm/lib/CMakeLists.txt +++ b/llvm/lib/CMakeLists.txt @@ -57,5 +57,4 @@ endif() # Component post-processing -LLVMBuildResolveComponentsLink() -LLVMBuildGenerateCFragment(OUTPUT ${LLVMCONFIGLIBRARYDEPENDENCIESINC}) +#LLVMBuildGenerateCFragment(OUTPUT ${LLVMCONFIGLIBRARYDEPENDENCIESINC}) diff --git a/llvm/lib/ExecutionEngine/JITLink/CMakeLists.txt b/llvm/lib/ExecutionEngine/JITLink/CMakeLists.txt --- a/llvm/lib/ExecutionEngine/JITLink/CMakeLists.txt +++ b/llvm/lib/ExecutionEngine/JITLink/CMakeLists.txt @@ -24,10 +24,3 @@ OrcTargetProcess Support ) - -target_link_libraries(LLVMJITLink - PRIVATE - LLVMObject - LLVMOrcTargetProcess - LLVMSupport -) diff --git a/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt b/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt --- a/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt +++ b/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt @@ -32,6 +32,9 @@ intrinsics_gen LINK_COMPONENTS + Analysis + BitReader + BitWriter Core ExecutionEngine JITLink @@ -48,11 +51,3 @@ add_subdirectory(Shared) add_subdirectory(TargetProcess) - -target_link_libraries(LLVMOrcJIT - PRIVATE - LLVMAnalysis - LLVMBitReader - LLVMBitWriter - LLVMPasses - ) diff --git a/llvm/lib/FileCheck/CMakeLists.txt b/llvm/lib/FileCheck/CMakeLists.txt --- a/llvm/lib/FileCheck/CMakeLists.txt +++ b/llvm/lib/FileCheck/CMakeLists.txt @@ -3,6 +3,7 @@ ADDITIONAL_HEADER_DIRS "${LLVM_MAIN_INCLUDE_DIR}/llvm/FileCheck" -) -target_link_libraries(LLVMFileCheck LLVMSupport) + LINK_COMPONENTS + Support +) diff --git a/llvm/lib/Frontend/OpenACC/CMakeLists.txt b/llvm/lib/Frontend/OpenACC/CMakeLists.txt --- a/llvm/lib/Frontend/OpenACC/CMakeLists.txt +++ b/llvm/lib/Frontend/OpenACC/CMakeLists.txt @@ -12,7 +12,8 @@ DEPENDS acc_gen acc_cpp -) -target_link_libraries(LLVMFrontendOpenACC LLVMSupport) + LINK_COMPONENTS + Support +) diff --git a/llvm/lib/Support/CMakeLists.txt b/llvm/lib/Support/CMakeLists.txt --- a/llvm/lib/Support/CMakeLists.txt +++ b/llvm/lib/Support/CMakeLists.txt @@ -231,6 +231,10 @@ Demangle ) +llvm_component_get_props_target(_props_target LLVMSupport) +llvm_component_get_compile_targets(_compile_targets LLVMSupport) +llvm_component_get_link_targets(_link_targets LLVMSupport) + set(llvm_system_libs ${system_libs}) # This block is only needed for llvm-config. When we deprecate llvm-config and @@ -253,22 +257,22 @@ set(llvm_system_libs ${llvm_system_libs} "${terminfo_library}") endif() -set_property(TARGET LLVMSupport PROPERTY LLVM_SYSTEM_LIBS "${llvm_system_libs}") +set_property(TARGET ${_prop_target} PROPERTY LLVM_SYSTEM_LIBS "${llvm_system_libs}") if(LLVM_INTEGRATED_CRT_ALLOC) if(LLVM_INTEGRATED_CRT_ALLOC MATCHES "snmalloc$") - set_property(TARGET LLVMSupport PROPERTY CXX_STANDARD 17) + set_property(TARGET ${_compile_targets} PROPERTY CXX_STANDARD 17) add_definitions(-D_SILENCE_CXX17_ITERATOR_BASE_CLASS_DEPRECATION_WARNING) if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" AND "${CMAKE_SYSTEM_PROCESSOR}" MATCHES "x86_64") - set_property(TARGET LLVMSupport PROPERTY COMPILE_FLAGS "-mcx16") + set_property(TARGET ${_compile_targets} PROPERTY COMPILE_FLAGS "-mcx16") endif() endif() endif() if(LLVM_WITH_Z3) - target_include_directories(LLVMSupport SYSTEM + llvm_component_include_dirs(LLVMSupport SYSTEM PRIVATE ${Z3_INCLUDE_DIR} ) diff --git a/llvm/lib/Target/X86/AsmParser/CMakeLists.txt b/llvm/lib/Target/X86/AsmParser/CMakeLists.txt --- a/llvm/lib/Target/X86/AsmParser/CMakeLists.txt +++ b/llvm/lib/Target/X86/AsmParser/CMakeLists.txt @@ -5,9 +5,7 @@ MC MCParser Support - X86Desc - X86Info ADD_TO_COMPONENT - X86 + LLVMTargetX86 ) diff --git a/llvm/lib/Target/X86/CMakeLists.txt b/llvm/lib/Target/X86/CMakeLists.txt --- a/llvm/lib/Target/X86/CMakeLists.txt +++ b/llvm/lib/Target/X86/CMakeLists.txt @@ -1,4 +1,4 @@ -add_llvm_component_group(X86 HAS_JIT) +add_llvm_component_group(LLVMTargetX86 HAS_JIT) set(LLVM_TARGET_DEFINITIONS X86.td) @@ -91,14 +91,12 @@ SelectionDAG Support Target - X86Desc - X86Info GlobalISel ProfileData CFGuard ADD_TO_COMPONENT - X86 + LLVMTargetX86 ) add_subdirectory(AsmParser) diff --git a/llvm/lib/Target/X86/Disassembler/CMakeLists.txt b/llvm/lib/Target/X86/Disassembler/CMakeLists.txt --- a/llvm/lib/Target/X86/Disassembler/CMakeLists.txt +++ b/llvm/lib/Target/X86/Disassembler/CMakeLists.txt @@ -4,8 +4,7 @@ LINK_COMPONENTS MCDisassembler Support - X86Info ADD_TO_COMPONENT - X86 + LLVMTargetX86 ) diff --git a/llvm/lib/Target/X86/MCTargetDesc/CMakeLists.txt b/llvm/lib/Target/X86/MCTargetDesc/CMakeLists.txt --- a/llvm/lib/Target/X86/MCTargetDesc/CMakeLists.txt +++ b/llvm/lib/Target/X86/MCTargetDesc/CMakeLists.txt @@ -18,9 +18,8 @@ MC MCDisassembler Support - X86Info BinaryFormat ADD_TO_COMPONENT - X86 + LLVMTargetX86 ) diff --git a/llvm/lib/Target/X86/TargetInfo/CMakeLists.txt b/llvm/lib/Target/X86/TargetInfo/CMakeLists.txt --- a/llvm/lib/Target/X86/TargetInfo/CMakeLists.txt +++ b/llvm/lib/Target/X86/TargetInfo/CMakeLists.txt @@ -5,5 +5,5 @@ Support ADD_TO_COMPONENT - X86 + LLVMTargetX86 ) diff --git a/llvm/tools/llvm-config/CMakeLists.txt b/llvm/tools/llvm-config/CMakeLists.txt --- a/llvm/tools/llvm-config/CMakeLists.txt +++ b/llvm/tools/llvm-config/CMakeLists.txt @@ -9,8 +9,12 @@ ) # Compute the substitution values for various items. -get_property(SUPPORT_SYSTEM_LIBS TARGET LLVMSupport PROPERTY LLVM_SYSTEM_LIBS) -get_property(WINDOWSMANIFEST_SYSTEM_LIBS TARGET LLVMWindowsManifest PROPERTY LLVM_SYSTEM_LIBS) +llvm_component_get_props_target(_llvm_support_props_target LLVMSupport) +llvm_component_get_props_target(_llvm_windows_manifest_props_target LLVMWindowsManifest) + +get_property(SUPPORT_SYSTEM_LIBS TARGET ${_llvm_support_props_target} PROPERTY LLVM_SYSTEM_LIBS) +get_property(WINDOWSMANIFEST_SYSTEM_LIBS TARGET ${_llvm_windows_manifest_props_target} PROPERTY LLVM_SYSTEM_LIBS) + foreach(l ${SUPPORT_SYSTEM_LIBS} ${WINDOWSMANIFEST_SYSTEM_LIBS}) if(MSVC) set(SYSTEM_LIBS ${SYSTEM_LIBS} "${l}.lib") diff --git a/llvm/unittests/Target/X86/CMakeLists.txt b/llvm/unittests/Target/X86/CMakeLists.txt --- a/llvm/unittests/Target/X86/CMakeLists.txt +++ b/llvm/unittests/Target/X86/CMakeLists.txt @@ -11,11 +11,9 @@ MIRParser Support Target - X86CodeGen - X86Desc - X86Info + TargetX86 ) add_llvm_unittest(X86Tests MachineSizeOptsTest.cpp - ) +)