brintos

brintos / llvm-project-archived public Read only

0
0
Text · 31.2 KiB · 6589458 Raw
765 lines · plain
1include(TableGen)2include(GNUInstallDirs)3include(LLVMDistributionSupport)4 5function(mlir_tablegen ofn)6  tablegen(MLIR ${ARGV})7  set(TABLEGEN_OUTPUT ${TABLEGEN_OUTPUT} ${CMAKE_CURRENT_BINARY_DIR}/${ofn}8      PARENT_SCOPE)9 10  # Get the current set of include paths for this td file.11  cmake_parse_arguments(ARG "" "" "DEPENDS;EXTRA_INCLUDES" ${ARGN})12  get_directory_property(tblgen_includes INCLUDE_DIRECTORIES)13  list(APPEND tblgen_includes ${ARG_EXTRA_INCLUDES})14  # Filter out any empty include items.15  list(REMOVE_ITEM tblgen_includes "")16 17  # Build the absolute path for the current input file.18  if (IS_ABSOLUTE ${LLVM_TARGET_DEFINITIONS})19    set(LLVM_TARGET_DEFINITIONS_ABSOLUTE ${LLVM_TARGET_DEFINITIONS})20  else()21    set(LLVM_TARGET_DEFINITIONS_ABSOLUTE ${CMAKE_CURRENT_SOURCE_DIR}/${LLVM_TARGET_DEFINITIONS})22  endif()23 24  # Append the includes used for this file to the tablegen_compile_commands25  # file.26  file(APPEND ${CMAKE_BINARY_DIR}/tablegen_compile_commands.yml27      "--- !FileInfo:\n"28      "  filepath: \"${LLVM_TARGET_DEFINITIONS_ABSOLUTE}\"\n"29      "  includes: \"${CMAKE_CURRENT_SOURCE_DIR};${tblgen_includes}\"\n"30  )31endfunction()32 33# Clear out any pre-existing compile_commands file before processing. This34# allows for generating a clean compile_commands on each configure.35file(REMOVE ${CMAKE_BINARY_DIR}/pdll_compile_commands.yml)36 37# Declare a helper function/copy of tablegen rule for using tablegen without38# additional tblgen specific flags when invoking PDLL generator.39function(_pdll_tablegen project ofn)40  cmake_parse_arguments(ARG "" "" "DEPENDS;EXTRA_INCLUDES" ${ARGN})41  # Validate calling context.42  if(NOT ${project}_TABLEGEN_EXE)43    message(FATAL_ERROR "${project}_TABLEGEN_EXE not set")44  endif()45 46  # Use depfile instead of globbing arbitrary *.td(s) for Ninja. We force47  # CMake versions older than v3.30 on Windows to use the fallback behavior48  # due to a depfile parsing bug on Windows paths in versions prior to 3.30.49  # https://gitlab.kitware.com/cmake/cmake/-/issues/2594350  # CMake versions older than v3.23 on other platforms use the fallback51  # behavior as v3.22 and earlier fail to parse some depfiles that get52  # generated, and this behavior was fixed in CMake commit53  # e04a352cca523eba2ac0d60063a3799f5bb1c69e.54  cmake_policy(GET CMP0116 cmp0116_state)55  if(CMAKE_GENERATOR MATCHES "Ninja" AND cmp0116_state STREQUAL NEW56     AND NOT (CMAKE_HOST_WIN32 AND CMAKE_VERSION VERSION_LESS 3.30)57     AND NOT (CMAKE_VERSION VERSION_LESS 3.23))58    # CMake emits build targets as relative paths but Ninja doesn't identify59    # absolute path (in *.d) as relative path (in build.ninja). Post CMP0116,60    # CMake handles this discrepancy for us. Otherwise, we use the fallback61    # logic.62    set(additional_cmdline63      -o ${ofn}64      -d ${ofn}.d65      DEPFILE ${ofn}.d66      )67    set(local_tds)68    set(global_tds)69  else()70    file(GLOB local_tds "*.td")71    file(GLOB_RECURSE global_tds "${LLVM_MAIN_INCLUDE_DIR}/llvm/*.td")72    set(additional_cmdline73      -o ${CMAKE_CURRENT_BINARY_DIR}/${ofn}74      )75  endif()76 77  if (IS_ABSOLUTE ${LLVM_TARGET_DEFINITIONS})78    set(LLVM_TARGET_DEFINITIONS_ABSOLUTE ${LLVM_TARGET_DEFINITIONS})79  else()80    set(LLVM_TARGET_DEFINITIONS_ABSOLUTE81      ${CMAKE_CURRENT_SOURCE_DIR}/${LLVM_TARGET_DEFINITIONS})82  endif()83 84  if (CMAKE_GENERATOR MATCHES "Visual Studio")85    # Visual Studio has problems with llvm-tblgen's native --write-if-changed86    # behavior. Since it doesn't do restat optimizations anyway, just don't87    # pass --write-if-changed there.88    set(tblgen_change_flag)89  else()90    set(tblgen_change_flag "--write-if-changed")91  endif()92 93  # We need both _TABLEGEN_TARGET and _TABLEGEN_EXE in the  DEPENDS list94  # (both the target and the file) to have .inc files rebuilt on95  # a tablegen change, as cmake does not propagate file-level dependencies96  # of custom targets. See the following ticket for more information:97  # https://cmake.org/Bug/view.php?id=1585898  # The dependency on both, the target and the file, produces the same99  # dependency twice in the result file when100  # ("${${project}_TABLEGEN_TARGET}" STREQUAL "${${project}_TABLEGEN_EXE}")101  # but lets us having smaller and cleaner code here.102  get_directory_property(tblgen_includes INCLUDE_DIRECTORIES)103  list(APPEND tblgen_includes ${ARG_EXTRA_INCLUDES})104  # Filter out empty items before prepending each entry with -I105  list(REMOVE_ITEM tblgen_includes "")106  list(TRANSFORM tblgen_includes PREPEND -I)107 108  set(tablegen_exe ${${project}_TABLEGEN_EXE})109  set(tablegen_depends ${${project}_TABLEGEN_TARGET} ${tablegen_exe})110 111  add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${ofn}112    COMMAND ${tablegen_exe} ${ARG_UNPARSED_ARGUMENTS} -I ${CMAKE_CURRENT_SOURCE_DIR}113    ${tblgen_includes}114    ${LLVM_TARGET_DEFINITIONS_ABSOLUTE}115    ${tblgen_change_flag}116    ${additional_cmdline}117    # The file in LLVM_TARGET_DEFINITIONS may be not in the current118    # directory and local_tds may not contain it, so we must119    # explicitly list it here:120    DEPENDS ${ARG_DEPENDS} ${tablegen_depends}121      ${local_tds} ${global_tds}122    ${LLVM_TARGET_DEFINITIONS_ABSOLUTE}123    ${LLVM_TARGET_DEPENDS}124    COMMENT "Building ${ofn}..."125    )126 127  # `make clean' must remove all those generated files:128  set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES ${ofn})129 130  set(TABLEGEN_OUTPUT ${TABLEGEN_OUTPUT} ${CMAKE_CURRENT_BINARY_DIR}/${ofn} PARENT_SCOPE)131  set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/${ofn} PROPERTIES132    GENERATED 1)133endfunction()134 135# Declare a PDLL library in the current directory.136function(add_mlir_pdll_library target inputFile ofn)137  set(LLVM_TARGET_DEFINITIONS ${inputFile})138 139  _pdll_tablegen(MLIR_PDLL ${ofn} -x=cpp ${ARGN})140  set(TABLEGEN_OUTPUT ${TABLEGEN_OUTPUT} ${CMAKE_CURRENT_BINARY_DIR}/${ofn}141      PARENT_SCOPE)142 143  # Get the current set of include paths for this pdll file.144  cmake_parse_arguments(ARG "" "" "DEPENDS;EXTRA_INCLUDES" ${ARGN})145  get_directory_property(tblgen_includes INCLUDE_DIRECTORIES)146  list(APPEND tblgen_includes ${ARG_EXTRA_INCLUDES})147  # Filter out any empty include items.148  list(REMOVE_ITEM tblgen_includes "")149 150  # Build the absolute path for the current input file.151  if (IS_ABSOLUTE ${LLVM_TARGET_DEFINITIONS})152    set(LLVM_TARGET_DEFINITIONS_ABSOLUTE ${inputFile})153  else()154    set(LLVM_TARGET_DEFINITIONS_ABSOLUTE ${CMAKE_CURRENT_SOURCE_DIR}/${inputFile})155  endif()156 157  # Append the includes used for this file to the pdll_compilation_commands158  # file.159  file(APPEND ${CMAKE_BINARY_DIR}/pdll_compile_commands.yml160      "--- !FileInfo:\n"161      "  filepath: \"${LLVM_TARGET_DEFINITIONS_ABSOLUTE}\"\n"162      "  includes: \"${CMAKE_CURRENT_SOURCE_DIR};${tblgen_includes}\"\n"163  )164 165  add_public_tablegen_target(${target})166endfunction()167 168# Declare a dialect in the include directory169function(add_mlir_dialect dialect dialect_namespace)170  set(LLVM_TARGET_DEFINITIONS ${dialect}.td)171  mlir_tablegen(${dialect}.h.inc -gen-op-decls)172  mlir_tablegen(${dialect}.cpp.inc -gen-op-defs)173  mlir_tablegen(${dialect}Types.h.inc -gen-typedef-decls -typedefs-dialect=${dialect_namespace})174  mlir_tablegen(${dialect}Types.cpp.inc -gen-typedef-defs -typedefs-dialect=${dialect_namespace})175  mlir_tablegen(${dialect}Dialect.h.inc -gen-dialect-decls -dialect=${dialect_namespace})176  mlir_tablegen(${dialect}Dialect.cpp.inc -gen-dialect-defs -dialect=${dialect_namespace})177  add_mlir_dialect_tablegen_target(MLIR${dialect}IncGen)178endfunction()179 180# Declare sharded dialect operation declarations and definitions181function(add_sharded_ops ops_target shard_count)182  set(LLVM_TARGET_DEFINITIONS ${ops_target}.td)183  mlir_tablegen(${ops_target}.h.inc -gen-op-decls -op-shard-count=${shard_count})184  mlir_tablegen(${ops_target}.cpp.inc -gen-op-defs -op-shard-count=${shard_count})185  set(LLVM_TARGET_DEFINITIONS ${ops_target}.cpp)186  foreach(index RANGE ${shard_count})187    set(SHARDED_SRC ${ops_target}.${index}.cpp)188    list(APPEND SHARDED_SRCS ${SHARDED_SRC})189    tablegen(MLIR_SRC_SHARDER ${SHARDED_SRC} -op-shard-index=${index})190    set(TABLEGEN_OUTPUT ${TABLEGEN_OUTPUT} ${CMAKE_CURRENT_BINARY_DIR}/${SHARDED_SRC})191  endforeach()192  add_mlir_dialect_tablegen_target(MLIR${ops_target}ShardGen)193  set(SHARDED_SRCS ${SHARDED_SRCS} PARENT_SCOPE)194endfunction()195 196# Declare a dialect in the include directory197function(add_mlir_interface interface)198  set(LLVM_TARGET_DEFINITIONS ${interface}.td)199  mlir_tablegen(${interface}.h.inc -gen-op-interface-decls)200  mlir_tablegen(${interface}.cpp.inc -gen-op-interface-defs)201  add_mlir_generic_tablegen_target(MLIR${interface}IncGen)202endfunction()203 204# Add a dialect-specific tablegen target that generates headers in the include directory.205# In most cases, this is what should be used after invoking `mlir_tablegen`.206macro(add_mlir_dialect_tablegen_target target)207  add_public_tablegen_target(${target})208  add_dependencies(mlir-headers ${target})209endmacro()210 211# Add a dialect-independent tablegen target that generates headers in the include directory.212# Generally this is used for files outside of the Dialects/ folder, and also for interfaces213# that do not depend on dialect-specific headers.214macro(add_mlir_generic_tablegen_target target)215  add_public_tablegen_target(${target})216  add_dependencies(mlir-generic-headers ${target})217endmacro()218 219# Generate Documentation220function(add_mlir_doc doc_filename output_file output_directory command)221  set(LLVM_TARGET_DEFINITIONS ${doc_filename}.td)222  # The MLIR docs use Hugo, so we allow Hugo specific features here.223  tablegen(MLIR ${output_file}.md ${command} -allow-hugo-specific-features ${ARGN})224  set(GEN_DOC_FILE ${MLIR_BINARY_DIR}/docs/${output_directory}${output_file}.md)225  add_custom_command(226          OUTPUT ${GEN_DOC_FILE}227          COMMAND ${CMAKE_COMMAND} -E copy228                  ${CMAKE_CURRENT_BINARY_DIR}/${output_file}.md229                  ${GEN_DOC_FILE}230          DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${output_file}.md)231  add_custom_target(${output_file}DocGen DEPENDS ${GEN_DOC_FILE})232  set_target_properties(${output_file}DocGen PROPERTIES FOLDER "MLIR/Tablegenning/Docs")233  add_dependencies(mlir-doc ${output_file}DocGen)234endfunction()235 236# Sets ${srcs} to contain the list of additional headers for the target. Extra237# arguments are included into the list of additional headers.238function(_set_mlir_additional_headers_as_srcs)239  set(srcs)240  if(MSVC_IDE OR XCODE)241    # Add public headers242    file(RELATIVE_PATH lib_path243      ${MLIR_SOURCE_DIR}/lib/244      ${CMAKE_CURRENT_SOURCE_DIR}245    )246    if(NOT lib_path MATCHES "^[.][.]")247      file( GLOB_RECURSE headers248        ${MLIR_SOURCE_DIR}/include/mlir/${lib_path}/*.h249        ${MLIR_SOURCE_DIR}/include/mlir/${lib_path}/*.def250      )251      set_source_files_properties(${headers} PROPERTIES HEADER_FILE_ONLY ON)252 253      file( GLOB_RECURSE tds254        ${MLIR_SOURCE_DIR}/include/mlir/${lib_path}/*.td255      )256      source_group("TableGen descriptions" FILES ${tds})257      set_source_files_properties(${tds}} PROPERTIES HEADER_FILE_ONLY ON)258 259      if(headers OR tds)260        set(srcs ${headers} ${tds})261      endif()262    endif()263  endif(MSVC_IDE OR XCODE)264  if(srcs OR ARGN)265    set(srcs266      ADDITIONAL_HEADERS267      ${srcs}268      ${ARGN} # It may contain unparsed unknown args.269      PARENT_SCOPE270      )271  endif()272endfunction()273 274# Checks that the LLVM components are not listed in the extra arguments,275# assumed to be coming from the LINK_LIBS variable.276function(_check_llvm_components_usage name)277  # LINK_COMPONENTS is necessary to allow libLLVM.so to be properly278  # substituted for individual library dependencies if LLVM_LINK_LLVM_DYLIB279  # Perhaps this should be in llvm_add_library instead?  However, it fails280  # on libclang-cpp.so281  get_property(llvm_component_libs GLOBAL PROPERTY LLVM_COMPONENT_LIBS)282  foreach(lib ${ARGN})283    if(${lib} IN_LIST llvm_component_libs)284      message(SEND_ERROR "${name} specifies LINK_LIBS ${lib}, but LINK_LIBS cannot be used for LLVM libraries.  Please use LINK_COMPONENTS instead.")285    endif()286  endforeach()287endfunction()288 289function(add_mlir_example_library name)290  cmake_parse_arguments(ARG291    "SHARED;DISABLE_INSTALL"292    ""293    "ADDITIONAL_HEADERS;DEPENDS;LINK_COMPONENTS;LINK_LIBS"294    ${ARGN})295  _set_mlir_additional_headers_as_srcs(${ARG_ADDITIONAL_HEADERS})296  if (ARG_SHARED)297    set(LIBTYPE SHARED)298  else()299    if(BUILD_SHARED_LIBS)300      set(LIBTYPE SHARED)301    else()302      set(LIBTYPE STATIC)303    endif()304  endif()305 306  # MLIR libraries uniformly depend on LLVMSupport.  Just specify it once here.307  list(APPEND ARG_LINK_COMPONENTS Support)308  _check_llvm_components_usage(${name} ${ARG_LINK_LIBS})309 310  list(APPEND ARG_DEPENDS mlir-generic-headers)311 312  llvm_add_library(${name} ${LIBTYPE} ${ARG_UNPARSED_ARGUMENTS} ${srcs} DEPENDS ${ARG_DEPENDS} LINK_COMPONENTS ${ARG_LINK_COMPONENTS} LINK_LIBS ${ARG_LINK_LIBS})313  set_target_properties(${name} PROPERTIES FOLDER "MLIR/Examples")314  if (LLVM_BUILD_EXAMPLES AND NOT ${ARG_DISABLE_INSTALL})315    add_mlir_library_install(${name})316  else()317    set_target_properties(${name} PROPERTIES EXCLUDE_FROM_ALL ON)318  endif()319endfunction()320 321# Declare an mlir library which can be compiled in libMLIR.so322# In addition to everything that llvm_add_library accepts, this323# also has the following option:324# EXCLUDE_FROM_LIBMLIR325#   Don't include this library in libMLIR.so.  This option should be used326#   for test libraries, executable-specific libraries, or rarely used libraries327#   with large dependencies.  When using it, please link libraries included328#   in libMLIR via mlir_target_link_libraries(), to ensure that the library329#   does not pull in static dependencies when MLIR_LINK_MLIR_DYLIB=ON is used.330# OBJECT331#   The library's object library is referenced using "obj.${name}". For this to332#   work reliably, this flag ensures that the OBJECT library exists.333# ENABLE_AGGREGATION334#   Exports additional metadata,335#   and installs additional object files needed to include this as part of an336#   aggregate shared library.337#   TODO: Make this the default for all MLIR libraries once all libraries338#   are compatible with building an object library.339function(add_mlir_library name)340  cmake_parse_arguments(ARG341    "SHARED;INSTALL_WITH_TOOLCHAIN;EXCLUDE_FROM_LIBMLIR;DISABLE_INSTALL;ENABLE_AGGREGATION;OBJECT"342    ""343    "ADDITIONAL_HEADERS;DEPENDS;LINK_COMPONENTS;LINK_LIBS"344    ${ARGN})345  _set_mlir_additional_headers_as_srcs(${ARG_ADDITIONAL_HEADERS})346 347  # Determine type of library.348  if(ARG_SHARED)349    set(LIBTYPE SHARED)350  else()351    # llvm_add_library ignores BUILD_SHARED_LIBS if STATIC is explicitly set,352    # so we need to handle it here.353    if(BUILD_SHARED_LIBS)354      set(LIBTYPE SHARED)355    else()356      set(LIBTYPE STATIC)357    endif()358  endif()359 360  # Is an object library needed...?361  # Note that the XCode generator doesn't handle object libraries correctly and362  # usability is degraded in the Visual Studio solution generators.363  # llvm_add_library may also itself decide to create an object library.364  set(NEEDS_OBJECT_LIB OFF)365  if(ARG_OBJECT)366    # Yes, because the target "obj.${name}" is referenced.367    set(NEEDS_OBJECT_LIB ON)368  endif ()369  if(LLVM_BUILD_LLVM_DYLIB AND NOT ARG_EXCLUDE_FROM_LIBMLIR AND NOT XCODE)370    # Yes, because in addition to the shared library, the object files are371    # needed for linking into libMLIR.so (see mlir/tools/mlir-shlib/CMakeLists.txt).372    # For XCode, -force_load is used instead.373    # Windows is not supported (LLVM_BUILD_LLVM_DYLIB=ON will cause an error).374    set(NEEDS_OBJECT_LIB ON)375    set_property(GLOBAL APPEND PROPERTY MLIR_STATIC_LIBS ${name})376    set_property(GLOBAL APPEND PROPERTY MLIR_LLVM_LINK_COMPONENTS ${ARG_LINK_COMPONENTS})377    set_property(GLOBAL APPEND PROPERTY MLIR_LLVM_LINK_COMPONENTS ${LLVM_LINK_COMPONENTS})378  endif ()379  if(ARG_ENABLE_AGGREGATION AND NOT XCODE)380    # Yes, because this library is added to an aggergate library such as381    # libMLIR-C.so which is links together all the object files.382    # For XCode, -force_load is used instead.383    set(NEEDS_OBJECT_LIB ON)384  endif()385  if (NOT ARG_SHARED AND NOT ARG_EXCLUDE_FROM_LIBMLIR AND NOT XCODE AND NOT MSVC_IDE)386    # Yes, but only for legacy reasons. Also avoid object libraries for387    # Visual Studio solutions.388    set(NEEDS_OBJECT_LIB ON)389  endif()390  if(NEEDS_OBJECT_LIB)391    list(APPEND LIBTYPE OBJECT)392  endif()393 394  # MLIR libraries uniformly depend on LLVMSupport.  Just specify it once here.395  list(APPEND ARG_LINK_COMPONENTS Support)396  _check_llvm_components_usage(${name} ${ARG_LINK_LIBS})397 398  list(APPEND ARG_DEPENDS mlir-generic-headers)399  llvm_add_library(${name} ${LIBTYPE} ${ARG_UNPARSED_ARGUMENTS} ${srcs} DEPENDS ${ARG_DEPENDS} LINK_COMPONENTS ${ARG_LINK_COMPONENTS} LINK_LIBS ${ARG_LINK_LIBS})400 401  if(TARGET ${name})402    target_link_libraries(${name} INTERFACE ${LLVM_COMMON_LIBS})403    if(ARG_INSTALL_WITH_TOOLCHAIN)404      set_target_properties(${name} PROPERTIES MLIR_INSTALL_WITH_TOOLCHAIN TRUE)405    endif()406    if(NOT ARG_DISABLE_INSTALL)407      add_mlir_library_install(${name})408    endif()409  else()410    # Add empty "phony" target411    add_custom_target(${name})412  endif()413  set_target_properties(${name} PROPERTIES FOLDER "MLIR/Libraries")414 415  # Setup aggregate.416  if(ARG_ENABLE_AGGREGATION)417    # Compute and store the properties needed to build aggregates.418    set(AGGREGATE_OBJECTS)419    set(AGGREGATE_OBJECT_LIB)420    set(AGGREGATE_DEPS)421    if(XCODE)422      # XCode has limited support for object libraries. Instead, add dep flags423      # that force the entire library to be embedded.424      list(APPEND AGGREGATE_DEPS "-force_load" "${name}")425    elseif(TARGET obj.${name})426      # FIXME: *.obj can also be added via target_link_libraries since CMake 3.12.427      list(APPEND AGGREGATE_OBJECTS "$<TARGET_OBJECTS:obj.${name}>")428      list(APPEND AGGREGATE_OBJECT_LIB "obj.${name}")429    else()430      message(SEND_ERROR "Aggregate library not supported on this platform")431    endif()432 433    # For each declared dependency, transform it into a generator expression434    # which excludes it if the ultimate link target is excluding the library.435    set(NEW_LINK_LIBRARIES)436    get_target_property(CURRENT_LINK_LIBRARIES  ${name} LINK_LIBRARIES)437    get_mlir_filtered_link_libraries(NEW_LINK_LIBRARIES ${CURRENT_LINK_LIBRARIES})438    set_target_properties(${name} PROPERTIES LINK_LIBRARIES "${NEW_LINK_LIBRARIES}")439    list(APPEND AGGREGATE_DEPS ${NEW_LINK_LIBRARIES})440    set_target_properties(${name} PROPERTIES441      EXPORT_PROPERTIES "MLIR_AGGREGATE_OBJECT_LIB_IMPORTED;MLIR_AGGREGATE_DEP_LIBS_IMPORTED"442      MLIR_AGGREGATE_OBJECTS "${AGGREGATE_OBJECTS}"443      MLIR_AGGREGATE_DEPS "${AGGREGATE_DEPS}"444      MLIR_AGGREGATE_OBJECT_LIB_IMPORTED "${AGGREGATE_OBJECT_LIB}"445      MLIR_AGGREGATE_DEP_LIBS_IMPORTED "${CURRENT_LINK_LIBRARIES}"446    )447 448    # In order for out-of-tree projects to build aggregates of this library,449    # we need to install the OBJECT library.450    if(TARGET "obj.${name}" AND MLIR_INSTALL_AGGREGATE_OBJECTS AND NOT ARG_DISABLE_INSTALL)451      add_mlir_library_install(obj.${name})452    endif()453  endif()454endfunction(add_mlir_library)455 456macro(add_mlir_tool name)457  llvm_add_tool(MLIR ${ARGV})458endmacro()459 460# Sets a variable with a transformed list of link libraries such individual461# libraries will be dynamically excluded when evaluated on a final library462# which defines an MLIR_AGGREGATE_EXCLUDE_LIBS which contains any of the463# libraries. Each link library can be a generator expression but must not464# resolve to an arity > 1 (i.e. it can be optional).465function(get_mlir_filtered_link_libraries output)466  set(_results)467  foreach(linklib ${ARGN})468    # In English, what this expression does:469    # For each link library, resolve the property MLIR_AGGREGATE_EXCLUDE_LIBS470    # on the context target (i.e. the executable or shared library being linked)471    # and, if it is not in that list, emit the library name. Otherwise, empty.472    list(APPEND _results473      "$<$<NOT:$<IN_LIST:${linklib},$<GENEX_EVAL:$<TARGET_PROPERTY:MLIR_AGGREGATE_EXCLUDE_LIBS>>>>:${linklib}>"474    )475  endforeach()476  set(${output} "${_results}" PARENT_SCOPE)477endfunction(get_mlir_filtered_link_libraries)478 479# Declares an aggregate library. Such a library is a combination of arbitrary480# regular add_mlir_library() libraries with the special feature that they can481# be configured to statically embed some subset of their dependencies, as is482# typical when creating a .so/.dylib/.dll or a mondo static library.483#484# It is always safe to depend on the aggregate directly in order to compile/link485# against the superset of embedded entities and transitive deps.486#487# Arguments:488#   PUBLIC_LIBS: list of dependent libraries to add to the489#     INTERFACE_LINK_LIBRARIES property, exporting them to users. This list490#     will be transitively filtered to exclude any EMBED_LIBS.491#   EMBED_LIBS: list of dependent libraries that should be embedded directly492#     into this library. Each of these must be an add_mlir_library() library493#     without DISABLE_AGGREGATE.494#495# Note: This is a work in progress and is presently only sufficient for certain496# non nested cases involving the C-API.497function(add_mlir_aggregate name)498  cmake_parse_arguments(ARG499    "SHARED;STATIC"500    ""501    "PUBLIC_LIBS;EMBED_LIBS"502    ${ARGN})503  set(_libtype)504  if(ARG_STATIC)505    list(APPEND _libtype STATIC)506  endif()507  if(ARG_SHARED)508    list(APPEND _libtype SHARED)509  endif()510  set(_debugmsg)511 512  set(_embed_libs)513  set(_objects)514  set(_deps)515  foreach(lib ${ARG_EMBED_LIBS})516    # We have to handle imported vs in-tree differently:517    #   in-tree: To support arbitrary ordering, the generator expressions get518    #     set on the dependent target when it is constructed and then just519    #     eval'd here. This means we can build an aggregate from targets that520    #     may not yet be defined, which is typical for in-tree.521    #   imported: Exported properties do not support generator expressions, so522    #     we imperatively query and manage the expansion here. This is fine523    #     because imported targets will always be found/configured first and524    #     do not need to support arbitrary ordering. If CMake every supports525    #     exporting generator expressions, then this can be simplified.526    set(_is_imported OFF)527    if(TARGET ${lib})528      get_target_property(_is_imported ${lib} IMPORTED)529    endif()530 531    if(NOT _is_imported)532      # Evaluate the in-tree generator expressions directly (this allows target533      # order independence, since these aren't evaluated until the generate534      # phase).535      # What these expressions do:536      # In the context of this aggregate, resolve the list of OBJECTS and DEPS537      # that each library advertises and patch it into the whole.538      set(_local_objects $<TARGET_GENEX_EVAL:${name},$<TARGET_PROPERTY:${lib},MLIR_AGGREGATE_OBJECTS>>)539      set(_local_deps $<TARGET_GENEX_EVAL:${name},$<TARGET_PROPERTY:${lib},MLIR_AGGREGATE_DEPS>>)540    else()541      # It is an imported target, which can only have flat strings populated542      # (no generator expressions).543      # Rebuild the generator expressions from the imported flat string lists.544      if(NOT MLIR_INSTALL_AGGREGATE_OBJECTS)545        message(SEND_ERROR "Cannot build aggregate from imported targets which were not installed via MLIR_INSTALL_AGGREGATE_OBJECTS (for ${lib}).")546      endif()547 548      get_property(_has_object_lib_prop TARGET ${lib} PROPERTY MLIR_AGGREGATE_OBJECT_LIB_IMPORTED SET)549      get_property(_has_dep_libs_prop TARGET ${lib} PROPERTY MLIR_AGGREGATE_DEP_LIBS_IMPORTED SET)550      if(NOT _has_object_lib_prop OR NOT _has_dep_libs_prop)551        message(SEND_ERROR "Cannot create an aggregate out of imported ${lib}: It is missing properties indicating that it was built for aggregation")552      endif()553      get_target_property(_imp_local_object_lib ${lib} MLIR_AGGREGATE_OBJECT_LIB_IMPORTED)554      get_target_property(_imp_dep_libs ${lib} MLIR_AGGREGATE_DEP_LIBS_IMPORTED)555      set(_local_objects)556      if(_imp_local_object_lib)557        set(_local_objects "$<TARGET_OBJECTS:${_imp_local_object_lib}>")558      endif()559      # We should just be able to do this:560      #   get_mlir_filtered_link_libraries(_local_deps ${_imp_dep_libs})561      # However, CMake complains about the unqualified use of the one-arg562      # $<TARGET_PROPERTY> expression. So we do the same thing but use the563      # two-arg form which takes an explicit target.564      foreach(_imp_dep_lib ${_imp_dep_libs})565        # In English, what this expression does:566        # For each link library, resolve the property MLIR_AGGREGATE_EXCLUDE_LIBS567        # on the context target (i.e. the executable or shared library being linked)568        # and, if it is not in that list, emit the library name. Otherwise, empty.569        list(APPEND _local_deps570          "$<$<NOT:$<IN_LIST:${_imp_dep_lib},$<GENEX_EVAL:$<TARGET_PROPERTY:${name},MLIR_AGGREGATE_EXCLUDE_LIBS>>>>:${_imp_dep_lib}>"571        )572      endforeach()573    endif()574 575    list(APPEND _embed_libs ${lib})576    list(APPEND _objects ${_local_objects})577    list(APPEND _deps ${_local_deps})578 579    string(APPEND _debugmsg580      ": EMBED_LIB ${lib}:\n"581      "    OBJECTS = ${_local_objects}\n"582      "    DEPS = ${_local_deps}\n\n")583  endforeach()584 585  add_mlir_library(${name}586    ${_libtype}587    ${ARG_UNPARSED_ARGUMENTS}588    PARTIAL_SOURCES_INTENDED589    EXCLUDE_FROM_LIBMLIR590    LINK_LIBS PRIVATE591    ${_deps}592    ${ARG_PUBLIC_LIBS}593  )594  target_sources(${name} PRIVATE ${_objects})595 596  # Linux defaults to allowing undefined symbols in shared libraries whereas597  # many other platforms are more strict. We want these libraries to be598  # self contained, and we want any undefined symbols to be reported at599  # library construction time, not at library use, so make Linux strict too.600  # We make an exception for sanitizer builds, since the AddressSanitizer601  # run-time doesn't get linked into shared libraries.602  if((CMAKE_SYSTEM_NAME STREQUAL "Linux") AND (NOT LLVM_USE_SANITIZER))603    target_link_options(${name} PRIVATE604      "LINKER:-z,defs"605    )606  endif()607 608  # TODO: Should be transitive.609  set_target_properties(${name} PROPERTIES610    MLIR_AGGREGATE_EXCLUDE_LIBS "${_embed_libs}")611  if(WIN32)612    set_property(TARGET ${name} PROPERTY WINDOWS_EXPORT_ALL_SYMBOLS ON)613  endif()614 615  # Debugging generator expressions can be hard. Uncomment the below to emit616  # files next to the library with a lot of debug information:617  # string(APPEND _debugmsg618  #   ": MAIN LIBRARY:\n"619  #   "    OBJECTS = ${_objects}\n"620  #   "    SOURCES = $<TARGET_GENEX_EVAL:${name},$<TARGET_PROPERTY:${name},SOURCES>>\n"621  #   "    DEPS = ${_deps}\n"622  #   "    LINK_LIBRARIES = $<TARGET_GENEX_EVAL:${name},$<TARGET_PROPERTY:${name},LINK_LIBRARIES>>\n"623  #   "    MLIR_AGGREGATE_EXCLUDE_LIBS = $<TARGET_GENEX_EVAL:${name},$<TARGET_PROPERTY:${name},MLIR_AGGREGATE_EXCLUDE_LIBS>>\n"624  # )625  # file(GENERATE OUTPUT626  #   "${CMAKE_CURRENT_BINARY_DIR}/${name}.aggregate_debug.txt"627  #   CONTENT "${_debugmsg}"628  # )629endfunction(add_mlir_aggregate)630 631# Adds an MLIR library target for installation.632# This is usually done as part of add_mlir_library but is broken out for cases633# where non-standard library builds can be installed.634function(add_mlir_library_install name)635  get_target_property(_install_with_toolchain ${name} MLIR_INSTALL_WITH_TOOLCHAIN)636  if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY OR _install_with_toolchain)637    get_target_export_arg(${name} MLIR export_to_mlirtargets UMBRELLA mlir-libraries)638    install(TARGETS ${name}639      COMPONENT ${name}640      ${export_to_mlirtargets}641      LIBRARY DESTINATION lib${LLVM_LIBDIR_SUFFIX}642      ARCHIVE DESTINATION lib${LLVM_LIBDIR_SUFFIX}643      RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"644      # Note that CMake will create a directory like:645      #   objects-${CMAKE_BUILD_TYPE}/obj.LibName646      # and put object files there.647      OBJECTS DESTINATION lib${LLVM_LIBDIR_SUFFIX}648    )649 650    if (NOT LLVM_ENABLE_IDE)651      add_llvm_install_targets(install-${name}652                              DEPENDS ${name}653                              COMPONENT ${name})654    endif()655    set_property(GLOBAL APPEND PROPERTY MLIR_ALL_LIBS ${name})656  endif()657  set_property(GLOBAL APPEND PROPERTY MLIR_EXPORTS ${name})658endfunction()659 660# Declare an mlir library which is part of the public C-API.661function(add_mlir_public_c_api_library name)662  add_mlir_library(${name}663    ${ARGN}664    OBJECT665    EXCLUDE_FROM_LIBMLIR666    ENABLE_AGGREGATION667    ADDITIONAL_HEADER_DIRS668    ${MLIR_MAIN_INCLUDE_DIR}/mlir-c669  )670  # API libraries compile with hidden visibility and macros that enable671  # exporting from the DLL. Only apply to the obj lib, which only affects672  # the exports via a shared library.673  set_target_properties(obj.${name}674    PROPERTIES675    CXX_VISIBILITY_PRESET hidden676  )677  target_compile_definitions(obj.${name}678    PRIVATE679    -DMLIR_CAPI_BUILDING_LIBRARY=1680  )681endfunction()682 683# Declare the library associated with a dialect.684function(add_mlir_dialect_library name)685  set_property(GLOBAL APPEND PROPERTY MLIR_DIALECT_LIBS ${name})686  add_mlir_library(${ARGV} DEPENDS mlir-headers)687endfunction(add_mlir_dialect_library)688 689# Declare the library associated with a conversion.690function(add_mlir_conversion_library name)691  set_property(GLOBAL APPEND PROPERTY MLIR_CONVERSION_LIBS ${name})692  add_mlir_library(${ARGV} DEPENDS mlir-headers)693endfunction(add_mlir_conversion_library)694 695# Declare the library associated with an extension.696function(add_mlir_extension_library name)697  set_property(GLOBAL APPEND PROPERTY MLIR_EXTENSION_LIBS ${name})698  add_mlir_library(${ARGV} DEPENDS mlir-headers)699endfunction(add_mlir_extension_library)700 701# Declare the library associated with a translation.702function(add_mlir_translation_library name)703  set_property(GLOBAL APPEND PROPERTY MLIR_TRANSLATION_LIBS ${name})704  add_mlir_library(${ARGV} DEPENDS mlir-headers)705endfunction(add_mlir_translation_library)706 707# Verification tools to aid debugging.708function(mlir_check_link_libraries name)709  if(TARGET ${name})710    get_target_property(type ${name} TYPE)711    if (${type} STREQUAL "INTERFACE_LIBRARY")712      get_target_property(libs ${name} INTERFACE_LINK_LIBRARIES)713    else()714      get_target_property(libs ${name} LINK_LIBRARIES)715    endif()716    # message("${name} libs are: ${libs}")717    set(linking_llvm 0)718    foreach(lib ${libs})719      if(lib)720        if(${lib} MATCHES "^LLVM$")721          set(linking_llvm 1)722        endif()723        if((${lib} MATCHES "^LLVM.+") AND ${linking_llvm})724          # This will almost always cause execution problems, since the725          # same symbol might be loaded from 2 separate libraries.  This726          # often comes from referring to an LLVM library target727          # explicitly in target_link_libraries()728          message("WARNING: ${name} links LLVM and ${lib}!")729        endif()730      endif()731    endforeach()732  endif()733endfunction(mlir_check_link_libraries)734 735function(mlir_check_all_link_libraries name)736  mlir_check_link_libraries(${name})737  if(TARGET ${name})738    get_target_property(libs ${name} LINK_LIBRARIES)739    # message("${name} libs are: ${libs}")740    foreach(lib ${libs})741      mlir_check_link_libraries(${lib})742    endforeach()743  endif()744endfunction(mlir_check_all_link_libraries)745 746# Link target against a list of MLIR libraries. If MLIR_LINK_MLIR_DYLIB is747# enabled, this will link against the MLIR dylib instead of the static748# libraries.749#750# This function should be used instead of target_link_libraries() when linking751# MLIR libraries that are part of the MLIR dylib. For libraries that are not752# part of the dylib (like test libraries), target_link_libraries() should be753# used.754function(mlir_target_link_libraries target type)755  if (TARGET obj.${target})756    target_link_libraries(obj.${target} ${ARGN})757  endif()758 759  if (MLIR_LINK_MLIR_DYLIB)760    target_link_libraries(${target} ${type} MLIR)761  else()762    target_link_libraries(${target} ${type} ${ARGN})763  endif()764endfunction()765