1include(GNUInstallDirs) 2include(LLVMDistributionSupport) 3 4function(mlir_tablegen ofn) 5 tablegen(MLIR ${ARGV}) 6 set(TABLEGEN_OUTPUT ${TABLEGEN_OUTPUT} ${CMAKE_CURRENT_BINARY_DIR}/${ofn} 7 PARENT_SCOPE) 8 9 # Get the current set of include paths for this td file. 10 cmake_parse_arguments(ARG "" "" "DEPENDS;EXTRA_INCLUDES" ${ARGN}) 11 get_directory_property(tblgen_includes INCLUDE_DIRECTORIES) 12 list(APPEND tblgen_includes ${ARG_EXTRA_INCLUDES}) 13 # Filter out any empty include items. 14 list(REMOVE_ITEM tblgen_includes "") 15 16 # Build the absolute path for the current input file. 17 if (IS_ABSOLUTE ${LLVM_TARGET_DEFINITIONS}) 18 set(LLVM_TARGET_DEFINITIONS_ABSOLUTE ${LLVM_TARGET_DEFINITIONS}) 19 else() 20 set(LLVM_TARGET_DEFINITIONS_ABSOLUTE ${CMAKE_CURRENT_SOURCE_DIR}/${LLVM_TARGET_DEFINITIONS}) 21 endif() 22 23 # Append the includes used for this file to the tablegen_compile_commands 24 # file. 25 file(APPEND ${CMAKE_BINARY_DIR}/tablegen_compile_commands.yml 26 "--- !FileInfo:\n" 27 " filepath: \"${LLVM_TARGET_DEFINITIONS_ABSOLUTE}\"\n" 28 " includes: \"${CMAKE_CURRENT_SOURCE_DIR};${tblgen_includes}\"\n" 29 ) 30endfunction() 31 32# Clear out any pre-existing compile_commands file before processing. This 33# allows for generating a clean compile_commands on each configure. 34file(REMOVE ${CMAKE_BINARY_DIR}/pdll_compile_commands.yml) 35 36# Declare a helper function/copy of tablegen rule for using tablegen without 37# additional tblgen specific flags when invoking PDLL generator. 38function(_pdll_tablegen project ofn) 39 cmake_parse_arguments(ARG "" "" "DEPENDS;EXTRA_INCLUDES" ${ARGN}) 40 # Validate calling context. 41 if(NOT ${project}_TABLEGEN_EXE) 42 message(FATAL_ERROR "${project}_TABLEGEN_EXE not set") 43 endif() 44 45 # Use depfile instead of globbing arbitrary *.td(s) for Ninja. 46 if(CMAKE_GENERATOR MATCHES "Ninja") 47 # Make output path relative to build.ninja, assuming located on 48 # ${CMAKE_BINARY_DIR}. 49 # CMake emits build targets as relative paths but Ninja doesn't identify 50 # absolute path (in *.d) as relative path (in build.ninja) 51 # Note that tblgen is executed on ${CMAKE_BINARY_DIR} as working directory. 52 file(RELATIVE_PATH ofn_rel 53 ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/${ofn}) 54 set(additional_cmdline 55 -o ${ofn_rel} 56 -d ${ofn_rel}.d 57 WORKING_DIRECTORY ${CMAKE_BINARY_DIR} 58 DEPFILE ${CMAKE_CURRENT_BINARY_DIR}/${ofn}.d 59 ) 60 set(local_tds) 61 set(global_tds) 62 else() 63 file(GLOB local_tds "*.td") 64 file(GLOB_RECURSE global_tds "${LLVM_MAIN_INCLUDE_DIR}/llvm/*.td") 65 set(additional_cmdline 66 -o ${CMAKE_CURRENT_BINARY_DIR}/${ofn} 67 ) 68 endif() 69 70 if (IS_ABSOLUTE ${LLVM_TARGET_DEFINITIONS}) 71 set(LLVM_TARGET_DEFINITIONS_ABSOLUTE ${LLVM_TARGET_DEFINITIONS}) 72 else() 73 set(LLVM_TARGET_DEFINITIONS_ABSOLUTE 74 ${CMAKE_CURRENT_SOURCE_DIR}/${LLVM_TARGET_DEFINITIONS}) 75 endif() 76 77 if (CMAKE_GENERATOR MATCHES "Visual Studio") 78 # Visual Studio has problems with llvm-tblgen's native --write-if-changed 79 # behavior. Since it doesn't do restat optimizations anyway, just don't 80 # pass --write-if-changed there. 81 set(tblgen_change_flag) 82 else() 83 set(tblgen_change_flag "--write-if-changed") 84 endif() 85 86 # We need both _TABLEGEN_TARGET and _TABLEGEN_EXE in the DEPENDS list 87 # (both the target and the file) to have .inc files rebuilt on 88 # a tablegen change, as cmake does not propagate file-level dependencies 89 # of custom targets. See the following ticket for more information: 90 # https://cmake.org/Bug/view.php?id=15858 91 # The dependency on both, the target and the file, produces the same 92 # dependency twice in the result file when 93 # ("${${project}_TABLEGEN_TARGET}" STREQUAL "${${project}_TABLEGEN_EXE}") 94 # but lets us having smaller and cleaner code here. 95 get_directory_property(tblgen_includes INCLUDE_DIRECTORIES) 96 list(APPEND tblgen_includes ${ARG_EXTRA_INCLUDES}) 97 # Filter out empty items before prepending each entry with -I 98 list(REMOVE_ITEM tblgen_includes "") 99 list(TRANSFORM tblgen_includes PREPEND -I) 100 101 set(tablegen_exe ${${project}_TABLEGEN_EXE}) 102 set(tablegen_depends ${${project}_TABLEGEN_TARGET} ${tablegen_exe}) 103 104 add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${ofn} 105 COMMAND ${tablegen_exe} ${ARG_UNPARSED_ARGUMENTS} -I ${CMAKE_CURRENT_SOURCE_DIR} 106 ${tblgen_includes} 107 ${LLVM_TARGET_DEFINITIONS_ABSOLUTE} 108 ${tblgen_change_flag} 109 ${additional_cmdline} 110 # The file in LLVM_TARGET_DEFINITIONS may be not in the current 111 # directory and local_tds may not contain it, so we must 112 # explicitly list it here: 113 DEPENDS ${ARG_DEPENDS} ${tablegen_depends} 114 ${local_tds} ${global_tds} 115 ${LLVM_TARGET_DEFINITIONS_ABSOLUTE} 116 ${LLVM_TARGET_DEPENDS} 117 COMMENT "Building ${ofn}..." 118 ) 119 120 # `make clean' must remove all those generated files: 121 set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES ${ofn}) 122 123 set(TABLEGEN_OUTPUT ${TABLEGEN_OUTPUT} ${CMAKE_CURRENT_BINARY_DIR}/${ofn} PARENT_SCOPE) 124 set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/${ofn} PROPERTIES 125 GENERATED 1) 126endfunction() 127 128# Declare a PDLL library in the current directory. 129function(add_mlir_pdll_library target inputFile ofn) 130 set(LLVM_TARGET_DEFINITIONS ${inputFile}) 131 132 _pdll_tablegen(MLIR_PDLL ${ofn} -x=cpp ${ARGN}) 133 set(TABLEGEN_OUTPUT ${TABLEGEN_OUTPUT} ${CMAKE_CURRENT_BINARY_DIR}/${ofn} 134 PARENT_SCOPE) 135 136 # Get the current set of include paths for this pdll file. 137 cmake_parse_arguments(ARG "" "" "DEPENDS;EXTRA_INCLUDES" ${ARGN}) 138 get_directory_property(tblgen_includes INCLUDE_DIRECTORIES) 139 list(APPEND tblgen_includes ${ARG_EXTRA_INCLUDES}) 140 # Filter out any empty include items. 141 list(REMOVE_ITEM tblgen_includes "") 142 143 # Build the absolute path for the current input file. 144 if (IS_ABSOLUTE ${LLVM_TARGET_DEFINITIONS}) 145 set(LLVM_TARGET_DEFINITIONS_ABSOLUTE ${inputFile}) 146 else() 147 set(LLVM_TARGET_DEFINITIONS_ABSOLUTE ${CMAKE_CURRENT_SOURCE_DIR}/${inputFile}) 148 endif() 149 150 # Append the includes used for this file to the pdll_compilation_commands 151 # file. 152 file(APPEND ${CMAKE_BINARY_DIR}/pdll_compile_commands.yml 153 "--- !FileInfo:\n" 154 " filepath: \"${LLVM_TARGET_DEFINITIONS_ABSOLUTE}\"\n" 155 " includes: \"${CMAKE_CURRENT_SOURCE_DIR};${tblgen_includes}\"\n" 156 ) 157 158 add_public_tablegen_target(${target}) 159endfunction() 160 161# Declare a dialect in the include directory 162function(add_mlir_dialect dialect dialect_namespace) 163 set(LLVM_TARGET_DEFINITIONS ${dialect}.td) 164 mlir_tablegen(${dialect}.h.inc -gen-op-decls) 165 mlir_tablegen(${dialect}.cpp.inc -gen-op-defs) 166 mlir_tablegen(${dialect}Types.h.inc -gen-typedef-decls -typedefs-dialect=${dialect_namespace}) 167 mlir_tablegen(${dialect}Types.cpp.inc -gen-typedef-defs -typedefs-dialect=${dialect_namespace}) 168 mlir_tablegen(${dialect}Dialect.h.inc -gen-dialect-decls -dialect=${dialect_namespace}) 169 mlir_tablegen(${dialect}Dialect.cpp.inc -gen-dialect-defs -dialect=${dialect_namespace}) 170 add_public_tablegen_target(MLIR${dialect}IncGen) 171 add_dependencies(mlir-headers MLIR${dialect}IncGen) 172endfunction() 173 174# Declare sharded dialect operation declarations and definitions 175function(add_sharded_ops ops_target shard_count) 176 set(LLVM_TARGET_DEFINITIONS ${ops_target}.td) 177 mlir_tablegen(${ops_target}.h.inc -gen-op-decls -op-shard-count=${shard_count}) 178 mlir_tablegen(${ops_target}.cpp.inc -gen-op-defs -op-shard-count=${shard_count}) 179 set(LLVM_TARGET_DEFINITIONS ${ops_target}.cpp) 180 foreach(index RANGE ${shard_count}) 181 set(SHARDED_SRC ${ops_target}.${index}.cpp) 182 list(APPEND SHARDED_SRCS ${SHARDED_SRC}) 183 tablegen(MLIR_SRC_SHARDER ${SHARDED_SRC} -op-shard-index=${index}) 184 set(TABLEGEN_OUTPUT ${TABLEGEN_OUTPUT} ${CMAKE_CURRENT_BINARY_DIR}/${SHARDED_SRC}) 185 endforeach() 186 add_public_tablegen_target(MLIR${ops_target}ShardGen) 187 set(SHARDED_SRCS ${SHARDED_SRCS} PARENT_SCOPE) 188endfunction() 189 190# Declare a dialect in the include directory 191function(add_mlir_interface interface) 192 set(LLVM_TARGET_DEFINITIONS ${interface}.td) 193 mlir_tablegen(${interface}.h.inc -gen-op-interface-decls) 194 mlir_tablegen(${interface}.cpp.inc -gen-op-interface-defs) 195 add_public_tablegen_target(MLIR${interface}IncGen) 196 add_dependencies(mlir-generic-headers MLIR${interface}IncGen) 197endfunction() 198 199 200# Generate Documentation 201function(add_mlir_doc doc_filename output_file output_directory command) 202 set(LLVM_TARGET_DEFINITIONS ${doc_filename}.td) 203 # The MLIR docs use Hugo, so we allow Hugo specific features here. 204 tablegen(MLIR ${output_file}.md ${command} -allow-hugo-specific-features ${ARGN}) 205 set(GEN_DOC_FILE ${MLIR_BINARY_DIR}/docs/${output_directory}${output_file}.md) 206 add_custom_command( 207 OUTPUT ${GEN_DOC_FILE} 208 COMMAND ${CMAKE_COMMAND} -E copy 209 ${CMAKE_CURRENT_BINARY_DIR}/${output_file}.md 210 ${GEN_DOC_FILE} 211 DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${output_file}.md) 212 add_custom_target(${output_file}DocGen DEPENDS ${GEN_DOC_FILE}) 213 set_target_properties(${output_file}DocGen PROPERTIES FOLDER "MLIR/Tablegenning/Docs") 214 add_dependencies(mlir-doc ${output_file}DocGen) 215endfunction() 216 217# Sets ${srcs} to contain the list of additional headers for the target. Extra 218# arguments are included into the list of additional headers. 219function(_set_mlir_additional_headers_as_srcs) 220 set(srcs) 221 if(MSVC_IDE OR XCODE) 222 # Add public headers 223 file(RELATIVE_PATH lib_path 224 ${MLIR_SOURCE_DIR}/lib/ 225 ${CMAKE_CURRENT_SOURCE_DIR} 226 ) 227 if(NOT lib_path MATCHES "^[.][.]") 228 file( GLOB_RECURSE headers 229 ${MLIR_SOURCE_DIR}/include/mlir/${lib_path}/*.h 230 ${MLIR_SOURCE_DIR}/include/mlir/${lib_path}/*.def 231 ) 232 set_source_files_properties(${headers} PROPERTIES HEADER_FILE_ONLY ON) 233 234 file( GLOB_RECURSE tds 235 ${MLIR_SOURCE_DIR}/include/mlir/${lib_path}/*.td 236 ) 237 source_group("TableGen descriptions" FILES ${tds}) 238 set_source_files_properties(${tds}} PROPERTIES HEADER_FILE_ONLY ON) 239 240 if(headers OR tds) 241 set(srcs ${headers} ${tds}) 242 endif() 243 endif() 244 endif(MSVC_IDE OR XCODE) 245 if(srcs OR ARGN) 246 set(srcs 247 ADDITIONAL_HEADERS 248 ${srcs} 249 ${ARGN} # It may contain unparsed unknown args. 250 PARENT_SCOPE 251 ) 252 endif() 253endfunction() 254 255# Checks that the LLVM components are not listed in the extra arguments, 256# assumed to be coming from the LINK_LIBS variable. 257function(_check_llvm_components_usage name) 258 # LINK_COMPONENTS is necessary to allow libLLVM.so to be properly 259 # substituted for individual library dependencies if LLVM_LINK_LLVM_DYLIB 260 # Perhaps this should be in llvm_add_library instead? However, it fails 261 # on libclang-cpp.so 262 get_property(llvm_component_libs GLOBAL PROPERTY LLVM_COMPONENT_LIBS) 263 foreach(lib ${ARGN}) 264 if(${lib} IN_LIST llvm_component_libs) 265 message(SEND_ERROR "${name} specifies LINK_LIBS ${lib}, but LINK_LIBS cannot be used for LLVM libraries. Please use LINK_COMPONENTS instead.") 266 endif() 267 endforeach() 268endfunction() 269 270function(add_mlir_example_library name) 271 cmake_parse_arguments(ARG 272 "SHARED;DISABLE_INSTALL" 273 "" 274 "ADDITIONAL_HEADERS;DEPENDS;LINK_COMPONENTS;LINK_LIBS" 275 ${ARGN}) 276 _set_mlir_additional_headers_as_srcs(${ARG_ADDITIONAL_HEADERS}) 277 if (ARG_SHARED) 278 set(LIBTYPE SHARED) 279 else() 280 if(BUILD_SHARED_LIBS) 281 set(LIBTYPE SHARED) 282 else() 283 set(LIBTYPE STATIC) 284 endif() 285 endif() 286 287 # MLIR libraries uniformly depend on LLVMSupport. Just specify it once here. 288 list(APPEND ARG_LINK_COMPONENTS Support) 289 _check_llvm_components_usage(${name} ${ARG_LINK_LIBS}) 290 291 list(APPEND ARG_DEPENDS mlir-generic-headers) 292 293 llvm_add_library(${name} ${LIBTYPE} ${ARG_UNPARSED_ARGUMENTS} ${srcs} DEPENDS ${ARG_DEPENDS} LINK_COMPONENTS ${ARG_LINK_COMPONENTS} LINK_LIBS ${ARG_LINK_LIBS}) 294 set_target_properties(${name} PROPERTIES FOLDER "MLIR/Examples") 295 if (LLVM_BUILD_EXAMPLES AND NOT ${ARG_DISABLE_INSTALL}) 296 add_mlir_library_install(${name}) 297 else() 298 set_target_properties(${name} PROPERTIES EXCLUDE_FROM_ALL ON) 299 endif() 300endfunction() 301 302# Declare an mlir library which can be compiled in libMLIR.so 303# In addition to everything that llvm_add_library accepts, this 304# also has the following option: 305# EXCLUDE_FROM_LIBMLIR 306# Don't include this library in libMLIR.so. This option should be used 307# for test libraries, executable-specific libraries, or rarely used libraries 308# with large dependencies. When using it, please link libraries included 309# in libMLIR via mlir_target_link_libraries(), to ensure that the library 310# does not pull in static dependencies when MLIR_LINK_MLIR_DYLIB=ON is used. 311# OBJECT 312# The library's object library is referenced using "obj.${name}". For this to 313# work reliably, this flag ensures that the OBJECT library exists. 314# ENABLE_AGGREGATION 315# Exports additional metadata, 316# and installs additional object files needed to include this as part of an 317# aggregate shared library. 318# TODO: Make this the default for all MLIR libraries once all libraries 319# are compatible with building an object library. 320function(add_mlir_library name) 321 cmake_parse_arguments(ARG 322 "SHARED;INSTALL_WITH_TOOLCHAIN;EXCLUDE_FROM_LIBMLIR;DISABLE_INSTALL;ENABLE_AGGREGATION;OBJECT" 323 "" 324 "ADDITIONAL_HEADERS;DEPENDS;LINK_COMPONENTS;LINK_LIBS" 325 ${ARGN}) 326 _set_mlir_additional_headers_as_srcs(${ARG_ADDITIONAL_HEADERS}) 327 328 # Determine type of library. 329 if(ARG_SHARED) 330 set(LIBTYPE SHARED) 331 else() 332 # llvm_add_library ignores BUILD_SHARED_LIBS if STATIC is explicitly set, 333 # so we need to handle it here. 334 if(BUILD_SHARED_LIBS) 335 set(LIBTYPE SHARED) 336 else() 337 set(LIBTYPE STATIC) 338 endif() 339 endif() 340 341 # Is an object library needed...? 342 # Note that the XCode generator doesn't handle object libraries correctly and 343 # usability is degraded in the Visual Studio solution generators. 344 # llvm_add_library may also itself decide to create an object library. 345 set(NEEDS_OBJECT_LIB OFF) 346 if(ARG_OBJECT) 347 # Yes, because the target "obj.${name}" is referenced. 348 set(NEEDS_OBJECT_LIB ON) 349 endif () 350 if(LLVM_BUILD_LLVM_DYLIB AND NOT ARG_EXCLUDE_FROM_LIBMLIR AND NOT XCODE) 351 # Yes, because in addition to the shared library, the object files are 352 # needed for linking into libMLIR.so (see mlir/tools/mlir-shlib/CMakeLists.txt). 353 # For XCode, -force_load is used instead. 354 # Windows is not supported (LLVM_BUILD_LLVM_DYLIB=ON will cause an error). 355 set(NEEDS_OBJECT_LIB ON) 356 set_property(GLOBAL APPEND PROPERTY MLIR_STATIC_LIBS ${name}) 357 set_property(GLOBAL APPEND PROPERTY MLIR_LLVM_LINK_COMPONENTS ${ARG_LINK_COMPONENTS}) 358 set_property(GLOBAL APPEND PROPERTY MLIR_LLVM_LINK_COMPONENTS ${LLVM_LINK_COMPONENTS}) 359 endif () 360 if(ARG_ENABLE_AGGREGATION AND NOT XCODE) 361 # Yes, because this library is added to an aggergate library such as 362 # libMLIR-C.so which is links together all the object files. 363 # For XCode, -force_load is used instead. 364 set(NEEDS_OBJECT_LIB ON) 365 endif() 366 if (NOT ARG_SHARED AND NOT ARG_EXCLUDE_FROM_LIBMLIR AND NOT XCODE AND NOT MSVC_IDE) 367 # Yes, but only for legacy reasons. Also avoid object libraries for 368 # Visual Studio solutions. 369 set(NEEDS_OBJECT_LIB ON) 370 endif() 371 if(NEEDS_OBJECT_LIB) 372 list(APPEND LIBTYPE OBJECT) 373 endif() 374 375 # MLIR libraries uniformly depend on LLVMSupport. Just specify it once here. 376 list(APPEND ARG_LINK_COMPONENTS Support) 377 _check_llvm_components_usage(${name} ${ARG_LINK_LIBS}) 378 379 list(APPEND ARG_DEPENDS mlir-generic-headers) 380 llvm_add_library(${name} ${LIBTYPE} ${ARG_UNPARSED_ARGUMENTS} ${srcs} DEPENDS ${ARG_DEPENDS} LINK_COMPONENTS ${ARG_LINK_COMPONENTS} LINK_LIBS ${ARG_LINK_LIBS}) 381 382 if(TARGET ${name}) 383 target_link_libraries(${name} INTERFACE ${LLVM_COMMON_LIBS}) 384 if(NOT ARG_DISABLE_INSTALL) 385 add_mlir_library_install(${name}) 386 endif() 387 else() 388 # Add empty "phony" target 389 add_custom_target(${name}) 390 endif() 391 set_target_properties(${name} PROPERTIES FOLDER "MLIR/Libraries") 392 393 # Setup aggregate. 394 if(ARG_ENABLE_AGGREGATION) 395 # Compute and store the properties needed to build aggregates. 396 set(AGGREGATE_OBJECTS) 397 set(AGGREGATE_OBJECT_LIB) 398 set(AGGREGATE_DEPS) 399 if(XCODE) 400 # XCode has limited support for object libraries. Instead, add dep flags 401 # that force the entire library to be embedded. 402 list(APPEND AGGREGATE_DEPS "-force_load" "${name}") 403 elseif(TARGET obj.${name}) 404 # FIXME: *.obj can also be added via target_link_libraries since CMake 3.12. 405 list(APPEND AGGREGATE_OBJECTS "$<TARGET_OBJECTS:obj.${name}>") 406 list(APPEND AGGREGATE_OBJECT_LIB "obj.${name}") 407 else() 408 message(SEND_ERROR "Aggregate library not supported on this platform") 409 endif() 410 411 # For each declared dependency, transform it into a generator expression 412 # which excludes it if the ultimate link target is excluding the library. 413 set(NEW_LINK_LIBRARIES) 414 get_target_property(CURRENT_LINK_LIBRARIES ${name} LINK_LIBRARIES) 415 get_mlir_filtered_link_libraries(NEW_LINK_LIBRARIES ${CURRENT_LINK_LIBRARIES}) 416 set_target_properties(${name} PROPERTIES LINK_LIBRARIES "${NEW_LINK_LIBRARIES}") 417 list(APPEND AGGREGATE_DEPS ${NEW_LINK_LIBRARIES}) 418 set_target_properties(${name} PROPERTIES 419 EXPORT_PROPERTIES "MLIR_AGGREGATE_OBJECT_LIB_IMPORTED;MLIR_AGGREGATE_DEP_LIBS_IMPORTED" 420 MLIR_AGGREGATE_OBJECTS "${AGGREGATE_OBJECTS}" 421 MLIR_AGGREGATE_DEPS "${AGGREGATE_DEPS}" 422 MLIR_AGGREGATE_OBJECT_LIB_IMPORTED "${AGGREGATE_OBJECT_LIB}" 423 MLIR_AGGREGATE_DEP_LIBS_IMPORTED "${CURRENT_LINK_LIBRARIES}" 424 ) 425 426 # In order for out-of-tree projects to build aggregates of this library, 427 # we need to install the OBJECT library. 428 if(TARGET "obj.${name}" AND MLIR_INSTALL_AGGREGATE_OBJECTS AND NOT ARG_DISABLE_INSTALL) 429 add_mlir_library_install(obj.${name}) 430 endif() 431 endif() 432endfunction(add_mlir_library) 433 434macro(add_mlir_tool name) 435 llvm_add_tool(MLIR ${ARGV}) 436endmacro() 437 438# Sets a variable with a transformed list of link libraries such individual 439# libraries will be dynamically excluded when evaluated on a final library 440# which defines an MLIR_AGGREGATE_EXCLUDE_LIBS which contains any of the 441# libraries. Each link library can be a generator expression but must not 442# resolve to an arity > 1 (i.e. it can be optional). 443function(get_mlir_filtered_link_libraries output) 444 set(_results) 445 foreach(linklib ${ARGN}) 446 # In English, what this expression does: 447 # For each link library, resolve the property MLIR_AGGREGATE_EXCLUDE_LIBS 448 # on the context target (i.e. the executable or shared library being linked) 449 # and, if it is not in that list, emit the library name. Otherwise, empty. 450 list(APPEND _results 451 "$<$<NOT:$<IN_LIST:${linklib},$<GENEX_EVAL:$<TARGET_PROPERTY:MLIR_AGGREGATE_EXCLUDE_LIBS>>>>:${linklib}>" 452 ) 453 endforeach() 454 set(${output} "${_results}" PARENT_SCOPE) 455endfunction(get_mlir_filtered_link_libraries) 456 457# Declares an aggregate library. Such a library is a combination of arbitrary 458# regular add_mlir_library() libraries with the special feature that they can 459# be configured to statically embed some subset of their dependencies, as is 460# typical when creating a .so/.dylib/.dll or a mondo static library. 461# 462# It is always safe to depend on the aggregate directly in order to compile/link 463# against the superset of embedded entities and transitive deps. 464# 465# Arguments: 466# PUBLIC_LIBS: list of dependent libraries to add to the 467# INTERFACE_LINK_LIBRARIES property, exporting them to users. This list 468# will be transitively filtered to exclude any EMBED_LIBS. 469# EMBED_LIBS: list of dependent libraries that should be embedded directly 470# into this library. Each of these must be an add_mlir_library() library 471# without DISABLE_AGGREGATE. 472# 473# Note: This is a work in progress and is presently only sufficient for certain 474# non nested cases involving the C-API. 475function(add_mlir_aggregate name) 476 cmake_parse_arguments(ARG 477 "SHARED;STATIC" 478 "" 479 "PUBLIC_LIBS;EMBED_LIBS" 480 ${ARGN}) 481 set(_libtype) 482 if(ARG_STATIC) 483 list(APPEND _libtype STATIC) 484 endif() 485 if(ARG_SHARED) 486 list(APPEND _libtype SHARED) 487 endif() 488 set(_debugmsg) 489 490 set(_embed_libs) 491 set(_objects) 492 set(_deps) 493 foreach(lib ${ARG_EMBED_LIBS}) 494 # We have to handle imported vs in-tree differently: 495 # in-tree: To support arbitrary ordering, the generator expressions get 496 # set on the dependent target when it is constructed and then just 497 # eval'd here. This means we can build an aggregate from targets that 498 # may not yet be defined, which is typical for in-tree. 499 # imported: Exported properties do not support generator expressions, so 500 # we imperatively query and manage the expansion here. This is fine 501 # because imported targets will always be found/configured first and 502 # do not need to support arbitrary ordering. If CMake every supports 503 # exporting generator expressions, then this can be simplified. 504 set(_is_imported OFF) 505 if(TARGET ${lib}) 506 get_target_property(_is_imported ${lib} IMPORTED) 507 endif() 508 509 if(NOT _is_imported) 510 # Evaluate the in-tree generator expressions directly (this allows target 511 # order independence, since these aren't evaluated until the generate 512 # phase). 513 # What these expressions do: 514 # In the context of this aggregate, resolve the list of OBJECTS and DEPS 515 # that each library advertises and patch it into the whole. 516 set(_local_objects $<TARGET_GENEX_EVAL:${name},$<TARGET_PROPERTY:${lib},MLIR_AGGREGATE_OBJECTS>>) 517 set(_local_deps $<TARGET_GENEX_EVAL:${name},$<TARGET_PROPERTY:${lib},MLIR_AGGREGATE_DEPS>>) 518 else() 519 # It is an imported target, which can only have flat strings populated 520 # (no generator expressions). 521 # Rebuild the generator expressions from the imported flat string lists. 522 if(NOT MLIR_INSTALL_AGGREGATE_OBJECTS) 523 message(SEND_ERROR "Cannot build aggregate from imported targets which were not installed via MLIR_INSTALL_AGGREGATE_OBJECTS (for ${lib}).") 524 endif() 525 526 get_property(_has_object_lib_prop TARGET ${lib} PROPERTY MLIR_AGGREGATE_OBJECT_LIB_IMPORTED SET) 527 get_property(_has_dep_libs_prop TARGET ${lib} PROPERTY MLIR_AGGREGATE_DEP_LIBS_IMPORTED SET) 528 if(NOT _has_object_lib_prop OR NOT _has_dep_libs_prop) 529 message(SEND_ERROR "Cannot create an aggregate out of imported ${lib}: It is missing properties indicating that it was built for aggregation") 530 endif() 531 get_target_property(_imp_local_object_lib ${lib} MLIR_AGGREGATE_OBJECT_LIB_IMPORTED) 532 get_target_property(_imp_dep_libs ${lib} MLIR_AGGREGATE_DEP_LIBS_IMPORTED) 533 set(_local_objects) 534 if(_imp_local_object_lib) 535 set(_local_objects "$<TARGET_OBJECTS:${_imp_local_object_lib}>") 536 endif() 537 # We should just be able to do this: 538 # get_mlir_filtered_link_libraries(_local_deps ${_imp_dep_libs}) 539 # However, CMake complains about the unqualified use of the one-arg 540 # $<TARGET_PROPERTY> expression. So we do the same thing but use the 541 # two-arg form which takes an explicit target. 542 foreach(_imp_dep_lib ${_imp_dep_libs}) 543 # In English, what this expression does: 544 # For each link library, resolve the property MLIR_AGGREGATE_EXCLUDE_LIBS 545 # on the context target (i.e. the executable or shared library being linked) 546 # and, if it is not in that list, emit the library name. Otherwise, empty. 547 list(APPEND _local_deps 548 "$<$<NOT:$<IN_LIST:${_imp_dep_lib},$<GENEX_EVAL:$<TARGET_PROPERTY:${name},MLIR_AGGREGATE_EXCLUDE_LIBS>>>>:${_imp_dep_lib}>" 549 ) 550 endforeach() 551 endif() 552 553 list(APPEND _embed_libs ${lib}) 554 list(APPEND _objects ${_local_objects}) 555 list(APPEND _deps ${_local_deps}) 556 557 string(APPEND _debugmsg 558 ": EMBED_LIB ${lib}:\n" 559 " OBJECTS = ${_local_objects}\n" 560 " DEPS = ${_local_deps}\n\n") 561 endforeach() 562 563 add_mlir_library(${name} 564 ${_libtype} 565 ${ARG_UNPARSED_ARGUMENTS} 566 PARTIAL_SOURCES_INTENDED 567 EXCLUDE_FROM_LIBMLIR 568 LINK_LIBS PRIVATE 569 ${_deps} 570 ${ARG_PUBLIC_LIBS} 571 ) 572 target_sources(${name} PRIVATE ${_objects}) 573 574 # Linux defaults to allowing undefined symbols in shared libraries whereas 575 # many other platforms are more strict. We want these libraries to be 576 # self contained, and we want any undefined symbols to be reported at 577 # library construction time, not at library use, so make Linux strict too. 578 # We make an exception for sanitizer builds, since the AddressSanitizer 579 # run-time doesn't get linked into shared libraries. 580 if((CMAKE_SYSTEM_NAME STREQUAL "Linux") AND (NOT LLVM_USE_SANITIZER)) 581 target_link_options(${name} PRIVATE 582 "LINKER:-z,defs" 583 ) 584 endif() 585 586 # TODO: Should be transitive. 587 set_target_properties(${name} PROPERTIES 588 MLIR_AGGREGATE_EXCLUDE_LIBS "${_embed_libs}") 589 if(WIN32) 590 set_property(TARGET ${name} PROPERTY WINDOWS_EXPORT_ALL_SYMBOLS ON) 591 endif() 592 593 # Debugging generator expressions can be hard. Uncomment the below to emit 594 # files next to the library with a lot of debug information: 595 # string(APPEND _debugmsg 596 # ": MAIN LIBRARY:\n" 597 # " OBJECTS = ${_objects}\n" 598 # " SOURCES = $<TARGET_GENEX_EVAL:${name},$<TARGET_PROPERTY:${name},SOURCES>>\n" 599 # " DEPS = ${_deps}\n" 600 # " LINK_LIBRARIES = $<TARGET_GENEX_EVAL:${name},$<TARGET_PROPERTY:${name},LINK_LIBRARIES>>\n" 601 # " MLIR_AGGREGATE_EXCLUDE_LIBS = $<TARGET_GENEX_EVAL:${name},$<TARGET_PROPERTY:${name},MLIR_AGGREGATE_EXCLUDE_LIBS>>\n" 602 # ) 603 # file(GENERATE OUTPUT 604 # "${CMAKE_CURRENT_BINARY_DIR}/${name}.aggregate_debug.txt" 605 # CONTENT "${_debugmsg}" 606 # ) 607endfunction(add_mlir_aggregate) 608 609# Adds an MLIR library target for installation. 610# This is usually done as part of add_mlir_library but is broken out for cases 611# where non-standard library builds can be installed. 612function(add_mlir_library_install name) 613 if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY) 614 get_target_export_arg(${name} MLIR export_to_mlirtargets UMBRELLA mlir-libraries) 615 install(TARGETS ${name} 616 COMPONENT ${name} 617 ${export_to_mlirtargets} 618 LIBRARY DESTINATION lib${LLVM_LIBDIR_SUFFIX} 619 ARCHIVE DESTINATION lib${LLVM_LIBDIR_SUFFIX} 620 RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" 621 # Note that CMake will create a directory like: 622 # objects-${CMAKE_BUILD_TYPE}/obj.LibName 623 # and put object files there. 624 OBJECTS DESTINATION lib${LLVM_LIBDIR_SUFFIX} 625 ) 626 627 if (NOT LLVM_ENABLE_IDE) 628 add_llvm_install_targets(install-${name} 629 DEPENDS ${name} 630 COMPONENT ${name}) 631 endif() 632 set_property(GLOBAL APPEND PROPERTY MLIR_ALL_LIBS ${name}) 633 endif() 634 set_property(GLOBAL APPEND PROPERTY MLIR_EXPORTS ${name}) 635endfunction() 636 637# Declare an mlir library which is part of the public C-API. 638function(add_mlir_public_c_api_library name) 639 add_mlir_library(${name} 640 ${ARGN} 641 OBJECT 642 EXCLUDE_FROM_LIBMLIR 643 ENABLE_AGGREGATION 644 ADDITIONAL_HEADER_DIRS 645 ${MLIR_MAIN_INCLUDE_DIR}/mlir-c 646 ) 647 # API libraries compile with hidden visibility and macros that enable 648 # exporting from the DLL. Only apply to the obj lib, which only affects 649 # the exports via a shared library. 650 set_target_properties(obj.${name} 651 PROPERTIES 652 CXX_VISIBILITY_PRESET hidden 653 ) 654 target_compile_definitions(obj.${name} 655 PRIVATE 656 -DMLIR_CAPI_BUILDING_LIBRARY=1 657 ) 658endfunction() 659 660# Declare the library associated with a dialect. 661function(add_mlir_dialect_library name) 662 set_property(GLOBAL APPEND PROPERTY MLIR_DIALECT_LIBS ${name}) 663 add_mlir_library(${ARGV} DEPENDS mlir-headers) 664endfunction(add_mlir_dialect_library) 665 666# Declare the library associated with a conversion. 667function(add_mlir_conversion_library name) 668 set_property(GLOBAL APPEND PROPERTY MLIR_CONVERSION_LIBS ${name}) 669 add_mlir_library(${ARGV} DEPENDS mlir-headers) 670endfunction(add_mlir_conversion_library) 671 672# Declare the library associated with an extension. 673function(add_mlir_extension_library name) 674 set_property(GLOBAL APPEND PROPERTY MLIR_EXTENSION_LIBS ${name}) 675 add_mlir_library(${ARGV} DEPENDS mlir-headers) 676endfunction(add_mlir_extension_library) 677 678# Declare the library associated with a translation. 679function(add_mlir_translation_library name) 680 set_property(GLOBAL APPEND PROPERTY MLIR_TRANSLATION_LIBS ${name}) 681 add_mlir_library(${ARGV} DEPENDS mlir-headers) 682endfunction(add_mlir_translation_library) 683 684# Verification tools to aid debugging. 685function(mlir_check_link_libraries name) 686 if(TARGET ${name}) 687 get_target_property(type ${name} TYPE) 688 if (${type} STREQUAL "INTERFACE_LIBRARY") 689 get_target_property(libs ${name} INTERFACE_LINK_LIBRARIES) 690 else() 691 get_target_property(libs ${name} LINK_LIBRARIES) 692 endif() 693 # message("${name} libs are: ${libs}") 694 set(linking_llvm 0) 695 foreach(lib ${libs}) 696 if(lib) 697 if(${lib} MATCHES "^LLVM$") 698 set(linking_llvm 1) 699 endif() 700 if((${lib} MATCHES "^LLVM.+") AND ${linking_llvm}) 701 # This will almost always cause execution problems, since the 702 # same symbol might be loaded from 2 separate libraries. This 703 # often comes from referring to an LLVM library target 704 # explicitly in target_link_libraries() 705 message("WARNING: ${name} links LLVM and ${lib}!") 706 endif() 707 endif() 708 endforeach() 709 endif() 710endfunction(mlir_check_link_libraries) 711 712function(mlir_check_all_link_libraries name) 713 mlir_check_link_libraries(${name}) 714 if(TARGET ${name}) 715 get_target_property(libs ${name} LINK_LIBRARIES) 716 # message("${name} libs are: ${libs}") 717 foreach(lib ${libs}) 718 mlir_check_link_libraries(${lib}) 719 endforeach() 720 endif() 721endfunction(mlir_check_all_link_libraries) 722 723# Link target against a list of MLIR libraries. If MLIR_LINK_MLIR_DYLIB is 724# enabled, this will link against the MLIR dylib instead of the static 725# libraries. 726# 727# This function should be used instead of target_link_libraries() when linking 728# MLIR libraries that are part of the MLIR dylib. For libraries that are not 729# part of the dylib (like test libraries), target_link_libraries() should be 730# used. 731function(mlir_target_link_libraries target type) 732 if (TARGET obj.${target}) 733 target_link_libraries(obj.${target} ${ARGN}) 734 endif() 735 736 if (MLIR_LINK_MLIR_DYLIB) 737 target_link_libraries(${target} ${type} MLIR) 738 else() 739 target_link_libraries(${target} ${type} ${ARGN}) 740 endif() 741endfunction() 742