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 include_directories(${CMAKE_CURRENT_BINARY_DIR}) 9endfunction() 10 11# Declare a dialect in the include directory 12function(add_mlir_dialect dialect dialect_namespace) 13 set(LLVM_TARGET_DEFINITIONS ${dialect}.td) 14 mlir_tablegen(${dialect}.h.inc -gen-op-decls) 15 mlir_tablegen(${dialect}.cpp.inc -gen-op-defs) 16 mlir_tablegen(${dialect}Types.h.inc -gen-typedef-decls -typedefs-dialect=${dialect_namespace}) 17 mlir_tablegen(${dialect}Types.cpp.inc -gen-typedef-defs -typedefs-dialect=${dialect_namespace}) 18 mlir_tablegen(${dialect}Dialect.h.inc -gen-dialect-decls -dialect=${dialect_namespace}) 19 mlir_tablegen(${dialect}Dialect.cpp.inc -gen-dialect-defs -dialect=${dialect_namespace}) 20 add_public_tablegen_target(MLIR${dialect}IncGen) 21 add_dependencies(mlir-headers MLIR${dialect}IncGen) 22endfunction() 23 24# Declare a dialect in the include directory 25function(add_mlir_interface interface) 26 set(LLVM_TARGET_DEFINITIONS ${interface}.td) 27 mlir_tablegen(${interface}.h.inc -gen-op-interface-decls) 28 mlir_tablegen(${interface}.cpp.inc -gen-op-interface-defs) 29 add_public_tablegen_target(MLIR${interface}IncGen) 30 add_dependencies(mlir-generic-headers MLIR${interface}IncGen) 31endfunction() 32 33 34# Generate Documentation 35function(add_mlir_doc doc_filename output_file output_directory command) 36 set(LLVM_TARGET_DEFINITIONS ${doc_filename}.td) 37 tablegen(MLIR ${output_file}.md ${command} ${ARGN}) 38 set(GEN_DOC_FILE ${MLIR_BINARY_DIR}/docs/${output_directory}${output_file}.md) 39 add_custom_command( 40 OUTPUT ${GEN_DOC_FILE} 41 COMMAND ${CMAKE_COMMAND} -E copy 42 ${CMAKE_CURRENT_BINARY_DIR}/${output_file}.md 43 ${GEN_DOC_FILE} 44 DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${output_file}.md) 45 add_custom_target(${output_file}DocGen DEPENDS ${GEN_DOC_FILE}) 46 add_dependencies(mlir-doc ${output_file}DocGen) 47endfunction() 48 49# Declare an mlir library which can be compiled in libMLIR.so 50# In addition to everything that llvm_add_librar accepts, this 51# also has the following option: 52# EXCLUDE_FROM_LIBMLIR 53# Don't include this library in libMLIR.so. This option should be used 54# for test libraries, executable-specific libraries, or rarely used libraries 55# with large dependencies. 56# ENABLE_AGGREGATION 57# Forces generation of an OBJECT library, exports additional metadata, 58# and installs additional object files needed to include this as part of an 59# aggregate shared library. 60# TODO: Make this the default for all MLIR libraries once all libraries 61# are compatible with building an object library. 62function(add_mlir_library name) 63 cmake_parse_arguments(ARG 64 "SHARED;INSTALL_WITH_TOOLCHAIN;EXCLUDE_FROM_LIBMLIR;DISABLE_INSTALL;ENABLE_AGGREGATION" 65 "" 66 "ADDITIONAL_HEADERS;DEPENDS;LINK_COMPONENTS;LINK_LIBS" 67 ${ARGN}) 68 set(srcs) 69 if(MSVC_IDE OR XCODE) 70 # Add public headers 71 file(RELATIVE_PATH lib_path 72 ${MLIR_SOURCE_DIR}/lib/ 73 ${CMAKE_CURRENT_SOURCE_DIR} 74 ) 75 if(NOT lib_path MATCHES "^[.][.]") 76 file( GLOB_RECURSE headers 77 ${MLIR_SOURCE_DIR}/include/mlir/${lib_path}/*.h 78 ${MLIR_SOURCE_DIR}/include/mlir/${lib_path}/*.def 79 ) 80 set_source_files_properties(${headers} PROPERTIES HEADER_FILE_ONLY ON) 81 82 file( GLOB_RECURSE tds 83 ${MLIR_SOURCE_DIR}/include/mlir/${lib_path}/*.td 84 ) 85 source_group("TableGen descriptions" FILES ${tds}) 86 set_source_files_properties(${tds}} PROPERTIES HEADER_FILE_ONLY ON) 87 88 if(headers OR tds) 89 set(srcs ${headers} ${tds}) 90 endif() 91 endif() 92 endif(MSVC_IDE OR XCODE) 93 if(srcs OR ARG_ADDITIONAL_HEADERS) 94 set(srcs 95 ADDITIONAL_HEADERS 96 ${srcs} 97 ${ARG_ADDITIONAL_HEADERS} # It may contain unparsed unknown args. 98 ) 99 endif() 100 101 # Is an object library needed. 102 set(NEEDS_OBJECT_LIB OFF) 103 if(ARG_ENABLE_AGGREGATION) 104 set(NEEDS_OBJECT_LIB ON) 105 endif() 106 107 # Determine type of library. 108 if(ARG_SHARED) 109 set(LIBTYPE SHARED) 110 else() 111 # llvm_add_library ignores BUILD_SHARED_LIBS if STATIC is explicitly set, 112 # so we need to handle it here. 113 if(BUILD_SHARED_LIBS) 114 set(LIBTYPE SHARED) 115 else() 116 set(LIBTYPE STATIC) 117 endif() 118 # Test libraries and such shouldn't be include in libMLIR.so 119 if(NOT ARG_EXCLUDE_FROM_LIBMLIR) 120 set(NEEDS_OBJECT_LIB ON) 121 set_property(GLOBAL APPEND PROPERTY MLIR_STATIC_LIBS ${name}) 122 set_property(GLOBAL APPEND PROPERTY MLIR_LLVM_LINK_COMPONENTS ${ARG_LINK_COMPONENTS}) 123 set_property(GLOBAL APPEND PROPERTY MLIR_LLVM_LINK_COMPONENTS ${LLVM_LINK_COMPONENTS}) 124 endif() 125 endif() 126 127 if(NEEDS_OBJECT_LIB AND NOT XCODE) 128 # The Xcode generator doesn't handle object libraries correctly. 129 # We special case xcode when building aggregates. 130 list(APPEND LIBTYPE OBJECT) 131 endif() 132 133 # MLIR libraries uniformly depend on LLVMSupport. Just specify it once here. 134 list(APPEND ARG_LINK_COMPONENTS Support) 135 136 # LINK_COMPONENTS is necessary to allow libLLVM.so to be properly 137 # substituted for individual library dependencies if LLVM_LINK_LLVM_DYLIB 138 # Perhaps this should be in llvm_add_library instead? However, it fails 139 # on libclang-cpp.so 140 get_property(llvm_component_libs GLOBAL PROPERTY LLVM_COMPONENT_LIBS) 141 foreach(lib ${ARG_LINK_LIBS}) 142 if(${lib} IN_LIST llvm_component_libs) 143 message(SEND_ERROR "${name} specifies LINK_LIBS ${lib}, but LINK_LIBS cannot be used for LLVM libraries. Please use LINK_COMPONENTS instead.") 144 endif() 145 endforeach() 146 147 list(APPEND ARG_DEPENDS mlir-generic-headers) 148 llvm_add_library(${name} ${LIBTYPE} ${ARG_UNPARSED_ARGUMENTS} ${srcs} DEPENDS ${ARG_DEPENDS} LINK_COMPONENTS ${ARG_LINK_COMPONENTS} LINK_LIBS ${ARG_LINK_LIBS}) 149 150 if(TARGET ${name}) 151 target_link_libraries(${name} INTERFACE ${LLVM_COMMON_LIBS}) 152 if(NOT ARG_DISABLE_INSTALL) 153 add_mlir_library_install(${name}) 154 endif() 155 else() 156 # Add empty "phony" target 157 add_custom_target(${name}) 158 endif() 159 set_target_properties(${name} PROPERTIES FOLDER "MLIR libraries") 160 161 # Setup aggregate. 162 if(ARG_ENABLE_AGGREGATION) 163 # Compute and store the properties needed to build aggregates. 164 set(AGGREGATE_OBJECTS) 165 set(AGGREGATE_OBJECT_LIB) 166 set(AGGREGATE_DEPS) 167 if(XCODE) 168 # XCode has limited support for object libraries. Instead, add dep flags 169 # that force the entire library to be embedded. 170 list(APPEND AGGREGATE_DEPS "-force_load" "${name}") 171 else() 172 list(APPEND AGGREGATE_OBJECTS "$<TARGET_OBJECTS:obj.${name}>") 173 list(APPEND AGGREGATE_OBJECT_LIB "obj.${name}") 174 endif() 175 176 # For each declared dependency, transform it into a generator expression 177 # which excludes it if the ultimate link target is excluding the library. 178 set(NEW_LINK_LIBRARIES) 179 get_target_property(CURRENT_LINK_LIBRARIES ${name} LINK_LIBRARIES) 180 get_mlir_filtered_link_libraries(NEW_LINK_LIBRARIES ${CURRENT_LINK_LIBRARIES}) 181 set_target_properties(${name} PROPERTIES LINK_LIBRARIES "${NEW_LINK_LIBRARIES}") 182 list(APPEND AGGREGATE_DEPS ${NEW_LINK_LIBRARIES}) 183 set_target_properties(${name} PROPERTIES 184 EXPORT_PROPERTIES "MLIR_AGGREGATE_OBJECT_LIB_IMPORTED;MLIR_AGGREGATE_DEP_LIBS_IMPORTED" 185 MLIR_AGGREGATE_OBJECTS "${AGGREGATE_OBJECTS}" 186 MLIR_AGGREGATE_DEPS "${AGGREGATE_DEPS}" 187 MLIR_AGGREGATE_OBJECT_LIB_IMPORTED "${AGGREGATE_OBJECT_LIB}" 188 MLIR_AGGREGATE_DEP_LIBS_IMPORTED "${CURRENT_LINK_LIBRARIES}" 189 ) 190 191 # In order for out-of-tree projects to build aggregates of this library, 192 # we need to install the OBJECT library. 193 if(MLIR_INSTALL_AGGREGATE_OBJECTS AND NOT ARG_DISABLE_INSTALL) 194 add_mlir_library_install(obj.${name}) 195 endif() 196 endif() 197endfunction(add_mlir_library) 198 199# Sets a variable with a transformed list of link libraries such individual 200# libraries will be dynamically excluded when evaluated on a final library 201# which defines an MLIR_AGGREGATE_EXCLUDE_LIBS which contains any of the 202# libraries. Each link library can be a generator expression but must not 203# resolve to an arity > 1 (i.e. it can be optional). 204function(get_mlir_filtered_link_libraries output) 205 set(_results) 206 foreach(linklib ${ARGN}) 207 # In English, what this expression does: 208 # For each link library, resolve the property MLIR_AGGREGATE_EXCLUDE_LIBS 209 # on the context target (i.e. the executable or shared library being linked) 210 # and, if it is not in that list, emit the library name. Otherwise, empty. 211 list(APPEND _results 212 "$<$<NOT:$<IN_LIST:${linklib},$<GENEX_EVAL:$<TARGET_PROPERTY:MLIR_AGGREGATE_EXCLUDE_LIBS>>>>:${linklib}>" 213 ) 214 endforeach() 215 set(${output} "${_results}" PARENT_SCOPE) 216endfunction(get_mlir_filtered_link_libraries) 217 218# Declares an aggregate library. Such a library is a combination of arbitrary 219# regular add_mlir_library() libraries with the special feature that they can 220# be configured to statically embed some subset of their dependencies, as is 221# typical when creating a .so/.dylib/.dll or a mondo static library. 222# 223# It is always safe to depend on the aggregate directly in order to compile/link 224# against the superset of embedded entities and transitive deps. 225# 226# Arguments: 227# PUBLIC_LIBS: list of dependent libraries to add to the 228# INTERFACE_LINK_LIBRARIES property, exporting them to users. This list 229# will be transitively filtered to exclude any EMBED_LIBS. 230# EMBED_LIBS: list of dependent libraries that should be embedded directly 231# into this library. Each of these must be an add_mlir_library() library 232# without DISABLE_AGGREGATE. 233# 234# Note: This is a work in progress and is presently only sufficient for certain 235# non nested cases involving the C-API. 236function(add_mlir_aggregate name) 237 cmake_parse_arguments(ARG 238 "SHARED;STATIC" 239 "" 240 "PUBLIC_LIBS;EMBED_LIBS" 241 ${ARGN}) 242 set(_libtype) 243 if(ARG_STATIC) 244 list(APPEND _libtype STATIC) 245 endif() 246 if(ARG_SHARED) 247 list(APPEND _libtype SHARED) 248 endif() 249 set(_debugmsg) 250 251 set(_embed_libs) 252 set(_objects) 253 set(_deps) 254 foreach(lib ${ARG_EMBED_LIBS}) 255 # We have to handle imported vs in-tree differently: 256 # in-tree: To support arbitrary ordering, the generator expressions get 257 # set on the dependent target when it is constructed and then just 258 # eval'd here. This means we can build an aggregate from targets that 259 # may not yet be defined, which is typical for in-tree. 260 # imported: Exported properties do not support generator expressions, so 261 # we imperatively query and manage the expansion here. This is fine 262 # because imported targets will always be found/configured first and 263 # do not need to support arbitrary ordering. If CMake every supports 264 # exporting generator expressions, then this can be simplified. 265 set(_is_imported OFF) 266 if(TARGET ${lib}) 267 get_target_property(_is_imported ${lib} IMPORTED) 268 endif() 269 270 if(NOT _is_imported) 271 # Evaluate the in-tree generator expressions directly (this allows target 272 # order independence, since these aren't evaluated until the generate 273 # phase). 274 # What these expressions do: 275 # In the context of this aggregate, resolve the list of OBJECTS and DEPS 276 # that each library advertises and patch it into the whole. 277 set(_local_objects $<TARGET_GENEX_EVAL:${name},$<TARGET_PROPERTY:${lib},MLIR_AGGREGATE_OBJECTS>>) 278 set(_local_deps $<TARGET_GENEX_EVAL:${name},$<TARGET_PROPERTY:${lib},MLIR_AGGREGATE_DEPS>>) 279 else() 280 # It is an imported target, which can only have flat strings populated 281 # (no generator expressions). 282 # Rebuild the generator expressions from the imported flat string lists. 283 if(NOT MLIR_INSTALL_AGGREGATE_OBJECTS) 284 message(SEND_ERROR "Cannot build aggregate from imported targets which were not installed via MLIR_INSTALL_AGGREGATE_OBJECTS (for ${lib}).") 285 endif() 286 287 get_property(_has_object_lib_prop TARGET ${lib} PROPERTY MLIR_AGGREGATE_OBJECT_LIB_IMPORTED SET) 288 get_property(_has_dep_libs_prop TARGET ${lib} PROPERTY MLIR_AGGREGATE_DEP_LIBS_IMPORTED SET) 289 if(NOT _has_object_lib_prop OR NOT _has_dep_libs_prop) 290 message(SEND_ERROR "Cannot create an aggregate out of imported ${lib}: It is missing properties indicating that it was built for aggregation") 291 endif() 292 get_target_property(_imp_local_object_lib ${lib} MLIR_AGGREGATE_OBJECT_LIB_IMPORTED) 293 get_target_property(_imp_dep_libs ${lib} MLIR_AGGREGATE_DEP_LIBS_IMPORTED) 294 set(_local_objects) 295 if(_imp_local_object_lib) 296 set(_local_objects "$<TARGET_OBJECTS:${_imp_local_object_lib}>") 297 endif() 298 # We should just be able to do this: 299 # get_mlir_filtered_link_libraries(_local_deps ${_imp_dep_libs}) 300 # However, CMake complains about the unqualified use of the one-arg 301 # $<TARGET_PROPERTY> expression. So we do the same thing but use the 302 # two-arg form which takes an explicit target. 303 foreach(_imp_dep_lib ${_imp_dep_libs}) 304 # In English, what this expression does: 305 # For each link library, resolve the property MLIR_AGGREGATE_EXCLUDE_LIBS 306 # on the context target (i.e. the executable or shared library being linked) 307 # and, if it is not in that list, emit the library name. Otherwise, empty. 308 list(APPEND _local_deps 309 "$<$<NOT:$<IN_LIST:${_imp_dep_lib},$<GENEX_EVAL:$<TARGET_PROPERTY:${name},MLIR_AGGREGATE_EXCLUDE_LIBS>>>>:${_imp_dep_lib}>" 310 ) 311 endforeach() 312 endif() 313 314 list(APPEND _embed_libs ${lib}) 315 list(APPEND _objects ${_local_objects}) 316 list(APPEND _deps ${_local_deps}) 317 318 string(APPEND _debugmsg 319 ": EMBED_LIB ${lib}:\n" 320 " OBJECTS = ${_local_objects}\n" 321 " DEPS = ${_local_deps}\n\n") 322 endforeach() 323 324 # Unfortunately need to compile at least one source file, which is hard 325 # to guarantee, so just always generate one. We generate one vs using the 326 # LLVM common dummy.cpp because it works better out of tree. 327 set(_empty_src "${CMAKE_CURRENT_BINARY_DIR}/${name}__empty.cpp") 328 file(WRITE "${_empty_src}" "typedef int dummy;") 329 330 add_mlir_library(${name} 331 ${_libtype} 332 ${ARG_UNPARSED_ARGUMENTS} 333 PARTIAL_SOURCES_INTENDED 334 EXCLUDE_FROM_LIBMLIR 335 "${_empty_src}" 336 LINK_LIBS PRIVATE 337 ${_deps} 338 ${ARG_PUBLIC_LIBS} 339 ) 340 target_sources(${name} PRIVATE ${_objects}) 341 # TODO: Should be transitive. 342 set_target_properties(${name} PROPERTIES 343 MLIR_AGGREGATE_EXCLUDE_LIBS "${_embed_libs}") 344 if(MSVC) 345 set_property(TARGET ${name} PROPERTY WINDOWS_EXPORT_ALL_SYMBOLS ON) 346 endif() 347 348 # Debugging generator expressions can be hard. Uncomment the below to emit 349 # files next to the library with a lot of debug information: 350 # string(APPEND _debugmsg 351 # ": MAIN LIBRARY:\n" 352 # " OBJECTS = ${_objects}\n" 353 # " SOURCES = $<TARGET_GENEX_EVAL:${name},$<TARGET_PROPERTY:${name},SOURCES>>\n" 354 # " DEPS = ${_deps}\n" 355 # " LINK_LIBRARIES = $<TARGET_GENEX_EVAL:${name},$<TARGET_PROPERTY:${name},LINK_LIBRARIES>>\n" 356 # " MLIR_AGGREGATE_EXCLUDE_LIBS = $<TARGET_GENEX_EVAL:${name},$<TARGET_PROPERTY:${name},MLIR_AGGREGATE_EXCLUDE_LIBS>>\n" 357 # ) 358 # file(GENERATE OUTPUT 359 # "${CMAKE_CURRENT_BINARY_DIR}/${name}.aggregate_debug.txt" 360 # CONTENT "${_debugmsg}" 361 # ) 362endfunction(add_mlir_aggregate) 363 364# Adds an MLIR library target for installation. 365# This is usually done as part of add_mlir_library but is broken out for cases 366# where non-standard library builds can be installed. 367function(add_mlir_library_install name) 368 if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY) 369 get_target_export_arg(${name} MLIR export_to_mlirtargets UMBRELLA mlir-libraries) 370 install(TARGETS ${name} 371 COMPONENT ${name} 372 ${export_to_mlirtargets} 373 LIBRARY DESTINATION lib${LLVM_LIBDIR_SUFFIX} 374 ARCHIVE DESTINATION lib${LLVM_LIBDIR_SUFFIX} 375 RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" 376 # Note that CMake will create a directory like: 377 # objects-${CMAKE_BUILD_TYPE}/obj.LibName 378 # and put object files there. 379 OBJECTS DESTINATION lib${LLVM_LIBDIR_SUFFIX} 380 ) 381 382 if (NOT LLVM_ENABLE_IDE) 383 add_llvm_install_targets(install-${name} 384 DEPENDS ${name} 385 COMPONENT ${name}) 386 endif() 387 set_property(GLOBAL APPEND PROPERTY MLIR_ALL_LIBS ${name}) 388 endif() 389 set_property(GLOBAL APPEND PROPERTY MLIR_EXPORTS ${name}) 390endfunction() 391 392# Declare an mlir library which is part of the public C-API. 393function(add_mlir_public_c_api_library name) 394 add_mlir_library(${name} 395 ${ARGN} 396 EXCLUDE_FROM_LIBMLIR 397 ENABLE_AGGREGATION 398 ADDITIONAL_HEADER_DIRS 399 ${MLIR_MAIN_INCLUDE_DIR}/mlir-c 400 ) 401 # API libraries compile with hidden visibility and macros that enable 402 # exporting from the DLL. Only apply to the obj lib, which only affects 403 # the exports via a shared library. 404 set_target_properties(obj.${name} 405 PROPERTIES 406 CXX_VISIBILITY_PRESET hidden 407 ) 408 target_compile_definitions(obj.${name} 409 PRIVATE 410 -DMLIR_CAPI_BUILDING_LIBRARY=1 411 ) 412endfunction() 413 414# Declare the library associated with a dialect. 415function(add_mlir_dialect_library name) 416 set_property(GLOBAL APPEND PROPERTY MLIR_DIALECT_LIBS ${name}) 417 add_mlir_library(${ARGV} DEPENDS mlir-headers) 418endfunction(add_mlir_dialect_library) 419 420# Declare the library associated with a conversion. 421function(add_mlir_conversion_library name) 422 set_property(GLOBAL APPEND PROPERTY MLIR_CONVERSION_LIBS ${name}) 423 add_mlir_library(${ARGV} DEPENDS mlir-headers) 424endfunction(add_mlir_conversion_library) 425 426# Declare the library associated with a translation. 427function(add_mlir_translation_library name) 428 set_property(GLOBAL APPEND PROPERTY MLIR_TRANSLATION_LIBS ${name}) 429 add_mlir_library(${ARGV} DEPENDS mlir-headers) 430endfunction(add_mlir_translation_library) 431 432# Verification tools to aid debugging. 433function(mlir_check_link_libraries name) 434 if(TARGET ${name}) 435 get_target_property(type ${name} TYPE) 436 if (${type} STREQUAL "INTERFACE_LIBRARY") 437 get_target_property(libs ${name} INTERFACE_LINK_LIBRARIES) 438 else() 439 get_target_property(libs ${name} LINK_LIBRARIES) 440 endif() 441 # message("${name} libs are: ${libs}") 442 set(linking_llvm 0) 443 foreach(lib ${libs}) 444 if(lib) 445 if(${lib} MATCHES "^LLVM$") 446 set(linking_llvm 1) 447 endif() 448 if((${lib} MATCHES "^LLVM.+") AND ${linking_llvm}) 449 # This will almost always cause execution problems, since the 450 # same symbol might be loaded from 2 separate libraries. This 451 # often comes from referring to an LLVM library target 452 # explicitly in target_link_libraries() 453 message("WARNING: ${name} links LLVM and ${lib}!") 454 endif() 455 endif() 456 endforeach() 457 endif() 458endfunction(mlir_check_link_libraries) 459 460function(mlir_check_all_link_libraries name) 461 mlir_check_link_libraries(${name}) 462 if(TARGET ${name}) 463 get_target_property(libs ${name} LINK_LIBRARIES) 464 # message("${name} libs are: ${libs}") 465 foreach(lib ${libs}) 466 mlir_check_link_libraries(${lib}) 467 endforeach() 468 endif() 469endfunction(mlir_check_all_link_libraries) 470