From 09fa2f012fccb6f1cf2f540856e67f55431da800 Mon Sep 17 00:00:00 2001 From: Thomas Fransham Date: Mon, 14 Oct 2024 16:32:50 +0100 Subject: [PATCH] [Clang] Add explicit visibility symbol macros (#108276) This is part of the effort to support for enabling plugins on windows by adding better support for building llvm and clang as a DLL. These macros are similar to the ones i added in #96630, but are for clang. Added explicit symbol visibility macros definitions that are defined in a new header and will be used to for shared library builds of clang to export symbols. Updated clang cmake to define a macro to enable the symbol visibility macros and explicitly disable them for clang tools that always use static linking. --------- Co-authored-by: Aaron Ballman --- clang/cmake/modules/AddClang.cmake | 11 +++++ clang/include/clang/Support/Compiler.h | 63 ++++++++++++++++++++++++++ clang/tools/libclang/CMakeLists.txt | 4 ++ 3 files changed, 78 insertions(+) create mode 100644 clang/include/clang/Support/Compiler.h diff --git a/clang/cmake/modules/AddClang.cmake b/clang/cmake/modules/AddClang.cmake index 5327b5d2f08928..091aec98e93ca3 100644 --- a/clang/cmake/modules/AddClang.cmake +++ b/clang/cmake/modules/AddClang.cmake @@ -108,6 +108,17 @@ macro(add_clang_library name) endif() llvm_add_library(${name} ${LIBTYPE} ${ARG_UNPARSED_ARGUMENTS} ${srcs}) + if(MSVC AND NOT CLANG_LINK_CLANG_DYLIB) + # Make sure all consumers also turn off visibility macros so there not trying to dllimport symbols. + target_compile_definitions(${name} PUBLIC CLANG_BUILD_STATIC) + if(TARGET "obj.${name}") + target_compile_definitions("obj.${name}" PUBLIC CLANG_BUILD_STATIC) + endif() + elseif(NOT ARG_SHARED AND NOT ARG_STATIC) + # Clang component libraries linked in to clang-cpp are declared without SHARED or STATIC + target_compile_definitions("obj.${name}" PUBLIC CLANG_EXPORTS) + endif() + set(libs ${name}) if(ARG_SHARED AND ARG_STATIC) list(APPEND libs ${name}_static) diff --git a/clang/include/clang/Support/Compiler.h b/clang/include/clang/Support/Compiler.h new file mode 100644 index 00000000000000..c35815e106d2e2 --- /dev/null +++ b/clang/include/clang/Support/Compiler.h @@ -0,0 +1,63 @@ +//===-- clang/Support/Compiler.h - Compiler abstraction support -*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines explicit visibility macros used to export symbols from +// clang-cpp +// +//===----------------------------------------------------------------------===// + +#ifndef CLANG_SUPPORT_COMPILER_H +#define CLANG_SUPPORT_COMPILER_H + +#include "llvm/Support/Compiler.h" + +/// CLANG_ABI is the main export/visibility macro to mark something as +/// explicitly exported when clang is built as a shared library with everything +/// else that is unannotated having hidden visibility. +/// +/// CLANG_EXPORT_TEMPLATE is used on explicit template instantiations in source +/// files that were declared extern in a header. This macro is only set as a +/// compiler export attribute on windows, on other platforms it does nothing. +/// +/// CLANG_TEMPLATE_ABI is for annotating extern template declarations in headers +/// for both functions and classes. On windows its turned in to dllimport for +/// library consumers, for other platforms its a default visibility attribute. +#ifndef CLANG_ABI_GENERATING_ANNOTATIONS +// Marker to add to classes or functions in public headers that should not have +// export macros added to them by the clang tool +#define CLANG_ABI_NOT_EXPORTED +// Some libraries like those for tablegen are linked in to tools that used +// in the build so can't depend on the llvm shared library. If export macros +// were left enabled when building these we would get duplicate or +// missing symbol linker errors on windows. +#if defined(CLANG_BUILD_STATIC) +#define CLANG_ABI +#define CLANG_TEMPLATE_ABI +#define CLANG_EXPORT_TEMPLATE +#elif defined(_WIN32) && !defined(__MINGW32__) +#if defined(CLANG_EXPORTS) +#define CLANG_ABI __declspec(dllexport) +#define CLANG_TEMPLATE_ABI +#define CLANG_EXPORT_TEMPLATE __declspec(dllexport) +#else +#define CLANG_ABI __declspec(dllimport) +#define CLANG_TEMPLATE_ABI __declspec(dllimport) +#define CLANG_EXPORT_TEMPLATE +#endif +#elif defined(__ELF__) || defined(__MINGW32__) || defined(_AIX) +#define CLANG_ABI LLVM_ATTRIBUTE_VISIBILITY_DEFAULT +#define CLANG_TEMPLATE_ABI LLVM_ATTRIBUTE_VISIBILITY_DEFAULT +#define CLANG_EXPORT_TEMPLATE +#elif defined(__MACH__) || defined(__WASM__) +#define CLANG_ABI LLVM_ATTRIBUTE_VISIBILITY_DEFAULT +#define CLANG_TEMPLATE_ABI +#define CLANG_EXPORT_TEMPLATE +#endif +#endif + +#endif diff --git a/clang/tools/libclang/CMakeLists.txt b/clang/tools/libclang/CMakeLists.txt index 968b46acb784cb..00a1223c0831a7 100644 --- a/clang/tools/libclang/CMakeLists.txt +++ b/clang/tools/libclang/CMakeLists.txt @@ -167,6 +167,10 @@ if(ENABLE_SHARED) PROPERTIES VERSION ${LIBCLANG_LIBRARY_VERSION} DEFINE_SYMBOL _CINDEX_LIB_) + # Avoid declaring clang c++ symbols that are statically linked into libclang as dllimport'ed. + # If llvm/libclang-cpp dll is also being built for windows clang c++ symbols will still be + # implicitly be exported from libclang. + target_compile_definitions(libclang PRIVATE CLANG_BUILD_STATIC) elseif(APPLE) set(LIBCLANG_LINK_FLAGS " -Wl,-compatibility_version -Wl,1") set(LIBCLANG_LINK_FLAGS "${LIBCLANG_LINK_FLAGS} -Wl,-current_version -Wl,${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}.${LLVM_VERSION_PATCH}")