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