[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