[llvm] [llvm] refactor common export macros to llvm/Config (PR #149175)
Andrew Rogers via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 16 13:12:29 PDT 2025
https://github.com/andrurogerz created https://github.com/llvm/llvm-project/pull/149175
## Purpose
Eliminate code duplication in `LLVM_ABI` and related export macros by defining a foundational set of `LLVM_INTERFACE_` macros in a new config header `llvm/Config/export-config.h`.
## Overview
* Introduce a new `export-config.h.cmake` config file which contains new definitions of `LLVM_INTERFACE_` macros. These macros are always defined to the appropriate export/visibility annotation.
* Move definitions controlling individual library export annotations from `llvm-config.h.cmake` to the new `export-config.h.cmake` file.
* Update `LLVM_ABI` macro definitions in `llvm/Support/Compiler.h` to alias to the new `LLVM_INTERFACE_` macros, conditional on `LLVM_ENABLE_LLVM_EXPORT_ANNOTATIONS` being defined.
* Update 'LLVM_C_ABI` macro definition in `llvm-c/Visibility.h` to alias to `LLVM_INTERFACE_ABI`, conditional on `LLVM_ENABLE_LLVM_C_EXPORT_ANNOTATIONS` being defined.
## Background
The effort to build LLVM as a WIndows DLL is tracked in #109483. Additional context is provided in [this discourse](https://discourse.llvm.org/t/psa-annotating-llvm-public-interface/85307), and documentation for `LLVM_ABI` and related annotations is found in the LLVM repo [here](https://github.com/llvm/llvm-project/blob/main/llvm/docs/InterfaceExportAnnotations.rst).
## Validation
* Built llvm-project on Windows with `clang-cl` and MSVC `cl`.
* Built llvm-project on Linux with `clang` and `gcc`.
>From c61f069293c30b620d5f94294e6eaa5b56254418 Mon Sep 17 00:00:00 2001
From: Andrew Rogers <andrurogerz at gmail.com>
Date: Wed, 16 Jul 2025 11:56:36 -0700
Subject: [PATCH] [llvm] refactor common export macros to llvm/Config
---
llvm/CMakeLists.txt | 3 +
llvm/include/llvm-c/Visibility.h | 20 +----
.../include/llvm/Config/export-config.h.cmake | 88 +++++++++++++++++++
llvm/include/llvm/Config/llvm-config.h.cmake | 6 --
llvm/include/llvm/Support/Compiler.h | 45 +++-------
5 files changed, 104 insertions(+), 58 deletions(-)
create mode 100644 llvm/include/llvm/Config/export-config.h.cmake
diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt
index 3f8201fa426fe..d02b37d3820d2 100644
--- a/llvm/CMakeLists.txt
+++ b/llvm/CMakeLists.txt
@@ -1228,6 +1228,9 @@ endif()
configure_file(
${LLVM_MAIN_INCLUDE_DIR}/llvm/Config/config.h.cmake
${LLVM_INCLUDE_DIR}/llvm/Config/config.h)
+configure_file(
+ ${LLVM_MAIN_INCLUDE_DIR}/llvm/Config/export-config.h.cmake
+ ${LLVM_INCLUDE_DIR}/llvm/Config/export-config.h)
configure_file(
${LLVM_MAIN_INCLUDE_DIR}/llvm/Config/llvm-config.h.cmake
${LLVM_INCLUDE_DIR}/llvm/Config/llvm-config.h)
diff --git a/llvm/include/llvm-c/Visibility.h b/llvm/include/llvm-c/Visibility.h
index 371b981b6d32c..b1419d41cdbe8 100644
--- a/llvm/include/llvm-c/Visibility.h
+++ b/llvm/include/llvm-c/Visibility.h
@@ -16,29 +16,15 @@
#ifndef LLVM_C_VISIBILITY_H
#define LLVM_C_VISIBILITY_H
-#include "llvm/Config/llvm-config.h"
+#include "llvm/Config/export-config.h"
/// LLVM_C_ABI is the export/visibility macro used to mark symbols declared in
/// llvm-c as exported when built as a shared library.
-#if !defined(LLVM_ABI_GENERATING_ANNOTATIONS)
-// TODO(https://github.com/llvm/llvm-project/issues/145406): eliminate need for
-// two preprocessor definitions to gate LLVM_ABI macro definitions.
-#if defined(LLVM_ENABLE_LLVM_C_EXPORT_ANNOTATIONS) && \
- !defined(LLVM_BUILD_STATIC)
-#if defined(_WIN32) && !defined(__MINGW32__)
-#if defined(LLVM_EXPORTS)
-#define LLVM_C_ABI __declspec(dllexport)
+#if defined(LLVM_ENABLE_LLVM_C_EXPORT_ANNOTATIONS)
+#define LLVM_C_ABI LLVM_INTERFACE_ABI
#else
-#define LLVM_C_ABI __declspec(dllimport)
-#endif
-#elif defined(__has_attribute) && __has_attribute(visibility)
-#define LLVM_C_ABI __attribute__((visibility("default")))
-#endif
-#endif
-#if !defined(LLVM_C_ABI)
#define LLVM_C_ABI
#endif
-#endif
#endif
diff --git a/llvm/include/llvm/Config/export-config.h.cmake b/llvm/include/llvm/Config/export-config.h.cmake
new file mode 100644
index 0000000000000..33a7a497590fe
--- /dev/null
+++ b/llvm/include/llvm/Config/export-config.h.cmake
@@ -0,0 +1,88 @@
+/*===------- llvm/Config/export-config.h - export configuration ----- 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 contains configuration definitions controling which LLVM projects
+ and components require public ABI export for shared library builds. It also
+ contains generic LLVM_INTERFACE_ macro definitions that can be aliased by
+ libraries and components and used to decorate their public interface. */
+
+#ifndef LLVM_EXPORT_CONFIG_H
+#define LLVM_EXPORT_CONFIG_H
+
+/* Define if exporting LLVM public interface for shared library */
+#cmakedefine LLVM_ENABLE_LLVM_EXPORT_ANNOTATIONS
+
+/* Define if exporting LLVM-C public interface for shared library */
+#cmakedefine LLVM_ENABLE_LLVM_C_EXPORT_ANNOTATIONS
+
+/// LLVM_INTERFACE_ABI is the main export/visibility macro to mark something as explicitly
+/// exported when llvm is built as a shared library with everything else that is
+/// unannotated will have internal visibility.
+///
+/// LLVM_INTERFACE_ABI_EXPORT is for the special case for things like plugin symbol
+/// declarations or definitions where we don't want the macro to be switching
+/// between dllexport and dllimport on windows based on what codebase is being
+/// built, it will only be dllexport. For non windows platforms this macro
+/// behaves the same as LLVM_ABI.
+///
+/// LLVM_INTERFACE_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.
+///
+/// LLVM_INTERFACE_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.
+///
+/// LLVM_INTERFACE_ABI_FOR_TEST is for annotating symbols that are only exported because
+/// they are imported from a test. These symbols are not technically part of the
+/// LLVM public interface and could be conditionally excluded when not building
+/// tests in the future.
+///
+// Marker to add to classes or functions in public headers that should not have
+// export macros added to them by the clang tool
+#define LLVM_INTERFACE_ABI_NOT_EXPORTED
+// TODO(https://github.com/llvm/llvm-project/issues/145406): eliminate need for
+// two preprocessor definitions to gate LLVM_ABI macro definitions.
+#if !defined(LLVM_BUILD_STATIC)
+#if defined(_WIN32) && !defined(__MINGW32__)
+#if defined(LLVM_EXPORTS)
+#define LLVM_INTERFACE_ABI __declspec(dllexport)
+#define LLVM_INTERFACE_TEMPLATE_ABI
+#define LLVM_INTERFACE_EXPORT_TEMPLATE __declspec(dllexport)
+#else
+#define LLVM_INTERFACE_ABI __declspec(dllimport)
+#define LLVM_INTERFACE_TEMPLATE_ABI __declspec(dllimport)
+#define LLVM_INTERFACE_EXPORT_TEMPLATE
+#endif
+#define LLVM_INTERFACE_ABI_EXPORT __declspec(dllexport)
+#elif defined(__has_attribute) && __has_attribute(visibility)
+#if defined(__ELF__) || defined(__MINGW32__) || defined(_AIX) || \
+ defined(__MVS__) || defined(__CYGWIN__)
+#define LLVM_INTERFACE_ABI __attribute__((visibility("default")))
+#define LLVM_INTERFACE_TEMPLATE_ABI LLVM_INTERFACE_ABI
+#define LLVM_INTERFACE_EXPORT_TEMPLATE
+#define LLVM_INTERFACE_ABI_EXPORT LLVM_INTERFACE_ABI
+#elif defined(__MACH__) || defined(__WASM__) || defined(__EMSCRIPTEN__)
+#define LLVM_INTERFACE_ABI __attribute__((visibility("default")))
+#define LLVM_INTERFACE_TEMPLATE_ABI
+#define LLVM_INTERFACE_EXPORT_TEMPLATE
+#define LLVM_INTERFACE_ABI_EXPORT LLVM_INTERFACE_ABI
+#endif
+#endif
+#endif
+#if !defined(LLVM_INTERFACE_ABI)
+#define LLVM_INTERFACE_ABI
+#define LLVM_INTERFACE_TEMPLATE_ABI
+#define LLVM_INTERFACE_EXPORT_TEMPLATE
+#define LLVM_INTERFACE_ABI_EXPORT
+#endif
+#define LLVM_INTERFACE_ABI_FOR_TEST LLVM_INTERFACE_ABI
+
+#endif
diff --git a/llvm/include/llvm/Config/llvm-config.h.cmake b/llvm/include/llvm/Config/llvm-config.h.cmake
index a6832299e5b6b..a0ad517a6ecf4 100644
--- a/llvm/include/llvm/Config/llvm-config.h.cmake
+++ b/llvm/include/llvm/Config/llvm-config.h.cmake
@@ -110,12 +110,6 @@
/* Define if building LLVM with BUILD_SHARED_LIBS */
#cmakedefine LLVM_BUILD_SHARED_LIBS
-/* Define if exporting LLVM public interface for shared library */
-#cmakedefine LLVM_ENABLE_LLVM_EXPORT_ANNOTATIONS
-
-/* Define if exporting LLVM-C public interface for shared library */
-#cmakedefine LLVM_ENABLE_LLVM_C_EXPORT_ANNOTATIONS
-
/* Define if building LLVM with LLVM_FORCE_USE_OLD_TOOLCHAIN_LIBS */
#cmakedefine LLVM_FORCE_USE_OLD_TOOLCHAIN ${LLVM_FORCE_USE_OLD_TOOLCHAIN}
diff --git a/llvm/include/llvm/Support/Compiler.h b/llvm/include/llvm/Support/Compiler.h
index 297d3e9b04095..d2c6b675fef7d 100644
--- a/llvm/include/llvm/Support/Compiler.h
+++ b/llvm/include/llvm/Support/Compiler.h
@@ -15,6 +15,7 @@
#ifndef LLVM_SUPPORT_COMPILER_H
#define LLVM_SUPPORT_COMPILER_H
+#include "llvm/Config/export-config.h"
#include "llvm/Config/llvm-config.h"
#include <stddef.h>
@@ -176,46 +177,20 @@
/// LLVM public interface and could be conditionally excluded when not building
/// tests in the future.
///
-#ifndef LLVM_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 LLVM_ABI_NOT_EXPORTED
-// TODO(https://github.com/llvm/llvm-project/issues/145406): eliminate need for
-// two preprocessor definitions to gate LLVM_ABI macro definitions.
-#if defined(LLVM_ENABLE_LLVM_EXPORT_ANNOTATIONS) && !defined(LLVM_BUILD_STATIC)
-#if defined(_WIN32) && !defined(__MINGW32__)
-#if defined(LLVM_EXPORTS)
-#define LLVM_ABI __declspec(dllexport)
-#define LLVM_TEMPLATE_ABI
-#define LLVM_EXPORT_TEMPLATE __declspec(dllexport)
+#if defined(LLVM_ENABLE_LLVM_EXPORT_ANNOTATIONS)
+#define LLVM_ABI_NOT_EXPORTED LLVM_INTERFACE_ABI_NOT_EXPORTED
+#define LLVM_ABI LLVM_INTERFACE_ABI
+#define LLVM_TEMPLATE_ABI LLVM_INTERFACE_TEMPLATE_ABI
+#define LLVM_EXPORT_TEMPLATE LLVM_INTERFACE_EXPORT_TEMPLATE
+#define LLVM_ABI_EXPORT LLVM_INTERFACE_ABI_EXPORT
+#define LLVM_ABI_FOR_TEST LLVM_INTERFACE_ABI_FOR_TEST
#else
-#define LLVM_ABI __declspec(dllimport)
-#define LLVM_TEMPLATE_ABI __declspec(dllimport)
-#define LLVM_EXPORT_TEMPLATE
-#endif
-#define LLVM_ABI_EXPORT __declspec(dllexport)
-#elif __has_attribute(visibility)
-#if defined(__ELF__) || defined(__MINGW32__) || defined(_AIX) || \
- defined(__MVS__) || defined(__CYGWIN__)
-#define LLVM_ABI __attribute__((visibility("default")))
-#define LLVM_TEMPLATE_ABI LLVM_ABI
-#define LLVM_EXPORT_TEMPLATE
-#define LLVM_ABI_EXPORT LLVM_ABI
-#elif defined(__MACH__) || defined(__WASM__) || defined(__EMSCRIPTEN__)
-#define LLVM_ABI __attribute__((visibility("default")))
-#define LLVM_TEMPLATE_ABI
-#define LLVM_EXPORT_TEMPLATE
-#define LLVM_ABI_EXPORT LLVM_ABI
-#endif
-#endif
-#endif
-#if !defined(LLVM_ABI)
+#define LLVM_ABI_NOT_EXPORTED
#define LLVM_ABI
#define LLVM_TEMPLATE_ABI
#define LLVM_EXPORT_TEMPLATE
#define LLVM_ABI_EXPORT
-#endif
-#define LLVM_ABI_FOR_TEST LLVM_ABI
+#define LLVM_ABI_FOR_TEST
#endif
#if defined(__GNUC__)
More information about the llvm-commits
mailing list