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