1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684
|
include(GNUInstallDirs)
include(LLVMDistributionSupport)
# 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}/tablegen_compile_commands.yml)
function(mlir_tablegen ofn)
tablegen(MLIR ${ARGV})
set(TABLEGEN_OUTPUT ${TABLEGEN_OUTPUT} ${CMAKE_CURRENT_BINARY_DIR}/${ofn}
PARENT_SCOPE)
# Get the current set of include paths for this td 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 ${LLVM_TARGET_DEFINITIONS})
else()
set(LLVM_TARGET_DEFINITIONS_ABSOLUTE ${CMAKE_CURRENT_SOURCE_DIR}/${LLVM_TARGET_DEFINITIONS})
endif()
# Append the includes used for this file to the tablegen_compile_commands
# file.
file(APPEND ${CMAKE_BINARY_DIR}/tablegen_compile_commands.yml
"--- !FileInfo:\n"
" filepath: \"${LLVM_TARGET_DEFINITIONS_ABSOLUTE}\"\n"
" includes: \"${CMAKE_CURRENT_SOURCE_DIR};${tblgen_includes}\"\n"
)
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_TABLEGEN_FLAGS}
${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)
tablegen(MLIR ${output_file}.md ${command} ${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)
|