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