Skip to content

Commit 4cc7b41

Browse files
committed
Initial changes for explicit symbol visibility for shared library builds
Added conditional export macros in llvm/Support/Compiler.h Update cmake code to allow building llvm-shlib on windows appending /WHOLEARCHIVE:lib to the linker options. Remove the hardcoded CMake error from using LLVM_BUILD_LLVM_DYLIB on windows. Updated CMake to define macros to enable export macros. Use /Zc:dllexportInlines- when compiling with clang-cl on windows with a opt out CMake option to disable using it. Replace LLVM_EXTERNAL_VISIBILITY with new export macros.
1 parent 8345289 commit 4cc7b41

File tree

14 files changed

+169
-34
lines changed

14 files changed

+169
-34
lines changed

llvm/CMakeLists.txt

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -839,22 +839,36 @@ endif()
839839

840840
if(MSVC)
841841
option(LLVM_BUILD_LLVM_C_DYLIB "Build LLVM-C.dll (Windows only)" ON)
842-
# Set this variable to OFF here so it can't be set with a command-line
843-
# argument.
844-
set (LLVM_LINK_LLVM_DYLIB OFF)
842+
if(NOT LLVM_BUILD_LLVM_DYLIB_VIS)
843+
# Set this variable to OFF here so it can't be set with a command-line
844+
# argument.
845+
set (LLVM_LINK_LLVM_DYLIB OFF)
846+
endif()
845847
if (BUILD_SHARED_LIBS)
846848
message(FATAL_ERROR "BUILD_SHARED_LIBS options is not supported on Windows.")
847849
endif()
848-
else()
849-
option(LLVM_LINK_LLVM_DYLIB "Link tools against the libllvm dynamic library" OFF)
850+
else()
850851
option(LLVM_BUILD_LLVM_C_DYLIB "Build libllvm-c re-export library (Darwin only)" OFF)
852+
endif()
853+
854+
if(NOT MSVC OR LLVM_BUILD_LLVM_DYLIB_VIS)
855+
option(LLVM_LINK_LLVM_DYLIB "Link tools against the libllvm dynamic library" OFF)
851856
set(LLVM_BUILD_LLVM_DYLIB_default OFF)
852857
if(LLVM_LINK_LLVM_DYLIB OR LLVM_BUILD_LLVM_C_DYLIB)
853858
set(LLVM_BUILD_LLVM_DYLIB_default ON)
854859
endif()
855860
option(LLVM_BUILD_LLVM_DYLIB "Build libllvm dynamic library" ${LLVM_BUILD_LLVM_DYLIB_default})
856861
endif()
857862

863+
# Build llvm dynamic library with explicit symbol visibility on windows and default hidden symbol visibility on Linux
864+
if(LLVM_BUILD_LLVM_DYLIB_VIS)
865+
set(LLVM_BUILD_LLVM_DYLIB ON)
866+
if(MSVC)
867+
option(LLVM_DYLIB_EXPORT_INLINES "Force inline members of class to be dll exported when
868+
building with clang-cl so the libllvm dll is compatible with MSVC" OFF)
869+
endif()
870+
endif()
871+
858872
if (LLVM_LINK_LLVM_DYLIB AND BUILD_SHARED_LIBS)
859873
message(FATAL_ERROR "Cannot enable BUILD_SHARED_LIBS with LLVM_LINK_LLVM_DYLIB. We recommend disabling BUILD_SHARED_LIBS.")
860874
endif()

llvm/cmake/modules/AddLLVM.cmake

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -606,6 +606,10 @@ function(llvm_add_library name)
606606
endif()
607607
endforeach()
608608
endif()
609+
610+
if(ARG_DISABLE_LLVM_LINK_LLVM_DYLIB)
611+
target_compile_definitions(${obj_name} PRIVATE LLVM_BUILD_STATIC)
612+
endif()
609613
endif()
610614

611615
if(ARG_SHARED AND ARG_STATIC)
@@ -641,8 +645,36 @@ function(llvm_add_library name)
641645
endif()
642646
set_target_properties(${name} PROPERTIES FOLDER "${subproject_title}/Libraries")
643647

648+
## If were compiling with clang-cl use /Zc:dllexportInlines- to exclude inline
649+
## class members from being dllexport'ed to reduce compile time.
650+
## This will also keep us below the 64k exported symbol limit
651+
## https://blog.llvm.org/2018/11/30-faster-windows-builds-with-clang-cl_14.html
652+
if(LLVM_BUILD_LLVM_DYLIB AND NOT LLVM_DYLIB_EXPORT_INLINES AND
653+
MSVC AND CMAKE_CXX_COMPILER_ID MATCHES Clang)
654+
target_compile_options(${name} PUBLIC /Zc:dllexportInlines-)
655+
if(TARGET ${obj_name})
656+
target_compile_options(${obj_name} PUBLIC /Zc:dllexportInlines-)
657+
endif()
658+
endif()
659+
644660
if(ARG_COMPONENT_LIB)
645661
set_target_properties(${name} PROPERTIES LLVM_COMPONENT TRUE)
662+
if(LLVM_BUILD_LLVM_DYLIB OR BUILD_SHARED_LIBS)
663+
target_compile_definitions(${name} PRIVATE LLVM_EXPORTS)
664+
endif()
665+
666+
# When building shared objects for each target there are some internal APIs
667+
# that are used across shared objects which we can't hide.
668+
if (LLVM_BUILD_LLVM_DYLIB_VIS AND NOT BUILD_SHARED_LIBS AND NOT APPLE AND
669+
(NOT (WIN32 OR CYGWIN) OR (MINGW AND CMAKE_CXX_COMPILER_ID MATCHES "Clang")) AND
670+
NOT (${CMAKE_SYSTEM_NAME} MATCHES "AIX") AND
671+
NOT DEFINED CMAKE_CXX_VISIBILITY_PRESET)
672+
673+
set_target_properties(${name} PROPERTIES
674+
C_VISIBILITY_PRESET hidden
675+
CXX_VISIBILITY_PRESET hidden
676+
VISIBILITY_INLINES_HIDDEN YES)
677+
endif()
646678
set_property(GLOBAL APPEND PROPERTY LLVM_COMPONENT_LIBS ${name})
647679
endif()
648680

@@ -741,6 +773,9 @@ function(llvm_add_library name)
741773
if (LLVM_LINK_LLVM_DYLIB AND NOT ARG_DISABLE_LLVM_LINK_LLVM_DYLIB)
742774
set(llvm_libs LLVM)
743775
else()
776+
if(ARG_DISABLE_LLVM_LINK_LLVM_DYLIB)
777+
target_compile_definitions(${name} PRIVATE LLVM_BUILD_STATIC)
778+
endif()
744779
llvm_map_components_to_libnames(llvm_libs
745780
${ARG_LINK_COMPONENTS}
746781
${LLVM_LINK_COMPONENTS}
@@ -1116,6 +1151,16 @@ macro(add_llvm_executable name)
11161151
if (ARG_EXPORT_SYMBOLS)
11171152
export_executable_symbols(${name})
11181153
endif()
1154+
1155+
if(ARG_DISABLE_LLVM_LINK_LLVM_DYLIB OR NOT LLVM_LINK_LLVM_DYLIB)
1156+
target_compile_definitions(${name} PRIVATE LLVM_BUILD_STATIC)
1157+
endif()
1158+
1159+
if(LLVM_BUILD_LLVM_DYLIB_VIS AND NOT LLVM_DYLIB_EXPORT_INLINES AND
1160+
MSVC AND CMAKE_CXX_COMPILER_ID MATCHES Clang)
1161+
# This has to match how the libraries the executable is linked to are built or there be linker errors.
1162+
target_compile_options(${name} PRIVATE /Zc:dllexportInlines-)
1163+
endif()
11191164
endmacro(add_llvm_executable name)
11201165

11211166
# add_llvm_pass_plugin(name [NO_MODULE] ...)

llvm/cmake/modules/HandleLLVMOptions.cmake

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -754,6 +754,12 @@ if (MSVC)
754754
# any code that uses the LLVM_ALIGNAS macro), so this is must be disabled to
755755
# avoid unwanted alignment warnings.
756756
-wd4324 # Suppress 'structure was padded due to __declspec(align())'
757+
# This is triggered for every variable that is a template type of a class even
758+
# if there private when the class is dllexport'ed
759+
-wd4251 # Suppress 'needs to have dll-interface to be used by clients'
760+
# We only putting dll export on classes with out of line members so this
761+
# warning gets triggered a lot for bases we haven't exported'
762+
-wd4275 # non dll-interface class used as base for dll-interface class
757763

758764
# Promoted warnings.
759765
-w14062 # Promote 'enumerator in switch of enum is not handled' to level 1 warning.

llvm/include/llvm/ADT/Any.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525

2626
namespace llvm {
2727

28-
class LLVM_EXTERNAL_VISIBILITY Any {
28+
class LLVM_ABI Any {
2929

3030
// The `Typeid<T>::Id` static data member below is a globally unique
3131
// identifier for the type `T`. It is explicitly marked with default

llvm/include/llvm/Analysis/LazyCallGraph.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,7 @@ class LazyCallGraph {
416416
/// outer structure. SCCs do not support mutation of the call graph, that
417417
/// must be done through the containing \c RefSCC in order to fully reason
418418
/// about the ordering and connections of the graph.
419-
class LLVM_EXTERNAL_VISIBILITY SCC {
419+
class LLVM_ABI SCC {
420420
friend class LazyCallGraph;
421421
friend class LazyCallGraph::Node;
422422

llvm/include/llvm/Analysis/LoopInfo.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ extern template class LoopBase<BasicBlock, Loop>;
4141

4242
/// Represents a single loop in the control flow graph. Note that not all SCCs
4343
/// in the CFG are necessarily loops.
44-
class LLVM_EXTERNAL_VISIBILITY Loop : public LoopBase<BasicBlock, Loop> {
44+
class LLVM_ABI Loop : public LoopBase<BasicBlock, Loop> {
4545
public:
4646
/// A range representing the start and end location of a loop.
4747
class LocRange {

llvm/include/llvm/Analysis/LoopNestAnalysis.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ using LoopVectorTy = SmallVector<Loop *, 8>;
2525
class LPMUpdater;
2626

2727
/// This class represents a loop nest and can be used to query its properties.
28-
class LLVM_EXTERNAL_VISIBILITY LoopNest {
28+
class LLVM_ABI LoopNest {
2929
public:
3030
using InstrVectorTy = SmallVector<const Instruction *>;
3131

llvm/include/llvm/CodeGen/MachineFunction.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ struct LandingPadInfo {
254254
: LandingPadBlock(MBB) {}
255255
};
256256

257-
class LLVM_EXTERNAL_VISIBILITY MachineFunction {
257+
class LLVM_ABI MachineFunction {
258258
Function &F;
259259
const LLVMTargetMachine &Target;
260260
const TargetSubtargetInfo *STI;

llvm/include/llvm/IR/Function.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,7 @@ class User;
6060
class BranchProbabilityInfo;
6161
class BlockFrequencyInfo;
6262

63-
class LLVM_EXTERNAL_VISIBILITY Function : public GlobalObject,
64-
public ilist_node<Function> {
63+
class LLVM_ABI Function : public GlobalObject, public ilist_node<Function> {
6564
public:
6665
using BasicBlockListType = SymbolTableList<BasicBlock>;
6766

llvm/include/llvm/IR/Module.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ class VersionTuple;
6262
/// constant references to global variables in the module. When a global
6363
/// variable is destroyed, it should have no entries in the GlobalList.
6464
/// The main container class for the LLVM Intermediate Representation.
65-
class LLVM_EXTERNAL_VISIBILITY Module {
65+
class LLVM_ABI Module {
6666
/// @name Types And Enumerations
6767
/// @{
6868
public:

llvm/include/llvm/Support/Compiler.h

Lines changed: 68 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,8 @@
114114
/// this attribute will be made public and visible outside of any shared library
115115
/// they are linked in to.
116116

117-
#if LLVM_HAS_CPP_ATTRIBUTE(gnu::visibility)
117+
#if LLVM_HAS_CPP_ATTRIBUTE(gnu::visibility) && defined(__GNUC__) && \
118+
!defined(__clang__)
118119
#define LLVM_ATTRIBUTE_VISIBILITY_HIDDEN [[gnu::visibility("hidden")]]
119120
#define LLVM_ATTRIBUTE_VISIBILITY_DEFAULT [[gnu::visibility("default")]]
120121
#elif __has_attribute(visibility)
@@ -125,18 +126,79 @@
125126
#define LLVM_ATTRIBUTE_VISIBILITY_DEFAULT
126127
#endif
127128

128-
129-
#if (!(defined(_WIN32) || defined(__CYGWIN__)) || \
130-
(defined(__MINGW32__) && defined(__clang__)))
131-
#define LLVM_LIBRARY_VISIBILITY LLVM_ATTRIBUTE_VISIBILITY_HIDDEN
132129
#if defined(LLVM_BUILD_LLVM_DYLIB) || defined(LLVM_BUILD_SHARED_LIBS)
133130
#define LLVM_EXTERNAL_VISIBILITY LLVM_ATTRIBUTE_VISIBILITY_DEFAULT
134131
#else
135132
#define LLVM_EXTERNAL_VISIBILITY
136133
#endif
134+
135+
#if (!(defined(_WIN32) || defined(__CYGWIN__)) || \
136+
(defined(__MINGW32__) && defined(__clang__)))
137+
#define LLVM_LIBRARY_VISIBILITY LLVM_ATTRIBUTE_VISIBILITY_HIDDEN
138+
#define LLVM_ALWAYS_EXPORT LLVM_ATTRIBUTE_VISIBILITY_DEFAULT
139+
#elif defined(_WIN32)
140+
#define LLVM_ALWAYS_EXPORT __declspec(dllexport)
141+
#define LLVM_LIBRARY_VISIBILITY
137142
#else
138143
#define LLVM_LIBRARY_VISIBILITY
139-
#define LLVM_EXTERNAL_VISIBILITY
144+
#define LLVM_ALWAYS_EXPORT
145+
#endif
146+
147+
/// LLVM_ABI is the main export/visibility macro to mark something as explicitly
148+
/// exported when llvm is built as a shared library with everything else that is
149+
/// unannotated will have internal visibility.
150+
///
151+
/// LLVM_EXPORT_TEMPLATE is used on explicit template instantiations in source
152+
/// files that were declared extern in a header. This macro is only set as a
153+
/// compiler export attribute on windows, on other platforms it does nothing.
154+
///
155+
/// LLVM_TEMPLATE_ABI is for annotating extern template declarations in headers
156+
/// for both functions and classes. On windows its turned in to dllimport for
157+
/// library consumers, for other platforms its a default visibility attribute.
158+
///
159+
/// LLVM_C_ABI is used to annotated functions and data that need to be exported
160+
/// for the libllvm-c API. This used both for the llvm-c headers and for the
161+
/// functions declared in the different Target's c++ source files that don't
162+
/// include the header forward declaring them.
163+
#ifndef LLVM_ABI_GENERATING_ANNOTATIONS
164+
// Marker to add to classes or functions in public headers that should not have
165+
// export macros added to them by the clang tool
166+
#define LLVM_ABI_NOT_EXPORTED
167+
#if defined(LLVM_BUILD_LLVM_DYLIB) || defined(LLVM_BUILD_SHARED_LIBS) || \
168+
defined(LLVM_ENABLE_PLUGINS)
169+
// Some libraries like those for tablegen are linked in to tools that used
170+
// in the build so can't depend on the llvm shared library. If export macros
171+
// were left enabled when building these we would get duplicate or
172+
// missing symbol linker errors on windows.
173+
#if defined(LLVM_BUILD_STATIC)
174+
#define LLVM_ABI
175+
#define LLVM_TEMPLATE_ABI
176+
#define LLVM_EXPORT_TEMPLATE
177+
#elif defined(_WIN32)
178+
#if defined(LLVM_EXPORTS)
179+
#define LLVM_ABI __declspec(dllexport)
180+
#define LLVM_TEMPLATE_ABI
181+
#define LLVM_EXPORT_TEMPLATE __declspec(dllexport)
182+
#else
183+
#define LLVM_ABI __declspec(dllimport)
184+
#define LLVM_TEMPLATE_ABI __declspec(dllimport)
185+
#define LLVM_EXPORT_TEMPLATE
186+
#endif
187+
#elif defined(__ELF__)
188+
#define LLVM_ABI LLVM_ATTRIBUTE_VISIBILITY_DEFAULT
189+
#define LLVM_TEMPLATE_ABI LLVM_ATTRIBUTE_VISIBILITY_DEFAULT
190+
#define LLVM_EXPORT_TEMPLATE
191+
#elif defined(__MACH__) || defined(__WASM__)
192+
#define LLVM_ABI LLVM_ATTRIBUTE_VISIBILITY_DEFAULT
193+
#define LLVM_TEMPLATE_ABI
194+
#define LLVM_EXPORT_TEMPLATE
195+
#endif
196+
#else
197+
#define LLVM_ABI
198+
#define LLVM_TEMPLATE_ABI
199+
#define LLVM_EXPORT_TEMPLATE
200+
#endif
201+
#define LLVM_C_ABI LLVM_ABI
140202
#endif
141203

142204
#if defined(__GNUC__)

llvm/tools/llvm-shlib/CMakeLists.txt

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ if(LLVM_LINK_LLVM_DYLIB AND LLVM_DYLIB_EXPORTED_SYMBOL_FILE)
1111
endif()
1212

1313
if(LLVM_BUILD_LLVM_DYLIB)
14-
if(MSVC)
14+
if(MSVC AND NOT LLVM_BUILD_LLVM_DYLIB_VIS)
1515
message(FATAL_ERROR "Generating libLLVM is not supported on MSVC")
1616
endif()
1717
if(ZOS)
@@ -49,18 +49,27 @@ if(LLVM_BUILD_LLVM_DYLIB)
4949
${CMAKE_CURRENT_SOURCE_DIR}/simple_version_script.map.in
5050
${LLVM_LIBRARY_DIR}/tools/llvm-shlib/simple_version_script.map)
5151

52-
# GNU ld doesn't resolve symbols in the version script.
53-
set(LIB_NAMES -Wl,--whole-archive ${LIB_NAMES} -Wl,--no-whole-archive)
54-
if (NOT LLVM_LINKER_IS_SOLARISLD AND NOT MINGW)
55-
# Solaris ld does not accept global: *; so there is no way to version *all* global symbols
56-
set(LIB_NAMES -Wl,--version-script,${LLVM_LIBRARY_DIR}/tools/llvm-shlib/simple_version_script.map ${LIB_NAMES})
57-
endif()
58-
if (NOT MINGW AND NOT LLVM_LINKER_IS_SOLARISLD_ILLUMOS)
59-
# Optimize function calls for default visibility definitions to avoid PLT and
60-
# reduce dynamic relocations.
61-
# Note: for -fno-pic default, the address of a function may be different from
62-
# inside and outside libLLVM.so.
63-
target_link_options(LLVM PRIVATE LINKER:-Bsymbolic-functions)
52+
if(MSVC)
53+
target_link_directories(LLVM PRIVATE ${LLVM_LIBRARY_DIR})
54+
foreach(library ${LIB_NAMES})
55+
# FIXME figure out how to use LINK_LIBRARY:WHOLE_ARCHIVE without cmake errors
56+
# target_link_libraries(LLVM PRIVATE "$<LINK_LIBRARY:WHOLE_ARCHIVE,${library}>" )
57+
target_link_options(LLVM PRIVATE /WHOLEARCHIVE:${library}.lib)
58+
endforeach()
59+
else()
60+
# GNU ld doesn't resolve symbols in the version script.
61+
set(LIB_NAMES -Wl,--whole-archive ${LIB_NAMES} -Wl,--no-whole-archive)
62+
if (NOT LLVM_LINKER_IS_SOLARISLD AND NOT MINGW)
63+
# Solaris ld does not accept global: *; so there is no way to version *all* global symbols
64+
set(LIB_NAMES -Wl,--version-script,${LLVM_LIBRARY_DIR}/tools/llvm-shlib/simple_version_script.map ${LIB_NAMES})
65+
endif()
66+
if (NOT MINGW AND NOT LLVM_LINKER_IS_SOLARISLD_ILLUMOS)
67+
# Optimize function calls for default visibility definitions to avoid PLT and
68+
# reduce dynamic relocations.
69+
# Note: for -fno-pic default, the address of a function may be different from
70+
# inside and outside libLLVM.so.
71+
target_link_options(LLVM PRIVATE LINKER:-Bsymbolic-functions)
72+
endif()
6473
endif()
6574
endif()
6675

llvm/utils/TableGen/Basic/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ set(LLVM_LINK_COMPONENTS
88
TableGen
99
)
1010

11-
add_llvm_library(LLVMTableGenBasic OBJECT EXCLUDE_FROM_ALL
11+
add_llvm_library(LLVMTableGenBasic OBJECT EXCLUDE_FROM_ALL DISABLE_LLVM_LINK_LLVM_DYLIB
1212
CodeGenIntrinsics.cpp
1313
SDNodeProperties.cpp
1414
)

llvm/utils/TableGen/Common/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ set(LLVM_LINK_COMPONENTS
1010
TableGen
1111
)
1212

13-
add_llvm_library(LLVMTableGenCommon STATIC OBJECT EXCLUDE_FROM_ALL
13+
add_llvm_library(LLVMTableGenCommon STATIC OBJECT EXCLUDE_FROM_ALL DISABLE_LLVM_LINK_LLVM_DYLIB
1414
GlobalISel/CodeExpander.cpp
1515
GlobalISel/CombinerUtils.cpp
1616
GlobalISel/CXXPredicates.cpp

0 commit comments

Comments
 (0)