Skip to content

Commit 6244d87

Browse files
authored
Avoid object libraries in the VS IDE (#93519)
As discussed in #89743, when using the Visual Studio solution generators, object library projects are displayed as a collection of non-editable *.obj files. To look for the corresponding source files, one has to browse (or search) to the library's obj.libname project. This patch tries to avoid this as much as possible. For Clang, there is already an exception for XCode. We handle MSVC_IDE the same way. For MLIR, this is more complicated. There are explicit references to the obj.libname target that only work when there is an object library. This patch cleans up the reasons for why an object library is needed: 1. The obj.libname is modified in the calling CMakeLists.txt. Note that with use-only references, `add_library(<name> ALIAS <target>)` could have been used. 2. An `libMLIR.so` (mlir-shlib) is also created. This works by adding linking the object libraries' object files into the libMLIR.so (in addition to the library's own .so/.a). XCode is handled using the `-force_load` linker option instead. Windows is not supported. This mechanism is different from LLVM's llvm-shlib that is created by linking static libraries with `-Wl,--whole-archive` (and `-Wl,-all_load` on MacOS). 3. The library might be added to an aggregate library. In-tree, the seems to be only `libMLIR-C.so` and the standalone example. In XCode, it uses the object library and `-force_load` mechanism as above. Again, this is different from `libLLVM-C.so`. 4. Build an object library whenever it was before this patch, except when generating a Visual Studio solution. This condition could be removed, but I am trying to avoid build breakages of whatever configurations others use. This seems to never have worked with XCode because of the explicit references to obj.libname (reason 1.). I don't have access to XCode, but I tried to preserve the current working. IMHO there should be a common mechanism to build aggregate libraries for all LLVM projects instead of the 4 that we have now. As far as I can see, this means for LLVM there are the following changes on whether object libraries are created: 1. An object library is created even in XCode if FORCE_OBJECT_LIBRARY is set. I do not know how XCode handles it, but I also know CMake will abort otherwise. 2. An object library is created even for explicitly SHARED libraries for building `libMLIR.so`. Again, mlir-shlib does not work otherwise. `libMLIR.so` itself is created using SHARED so this patch is marking it as EXCLUDE_FROM_LIBMLIR. 3. For the second condition, it is now sensitive to whether the mlir-shlib is built at all (LLVM_BUILD_LLVM_DYLIB). However, an object library is still built using the fourth condition unless using the MSVC solution generator. That is, except with MSVC_IDE, when an object library was built before, it will also be an object library now.
1 parent d26808c commit 6244d87

File tree

7 files changed

+70
-28
lines changed

7 files changed

+70
-28
lines changed

clang/cmake/modules/AddClang.cmake

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,12 @@ macro(add_clang_library name)
9696
else()
9797
set(LIBTYPE STATIC)
9898
endif()
99-
if(NOT XCODE)
99+
if(NOT XCODE AND NOT MSVC_IDE)
100100
# The Xcode generator doesn't handle object libraries correctly.
101+
# The Visual Studio CMake generator does handle object libraries
102+
# correctly, but it is preferable to list the libraries with their
103+
# source files (instead of the object files and the source files in
104+
# a separate target in the "Object Libraries" folder)
101105
list(APPEND LIBTYPE OBJECT)
102106
endif()
103107
set_property(GLOBAL APPEND PROPERTY CLANG_STATIC_LIBS ${name})

clang/lib/Support/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ set(clangSupport_sources
1515

1616
add_clang_library(clangSupport ${clangSupport_sources})
1717

18-
if (NOT XCODE)
18+
if (TARGET obj.clangSupport)
1919
add_library(clangSupport_tablegen ALIAS obj.clangSupport)
2020
elseif (NOT LLVM_LINK_LLVM_DYLIB)
2121
add_library(clangSupport_tablegen ALIAS clangSupport)

flang/cmake/modules/AddFlang.cmake

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,19 +51,28 @@ function(add_flang_library name)
5151

5252
endif()
5353

54-
if (ARG_SHARED)
54+
if(ARG_SHARED AND ARG_STATIC)
55+
set(LIBTYPE SHARED STATIC)
56+
elseif(ARG_SHARED)
5557
set(LIBTYPE SHARED)
5658
else()
5759
# llvm_add_library ignores BUILD_SHARED_LIBS if STATIC is explicitly set,
5860
# so we need to handle it here.
59-
if (BUILD_SHARED_LIBS AND NOT ARG_STATIC)
60-
set(LIBTYPE SHARED OBJECT)
61+
if(BUILD_SHARED_LIBS)
62+
set(LIBTYPE SHARED)
6163
else()
62-
set(LIBTYPE STATIC OBJECT)
64+
set(LIBTYPE STATIC)
6365
endif()
64-
set_property(GLOBAL APPEND PROPERTY FLANG_STATIC_LIBS ${name})
66+
if(NOT XCODE AND NOT MSVC_IDE)
67+
# The Xcode generator doesn't handle object libraries correctly.
68+
# The Visual Studio CMake generator does handle object libraries
69+
# correctly, but it is preferable to list the libraries with their
70+
# source files (instead of the object files and the source files in
71+
# a separate target in the "Object Libraries" folder)
72+
list(APPEND LIBTYPE OBJECT)
73+
endif()
74+
set_property(GLOBAL APPEND PROPERTY CLANG_STATIC_LIBS ${name})
6575
endif()
66-
6776
llvm_add_library(${name} ${LIBTYPE} ${ARG_UNPARSED_ARGUMENTS} ${srcs})
6877

6978
clang_target_link_libraries(${name} PRIVATE ${ARG_CLANG_LIBS})

mlir/cmake/modules/AddMLIR.cmake

Lines changed: 42 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -306,26 +306,23 @@ endfunction()
306306
# Don't include this library in libMLIR.so. This option should be used
307307
# for test libraries, executable-specific libraries, or rarely used libraries
308308
# 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.
309312
# ENABLE_AGGREGATION
310-
# Forces generation of an OBJECT library, exports additional metadata,
313+
# Exports additional metadata,
311314
# and installs additional object files needed to include this as part of an
312315
# aggregate shared library.
313316
# TODO: Make this the default for all MLIR libraries once all libraries
314317
# are compatible with building an object library.
315318
function(add_mlir_library name)
316319
cmake_parse_arguments(ARG
317-
"SHARED;INSTALL_WITH_TOOLCHAIN;EXCLUDE_FROM_LIBMLIR;DISABLE_INSTALL;ENABLE_AGGREGATION"
320+
"SHARED;INSTALL_WITH_TOOLCHAIN;EXCLUDE_FROM_LIBMLIR;DISABLE_INSTALL;ENABLE_AGGREGATION;OBJECT"
318321
""
319322
"ADDITIONAL_HEADERS;DEPENDS;LINK_COMPONENTS;LINK_LIBS"
320323
${ARGN})
321324
_set_mlir_additional_headers_as_srcs(${ARG_ADDITIONAL_HEADERS})
322325

323-
# Is an object library needed.
324-
set(NEEDS_OBJECT_LIB OFF)
325-
if(ARG_ENABLE_AGGREGATION)
326-
set(NEEDS_OBJECT_LIB ON)
327-
endif()
328-
329326
# Determine type of library.
330327
if(ARG_SHARED)
331328
set(LIBTYPE SHARED)
@@ -337,18 +334,39 @@ function(add_mlir_library name)
337334
else()
338335
set(LIBTYPE STATIC)
339336
endif()
340-
# Test libraries and such shouldn't be include in libMLIR.so
341-
if(NOT ARG_EXCLUDE_FROM_LIBMLIR)
342-
set(NEEDS_OBJECT_LIB ON)
343-
set_property(GLOBAL APPEND PROPERTY MLIR_STATIC_LIBS ${name})
344-
set_property(GLOBAL APPEND PROPERTY MLIR_LLVM_LINK_COMPONENTS ${ARG_LINK_COMPONENTS})
345-
set_property(GLOBAL APPEND PROPERTY MLIR_LLVM_LINK_COMPONENTS ${LLVM_LINK_COMPONENTS})
346-
endif()
347337
endif()
348338

349-
if(NEEDS_OBJECT_LIB AND NOT XCODE)
350-
# The Xcode generator doesn't handle object libraries correctly.
351-
# We special case xcode when building aggregates.
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)
352370
list(APPEND LIBTYPE OBJECT)
353371
endif()
354372

@@ -380,9 +398,12 @@ function(add_mlir_library name)
380398
# XCode has limited support for object libraries. Instead, add dep flags
381399
# that force the entire library to be embedded.
382400
list(APPEND AGGREGATE_DEPS "-force_load" "${name}")
383-
else()
401+
elseif(TARGET obj.${name})
402+
# FIXME: *.obj can also be added via target_link_libraries since CMake 3.12.
384403
list(APPEND AGGREGATE_OBJECTS "$<TARGET_OBJECTS:obj.${name}>")
385404
list(APPEND AGGREGATE_OBJECT_LIB "obj.${name}")
405+
else()
406+
message(SEND_ERROR "Aggregate library not supported on this platform")
386407
endif()
387408

388409
# For each declared dependency, transform it into a generator expression
@@ -402,7 +423,7 @@ function(add_mlir_library name)
402423

403424
# In order for out-of-tree projects to build aggregates of this library,
404425
# we need to install the OBJECT library.
405-
if(MLIR_INSTALL_AGGREGATE_OBJECTS AND NOT ARG_DISABLE_INSTALL)
426+
if(TARGET "obj.${name}" AND MLIR_INSTALL_AGGREGATE_OBJECTS AND NOT ARG_DISABLE_INSTALL)
406427
add_mlir_library_install(obj.${name})
407428
endif()
408429
endif()
@@ -615,6 +636,7 @@ endfunction()
615636
function(add_mlir_public_c_api_library name)
616637
add_mlir_library(${name}
617638
${ARGN}
639+
OBJECT
618640
EXCLUDE_FROM_LIBMLIR
619641
ENABLE_AGGREGATION
620642
ADDITIONAL_HEADER_DIRS

mlir/lib/Dialect/GPU/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ add_mlir_dialect_library(MLIRGPUTransforms
5757
Transforms/SPIRVAttachTarget.cpp
5858
Transforms/SubgroupReduceLowering.cpp
5959
Transforms/Utils.cpp
60+
61+
OBJECT
6062

6163
ADDITIONAL_HEADER_DIRS
6264
${MLIR_MAIN_INCLUDE_DIR}/mlir/Dialect/GPU

mlir/lib/Target/LLVM/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ endif()
3232
add_mlir_dialect_library(MLIRNVVMTarget
3333
NVVM/Target.cpp
3434

35+
OBJECT
36+
3537
ADDITIONAL_HEADER_DIRS
3638
${MLIR_MAIN_INCLUDE_DIR}/mlir/Dialect/LLVMIR
3739

@@ -109,6 +111,8 @@ endif()
109111
add_mlir_dialect_library(MLIRROCDLTarget
110112
ROCDL/Target.cpp
111113

114+
OBJECT
115+
112116
LINK_COMPONENTS
113117
MCParser
114118
${AMDGPU_LIBS}

mlir/tools/mlir-shlib/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ if(LLVM_BUILD_LLVM_DYLIB)
3434
add_mlir_library(
3535
MLIR
3636
SHARED
37+
EXCLUDE_FROM_LIBMLIR
3738
${INSTALL_WITH_TOOLCHAIN}
3839
mlir-shlib.cpp
3940
${_OBJECTS}

0 commit comments

Comments
 (0)