diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt --- a/llvm/CMakeLists.txt +++ b/llvm/CMakeLists.txt @@ -331,6 +331,9 @@ option(BUILD_SHARED_LIBS "Build all libraries as shared libraries instead of static" OFF) +option(LLVM_BUILD_SHARED_COMPONENTS + "Build each component as a shared library (or DLL)" OFF) + option(LLVM_ENABLE_BACKTRACES "Enable embedding backtraces on crash." ON) if(LLVM_ENABLE_BACKTRACES) set(ENABLE_BACKTRACES 1) @@ -927,6 +930,7 @@ # use export_executable_symbols(target). set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") +include(LLVMComponents) include(AddLLVM) include(TableGen) 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 @@ -408,6 +408,9 @@ # This is used to specify that this is a component library of # LLVM which means that the source resides in llvm/lib/ and it is a # candidate for inclusion into libLLVM.so. +# PARTIAL_SOURCES_INTENDED +# If present, then this library is expected to not consume all source +# files in a directory, and the corresponding checks are disabled. # ) function(llvm_add_library name) cmake_parse_arguments(ARG @@ -423,7 +426,9 @@ if(ARG_OBJLIBS) set(ALL_FILES ${ARG_OBJLIBS}) else() - llvm_process_sources(ALL_FILES ${ARG_UNPARSED_ARGUMENTS} ${ARG_ADDITIONAL_HEADERS}) + llvm_process_sources(ALL_FILES + ${ARG_PARTIAL_SOURCES_INTENDED} + ${ARG_UNPARSED_ARGUMENTS} ${ARG_ADDITIONAL_HEADERS}) endif() if(ARG_MODULE) @@ -488,6 +493,18 @@ add_dependencies(${obj_name} ${link_lib}) endif() endforeach() + # TODO: See if we can get this check working. + # foreach(link_lib ${LINK_LIBS_ARG_PUBLIC} ${LINK_LIBS_ARG_PRIVATE}) + # if(TARGET ${link_lib}) + # get_target_property(_library_is_component ${link_lib} LLVM_LIBRARY_IS_NEWCOMPONENT) + # if(_library_is_component) + # message(SEND_ERROR + # "Cannot LINK_LIBS to a library that is part of a component. " + # "Add it to LINK_COMPONENTS or reference it via llvm-component:: " + # "(or if using within a component, add it via LINK_LIBS_INTERNAL.") + # endif() + # endif() + # endforeach() endif() endif() @@ -615,12 +632,19 @@ set(llvm_libs ${ARG_PLUGIN_TOOL}) elseif (NOT ARG_COMPONENT_LIB) if (LLVM_LINK_LLVM_DYLIB AND NOT ARG_DISABLE_LLVM_LINK_LLVM_DYLIB) + message(STATUS "!!!! ERROR !!! ROBOT DISASSEMBLED") set(llvm_libs LLVM) else() + # TODO: Unify this mapping of components to targets. + # set(llvm_libs ${ARG_LINK_COMPONENTS} ${LLVM_LINK_COMPONENTS}) + # list(TRANSFORM llvm_libs PREPEND "llvm-component::LLVM") + # message(STATUS " : Mapped component libs ${name} -> ${llvm_libs}") + #set(llvm-libs llvm-component::LLVMSupport) llvm_map_components_to_libnames(llvm_libs ${ARG_LINK_COMPONENTS} ${LLVM_LINK_COMPONENTS} ) + list(TRANSFORM llvm_libs PREPEND "llvm-component::") endif() else() # Components have not been defined explicitly in CMake, so add the @@ -630,6 +654,7 @@ # It would be nice to verify that we have the dependencies for this library # name, but using get_property(... SET) doesn't suffice to determine if a # property has been set to an empty value. + message(STATUS "!!!! ERROR !!! ROBOT DISASSEMBLED") set_property(TARGET ${name} PROPERTY LLVM_LINK_COMPONENTS ${ARG_LINK_COMPONENTS} ${LLVM_LINK_COMPONENTS}) # These two properties are internal properties only used to make sure the @@ -724,13 +749,20 @@ # 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) + llvm_component_add_library(${name} + EXCLUDE_FROM_ALL PARTIAL_SOURCES_INTENDED + ADD_TO_COMPONENT ${_component_name} + ${_dummy_file} + ${ARG_UNPARSED_ARGUMENTS} + LINK_COMPONENTS ${ARG_LINK_COMPONENTS}) + + # TODO: FIX ME! (or delete - nothing seems to reference?) + # if(ARG_HAS_JIT) + # set_property(TARGET ${name} PROPERTY COMPONENT_HAS_JIT ON) + # endif() endfunction() # An LLVM component is a cmake target with the following cmake properties @@ -748,18 +780,99 @@ "COMPONENT_NAME;ADD_TO_COMPONENT" "" ${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}) - endif() - - if(ARG_ADD_TO_COMPONENT) - set_property(TARGET ${ARG_ADD_TO_COMPONENT} APPEND PROPERTY LLVM_LINK_COMPONENTS ${component_name}) - endif() - + # TODO: Why does it need the prefix? + set(_component_name LLVM${ARG_COMPONENT_NAME}) + endif() + 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() + + llvm_component_add_library(${name} ADD_TO_COMPONENT ${_component_name} + ${ARG_UNPARSED_ARGUMENTS}) + + # Usually done by add_llvm_library but managed separately here. + # Needed in order to map some component name forms. + set_property( GLOBAL APPEND PROPERTY LLVM_LIBS ${name} ) + + # if(ARG_ADD_TO_COMPONENT) + # # Add to an existing LLVM component. + # set(_shared_args ADD_TO_SHARED_COMPONENT ${ARG_ADD_TO_COMPONENT}) + # elseif(ARG_COMPONENT_NAME) + # set(_group_name "LLVM${ARG_COMPONENT_NAME}") + # add_llvm_component_group(${_group_name}) + # set(_shared_args ADD_TO_SHARED_COMPONENT ${_group_name}) + # else() + # # Create a same-named component and add to that. + # set(_shared_args) + # endif() + + # llvm_shared_component_add_library(${name} + # ${_shared_args} + # ${ARG_UNPARSED_ARGUMENTS} + # ) + + # if(NOT LLVM_BUILD_SHARED_COMPONENTS) + # export_llvm_library(${name} ${ARG_UNPARSED_ARGUMENTS}) + # elseif(NOT ARG_COMPONENT_NAME AND NOT ARG_ADD_TO_COMPONENT) + # # If we just created a new component, export it. + # export_llvm_library(${name} ${ARG_UNPARSED_ARGUMENTS}) + # endif() + + # TODO: Export/install it if not building shared components. + + # if(LLVM_BUILD_SHARED_COMPONENTS) + # # Building each top-level component as its own shared library. + # if(NOT ARG_ADD_TO_COMPONENT) + # # Library is a top-level component. + # message(STATUS "add_llvm_component_library top-level ${name}") + # add_llvm_library(${name} SHARED + # COMPONENT_LIB + # ${ARG_UNPARSED_ARGUMENTS}) + # 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() + # else() + # message(STATUS "add_llvm_component_library subordinate ${name} ( -> ${ARG_ADD_TO_COMPONENT} )") + # # Library is a subordinate component of a top-level component. + # #set_property(TARGET ${ARG_ADD_TO_COMPONENT} APPEND PROPERTY LLVM_LINK_COMPONENTS ${component_name}) + # add_llvm_library(${name} STATIC OBJECT COMPONENT_LIB ${ARG_UNPARSED_ARGUMENTS}) + # target_sources(${ARG_ADD_TO_COMPONENT} PUBLIC $) + # 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() + + # # Now get the LLVM_LINK_COMPONENTS of the subordinate library and add it + # # to the top-level. + # get_property(_child_llvm_link_components TARGET ${name} PROPERTY LLVM_LINK_COMPONENTS) + # message(STATUS " -> Add child components (to ${ARG_ADD_TO_COMPONENT}) ${_child_llvm_link_components}") + # set_property(TARGET ${ARG_ADD_TO_COMPONENT} APPEND PROPERTY LLVM_LINK_COMPONENTS ${_child_llvm_link_components}) + # endif() + # else() + # # Not building each component as its own shared library. + # add_llvm_library( + # ${name} COMPONENT_LIB ${ARG_UNPARSED_ARGUMENTS} + # ) + # 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() + # endif() endfunction() macro(add_llvm_library name) @@ -775,7 +888,15 @@ else() llvm_add_library(${name} ${ARG_UNPARSED_ARGUMENTS}) endif() + export_llvm_library(${name} ${ARGN}) +endmacro() +macro(export_llvm_library name) + cmake_parse_arguments(ARG + "SHARED;BUILDTREE_ONLY;MODULE;INSTALL_WITH_TOOLCHAIN" + "" + "" + ${ARGN}) # Libraries that are meant to only be exposed via the build tree only are # never installed and are only exported as a target in the special build tree # config file. @@ -821,7 +942,7 @@ else() set_target_properties(${name} PROPERTIES FOLDER "Libraries") endif() -endmacro(add_llvm_library name) +endmacro(export_llvm_library name) macro(add_llvm_executable name) cmake_parse_arguments(ARG @@ -902,7 +1023,16 @@ 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} ) + + # TODO: Finish this. Duplicated with llvm_add_library + # TODO: Set the LLVM_LINK_STATIC property + # llvm_config( ${name} ${USE_SHARED} ${LLVM_LINK_COMPONENTS} ) + llvm_map_components_to_libnames(llvm_libs + ${LLVM_LINK_COMPONENTS} + ) + list(TRANSFORM llvm_libs PREPEND "llvm-component::") + target_link_libraries(${name} PRIVATE ${llvm_libs}) + if( LLVM_COMMON_DEPENDS ) add_dependencies( ${name} ${LLVM_COMMON_DEPENDS} ) endif( LLVM_COMMON_DEPENDS ) 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 @@ -39,8 +39,11 @@ unset(llvmbuild_libname) set(llvmbuild_libdeps ${all_component_libdeps}) else() - get_property(llvmbuild_libname TARGET ${llvmbuild_component} PROPERTY LLVM_COMPONENT_NAME) - get_property(llvmbuild_libdeps TARGET ${llvmbuild_component} PROPERTY LLVM_LINK_COMPONENTS) + # TODO: Fix me. + set(llvmbuild_libname "FIXME_llvmbuild_libname") + set(llvmbuild_libdeps "FIXME_llvmbuild_libdeps") + #get_property(llvmbuild_libname TARGET ${llvmbuild_component} PROPERTY LLVM_COMPONENT_NAME) + #get_property(llvmbuild_libdeps TARGET ${llvmbuild_component} PROPERTY LLVM_LINK_COMPONENTS) endif() string(TOLOWER ${llvmbuild_component} llvmbuild_componentname) @@ -78,27 +81,30 @@ # 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() + # TODO: Fix this. + # 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() + # 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() + # TODO: Delete this. + # get_property(llvm_components GLOBAL PROPERTY LLVM_COMPONENT_LIBS) + # foreach(llvm_component ${llvm_components}) + # message(STATUS " ++ Fixup ${llvm_component}") + # 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) + # message(STATUS " >> (${libtype}) ${llvm_libs}") + # target_link_libraries(${llvm_component} ${libtype} ${llvm_libs}) + # endif() + # endforeach() endfunction() 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,374 @@ +# 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) With a special `llvm-component::` namespace prefixed to the component +# name in target_link_libraries (or LINK_LIBS if using an llvm_add_library +# derived macro). Example: `llvm-component::LLVMSupport`. +# 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` and dependencies on `llvm-component::` +# namespaces. +# +# 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` (which delegates most of its processing to +# `llvm_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 only useful in the case of +# assembling multi-library components that have intra-component dependencies. +# In these cases, libraries within the same component can depend on each other +# via `target_link_libraries`/`LINK_LIBS` using this library name. Within a +# component, libraries must not depend on the public `llvm-component::` +# target for their component (and doing so will be flagged as a dependency +# cycle). +# +# 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}` (on disk as `${libname}_static`): The library added to a +# component. Always created as a `STATIC OBJECT` library on Unix-like +# systems. May have other ancillary libraries created for Windows. +# * `${componentname}_interface`: INTERFACE library that +# `llvm-component::${componentname}` aliases to. +# * `${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). +# +# 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" + "" + ${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 static library and object archive. + set(_static_target ${name}) + llvm_add_library(${_static_target} STATIC OBJECT + # Since we want any dynamic library (i.e. libMyComponent.so) to be the + # primary name, move the static library to a _static suffixed name. + OUTPUT_NAME "${name}_static" + #EXPORT_NAME "${name}" + ${ARG_UNPARSED_ARGUMENTS}) + # 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(${_static_library} PROPERTIES + LLVM_LIBRARY_IS_NEWCOMPONENT TRUE) + + # Create the interface library for the component, if it has not already + # been created. + set(_interface_target ${_component_name}_interface) + if(NOT TARGET ${_interface_target}) + add_library(${_interface_target} INTERFACE) + llvm_component_export_target(${_interface_target}) + # And alias it for easy use. + add_library(llvm-component::${_component_name} ALIAS ${_interface_target}) + endif() + + # 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. + llvm_component_get_props_target(_props_target ${_component_name}) + if(NOT TARGET ${_props_target}) + add_custom_target(${_props_target}) + endif() + + # When building a multi-library component, we will end up with cases where + # the library name (i.e. LLVMX86Desc) differs from the component name + # (i.e. X86). However, it is quite wide-spread for consumers to still want + # to link to these sub-component libraries as if they were components in + # their own right. In order to support this, we simply alias the sub-component + # library name into the llvm-component:: namespace, pointing back to the + # main component. This has the nice side-effect that if *within* a component, + # you depend on a sub-component in such a way, CMake will detect a cycle in + # the dependency graph and tell you explicitly what is wrong (an this only + # affects *implementations* of a component, which are fine to hold to a + # higher bar than consumers). + if(NOT ${name} STREQUAL ${_component_name}) + add_library(llvm-component::${name} ALIAS ${_interface_target}) + 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_target_properties(${_props_target} PROPERTIES + LLVM_NEWCOMPONENT_INTERFACE_TARGET ${_interface_target} + LLVM_NEWCOMPONENT_COMPILE_TARGETS obj.${name} + LLVM_NEWCOMPONENT_LINK_TARGETS ${name} + ) + + # Locate the component shared library target that corresponds to this + # component name. + llvm_component_get_shared_target(_shared_target ${_component_name}) + if(_shared_target) + set_property(TARGET ${_props_target} APPEND PROPERTY + LLVM_NEWCOMPONENT_LINK_TARGETS ${_shared_target} + ) + + # Add objects to the shared library target sources. + target_sources(${_shared_target} + PRIVATE $) + + # TODO: Propagate link libraries and link components from the library. + get_target_property(_link_libraries ${_static_target} LINK_LIBRARIES) + if(_link_libraries) + target_link_libraries(${_shared_target} PRIVATE ${_link_libraries}) + endif() + endif() + + # Set compile/link settings (uses utility functions as callers will to + # verify). + llvm_component_get_compile_targets(_compile_targets ${_component_name}) + llvm_component_get_link_targets(_link_targets ${_component_name}) + if(ARG_EXPORT_EXPLICIT_SYBMOLS) + set_property(TARGET ${_compile_targets} CXX_VISIBILITY_PRESET "hidden") + set_property(TARGET ${_compile_targets} C_VISIBILITY_PRESET "hidden") + endif() + + # Export the static library. + llvm_component_export_target(${_static_target} STATIC) + + # Extend the link libraries of the interface library appropriately. + target_link_libraries(${_interface_target} INTERFACE + $<$>:${_static_target}> + ) + if(_shared_target) + # Shared libraries enabled, non-static uses shared. + target_link_libraries(${_interface_target} INTERFACE + $<$>>:${_shared_target}> + ) + else() + # Shared libraries disabled, non-static is still static. + target_link_libraries(${_interface_target} INTERFACE + $<$>>:${_static_target}> + ) + endif() +endfunction() + +function(llvm_component_export_target name) + cmake_parse_arguments(ARG + "STATIC" + "" + "" + ${ARGN}) + + set(export_to_llvmexports) + + # Note: Shared library components are always exported. Static components + # are exported conditionally. + if(NOT ARG_STATIC OR ${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() + + install(TARGETS ${name} + ${export_to_llvmexports} + LIBRARY DESTINATION lib${LLVM_LIBDIR_SUFFIX} COMPONENT ${name} + ARCHIVE DESTINATION lib${LLVM_LIBDIR_SUFFIX} COMPONENT ${name} + RUNTIME DESTINATION bin COMPONENT ${name}) + + if (NOT LLVM_ENABLE_IDE) + add_llvm_install_targets(install-${name} + DEPENDS ${name} + COMPONENT ${name}) + endif() + + set_property(GLOBAL APPEND PROPERTY LLVM_EXPORTS ${name}) +endfunction() + +# Finds the shared library target that corresponds to the requested +# `component_name`, setting it in `out_target_name`. Resolves to +# ${component_name}-NOTFOUND if shared library building is disabled. +function(llvm_component_get_shared_target out_target_name component_name) + if(NOT LLVM_BUILD_SHARED_COMPONENTS) + set(${_out_target_name} ${component_name}-NOTFOUND PARENT_SCOPE) + return() + endif() + + get_property(_shared_target GLOBAL + PROPERTY LLVM_NEWCOMPONENT_${component_name}_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(GLOBAL PROPERTY + LLVM_NEWCOMPONENT_${component_name}_SHARED_TARGET ${_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. + llvm_component_create_dummy_source(_dummy_file ${component_name}) + llvm_add_library(${_shared_target} + OUTPUT_NAME ${component_name} + SHARED PARTIAL_SOURCES_INTENDED + ${_dummy_file}) + endif() + + set(${out_target_name} ${_shared_target} PARENT_SCOPE) +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/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,10 @@ OrcTargetProcess Support ) - -target_link_libraries(LLVMJITLink - PRIVATE - LLVMObject - LLVMOrcTargetProcess - LLVMSupport -) + +# 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,10 @@ intrinsics_gen LINK_COMPONENTS + Analysis + BitReader + BitWriter + Passes Core ExecutionEngine JITLink @@ -49,10 +53,10 @@ add_subdirectory(Shared) add_subdirectory(TargetProcess) -target_link_libraries(LLVMOrcJIT - PRIVATE - LLVMAnalysis - LLVMBitReader - LLVMBitWriter - LLVMPasses - ) +# 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/CMakeLists.txt b/llvm/lib/Target/CMakeLists.txt --- a/llvm/lib/Target/CMakeLists.txt +++ b/llvm/lib/Target/CMakeLists.txt @@ -21,7 +21,7 @@ # When building shared objects for each target there are some internal APIs # that are used across shared objects which we can't hide. -if (NOT BUILD_SHARED_LIBS AND NOT APPLE) +if (LLVM_BUILD_LLVM_DYLIB AND NOT APPLE) # Set default visibility to hidden, so we don't export all the Target classes # in libLLVM.so. set(CMAKE_CXX_VISIBILITY_PRESET hidden) 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,8 +5,13 @@ MC MCParser Support - X86Desc - X86Info + # TODO: Intra-component linkage needs to be via LINK_LIBS, not LINK_COMPONENTS + # X86Desc + # X86Info + + LINK_LIBS PRIVATE + LLVMX86Desc + LLVMX86Info ADD_TO_COMPONENT X86 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 @@ -91,12 +91,17 @@ SelectionDAG Support Target - X86Desc - X86Info + # TODO: Intra-component linkage needs to be via LINK_LIBS, not LINK_COMPONENTS + #X86Desc + #X86Info GlobalISel ProfileData CFGuard + LINK_LIBS PRIVATE + LLVMX86Desc + LLVMX86Info + ADD_TO_COMPONENT X86 ) 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,13 @@ MC MCDisassembler Support - X86Info + # TODO: Intra-component linkage needs to be via LINK_LIBS, not LINK_COMPONENTS + # X86Info BinaryFormat + LINK_LIBS PRIVATE + LLVMX86Info + ADD_TO_COMPONENT X86 ) diff --git a/llvm/lib/Target/X86/X86FloatingPoint.cpp b/llvm/lib/Target/X86/X86FloatingPoint.cpp --- a/llvm/lib/Target/X86/X86FloatingPoint.cpp +++ b/llvm/lib/Target/X86/X86FloatingPoint.cpp @@ -302,6 +302,7 @@ char FPS::ID = 0; + INITIALIZE_PASS_BEGIN(FPS, DEBUG_TYPE, "X86 FP Stackifier", false, false) INITIALIZE_PASS_DEPENDENCY(EdgeBundles) diff --git a/llvm/tools/llvm-cfi-verify/CMakeLists.txt b/llvm/tools/llvm-cfi-verify/CMakeLists.txt --- a/llvm/tools/llvm-cfi-verify/CMakeLists.txt +++ b/llvm/tools/llvm-cfi-verify/CMakeLists.txt @@ -15,4 +15,7 @@ ) add_subdirectory(lib) +# TODO: Can be dynamic linked once LLVMCFIVerify is converted to a component +# library. +set_target_properties(llvm-cfi-verify PROPERTIES LLVM_LINK_STATIC ON) target_link_libraries(llvm-cfi-verify PRIVATE LLVMCFIVerify) diff --git a/llvm/tools/llvm-cfi-verify/lib/CMakeLists.txt b/llvm/tools/llvm-cfi-verify/lib/CMakeLists.txt --- a/llvm/tools/llvm-cfi-verify/lib/CMakeLists.txt +++ b/llvm/tools/llvm-cfi-verify/lib/CMakeLists.txt @@ -1,3 +1,5 @@ +# TODO: Can be converted to a component library and static linkage opted in +# at the executable level. add_library(LLVMCFIVerify STATIC FileAnalysis.cpp 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) +# TODO: Fix ME! +#get_property(SUPPORT_SYSTEM_LIBS TARGET LLVMSupport PROPERTY LLVM_SYSTEM_LIBS) +#get_property(WINDOWSMANIFEST_SYSTEM_LIBS TARGET LLVMWindowsManifest PROPERTY LLVM_SYSTEM_LIBS) +set(SUPPORT_SYSTEM_LIBS) +set(WINDOWSMANIFEST_SYSTEM_LIBS) + foreach(l ${SUPPORT_SYSTEM_LIBS} ${WINDOWSMANIFEST_SYSTEM_LIBS}) if(MSVC) set(SYSTEM_LIBS ${SYSTEM_LIBS} "${l}.lib") diff --git a/llvm/tools/llvm-exegesis/lib/CMakeLists.txt b/llvm/tools/llvm-exegesis/lib/CMakeLists.txt --- a/llvm/tools/llvm-exegesis/lib/CMakeLists.txt +++ b/llvm/tools/llvm-exegesis/lib/CMakeLists.txt @@ -19,6 +19,8 @@ set(LLVM_EXEGESIS_TARGETS "${LLVM_EXEGESIS_TARGETS} ${TARGETS_TO_APPEND}" PARENT_SCOPE) +# TODO: This can now become a regular component library and if static linkage +# is desired, LLVM_LINK_STATIC can be given at the executable level. add_library(LLVMExegesis STATIC Analysis.cpp diff --git a/llvm/unittests/tools/llvm-cfi-verify/CMakeLists.txt b/llvm/unittests/tools/llvm-cfi-verify/CMakeLists.txt --- a/llvm/unittests/tools/llvm-cfi-verify/CMakeLists.txt +++ b/llvm/unittests/tools/llvm-cfi-verify/CMakeLists.txt @@ -14,4 +14,7 @@ FileAnalysis.cpp GraphBuilder.cpp ) +# TODO: Can be dynamic linked once LLVMCFIVerify is converted to a component +# library. +set_target_properties(CFIVerifyTests PROPERTIES LLVM_LINK_STATIC ON) target_link_libraries(CFIVerifyTests PRIVATE LLVMCFIVerify) diff --git a/llvm/unittests/tools/llvm-exegesis/CMakeLists.txt b/llvm/unittests/tools/llvm-exegesis/CMakeLists.txt --- a/llvm/unittests/tools/llvm-exegesis/CMakeLists.txt +++ b/llvm/unittests/tools/llvm-exegesis/CMakeLists.txt @@ -17,6 +17,7 @@ RegisterValueTest.cpp SnippetGeneratorTest.cpp ) +set_target_properties(LLVMExegesisTests PROPERTIES LLVM_LINK_STATIC ON) target_link_libraries(LLVMExegesisTests PRIVATE LLVMExegesis) if(LLVM_TARGETS_TO_BUILD MATCHES "X86") diff --git a/llvm/unittests/tools/llvm-exegesis/X86/CMakeLists.txt b/llvm/unittests/tools/llvm-exegesis/X86/CMakeLists.txt --- a/llvm/unittests/tools/llvm-exegesis/X86/CMakeLists.txt +++ b/llvm/unittests/tools/llvm-exegesis/X86/CMakeLists.txt @@ -23,6 +23,7 @@ SnippetRepetitorTest.cpp TargetTest.cpp ) +set_target_properties(LLVMExegesisX86Tests PROPERTIES LLVM_LINK_STATIC ON) target_link_libraries(LLVMExegesisX86Tests PRIVATE LLVMExegesis LLVMExegesisX86) diff --git a/llvm/utils/FileCheck/CMakeLists.txt b/llvm/utils/FileCheck/CMakeLists.txt --- a/llvm/utils/FileCheck/CMakeLists.txt +++ b/llvm/utils/FileCheck/CMakeLists.txt @@ -1,5 +1,10 @@ +set(LLVM_LINK_COMPONENTS + FileCheck + Support +) add_llvm_utility(FileCheck FileCheck.cpp ) -target_link_libraries(FileCheck PRIVATE LLVMFileCheck LLVMSupport) +set_target_properties(FileCheck PROPERTIES LLVM_LINK_STATIC ON) +#target_link_libraries(FileCheck PRIVATE LLVMFileCheck LLVMSupport) diff --git a/llvm/utils/yaml-bench/CMakeLists.txt b/llvm/utils/yaml-bench/CMakeLists.txt --- a/llvm/utils/yaml-bench/CMakeLists.txt +++ b/llvm/utils/yaml-bench/CMakeLists.txt @@ -1,5 +1,8 @@ +set(LLVM_LINK_COMPONENTS + Support +) add_llvm_utility(yaml-bench YAMLBench.cpp ) -target_link_libraries(yaml-bench PRIVATE LLVMSupport) +#target_link_libraries(yaml-bench PRIVATE LLVMSupport)