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