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