From 394a509ae103b300f65c996be5cbc3ba73c72a94 Mon Sep 17 00:00:00 2001 From: Andrew Rogers Date: Tue, 6 May 2025 09:49:38 -0700 Subject: [PATCH 1/4] [doc] add documentation for IDS --- Docs/ExportMacroDefinitions.md | 44 ++++++++++ README.md | 154 ++++++++++++++++++++++++++++++++- 2 files changed, 197 insertions(+), 1 deletion(-) create mode 100644 Docs/ExportMacroDefinitions.md diff --git a/Docs/ExportMacroDefinitions.md b/Docs/ExportMacroDefinitions.md new file mode 100644 index 0000000..92556b8 --- /dev/null +++ b/Docs/ExportMacroDefinitions.md @@ -0,0 +1,44 @@ +## Export Macro Definitions + +A common approach for annotating project’s public interface is by defining a +set of preprocessor macros that are used instead of adding annotations directly +to the source. This approach allows supporting visibility annotations +(`[[gnu::visibility]]`, `__visibility__`) when building for Linux and MacOS and +DLL import/export annotations (`__declspec(dllimport)`, +`__declspec(dllexport)`) when building for Windows. + +For example, the `PUBLIC_ABI` macro defined below can be added to symbols in a +project’s header files files that should be externally visible. + +```cpp +#ifdef _WIN32 +#ifdef EXPORTING_ABI +// When building the Windows DLL, the public API must be annotated for exported. +#define PUBLIC_ABI __declspec(dllexport) +#else +// When building clients of the Windows DLL, the public API must be annotated for import. +#define PUBLIC_ABI __declspec(dllimport) +#endif +#elif defined(__cplusplus) && defined(__has_cpp_attribute) && \ + __has_cpp_attribute(gnu::visibility) && defined(__GNUC__) && !defined(__clang__) +// When supported, use the gnu::visibility C++ attribute to set visibility to default. +#define PUBLIC_API [[gnu::visibility("default")]] +#elif defined(__has_attribute) && __has_attribute(visibility) +// Otherwise, use the __attribute__ to set visibility to default. +#define PUBLIC_ABI __attribute__((visibility("default"))) +#else +#error "Required visibility attribute are not supported by compiler!" +#endif +``` + +A Windows project using these macros must be built with `EXPORTING_ABI` defined +so that public symbols are annotated for export with `__declspec(dllexport)`. +When building the client, however, `EXPORTING_ABI` must not be defined so the +same set of public symbols will be properly annotated for import with +`__declspec(dllimport)`. + +An ELF shared library or Mach-O dylib project will have all symbols publicly +visible by default so annotations are not strictly required. However, when a +project is built with default hidden symbol visibility using +`-fvisibility-default=hidden`, individual symbols must be explicitly exported +using a visibility annotations. diff --git a/README.md b/README.md index 67245e1..7b5d2a4 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,154 @@ # Interface Definition Scanner (IDS) -Interface Analysis Utility + +IDS is tool for automatically identifying and annotating the public interface of +a C++ project. It is built on Clang’s +[LibTooling](https://clang.llvm.org/docs/LibTooling.html) framework. It is +primarily designed for adding import/export annotations to a Windows DLL +project, but can also be used to add visibility annotations for ELF shared +library or Mach-O dylib projects. + +## Building IDS + +IDS can be built either as an LLVM external project or as a stand-alone project. + +### LLVM External Project + +IDS can be built as a sub-project of LLVM by setting `LLVM_EXTERNAL_PROJECTS`. +This greatly improves the editing and debugging experience in Visual Studio when +navigating to Clang code from the IDS code. Please see [Getting Started with the +LLVM +Project](https://llvm.org/docs/GettingStarted.html#getting-the-source-code-and-building-llvm) +for more info on building LLVM and Clang. + +The CMake variables `LLVM_EXTERNAL_PROJECTS` and `LLVM_EXTERNAL_IDS_SOURCE_DIR` +variables must be set for IDS to build as part of the LLVM build. + +Testing IDS also requires `LIT_EXECUTABLE` and `FILECHECK_EXECUTABLE` to specify +the locations of `lit.py` and `FileCheck`, which are located in the LLVM source +and LLVM build output directory. + +```bash +cmake -G Ninja \ + -B /home/user/src/llvm-project/build \ + -S /home/user/src/llvm-project/llvm \ + -DCMAKE_BUILD_TYPE=Release \ + -DLLVM_ENABLE_PROJECTS="llvm;clang" \ + -DLLVM_EXTERNAL_PROJECTS="IDS" \ + -DLLVM_EXTERNAL_IDS_SOURCE_DIR="/home/user/src/ids" \ + -DLIT_EXECUTABLE=/home/user/src/llvm-project/llvm/utils/lit/lit.py \ + -DFILECHECK_EXECUTABLE=/home/user/src/llvm-project/build/bin/FileCheck + +cmake --build /home/user/src/llvm-project/build --target idt +cmake --build /home/user/src/llvm-project/build --target check-ids +``` + +### Stand-Alone Build + +To build IDS as a stand-alone project, `LLVM_DIR` and `Clang_DIR` variables must +be provided to specify the locations of local LLVM and Clang libraries. These +can refer to locally built LLVM and Clang libraries, or to pre-built LLVM +package that includes the Clang development libraries. + +Testing IDS also requires `LIT_EXECUTABLE` and `FILECHECK_EXECUTABLE` to specify +the locations of `lit.py` and `FileCheck` , which are not typically included in +a pre-built LLVM package. + +```bash +cmake -G Ninja \ + -B /home/user/src/ids/build \ + -S home/user/src/ids \ + -DCMAKE_BUILD_TYPE=Release \ + -DLIT_EXECUTABLE=/home/user/src/llvm-project/llvm/utils/lit/lit.py \ + -DFILECHECK_EXECUTABLE=/home/user/src/llvm-project/build/bin/FileCheck \ + -DLLVM_DIR=/home/user/src/llvm-project/build/lib/cmake/llvm \ + -DClang_DIR=/home/user/src/llvm-project/build/lib/cmake/clang + +cmake --build S:\ids\build --target idt +cmake --build S:\ids\build --target check-ids +``` + +## Running IDS + +There are a number of command-line arguments to IDS that dictate its behavior. + +```bash +USAGE: idt [options] [... ] + +OPTIONS: + +Generic Options: + + --help - Display available options (--help-hidden for more) + --help-list - Display list of available options (--help-list-hidden for more) + --version - Display the version of this program + +interface definition scanner options: + + --apply-fixits - Apply suggested changes to decorate interfaces + --export-macro= - The macro to decorate interfaces with + --extra-arg= - Additional argument to append to the compiler command line + --extra-arg-before= - Additional argument to prepend to the compiler command line + --ignore= - Ignore one or more functions + --include-header=
- Header required for export macro + --inplace - Apply suggested changes in-place + -p - Build path +``` + +At a minimum, the `--export-macro` argument must be provided to specify the +macro used to annotate public symbols. See [Export Macro +Definitions](Docs/ExportMacroDefinitions.md) for details. Additionally, at +least one source file must be specified as a positional argument. + +While it is possible to specify a number of source files, IDS generally works +better when invoked to process one file at a time. + +### Windows Example + +```powershell +S:\Source\ids\build\bin\idt.exe ` + -p S:\Source\MyProject\build ` + --apply-fixits ` + --inplace ` + --export-macro=PUBLIC_ABI ` + --include-header="include/MyAnnotations.h" ` + --extra-arg="-DPUBLIC_ABI=__declspec(dllexport)" ` + --extra-arg="-Wno-macro-redefined" ` + --extra-arg="-fno-delayed-template-parsing" ` + S:\Source\MyProject\include\ProjectHeader1.h ` + S:\Source\MyProject\include\ProjectHeader2.h +``` + +### Linux Example + +```bash +/home/user/src/ids/out/bin/idt \ + -p /home/user/src/MyProject/build \ + --apply-fixits \ + --inplace \ + --export-macro=PUBLIC_ABI \ + --include-header="include/MyAnnotations.h" \ + --extra-arg="-DLLVM_ABI=[[gnu::visibility(\"default\")]]" \ + --extra-arg="-Wno-macro-redefined" \ + S:\Source\MyProject\include\ProjectHeader1.h \ + S:\Source\MyProject\include\ProjectHeader2.h +``` + +The arguments in the above examples have the following effects: +- `-p` refers to the build directory for the project containing a + `compile_commands.json` file used by IDS to configure build options +- `--apply-fixits` and `--inplace` instruct IDS to modify the source file in + place +- `--export-macro` indicates that the `PUBLIC_ABI` macro will be used to + annotate public symbols +- `--include-header` specifies a local header file that will be added as a + `#include` in the processed source files if needed. This would typically + refer to the header file containing the export macro definition. +- The first two `--extra-arg` arguments ensure that `PUBLIC_ABI` is always + defined (differently for Windows and Linux), and suppress the warning emitted + if it already is. These arguments ensure the `PUBLIC_ABI` annotation is not + mistakenly added to a symbol that already has it. +- The third `--extra-arg` argument is Windows-specific and ensures that + templates are always expanded while parsing. It is ensures overloaded private + methods get properly exported when referenced only from inline templates. +- The trailing positional arguments are the names of source files for IDS to + scan. From 2a82967a4baa4c914abf05db23e062a615feb020 Mon Sep 17 00:00:00 2001 From: Andrew Rogers Date: Tue, 6 May 2025 11:21:24 -0700 Subject: [PATCH 2/4] [doc] split out documentation from README.md --- Docs/Building.md | 59 +++++++++++++++++++ Docs/Running.md | 86 +++++++++++++++++++++++++++ README.md | 149 ++--------------------------------------------- 3 files changed, 149 insertions(+), 145 deletions(-) create mode 100644 Docs/Building.md create mode 100644 Docs/Running.md diff --git a/Docs/Building.md b/Docs/Building.md new file mode 100644 index 0000000..7039d2b --- /dev/null +++ b/Docs/Building.md @@ -0,0 +1,59 @@ +# Building IDS + +IDS can be built either as an LLVM external project or as a stand-alone project. + +## LLVM External Project + +IDS can be built as a sub-project of LLVM by setting `LLVM_EXTERNAL_PROJECTS`. +This greatly improves the editing and debugging experience in Visual Studio when +navigating to Clang code from the IDS code. Please see [Getting Started with the +LLVM +Project](https://llvm.org/docs/GettingStarted.html#getting-the-source-code-and-building-llvm) +for more info on building LLVM and Clang. + +The CMake variables `LLVM_EXTERNAL_PROJECTS` and `LLVM_EXTERNAL_IDS_SOURCE_DIR` +variables must be set for IDS to build as part of the LLVM build. + +Testing IDS also requires `LIT_EXECUTABLE` and `FILECHECK_EXECUTABLE` to specify +the locations of `lit.py` and `FileCheck`, which are located in the LLVM source +and LLVM build output directory. + +```bash +cmake -G Ninja \ + -B /home/user/src/llvm-project/build \ + -S /home/user/src/llvm-project/llvm \ + -DCMAKE_BUILD_TYPE=Release \ + -DLLVM_ENABLE_PROJECTS="llvm;clang" \ + -DLLVM_EXTERNAL_PROJECTS="IDS" \ + -DLLVM_EXTERNAL_IDS_SOURCE_DIR="/home/user/src/ids" \ + -DLIT_EXECUTABLE=/home/user/src/llvm-project/llvm/utils/lit/lit.py \ + -DFILECHECK_EXECUTABLE=/home/user/src/llvm-project/build/bin/FileCheck + +cmake --build /home/user/src/llvm-project/build --target idt +cmake --build /home/user/src/llvm-project/build --target check-ids +``` + +## Stand-Alone Build + +To build IDS as a stand-alone project, `LLVM_DIR` and `Clang_DIR` variables must +be provided to specify the locations of local LLVM and Clang libraries. These +can refer to locally built LLVM and Clang libraries, or to pre-built LLVM +package that includes the Clang development libraries. + +Testing IDS also requires `LIT_EXECUTABLE` and `FILECHECK_EXECUTABLE` to specify +the locations of `lit.py` and `FileCheck` , which are not typically included in +a pre-built LLVM package. + +```bash +cmake -G Ninja \ + -B /home/user/src/ids/build \ + -S home/user/src/ids \ + -DCMAKE_BUILD_TYPE=Release \ + -DLIT_EXECUTABLE=/home/user/src/llvm-project/llvm/utils/lit/lit.py \ + -DFILECHECK_EXECUTABLE=/home/user/src/llvm-project/build/bin/FileCheck \ + -DLLVM_DIR=/home/user/src/llvm-project/build/lib/cmake/llvm \ + -DClang_DIR=/home/user/src/llvm-project/build/lib/cmake/clang + +cmake --build S:\ids\build --target idt +cmake --build S:\ids\build --target check-ids +``` diff --git a/Docs/Running.md b/Docs/Running.md new file mode 100644 index 0000000..2812eae --- /dev/null +++ b/Docs/Running.md @@ -0,0 +1,86 @@ +# Running IDS + +There are a number of command-line arguments to IDS that dictate its behavior. + +```bash +USAGE: idt [options] [... ] + +OPTIONS: + +Generic Options: + + --help - Display available options (--help-hidden for more) + --help-list - Display list of available options (--help-list-hidden for more) + --version - Display the version of this program + +interface definition scanner options: + + --apply-fixits - Apply suggested changes to decorate interfaces + --export-macro= - The macro to decorate interfaces with + --extra-arg= - Additional argument to append to the compiler command line + --extra-arg-before= - Additional argument to prepend to the compiler command line + --ignore= - Ignore one or more functions + --include-header=
- Header required for export macro + --inplace - Apply suggested changes in-place + -p - Build path +``` + +At a minimum, the `--export-macro` argument must be provided to specify the +macro used to annotate public symbols. See [Export Macro +Definitions](Docs/ExportMacroDefinitions.md) for details. Additionally, at +least one source file must be specified as a positional argument. + +While it is possible to specify a number of source files, IDS generally works +better when invoked to process one file at a time. + +## Windows Example + +```powershell +S:\Source\ids\build\bin\idt.exe ` + -p S:\Source\MyProject\build ` + --apply-fixits ` + --inplace ` + --export-macro=PUBLIC_ABI ` + --include-header="include/MyAnnotations.h" ` + --extra-arg="-DPUBLIC_ABI=__declspec(dllexport)" ` + --extra-arg="-Wno-macro-redefined" ` + --extra-arg="-fno-delayed-template-parsing" ` + S:\Source\MyProject\include\ProjectHeader1.h ` + S:\Source\MyProject\include\ProjectHeader2.h +``` + +## Linux Example + +```bash +/home/user/src/ids/out/bin/idt \ + -p /home/user/src/MyProject/build \ + --apply-fixits \ + --inplace \ + --export-macro=PUBLIC_ABI \ + --include-header="include/MyAnnotations.h" \ + --extra-arg="-DLLVM_ABI=[[gnu::visibility(\"default\")]]" \ + --extra-arg="-Wno-macro-redefined" \ + S:\Source\MyProject\include\ProjectHeader1.h \ + S:\Source\MyProject\include\ProjectHeader2.h +``` + +The arguments in the above examples have the following effects: +- `-p` refers to the build directory for the project containing a + `compile_commands.json` file used by IDS to configure build options +- `--apply-fixits` and `--inplace` instruct IDS to modify the source file in + place +- `--export-macro` indicates that the `PUBLIC_ABI` macro will be used to + annotate public symbols +- `--include-header` specifies a local header file that will be added as a + `#include` in the processed source files if needed. This would typically + refer to the header file containing the export macro definition. +- The first two `--extra-arg` arguments ensure that `PUBLIC_ABI` is always + defined (differently for Windows and Linux), and suppress the warning emitted + if it already is. These arguments ensure the `PUBLIC_ABI` annotation is not + mistakenly added to a symbol that already has it. +- The third `--extra-arg` argument is Windows-specific and ensures that + templates are always expanded while parsing. It is ensures overloaded private + methods get properly exported when referenced only from inline templates. +- The trailing positional arguments are the names of source files for IDS to + scan. + diff --git a/README.md b/README.md index 7b5d2a4..410d6a9 100644 --- a/README.md +++ b/README.md @@ -7,148 +7,7 @@ primarily designed for adding import/export annotations to a Windows DLL project, but can also be used to add visibility annotations for ELF shared library or Mach-O dylib projects. -## Building IDS - -IDS can be built either as an LLVM external project or as a stand-alone project. - -### LLVM External Project - -IDS can be built as a sub-project of LLVM by setting `LLVM_EXTERNAL_PROJECTS`. -This greatly improves the editing and debugging experience in Visual Studio when -navigating to Clang code from the IDS code. Please see [Getting Started with the -LLVM -Project](https://llvm.org/docs/GettingStarted.html#getting-the-source-code-and-building-llvm) -for more info on building LLVM and Clang. - -The CMake variables `LLVM_EXTERNAL_PROJECTS` and `LLVM_EXTERNAL_IDS_SOURCE_DIR` -variables must be set for IDS to build as part of the LLVM build. - -Testing IDS also requires `LIT_EXECUTABLE` and `FILECHECK_EXECUTABLE` to specify -the locations of `lit.py` and `FileCheck`, which are located in the LLVM source -and LLVM build output directory. - -```bash -cmake -G Ninja \ - -B /home/user/src/llvm-project/build \ - -S /home/user/src/llvm-project/llvm \ - -DCMAKE_BUILD_TYPE=Release \ - -DLLVM_ENABLE_PROJECTS="llvm;clang" \ - -DLLVM_EXTERNAL_PROJECTS="IDS" \ - -DLLVM_EXTERNAL_IDS_SOURCE_DIR="/home/user/src/ids" \ - -DLIT_EXECUTABLE=/home/user/src/llvm-project/llvm/utils/lit/lit.py \ - -DFILECHECK_EXECUTABLE=/home/user/src/llvm-project/build/bin/FileCheck - -cmake --build /home/user/src/llvm-project/build --target idt -cmake --build /home/user/src/llvm-project/build --target check-ids -``` - -### Stand-Alone Build - -To build IDS as a stand-alone project, `LLVM_DIR` and `Clang_DIR` variables must -be provided to specify the locations of local LLVM and Clang libraries. These -can refer to locally built LLVM and Clang libraries, or to pre-built LLVM -package that includes the Clang development libraries. - -Testing IDS also requires `LIT_EXECUTABLE` and `FILECHECK_EXECUTABLE` to specify -the locations of `lit.py` and `FileCheck` , which are not typically included in -a pre-built LLVM package. - -```bash -cmake -G Ninja \ - -B /home/user/src/ids/build \ - -S home/user/src/ids \ - -DCMAKE_BUILD_TYPE=Release \ - -DLIT_EXECUTABLE=/home/user/src/llvm-project/llvm/utils/lit/lit.py \ - -DFILECHECK_EXECUTABLE=/home/user/src/llvm-project/build/bin/FileCheck \ - -DLLVM_DIR=/home/user/src/llvm-project/build/lib/cmake/llvm \ - -DClang_DIR=/home/user/src/llvm-project/build/lib/cmake/clang - -cmake --build S:\ids\build --target idt -cmake --build S:\ids\build --target check-ids -``` - -## Running IDS - -There are a number of command-line arguments to IDS that dictate its behavior. - -```bash -USAGE: idt [options] [... ] - -OPTIONS: - -Generic Options: - - --help - Display available options (--help-hidden for more) - --help-list - Display list of available options (--help-list-hidden for more) - --version - Display the version of this program - -interface definition scanner options: - - --apply-fixits - Apply suggested changes to decorate interfaces - --export-macro= - The macro to decorate interfaces with - --extra-arg= - Additional argument to append to the compiler command line - --extra-arg-before= - Additional argument to prepend to the compiler command line - --ignore= - Ignore one or more functions - --include-header=
- Header required for export macro - --inplace - Apply suggested changes in-place - -p - Build path -``` - -At a minimum, the `--export-macro` argument must be provided to specify the -macro used to annotate public symbols. See [Export Macro -Definitions](Docs/ExportMacroDefinitions.md) for details. Additionally, at -least one source file must be specified as a positional argument. - -While it is possible to specify a number of source files, IDS generally works -better when invoked to process one file at a time. - -### Windows Example - -```powershell -S:\Source\ids\build\bin\idt.exe ` - -p S:\Source\MyProject\build ` - --apply-fixits ` - --inplace ` - --export-macro=PUBLIC_ABI ` - --include-header="include/MyAnnotations.h" ` - --extra-arg="-DPUBLIC_ABI=__declspec(dllexport)" ` - --extra-arg="-Wno-macro-redefined" ` - --extra-arg="-fno-delayed-template-parsing" ` - S:\Source\MyProject\include\ProjectHeader1.h ` - S:\Source\MyProject\include\ProjectHeader2.h -``` - -### Linux Example - -```bash -/home/user/src/ids/out/bin/idt \ - -p /home/user/src/MyProject/build \ - --apply-fixits \ - --inplace \ - --export-macro=PUBLIC_ABI \ - --include-header="include/MyAnnotations.h" \ - --extra-arg="-DLLVM_ABI=[[gnu::visibility(\"default\")]]" \ - --extra-arg="-Wno-macro-redefined" \ - S:\Source\MyProject\include\ProjectHeader1.h \ - S:\Source\MyProject\include\ProjectHeader2.h -``` - -The arguments in the above examples have the following effects: -- `-p` refers to the build directory for the project containing a - `compile_commands.json` file used by IDS to configure build options -- `--apply-fixits` and `--inplace` instruct IDS to modify the source file in - place -- `--export-macro` indicates that the `PUBLIC_ABI` macro will be used to - annotate public symbols -- `--include-header` specifies a local header file that will be added as a - `#include` in the processed source files if needed. This would typically - refer to the header file containing the export macro definition. -- The first two `--extra-arg` arguments ensure that `PUBLIC_ABI` is always - defined (differently for Windows and Linux), and suppress the warning emitted - if it already is. These arguments ensure the `PUBLIC_ABI` annotation is not - mistakenly added to a symbol that already has it. -- The third `--extra-arg` argument is Windows-specific and ensures that - templates are always expanded while parsing. It is ensures overloaded private - methods get properly exported when referenced only from inline templates. -- The trailing positional arguments are the names of source files for IDS to - scan. +## Documentation +- [Building IDS](Docs/Building.md) +- [Running IDS](Docs/Running.md) +- [Export Macro Definitions](Docs/ExportMacroDefinitions.md) From 54d86e690406db06e8dc48fd08a081909fb6c461 Mon Sep 17 00:00:00 2001 From: Andrew Rogers Date: Tue, 6 May 2025 13:25:59 -0700 Subject: [PATCH 3/4] PR feedback: update export macro documentation to match CMake --- Docs/ExportMacroDefinitions.md | 51 +++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 23 deletions(-) diff --git a/Docs/ExportMacroDefinitions.md b/Docs/ExportMacroDefinitions.md index 92556b8..f00196a 100644 --- a/Docs/ExportMacroDefinitions.md +++ b/Docs/ExportMacroDefinitions.md @@ -1,4 +1,4 @@ -## Export Macro Definitions +# Export Macro Definitions A common approach for annotating project’s public interface is by defining a set of preprocessor macros that are used instead of adding annotations directly @@ -7,38 +7,43 @@ to the source. This approach allows supporting visibility annotations DLL import/export annotations (`__declspec(dllimport)`, `__declspec(dllexport)`) when building for Windows. -For example, the `PUBLIC_ABI` macro defined below can be added to symbols in a +For example, the `PROJECT_EXPORT` macro defined below can be added to symbols in a project’s header files files that should be externally visible. ```cpp -#ifdef _WIN32 -#ifdef EXPORTING_ABI -// When building the Windows DLL, the public API must be annotated for exported. -#define PUBLIC_ABI __declspec(dllexport) +#if defined(PROJECT_EXPORT_STATIC) +/* We are building Project as a static library (no exports) */ +# define PROJECT_EXPORT #else -// When building clients of the Windows DLL, the public API must be annotated for import. -#define PUBLIC_ABI __declspec(dllimport) -#endif -#elif defined(__cplusplus) && defined(__has_cpp_attribute) && \ - __has_cpp_attribute(gnu::visibility) && defined(__GNUC__) && !defined(__clang__) -// When supported, use the gnu::visibility C++ attribute to set visibility to default. -#define PUBLIC_API [[gnu::visibility("default")]] -#elif defined(__has_attribute) && __has_attribute(visibility) -// Otherwise, use the __attribute__ to set visibility to default. -#define PUBLIC_ABI __attribute__((visibility("default"))) -#else -#error "Required visibility attribute are not supported by compiler!" +/* We are building Project as a shared library */ +# if defined(_WIN32) +# if defined(Project_EXPORTS) + /* We are building this library */ +# define PROJECT_EXPORT __declspec(dllexport) +# else + /* We are using this library */ +# define PROJECT_EXPORT __declspec(dllimport) +# endif +# else +# define PROJECT_EXPORT __visibility__((visibility("default"))) +# endif #endif ``` -A Windows project using these macros must be built with `EXPORTING_ABI` defined -so that public symbols are annotated for export with `__declspec(dllexport)`. -When building the client, however, `EXPORTING_ABI` must not be defined so the -same set of public symbols will be properly annotated for import with -`__declspec(dllimport)`. +A Windows project using these macros must be built with `Project_EXPORTS` +defined so that public symbols are annotated for export with +`__declspec(dllexport)`. When building clients of the project, however, +`Project_EXPORTS` must not be defined so the same set of public symbols will be +properly annotated for import with `__declspec(dllimport)`. An ELF shared library or Mach-O dylib project will have all symbols publicly visible by default so annotations are not strictly required. However, when a project is built with default hidden symbol visibility using `-fvisibility-default=hidden`, individual symbols must be explicitly exported using a visibility annotations. + +## CMake Support +When building with CMake, the `generate_export_header()` function can be used +to auto-generate a header with appropriate export macro definitions. See [CMake +documentation](https://cmake.org/cmake/help/latest/module/GenerateExportHeader.html) +for details. From cc6e870a718c291a8b43cebc49b6e5f60d7810d8 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Tue, 6 May 2025 14:10:14 -0700 Subject: [PATCH 4/4] Apply suggestions from code review --- Docs/ExportMacroDefinitions.md | 12 ++++++------ Docs/Running.md | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Docs/ExportMacroDefinitions.md b/Docs/ExportMacroDefinitions.md index f00196a..bb13ef3 100644 --- a/Docs/ExportMacroDefinitions.md +++ b/Docs/ExportMacroDefinitions.md @@ -7,25 +7,25 @@ to the source. This approach allows supporting visibility annotations DLL import/export annotations (`__declspec(dllimport)`, `__declspec(dllexport)`) when building for Windows. -For example, the `PROJECT_EXPORT` macro defined below can be added to symbols in a +For example, the `Project_ABI` macro defined below can be added to symbols in a project’s header files files that should be externally visible. ```cpp -#if defined(PROJECT_EXPORT_STATIC) +#if defined(PROJECT_STATIC) /* We are building Project as a static library (no exports) */ -# define PROJECT_EXPORT +# define Project_ABI #else /* We are building Project as a shared library */ # if defined(_WIN32) # if defined(Project_EXPORTS) /* We are building this library */ -# define PROJECT_EXPORT __declspec(dllexport) +# define Project_ABI __declspec(dllexport) # else /* We are using this library */ -# define PROJECT_EXPORT __declspec(dllimport) +# define Project_ABI __declspec(dllimport) # endif # else -# define PROJECT_EXPORT __visibility__((visibility("default"))) +# define Project_ABI __visibility__((__visibility__("default"))) # endif #endif ``` diff --git a/Docs/Running.md b/Docs/Running.md index 2812eae..6cb004f 100644 --- a/Docs/Running.md +++ b/Docs/Running.md @@ -58,7 +58,7 @@ S:\Source\ids\build\bin\idt.exe ` --inplace \ --export-macro=PUBLIC_ABI \ --include-header="include/MyAnnotations.h" \ - --extra-arg="-DLLVM_ABI=[[gnu::visibility(\"default\")]]" \ + --extra-arg='-DLLVM_ABI=[[gnu::visibility("default")]]' \ --extra-arg="-Wno-macro-redefined" \ S:\Source\MyProject\include\ProjectHeader1.h \ S:\Source\MyProject\include\ProjectHeader2.h