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