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