Skip to content

Commit 59f8796

Browse files
authored
Initial changes for llvm shared library build using explicit visibility annotations
These are my initial build and code changes to supporting building llvm as shared library/DLL on windows(without force exporting all symbols) and making symbol visibility hidden by default on Linux which adding explicit symbol visibility macros to the whole llvm codebase. Updated cmake code to allow building llvm-shlib on windows by appending /WHOLEARCHIVE:lib to the linker options. Remove the hardcoded CMake error from using LLVM_BUILD_LLVM_DYLIB on windows. Updated CMake to define new macros to control conditional export macros in llvm/Support/Compiler.h Use /Zc:dllexportInlines- when compiling with clang-cl on windows with a opt out CMake option to disable using it. Replace some use of LLVM_EXTERNAL_VISIBILITY with new export macros. Some of the cmake and code changes are based on @tstellar's earlier PR #67502. I have Windows building using clang-cl, while for MSVC its at-least able to build libllvm, but some tests can't build because llvm iterator template metaprogramming that doesn't work well with dllexport. Linux should build without issue. My full branch is here https://github.com/fsfod/llvm-project/tree/llvm-export-api-20.0 and including all the auto generated export macros from clang tooling based system.
1 parent fb14941 commit 59f8796

File tree

14 files changed

+180
-39
lines changed

14 files changed

+180
-39
lines changed

llvm/CMakeLists.txt

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
cmake_minimum_required(VERSION 3.20.0)
44

5+
include(CMakeDependentOption)
6+
57
set(LLVM_COMMON_CMAKE_UTILS ${CMAKE_CURRENT_SOURCE_DIR}/../cmake)
68
include(${LLVM_COMMON_CMAKE_UTILS}/Modules/CMakePolicy.cmake
79
NO_POLICY_SCOPE)
@@ -839,20 +841,40 @@ endif()
839841

840842
if(MSVC)
841843
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)
845844
if (BUILD_SHARED_LIBS)
846845
message(FATAL_ERROR "BUILD_SHARED_LIBS options is not supported on Windows.")
847846
endif()
848-
else()
849-
option(LLVM_LINK_LLVM_DYLIB "Link tools against the libllvm dynamic library" OFF)
847+
else()
850848
option(LLVM_BUILD_LLVM_C_DYLIB "Build libllvm-c re-export library (Darwin only)" OFF)
851-
set(LLVM_BUILD_LLVM_DYLIB_default OFF)
852-
if(LLVM_LINK_LLVM_DYLIB OR LLVM_BUILD_LLVM_C_DYLIB)
853-
set(LLVM_BUILD_LLVM_DYLIB_default ON)
854-
endif()
855-
option(LLVM_BUILD_LLVM_DYLIB "Build libllvm dynamic library" ${LLVM_BUILD_LLVM_DYLIB_default})
849+
endif()
850+
851+
# Used to test building the llvm shared library with explicit symbol visibility on
852+
# Windows and Linux. For ELF platforms default symbols visibility is set to hidden.
853+
set(LLVM_BUILD_LLVM_DYLIB_VIS FALSE CACHE BOOL "")
854+
mark_as_advanced(LLVM_BUILD_LLVM_DYLIB_VIS)
855+
856+
set(CAN_BUILD_LLVM_DYLIB OFF)
857+
if(NOT MSVC OR LLVM_BUILD_LLVM_DYLIB_VIS)
858+
set(CAN_BUILD_LLVM_DYLIB ON)
859+
endif()
860+
861+
cmake_dependent_option(LLVM_LINK_LLVM_DYLIB "Link tools against the libllvm dynamic library" OFF
862+
"CAN_BUILD_LLVM_DYLIB" OFF)
863+
864+
set(LLVM_BUILD_LLVM_DYLIB_default OFF)
865+
if(LLVM_LINK_LLVM_DYLIB OR LLVM_BUILD_LLVM_C_DYLIB)
866+
set(LLVM_BUILD_LLVM_DYLIB_default ON)
867+
endif()
868+
cmake_dependent_option(LLVM_BUILD_LLVM_DYLIB "Build libllvm dynamic library" ${LLVM_BUILD_LLVM_DYLIB_default}
869+
"CAN_BUILD_LLVM_DYLIB" OFF)
870+
871+
cmake_dependent_option(LLVM_DYLIB_EXPORT_INLINES "Force inline members of classes to be DLL exported when
872+
building with clang-cl so the libllvm DLL is compatible with MSVC"
873+
OFF
874+
"MSVC;LLVM_BUILD_LLVM_DYLIB_VIS" OFF)
875+
876+
if(LLVM_BUILD_LLVM_DYLIB_VIS)
877+
set(LLVM_BUILD_LLVM_DYLIB ON)
856878
endif()
857879

858880
if (LLVM_LINK_LLVM_DYLIB AND BUILD_SHARED_LIBS)

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
@@ -412,7 +412,7 @@ class LazyCallGraph {
412412
/// outer structure. SCCs do not support mutation of the call graph, that
413413
/// must be done through the containing \c RefSCC in order to fully reason
414414
/// about the ordering and connections of the graph.
415-
class LLVM_EXTERNAL_VISIBILITY SCC {
415+
class LLVM_ABI SCC {
416416
friend class LazyCallGraph;
417417
friend class LazyCallGraph::Node;
418418

llvm/include/llvm/Analysis/LoopInfo.h

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

3737
/// Represents a single loop in the control flow graph. Note that not all SCCs
3838
/// in the CFG are necessarily loops.
39-
class LLVM_EXTERNAL_VISIBILITY Loop : public LoopBase<BasicBlock, Loop> {
39+
class LLVM_ABI Loop : public LoopBase<BasicBlock, Loop> {
4040
public:
4141
/// A range representing the start and end location of a loop.
4242
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:

0 commit comments

Comments
 (0)