@@ -52,9 +52,15 @@ endfunction()
52
52
# Don't include this library in libMLIR.so. This option should be used
53
53
# for test libraries, executable-specific libraries, or rarely used libraries
54
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.
55
61
function (add_mlir_library name )
56
62
cmake_parse_arguments (ARG
57
- "SHARED;INSTALL_WITH_TOOLCHAIN;EXCLUDE_FROM_LIBMLIR;DISABLE_INSTALL"
63
+ "SHARED;INSTALL_WITH_TOOLCHAIN;EXCLUDE_FROM_LIBMLIR;DISABLE_INSTALL;ENABLE_AGGREGATION "
58
64
""
59
65
"ADDITIONAL_HEADERS;DEPENDS;LINK_COMPONENTS;LINK_LIBS"
60
66
${ARGN} )
@@ -90,6 +96,14 @@ function(add_mlir_library name)
90
96
${ARG_ADDITIONAL_HEADERS} # It may contain unparsed unknown args.
91
97
)
92
98
endif ()
99
+
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 ()
105
+
106
+ # Determine type of library.
93
107
if (ARG_SHARED)
94
108
set (LIBTYPE SHARED)
95
109
else ()
@@ -100,18 +114,21 @@ function(add_mlir_library name)
100
114
else ()
101
115
set (LIBTYPE STATIC )
102
116
endif ()
103
- if (NOT XCODE)
104
- # The Xcode generator doesn't handle object libraries correctly.
105
- list (APPEND LIBTYPE OBJECT)
106
- endif ()
107
117
# Test libraries and such shouldn't be include in libMLIR.so
108
118
if (NOT ARG_EXCLUDE_FROM_LIBMLIR)
119
+ set (NEEDS_OBJECT_LIB ON )
109
120
set_property (GLOBAL APPEND PROPERTY MLIR_STATIC_LIBS ${name} )
110
121
set_property (GLOBAL APPEND PROPERTY MLIR_LLVM_LINK_COMPONENTS ${ARG_LINK_COMPONENTS} )
111
122
set_property (GLOBAL APPEND PROPERTY MLIR_LLVM_LINK_COMPONENTS ${LLVM_LINK_COMPONENTS} )
112
123
endif ()
113
124
endif ()
114
125
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 ()
131
+
115
132
# MLIR libraries uniformly depend on LLVMSupport. Just specify it once here.
116
133
list (APPEND ARG_LINK_COMPONENTS Support)
117
134
@@ -139,8 +156,203 @@ function(add_mlir_library name)
139
156
add_custom_target (${name} )
140
157
endif ()
141
158
set_target_properties (${name} PROPERTIES FOLDER "MLIR libraries" )
159
+
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 ()
174
+
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
+ )
189
+
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 ()
142
196
endfunction (add_mlir_library)
143
197
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)
216
+
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.
221
+ #
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.
224
+ #
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.
232
+ #
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)
249
+
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 ()
268
+
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 ()
308
+
309
+ list (APPEND _embed_libs ${lib} )
310
+ list (APPEND _objects ${_local_objects} )
311
+ list (APPEND _deps ${_local_deps} )
312
+
313
+ string (APPEND _debugmsg
314
+ ": EMBED_LIB ${lib} :\n "
315
+ " OBJECTS = ${_local_objects} \n "
316
+ " DEPS = ${_local_deps} \n\n " )
317
+ endforeach ()
318
+
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;" )
324
+
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)
355
+
144
356
# Adds an MLIR library target for installation.
145
357
# This is usually done as part of add_mlir_library but is broken out for cases
146
358
# where non-standard library builds can be installed.
@@ -152,7 +364,12 @@ function(add_mlir_library_install name)
152
364
${export_to_mlirtargets}
153
365
LIBRARY DESTINATION lib${LLVM_LIBDIR_SUFFIX}
154
366
ARCHIVE DESTINATION lib${LLVM_LIBDIR_SUFFIX}
155
- RUNTIME DESTINATION bin)
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
+ )
156
373
157
374
if (NOT LLVM_ENABLE_IDE)
158
375
add_llvm_install_targets(install -${name}
@@ -168,9 +385,8 @@ endfunction()
168
385
function (add_mlir_public_c_api_library name )
169
386
add_mlir_library(${name}
170
387
${ARGN}
171
- # NOTE: Generates obj.${name} which is used for shared library building.
172
- OBJECT
173
388
EXCLUDE_FROM_LIBMLIR
389
+ ENABLE_AGGREGATION
174
390
ADDITIONAL_HEADER_DIRS
175
391
${MLIR_MAIN_INCLUDE_DIR} /mlir-c
176
392
)
0 commit comments