This file is a list of files and their required include dirs, used by the TableGen LSP server (https://mlir.llvm.org/docs/Tools/MLIRLSP/#tablegen-lsp-language-server--tblgen-lsp-server). Initialy this only included MLIR TableGen files, so I've expanded that by moving it into llvm so all projects that use the llvm `tablegen` function will be added to the file. You could already do some things in llvm TableGen files without this, but were limited with files that don't include their dependencies using `include`, only with command line arguments. Once those are in the yml file, the language server sees all that and go to definition etc. all works.
659 lines
26 KiB
CMake
659 lines
26 KiB
CMake
include(GNUInstallDirs)
|
|
include(LLVMDistributionSupport)
|
|
|
|
function(mlir_tablegen ofn)
|
|
tablegen(MLIR ${ARGV})
|
|
set(TABLEGEN_OUTPUT ${TABLEGEN_OUTPUT} ${CMAKE_CURRENT_BINARY_DIR}/${ofn}
|
|
PARENT_SCOPE)
|
|
endfunction()
|
|
|
|
# Clear out any pre-existing compile_commands file before processing. This
|
|
# allows for generating a clean compile_commands on each configure.
|
|
file(REMOVE ${CMAKE_BINARY_DIR}/pdll_compile_commands.yml)
|
|
|
|
# Declare a helper function/copy of tablegen rule for using tablegen without
|
|
# additional tblgen specific flags when invoking PDLL generator.
|
|
function(_pdll_tablegen project ofn)
|
|
cmake_parse_arguments(ARG "" "" "DEPENDS;EXTRA_INCLUDES" ${ARGN})
|
|
# Validate calling context.
|
|
if(NOT ${project}_TABLEGEN_EXE)
|
|
message(FATAL_ERROR "${project}_TABLEGEN_EXE not set")
|
|
endif()
|
|
|
|
# Use depfile instead of globbing arbitrary *.td(s) for Ninja.
|
|
if(CMAKE_GENERATOR MATCHES "Ninja")
|
|
# Make output path relative to build.ninja, assuming located on
|
|
# ${CMAKE_BINARY_DIR}.
|
|
# CMake emits build targets as relative paths but Ninja doesn't identify
|
|
# absolute path (in *.d) as relative path (in build.ninja)
|
|
# Note that tblgen is executed on ${CMAKE_BINARY_DIR} as working directory.
|
|
file(RELATIVE_PATH ofn_rel
|
|
${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/${ofn})
|
|
set(additional_cmdline
|
|
-o ${ofn_rel}
|
|
-d ${ofn_rel}.d
|
|
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
|
DEPFILE ${CMAKE_CURRENT_BINARY_DIR}/${ofn}.d
|
|
)
|
|
set(local_tds)
|
|
set(global_tds)
|
|
else()
|
|
file(GLOB local_tds "*.td")
|
|
file(GLOB_RECURSE global_tds "${LLVM_MAIN_INCLUDE_DIR}/llvm/*.td")
|
|
set(additional_cmdline
|
|
-o ${CMAKE_CURRENT_BINARY_DIR}/${ofn}
|
|
)
|
|
endif()
|
|
|
|
if (IS_ABSOLUTE ${LLVM_TARGET_DEFINITIONS})
|
|
set(LLVM_TARGET_DEFINITIONS_ABSOLUTE ${LLVM_TARGET_DEFINITIONS})
|
|
else()
|
|
set(LLVM_TARGET_DEFINITIONS_ABSOLUTE
|
|
${CMAKE_CURRENT_SOURCE_DIR}/${LLVM_TARGET_DEFINITIONS})
|
|
endif()
|
|
|
|
if (CMAKE_GENERATOR MATCHES "Visual Studio")
|
|
# Visual Studio has problems with llvm-tblgen's native --write-if-changed
|
|
# behavior. Since it doesn't do restat optimizations anyway, just don't
|
|
# pass --write-if-changed there.
|
|
set(tblgen_change_flag)
|
|
else()
|
|
set(tblgen_change_flag "--write-if-changed")
|
|
endif()
|
|
|
|
# We need both _TABLEGEN_TARGET and _TABLEGEN_EXE in the DEPENDS list
|
|
# (both the target and the file) to have .inc files rebuilt on
|
|
# a tablegen change, as cmake does not propagate file-level dependencies
|
|
# of custom targets. See the following ticket for more information:
|
|
# https://cmake.org/Bug/view.php?id=15858
|
|
# The dependency on both, the target and the file, produces the same
|
|
# dependency twice in the result file when
|
|
# ("${${project}_TABLEGEN_TARGET}" STREQUAL "${${project}_TABLEGEN_EXE}")
|
|
# but lets us having smaller and cleaner code here.
|
|
get_directory_property(tblgen_includes INCLUDE_DIRECTORIES)
|
|
list(APPEND tblgen_includes ${ARG_EXTRA_INCLUDES})
|
|
# Filter out empty items before prepending each entry with -I
|
|
list(REMOVE_ITEM tblgen_includes "")
|
|
list(TRANSFORM tblgen_includes PREPEND -I)
|
|
|
|
set(tablegen_exe ${${project}_TABLEGEN_EXE})
|
|
set(tablegen_depends ${${project}_TABLEGEN_TARGET} ${tablegen_exe})
|
|
|
|
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${ofn}
|
|
COMMAND ${tablegen_exe} ${ARG_UNPARSED_ARGUMENTS} -I ${CMAKE_CURRENT_SOURCE_DIR}
|
|
${tblgen_includes}
|
|
${LLVM_TARGET_DEFINITIONS_ABSOLUTE}
|
|
${tblgen_change_flag}
|
|
${additional_cmdline}
|
|
# The file in LLVM_TARGET_DEFINITIONS may be not in the current
|
|
# directory and local_tds may not contain it, so we must
|
|
# explicitly list it here:
|
|
DEPENDS ${ARG_DEPENDS} ${tablegen_depends}
|
|
${local_tds} ${global_tds}
|
|
${LLVM_TARGET_DEFINITIONS_ABSOLUTE}
|
|
${LLVM_TARGET_DEPENDS}
|
|
COMMENT "Building ${ofn}..."
|
|
)
|
|
|
|
# `make clean' must remove all those generated files:
|
|
set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES ${ofn})
|
|
|
|
set(TABLEGEN_OUTPUT ${TABLEGEN_OUTPUT} ${CMAKE_CURRENT_BINARY_DIR}/${ofn} PARENT_SCOPE)
|
|
set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/${ofn} PROPERTIES
|
|
GENERATED 1)
|
|
endfunction()
|
|
|
|
# Declare a PDLL library in the current directory.
|
|
function(add_mlir_pdll_library target inputFile ofn)
|
|
set(LLVM_TARGET_DEFINITIONS ${inputFile})
|
|
|
|
_pdll_tablegen(MLIR_PDLL ${ofn} -x=cpp ${ARGN})
|
|
set(TABLEGEN_OUTPUT ${TABLEGEN_OUTPUT} ${CMAKE_CURRENT_BINARY_DIR}/${ofn}
|
|
PARENT_SCOPE)
|
|
|
|
# Get the current set of include paths for this pdll file.
|
|
cmake_parse_arguments(ARG "" "" "DEPENDS;EXTRA_INCLUDES" ${ARGN})
|
|
get_directory_property(tblgen_includes INCLUDE_DIRECTORIES)
|
|
list(APPEND tblgen_includes ${ARG_EXTRA_INCLUDES})
|
|
# Filter out any empty include items.
|
|
list(REMOVE_ITEM tblgen_includes "")
|
|
|
|
# Build the absolute path for the current input file.
|
|
if (IS_ABSOLUTE ${LLVM_TARGET_DEFINITIONS})
|
|
set(LLVM_TARGET_DEFINITIONS_ABSOLUTE ${inputFile})
|
|
else()
|
|
set(LLVM_TARGET_DEFINITIONS_ABSOLUTE ${CMAKE_CURRENT_SOURCE_DIR}/${inputFile})
|
|
endif()
|
|
|
|
# Append the includes used for this file to the pdll_compilation_commands
|
|
# file.
|
|
file(APPEND ${CMAKE_BINARY_DIR}/pdll_compile_commands.yml
|
|
"--- !FileInfo:\n"
|
|
" filepath: \"${LLVM_TARGET_DEFINITIONS_ABSOLUTE}\"\n"
|
|
" includes: \"${CMAKE_CURRENT_SOURCE_DIR};${tblgen_includes}\"\n"
|
|
)
|
|
|
|
add_public_tablegen_target(${target})
|
|
endfunction()
|
|
|
|
# Declare a dialect in the include directory
|
|
function(add_mlir_dialect dialect dialect_namespace)
|
|
set(LLVM_TARGET_DEFINITIONS ${dialect}.td)
|
|
mlir_tablegen(${dialect}.h.inc -gen-op-decls)
|
|
mlir_tablegen(${dialect}.cpp.inc -gen-op-defs)
|
|
mlir_tablegen(${dialect}Types.h.inc -gen-typedef-decls -typedefs-dialect=${dialect_namespace})
|
|
mlir_tablegen(${dialect}Types.cpp.inc -gen-typedef-defs -typedefs-dialect=${dialect_namespace})
|
|
mlir_tablegen(${dialect}Dialect.h.inc -gen-dialect-decls -dialect=${dialect_namespace})
|
|
mlir_tablegen(${dialect}Dialect.cpp.inc -gen-dialect-defs -dialect=${dialect_namespace})
|
|
add_public_tablegen_target(MLIR${dialect}IncGen)
|
|
add_dependencies(mlir-headers MLIR${dialect}IncGen)
|
|
endfunction()
|
|
|
|
# Declare a dialect in the include directory
|
|
function(add_mlir_interface interface)
|
|
set(LLVM_TARGET_DEFINITIONS ${interface}.td)
|
|
mlir_tablegen(${interface}.h.inc -gen-op-interface-decls)
|
|
mlir_tablegen(${interface}.cpp.inc -gen-op-interface-defs)
|
|
add_public_tablegen_target(MLIR${interface}IncGen)
|
|
add_dependencies(mlir-generic-headers MLIR${interface}IncGen)
|
|
endfunction()
|
|
|
|
|
|
# Generate Documentation
|
|
function(add_mlir_doc doc_filename output_file output_directory command)
|
|
set(LLVM_TARGET_DEFINITIONS ${doc_filename}.td)
|
|
# The MLIR docs use Hugo, so we allow Hugo specific features here.
|
|
tablegen(MLIR ${output_file}.md ${command} -allow-hugo-specific-features ${ARGN})
|
|
set(GEN_DOC_FILE ${MLIR_BINARY_DIR}/docs/${output_directory}${output_file}.md)
|
|
add_custom_command(
|
|
OUTPUT ${GEN_DOC_FILE}
|
|
COMMAND ${CMAKE_COMMAND} -E copy
|
|
${CMAKE_CURRENT_BINARY_DIR}/${output_file}.md
|
|
${GEN_DOC_FILE}
|
|
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${output_file}.md)
|
|
add_custom_target(${output_file}DocGen DEPENDS ${GEN_DOC_FILE})
|
|
add_dependencies(mlir-doc ${output_file}DocGen)
|
|
endfunction()
|
|
|
|
# Sets ${srcs} to contain the list of additional headers for the target. Extra
|
|
# arguments are included into the list of additional headers.
|
|
function(_set_mlir_additional_headers_as_srcs)
|
|
set(srcs)
|
|
if(MSVC_IDE OR XCODE)
|
|
# Add public headers
|
|
file(RELATIVE_PATH lib_path
|
|
${MLIR_SOURCE_DIR}/lib/
|
|
${CMAKE_CURRENT_SOURCE_DIR}
|
|
)
|
|
if(NOT lib_path MATCHES "^[.][.]")
|
|
file( GLOB_RECURSE headers
|
|
${MLIR_SOURCE_DIR}/include/mlir/${lib_path}/*.h
|
|
${MLIR_SOURCE_DIR}/include/mlir/${lib_path}/*.def
|
|
)
|
|
set_source_files_properties(${headers} PROPERTIES HEADER_FILE_ONLY ON)
|
|
|
|
file( GLOB_RECURSE tds
|
|
${MLIR_SOURCE_DIR}/include/mlir/${lib_path}/*.td
|
|
)
|
|
source_group("TableGen descriptions" FILES ${tds})
|
|
set_source_files_properties(${tds}} PROPERTIES HEADER_FILE_ONLY ON)
|
|
|
|
if(headers OR tds)
|
|
set(srcs ${headers} ${tds})
|
|
endif()
|
|
endif()
|
|
endif(MSVC_IDE OR XCODE)
|
|
if(srcs OR ARGN)
|
|
set(srcs
|
|
ADDITIONAL_HEADERS
|
|
${srcs}
|
|
${ARGN} # It may contain unparsed unknown args.
|
|
PARENT_SCOPE
|
|
)
|
|
endif()
|
|
endfunction()
|
|
|
|
# Checks that the LLVM components are not listed in the extra arguments,
|
|
# assumed to be coming from the LINK_LIBS variable.
|
|
function(_check_llvm_components_usage name)
|
|
# LINK_COMPONENTS is necessary to allow libLLVM.so to be properly
|
|
# substituted for individual library dependencies if LLVM_LINK_LLVM_DYLIB
|
|
# Perhaps this should be in llvm_add_library instead? However, it fails
|
|
# on libclang-cpp.so
|
|
get_property(llvm_component_libs GLOBAL PROPERTY LLVM_COMPONENT_LIBS)
|
|
foreach(lib ${ARGN})
|
|
if(${lib} IN_LIST llvm_component_libs)
|
|
message(SEND_ERROR "${name} specifies LINK_LIBS ${lib}, but LINK_LIBS cannot be used for LLVM libraries. Please use LINK_COMPONENTS instead.")
|
|
endif()
|
|
endforeach()
|
|
endfunction()
|
|
|
|
function(add_mlir_example_library name)
|
|
cmake_parse_arguments(ARG
|
|
"SHARED;DISABLE_INSTALL"
|
|
""
|
|
"ADDITIONAL_HEADERS;DEPENDS;LINK_COMPONENTS;LINK_LIBS"
|
|
${ARGN})
|
|
_set_mlir_additional_headers_as_srcs(${ARG_ADDITIONAL_HEADERS})
|
|
if (ARG_SHARED)
|
|
set(LIBTYPE SHARED)
|
|
else()
|
|
if(BUILD_SHARED_LIBS)
|
|
set(LIBTYPE SHARED)
|
|
else()
|
|
set(LIBTYPE STATIC)
|
|
endif()
|
|
endif()
|
|
|
|
# MLIR libraries uniformly depend on LLVMSupport. Just specify it once here.
|
|
list(APPEND ARG_LINK_COMPONENTS Support)
|
|
_check_llvm_components_usage(${name} ${ARG_LINK_LIBS})
|
|
|
|
list(APPEND ARG_DEPENDS mlir-generic-headers)
|
|
|
|
llvm_add_library(${name} ${LIBTYPE} ${ARG_UNPARSED_ARGUMENTS} ${srcs} DEPENDS ${ARG_DEPENDS} LINK_COMPONENTS ${ARG_LINK_COMPONENTS} LINK_LIBS ${ARG_LINK_LIBS})
|
|
set_target_properties(${name} PROPERTIES FOLDER "Examples")
|
|
if (LLVM_BUILD_EXAMPLES AND NOT ${ARG_DISABLE_INSTALL})
|
|
add_mlir_library_install(${name})
|
|
else()
|
|
set_target_properties(${name} PROPERTIES EXCLUDE_FROM_ALL ON)
|
|
endif()
|
|
endfunction()
|
|
|
|
# Declare an mlir library which can be compiled in libMLIR.so
|
|
# In addition to everything that llvm_add_library accepts, this
|
|
# also has the following option:
|
|
# EXCLUDE_FROM_LIBMLIR
|
|
# Don't include this library in libMLIR.so. This option should be used
|
|
# for test libraries, executable-specific libraries, or rarely used libraries
|
|
# with large dependencies.
|
|
# ENABLE_AGGREGATION
|
|
# Forces generation of an OBJECT library, exports additional metadata,
|
|
# and installs additional object files needed to include this as part of an
|
|
# aggregate shared library.
|
|
# TODO: Make this the default for all MLIR libraries once all libraries
|
|
# are compatible with building an object library.
|
|
function(add_mlir_library name)
|
|
cmake_parse_arguments(ARG
|
|
"SHARED;INSTALL_WITH_TOOLCHAIN;EXCLUDE_FROM_LIBMLIR;DISABLE_INSTALL;ENABLE_AGGREGATION"
|
|
""
|
|
"ADDITIONAL_HEADERS;DEPENDS;LINK_COMPONENTS;LINK_LIBS"
|
|
${ARGN})
|
|
_set_mlir_additional_headers_as_srcs(${ARG_ADDITIONAL_HEADERS})
|
|
|
|
# Is an object library needed.
|
|
set(NEEDS_OBJECT_LIB OFF)
|
|
if(ARG_ENABLE_AGGREGATION)
|
|
set(NEEDS_OBJECT_LIB ON)
|
|
endif()
|
|
|
|
# Determine type of library.
|
|
if(ARG_SHARED)
|
|
set(LIBTYPE SHARED)
|
|
else()
|
|
# llvm_add_library ignores BUILD_SHARED_LIBS if STATIC is explicitly set,
|
|
# so we need to handle it here.
|
|
if(BUILD_SHARED_LIBS)
|
|
set(LIBTYPE SHARED)
|
|
else()
|
|
set(LIBTYPE STATIC)
|
|
endif()
|
|
# Test libraries and such shouldn't be include in libMLIR.so
|
|
if(NOT ARG_EXCLUDE_FROM_LIBMLIR)
|
|
set(NEEDS_OBJECT_LIB ON)
|
|
set_property(GLOBAL APPEND PROPERTY MLIR_STATIC_LIBS ${name})
|
|
set_property(GLOBAL APPEND PROPERTY MLIR_LLVM_LINK_COMPONENTS ${ARG_LINK_COMPONENTS})
|
|
set_property(GLOBAL APPEND PROPERTY MLIR_LLVM_LINK_COMPONENTS ${LLVM_LINK_COMPONENTS})
|
|
endif()
|
|
endif()
|
|
|
|
if(NEEDS_OBJECT_LIB AND NOT XCODE)
|
|
# The Xcode generator doesn't handle object libraries correctly.
|
|
# We special case xcode when building aggregates.
|
|
list(APPEND LIBTYPE OBJECT)
|
|
endif()
|
|
|
|
# MLIR libraries uniformly depend on LLVMSupport. Just specify it once here.
|
|
list(APPEND ARG_LINK_COMPONENTS Support)
|
|
_check_llvm_components_usage(${name} ${ARG_LINK_LIBS})
|
|
|
|
list(APPEND ARG_DEPENDS mlir-generic-headers)
|
|
llvm_add_library(${name} ${LIBTYPE} ${ARG_UNPARSED_ARGUMENTS} ${srcs} DEPENDS ${ARG_DEPENDS} LINK_COMPONENTS ${ARG_LINK_COMPONENTS} LINK_LIBS ${ARG_LINK_LIBS})
|
|
|
|
if(TARGET ${name})
|
|
target_link_libraries(${name} INTERFACE ${LLVM_COMMON_LIBS})
|
|
if(NOT ARG_DISABLE_INSTALL)
|
|
add_mlir_library_install(${name})
|
|
endif()
|
|
else()
|
|
# Add empty "phony" target
|
|
add_custom_target(${name})
|
|
endif()
|
|
set_target_properties(${name} PROPERTIES FOLDER "MLIR libraries")
|
|
|
|
# Setup aggregate.
|
|
if(ARG_ENABLE_AGGREGATION)
|
|
# Compute and store the properties needed to build aggregates.
|
|
set(AGGREGATE_OBJECTS)
|
|
set(AGGREGATE_OBJECT_LIB)
|
|
set(AGGREGATE_DEPS)
|
|
if(XCODE)
|
|
# XCode has limited support for object libraries. Instead, add dep flags
|
|
# that force the entire library to be embedded.
|
|
list(APPEND AGGREGATE_DEPS "-force_load" "${name}")
|
|
else()
|
|
list(APPEND AGGREGATE_OBJECTS "$<TARGET_OBJECTS:obj.${name}>")
|
|
list(APPEND AGGREGATE_OBJECT_LIB "obj.${name}")
|
|
endif()
|
|
|
|
# For each declared dependency, transform it into a generator expression
|
|
# which excludes it if the ultimate link target is excluding the library.
|
|
set(NEW_LINK_LIBRARIES)
|
|
get_target_property(CURRENT_LINK_LIBRARIES ${name} LINK_LIBRARIES)
|
|
get_mlir_filtered_link_libraries(NEW_LINK_LIBRARIES ${CURRENT_LINK_LIBRARIES})
|
|
set_target_properties(${name} PROPERTIES LINK_LIBRARIES "${NEW_LINK_LIBRARIES}")
|
|
list(APPEND AGGREGATE_DEPS ${NEW_LINK_LIBRARIES})
|
|
set_target_properties(${name} PROPERTIES
|
|
EXPORT_PROPERTIES "MLIR_AGGREGATE_OBJECT_LIB_IMPORTED;MLIR_AGGREGATE_DEP_LIBS_IMPORTED"
|
|
MLIR_AGGREGATE_OBJECTS "${AGGREGATE_OBJECTS}"
|
|
MLIR_AGGREGATE_DEPS "${AGGREGATE_DEPS}"
|
|
MLIR_AGGREGATE_OBJECT_LIB_IMPORTED "${AGGREGATE_OBJECT_LIB}"
|
|
MLIR_AGGREGATE_DEP_LIBS_IMPORTED "${CURRENT_LINK_LIBRARIES}"
|
|
)
|
|
|
|
# In order for out-of-tree projects to build aggregates of this library,
|
|
# we need to install the OBJECT library.
|
|
if(MLIR_INSTALL_AGGREGATE_OBJECTS AND NOT ARG_DISABLE_INSTALL)
|
|
add_mlir_library_install(obj.${name})
|
|
endif()
|
|
endif()
|
|
endfunction(add_mlir_library)
|
|
|
|
macro(add_mlir_tool name)
|
|
llvm_add_tool(MLIR ${ARGV})
|
|
endmacro()
|
|
|
|
# Sets a variable with a transformed list of link libraries such individual
|
|
# libraries will be dynamically excluded when evaluated on a final library
|
|
# which defines an MLIR_AGGREGATE_EXCLUDE_LIBS which contains any of the
|
|
# libraries. Each link library can be a generator expression but must not
|
|
# resolve to an arity > 1 (i.e. it can be optional).
|
|
function(get_mlir_filtered_link_libraries output)
|
|
set(_results)
|
|
foreach(linklib ${ARGN})
|
|
# In English, what this expression does:
|
|
# For each link library, resolve the property MLIR_AGGREGATE_EXCLUDE_LIBS
|
|
# on the context target (i.e. the executable or shared library being linked)
|
|
# and, if it is not in that list, emit the library name. Otherwise, empty.
|
|
list(APPEND _results
|
|
"$<$<NOT:$<IN_LIST:${linklib},$<GENEX_EVAL:$<TARGET_PROPERTY:MLIR_AGGREGATE_EXCLUDE_LIBS>>>>:${linklib}>"
|
|
)
|
|
endforeach()
|
|
set(${output} "${_results}" PARENT_SCOPE)
|
|
endfunction(get_mlir_filtered_link_libraries)
|
|
|
|
# Declares an aggregate library. Such a library is a combination of arbitrary
|
|
# regular add_mlir_library() libraries with the special feature that they can
|
|
# be configured to statically embed some subset of their dependencies, as is
|
|
# typical when creating a .so/.dylib/.dll or a mondo static library.
|
|
#
|
|
# It is always safe to depend on the aggregate directly in order to compile/link
|
|
# against the superset of embedded entities and transitive deps.
|
|
#
|
|
# Arguments:
|
|
# PUBLIC_LIBS: list of dependent libraries to add to the
|
|
# INTERFACE_LINK_LIBRARIES property, exporting them to users. This list
|
|
# will be transitively filtered to exclude any EMBED_LIBS.
|
|
# EMBED_LIBS: list of dependent libraries that should be embedded directly
|
|
# into this library. Each of these must be an add_mlir_library() library
|
|
# without DISABLE_AGGREGATE.
|
|
#
|
|
# Note: This is a work in progress and is presently only sufficient for certain
|
|
# non nested cases involving the C-API.
|
|
function(add_mlir_aggregate name)
|
|
cmake_parse_arguments(ARG
|
|
"SHARED;STATIC"
|
|
""
|
|
"PUBLIC_LIBS;EMBED_LIBS"
|
|
${ARGN})
|
|
set(_libtype)
|
|
if(ARG_STATIC)
|
|
list(APPEND _libtype STATIC)
|
|
endif()
|
|
if(ARG_SHARED)
|
|
list(APPEND _libtype SHARED)
|
|
endif()
|
|
set(_debugmsg)
|
|
|
|
set(_embed_libs)
|
|
set(_objects)
|
|
set(_deps)
|
|
foreach(lib ${ARG_EMBED_LIBS})
|
|
# We have to handle imported vs in-tree differently:
|
|
# in-tree: To support arbitrary ordering, the generator expressions get
|
|
# set on the dependent target when it is constructed and then just
|
|
# eval'd here. This means we can build an aggregate from targets that
|
|
# may not yet be defined, which is typical for in-tree.
|
|
# imported: Exported properties do not support generator expressions, so
|
|
# we imperatively query and manage the expansion here. This is fine
|
|
# because imported targets will always be found/configured first and
|
|
# do not need to support arbitrary ordering. If CMake every supports
|
|
# exporting generator expressions, then this can be simplified.
|
|
set(_is_imported OFF)
|
|
if(TARGET ${lib})
|
|
get_target_property(_is_imported ${lib} IMPORTED)
|
|
endif()
|
|
|
|
if(NOT _is_imported)
|
|
# Evaluate the in-tree generator expressions directly (this allows target
|
|
# order independence, since these aren't evaluated until the generate
|
|
# phase).
|
|
# What these expressions do:
|
|
# In the context of this aggregate, resolve the list of OBJECTS and DEPS
|
|
# that each library advertises and patch it into the whole.
|
|
set(_local_objects $<TARGET_GENEX_EVAL:${name},$<TARGET_PROPERTY:${lib},MLIR_AGGREGATE_OBJECTS>>)
|
|
set(_local_deps $<TARGET_GENEX_EVAL:${name},$<TARGET_PROPERTY:${lib},MLIR_AGGREGATE_DEPS>>)
|
|
else()
|
|
# It is an imported target, which can only have flat strings populated
|
|
# (no generator expressions).
|
|
# Rebuild the generator expressions from the imported flat string lists.
|
|
if(NOT MLIR_INSTALL_AGGREGATE_OBJECTS)
|
|
message(SEND_ERROR "Cannot build aggregate from imported targets which were not installed via MLIR_INSTALL_AGGREGATE_OBJECTS (for ${lib}).")
|
|
endif()
|
|
|
|
get_property(_has_object_lib_prop TARGET ${lib} PROPERTY MLIR_AGGREGATE_OBJECT_LIB_IMPORTED SET)
|
|
get_property(_has_dep_libs_prop TARGET ${lib} PROPERTY MLIR_AGGREGATE_DEP_LIBS_IMPORTED SET)
|
|
if(NOT _has_object_lib_prop OR NOT _has_dep_libs_prop)
|
|
message(SEND_ERROR "Cannot create an aggregate out of imported ${lib}: It is missing properties indicating that it was built for aggregation")
|
|
endif()
|
|
get_target_property(_imp_local_object_lib ${lib} MLIR_AGGREGATE_OBJECT_LIB_IMPORTED)
|
|
get_target_property(_imp_dep_libs ${lib} MLIR_AGGREGATE_DEP_LIBS_IMPORTED)
|
|
set(_local_objects)
|
|
if(_imp_local_object_lib)
|
|
set(_local_objects "$<TARGET_OBJECTS:${_imp_local_object_lib}>")
|
|
endif()
|
|
# We should just be able to do this:
|
|
# get_mlir_filtered_link_libraries(_local_deps ${_imp_dep_libs})
|
|
# However, CMake complains about the unqualified use of the one-arg
|
|
# $<TARGET_PROPERTY> expression. So we do the same thing but use the
|
|
# two-arg form which takes an explicit target.
|
|
foreach(_imp_dep_lib ${_imp_dep_libs})
|
|
# In English, what this expression does:
|
|
# For each link library, resolve the property MLIR_AGGREGATE_EXCLUDE_LIBS
|
|
# on the context target (i.e. the executable or shared library being linked)
|
|
# and, if it is not in that list, emit the library name. Otherwise, empty.
|
|
list(APPEND _local_deps
|
|
"$<$<NOT:$<IN_LIST:${_imp_dep_lib},$<GENEX_EVAL:$<TARGET_PROPERTY:${name},MLIR_AGGREGATE_EXCLUDE_LIBS>>>>:${_imp_dep_lib}>"
|
|
)
|
|
endforeach()
|
|
endif()
|
|
|
|
list(APPEND _embed_libs ${lib})
|
|
list(APPEND _objects ${_local_objects})
|
|
list(APPEND _deps ${_local_deps})
|
|
|
|
string(APPEND _debugmsg
|
|
": EMBED_LIB ${lib}:\n"
|
|
" OBJECTS = ${_local_objects}\n"
|
|
" DEPS = ${_local_deps}\n\n")
|
|
endforeach()
|
|
|
|
add_mlir_library(${name}
|
|
${_libtype}
|
|
${ARG_UNPARSED_ARGUMENTS}
|
|
PARTIAL_SOURCES_INTENDED
|
|
EXCLUDE_FROM_LIBMLIR
|
|
LINK_LIBS PRIVATE
|
|
${_deps}
|
|
${ARG_PUBLIC_LIBS}
|
|
)
|
|
target_sources(${name} PRIVATE ${_objects})
|
|
|
|
# Linux defaults to allowing undefined symbols in shared libraries whereas
|
|
# many other platforms are more strict. We want these libraries to be
|
|
# self contained, and we want any undefined symbols to be reported at
|
|
# library construction time, not at library use, so make Linux strict too.
|
|
# We make an exception for sanitizer builds, since the AddressSanitizer
|
|
# run-time doesn't get linked into shared libraries.
|
|
if((CMAKE_SYSTEM_NAME STREQUAL "Linux") AND (NOT LLVM_USE_SANITIZER))
|
|
target_link_options(${name} PRIVATE
|
|
"LINKER:-z,defs"
|
|
)
|
|
endif()
|
|
|
|
# TODO: Should be transitive.
|
|
set_target_properties(${name} PROPERTIES
|
|
MLIR_AGGREGATE_EXCLUDE_LIBS "${_embed_libs}")
|
|
if(MSVC)
|
|
set_property(TARGET ${name} PROPERTY WINDOWS_EXPORT_ALL_SYMBOLS ON)
|
|
endif()
|
|
|
|
# Debugging generator expressions can be hard. Uncomment the below to emit
|
|
# files next to the library with a lot of debug information:
|
|
# string(APPEND _debugmsg
|
|
# ": MAIN LIBRARY:\n"
|
|
# " OBJECTS = ${_objects}\n"
|
|
# " SOURCES = $<TARGET_GENEX_EVAL:${name},$<TARGET_PROPERTY:${name},SOURCES>>\n"
|
|
# " DEPS = ${_deps}\n"
|
|
# " LINK_LIBRARIES = $<TARGET_GENEX_EVAL:${name},$<TARGET_PROPERTY:${name},LINK_LIBRARIES>>\n"
|
|
# " MLIR_AGGREGATE_EXCLUDE_LIBS = $<TARGET_GENEX_EVAL:${name},$<TARGET_PROPERTY:${name},MLIR_AGGREGATE_EXCLUDE_LIBS>>\n"
|
|
# )
|
|
# file(GENERATE OUTPUT
|
|
# "${CMAKE_CURRENT_BINARY_DIR}/${name}.aggregate_debug.txt"
|
|
# CONTENT "${_debugmsg}"
|
|
# )
|
|
endfunction(add_mlir_aggregate)
|
|
|
|
# Adds an MLIR library target for installation.
|
|
# This is usually done as part of add_mlir_library but is broken out for cases
|
|
# where non-standard library builds can be installed.
|
|
function(add_mlir_library_install name)
|
|
if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY)
|
|
get_target_export_arg(${name} MLIR export_to_mlirtargets UMBRELLA mlir-libraries)
|
|
install(TARGETS ${name}
|
|
COMPONENT ${name}
|
|
${export_to_mlirtargets}
|
|
LIBRARY DESTINATION lib${LLVM_LIBDIR_SUFFIX}
|
|
ARCHIVE DESTINATION lib${LLVM_LIBDIR_SUFFIX}
|
|
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
|
|
# Note that CMake will create a directory like:
|
|
# objects-${CMAKE_BUILD_TYPE}/obj.LibName
|
|
# and put object files there.
|
|
OBJECTS DESTINATION lib${LLVM_LIBDIR_SUFFIX}
|
|
)
|
|
|
|
if (NOT LLVM_ENABLE_IDE)
|
|
add_llvm_install_targets(install-${name}
|
|
DEPENDS ${name}
|
|
COMPONENT ${name})
|
|
endif()
|
|
set_property(GLOBAL APPEND PROPERTY MLIR_ALL_LIBS ${name})
|
|
endif()
|
|
set_property(GLOBAL APPEND PROPERTY MLIR_EXPORTS ${name})
|
|
endfunction()
|
|
|
|
# Declare an mlir library which is part of the public C-API.
|
|
function(add_mlir_public_c_api_library name)
|
|
add_mlir_library(${name}
|
|
${ARGN}
|
|
EXCLUDE_FROM_LIBMLIR
|
|
ENABLE_AGGREGATION
|
|
ADDITIONAL_HEADER_DIRS
|
|
${MLIR_MAIN_INCLUDE_DIR}/mlir-c
|
|
)
|
|
# API libraries compile with hidden visibility and macros that enable
|
|
# exporting from the DLL. Only apply to the obj lib, which only affects
|
|
# the exports via a shared library.
|
|
set_target_properties(obj.${name}
|
|
PROPERTIES
|
|
CXX_VISIBILITY_PRESET hidden
|
|
)
|
|
target_compile_definitions(obj.${name}
|
|
PRIVATE
|
|
-DMLIR_CAPI_BUILDING_LIBRARY=1
|
|
)
|
|
endfunction()
|
|
|
|
# Declare the library associated with a dialect.
|
|
function(add_mlir_dialect_library name)
|
|
set_property(GLOBAL APPEND PROPERTY MLIR_DIALECT_LIBS ${name})
|
|
add_mlir_library(${ARGV} DEPENDS mlir-headers)
|
|
endfunction(add_mlir_dialect_library)
|
|
|
|
# Declare the library associated with a conversion.
|
|
function(add_mlir_conversion_library name)
|
|
set_property(GLOBAL APPEND PROPERTY MLIR_CONVERSION_LIBS ${name})
|
|
add_mlir_library(${ARGV} DEPENDS mlir-headers)
|
|
endfunction(add_mlir_conversion_library)
|
|
|
|
# Declare the library associated with an extension.
|
|
function(add_mlir_extension_library name)
|
|
set_property(GLOBAL APPEND PROPERTY MLIR_EXTENSION_LIBS ${name})
|
|
add_mlir_library(${ARGV} DEPENDS mlir-headers)
|
|
endfunction(add_mlir_extension_library)
|
|
|
|
# Declare the library associated with a translation.
|
|
function(add_mlir_translation_library name)
|
|
set_property(GLOBAL APPEND PROPERTY MLIR_TRANSLATION_LIBS ${name})
|
|
add_mlir_library(${ARGV} DEPENDS mlir-headers)
|
|
endfunction(add_mlir_translation_library)
|
|
|
|
# Verification tools to aid debugging.
|
|
function(mlir_check_link_libraries name)
|
|
if(TARGET ${name})
|
|
get_target_property(type ${name} TYPE)
|
|
if (${type} STREQUAL "INTERFACE_LIBRARY")
|
|
get_target_property(libs ${name} INTERFACE_LINK_LIBRARIES)
|
|
else()
|
|
get_target_property(libs ${name} LINK_LIBRARIES)
|
|
endif()
|
|
# message("${name} libs are: ${libs}")
|
|
set(linking_llvm 0)
|
|
foreach(lib ${libs})
|
|
if(lib)
|
|
if(${lib} MATCHES "^LLVM$")
|
|
set(linking_llvm 1)
|
|
endif()
|
|
if((${lib} MATCHES "^LLVM.+") AND ${linking_llvm})
|
|
# This will almost always cause execution problems, since the
|
|
# same symbol might be loaded from 2 separate libraries. This
|
|
# often comes from referring to an LLVM library target
|
|
# explicitly in target_link_libraries()
|
|
message("WARNING: ${name} links LLVM and ${lib}!")
|
|
endif()
|
|
endif()
|
|
endforeach()
|
|
endif()
|
|
endfunction(mlir_check_link_libraries)
|
|
|
|
function(mlir_check_all_link_libraries name)
|
|
mlir_check_link_libraries(${name})
|
|
if(TARGET ${name})
|
|
get_target_property(libs ${name} LINK_LIBRARIES)
|
|
# message("${name} libs are: ${libs}")
|
|
foreach(lib ${libs})
|
|
mlir_check_link_libraries(${lib})
|
|
endforeach()
|
|
endif()
|
|
endfunction(mlir_check_all_link_libraries)
|