# Filtering symbols from WINDOWS\_EXPORT\_ALL\_SYMBOLS?

**URL:** https://discourse.cmake.org/t/filtering-symbols-from-windows-export-all-symbols/2598
**Category:** Usage
**Tags:** os:windows, comp:msvc
**Created:** [January 22, 2021, 12:55am UTC](https://discourse.cmake.org/t/filtering-symbols-from-windows-export-all-symbols/2598 "2021-01-22T00:55:41Z")
**Posts on this page:** 9
**Page:** 1

<div class="post-metadata">

### Author: ![steven-johnson](https://discourse.cmake.org/user_avatar/discourse.cmake.org/steven-johnson/32/448_2.png) [@steven-johnson](https://discourse.cmake.org/u/steven-johnson)
#### Post date: [January 22, 2021, 12:55am UTC](https://discourse.cmake.org/t/filtering-symbols-from-windows-export-all-symbols/2598/1 "2021-01-22T00:55:41Z")

</div>

When I build a shared library / DLL, I’d like to be able to selectively export only symbols that match certain pattern (e.g. the ‘public’ namespace for my library), excluding things that are internal, or brought in from other imported libraries.

GCC/Clang/XCode linkers support using glob-style patterns for exports (which is perfect for my use case), but MSVC’s .def file doesn’t, alas.

However: what WINDOWS\_EXPORT\_ALL\_SYMBOLS is doing under the hood (building up a list of all known global symbols) is close enough (I just have to filter out the symbols that don’t match my pattern).

Before I reinvent the wheel by writing this tool from scratch, I thought I’d ask:

- Is there a (legit) way to edit/modify the .def file that CMake creates internally for this purpose? (i.e., after the .def file is created, but before it is handed to the linker?)
- Failing that, is there a (legit) way for me to just tell CMake to explicitly create that .def file as an ordinary build step, which I can build rules around?

---

<div class="post-metadata">

### Author: ![alex](https://discourse.cmake.org/user_avatar/discourse.cmake.org/alex/32/125_2.png) [@alex](https://discourse.cmake.org/u/alex)
#### Post date: [January 22, 2021, 1:33am UTC](https://discourse.cmake.org/t/filtering-symbols-from-windows-export-all-symbols/2598/2 "2021-01-22T01:33:36Z")

</div>

For additional context: selectively exporting from a library (eg. via GenerateExportHeader) is insufficient when static-only dependencies do not selectively export. Either way, one requires linker-specific hackery to suppress the symbols from the static libraries (e.g. `LINKER:-exclude-libs,ALL` for GNU ld).

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [January 22, 2021, 2:06pm UTC](https://discourse.cmake.org/t/filtering-symbols-from-windows-export-all-symbols/2598/3 "2021-01-22T14:06:24Z")

</div>

> [@steven-johnson](#):
>
> Is there a (legit) way to edit/modify the .def file that CMake creates internally for this purpose? (i.e., after the .def file is created, but before it is handed to the linker?)

I don’t believe so. However, a feature to add include/exclude regexes might make sense, though the name of the property then gets a little wonky.

> [@steven-johnson](#):
>
> Failing that, is there a (legit) way for me to just tell CMake to explicitly create that .def file as an ordinary build step, which I can build rules around?

Hmm. I don’t think so. There’s no place for “after all `.o` files are built, but before linking” unless you use an intermediate `OBJECT` library. Something like:

```cmake
add_library(foo-objects OBJECT ${sources})
add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/foo.def"
  DEPENDS $<TARGET_OBJECTS:foo-objects> # Might need 3.20; use `foo-objects` if this doesn't work.
  create_def_file "${CMAKE_CURRENT_BINARY_DIR}/foo.def" $<TARGET_OBJECTS:foo-objects>)
add_library(foo SHARED # or STATIC?
  "${CMAKE_CURRENT_BINARY_DIR}/foo.def")
target_link_libraries(foo PRIVATE foo-objects) # will add objects to the foo library.

```

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [January 22, 2021, 2:07pm UTC](https://discourse.cmake.org/t/filtering-symbols-from-windows-export-all-symbols/2598/4 "2021-01-22T14:07:44Z")

</div>

Note that for multi-config generators, using `$<CONFIG>` in the output would be handy, but that will definitely need CMake 3.20.

---

<div class="post-metadata">

### Author: ![alex](https://discourse.cmake.org/user_avatar/discourse.cmake.org/alex/32/125_2.png) [@alex](https://discourse.cmake.org/u/alex)
#### Post date: [January 22, 2021, 2:49pm UTC](https://discourse.cmake.org/t/filtering-symbols-from-windows-export-all-symbols/2598/5 "2021-01-22T14:49:45Z")

</div>

> [@ben.boeckel](#):
>
> Hmm. I don’t think so. There’s no place for “after all `.o` files are built, but before linking” unless you use an intermediate `OBJECT` library. Something like:

What is the `PRE_LINK` option in `add_custom_command(TARGET ...)` for, then? [From the docs:](https://cmake.org/cmake/help/latest/command/add_custom_command.html#build-events)

> Run after sources have been compiled but before linking the binary or running the librarian or archiver tool of a static library.

Is the `exports.def` file created _after_ any custom `PRE_LINK` steps?

> [@ben.boeckel](#):
>
> Note that for multi-config generators, using `$<CONFIG>` in the output would be handy, but that will definitely need CMake 3.20.

Pre-CMake 3.20, `CMAKE_CFG_INTDIR` would work, right?

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [January 22, 2021, 3:16pm UTC](https://discourse.cmake.org/t/filtering-symbols-from-windows-export-all-symbols/2598/6 "2021-01-22T15:16:05Z")

</div>

> [@alex](#):
>
> What is the `PRE_LINK` option in `add_custom_command(TARGET ...)` for, then?

That exists, but there’s no mechanism to change the link command from there (and, e.g., add a source file). CMake either needs to see a custom command making it or it already exist for it to be a source file.

> [@alex](#):
>
> Pre-CMake 3.20, `CMAKE_CFG_INTDIR` would work, right?

On Visual Studio at least, yes. I don’t know how Xcode does it.

---

<div class="post-metadata">

### Author: ![alex](https://discourse.cmake.org/user_avatar/discourse.cmake.org/alex/32/125_2.png) [@alex](https://discourse.cmake.org/u/alex)
#### Post date: [January 22, 2021, 3:28pm UTC](https://discourse.cmake.org/t/filtering-symbols-from-windows-export-all-symbols/2598/7 "2021-01-22T15:28:27Z")

</div>

> [@ben.boeckel](#):
>
> That exists, but there’s no mechanism to change the link command from there (and, e.g., add a source file). CMake either needs to see a custom command making it or it already exist for it to be a source file.

Well, could one not edit the CMake-generated `exports.def` in place from a `PRE_LINK` command? Maybe run `cmake -P` with a custom filtering script? The dependencies happen to be correct because `exports.def` has to be recreated if any object file changes, so the `PRE_LINK` trigger will always run because the link step depends on `exports.def`.

The key is whether or not `exports.def` gets created _before_ or _after_ user-supplied/custom `PRE_LINK` commands.

> [@ben.boeckel](#):
>
> On Visual Studio at least, yes. I don’t know how Xcode does it.

XCode supports linker scripts via `LINKER:-exported_symbols_list,${linker_script}`. 🙂

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [January 22, 2021, 4:44pm UTC](https://discourse.cmake.org/t/filtering-symbols-from-windows-export-all-symbols/2598/8 "2021-01-22T16:44:34Z")

</div>

> [@alex](#):
>
> Well, could one not edit the CMake-generated `exports.def` in place from a `PRE_LINK` command? Maybe run `cmake -P` with a custom filtering script? The dependencies happen to be correct because `exports.def` has to be recreated if any object file changes, so the `PRE_LINK` trigger will always run because the link step depends on `exports.def`.

While I don’t think there’s a conceptual problem with that, there are a few problems:

- how to get the path to the `exports.def` CMake is going to use?
- what if it is made after `PRE_LINK` (AFAIK, we don’t guarantee when the file (assuming there is one!) is ready right now).

I think the `OBJECT` library approach I put above is the most reliable one today.

> [@alex](#):
>
> XCode supports linker scripts

I was more talking about `CMAKE_CFG_DIR` than linker scripts 🙂 .

---

<div class="post-metadata">

### Author: ![steven-johnson](https://discourse.cmake.org/user_avatar/discourse.cmake.org/steven-johnson/32/448_2.png) [@steven-johnson](https://discourse.cmake.org/u/steven-johnson)
#### Post date: [January 22, 2021, 5:20pm UTC](https://discourse.cmake.org/t/filtering-symbols-from-windows-export-all-symbols/2598/9 "2021-01-22T17:20:00Z")

</div>

> [@alex](#):
>
> XCode supports linker scripts via `LINKER:-exported_symbols_list,${linker_script}`. 🙂

(nit nit: XCode doesn’t support linker scripts in the same way that GCC does; it’s strictly a list of “export these symbols and hide everything else”, but with glob expressions allowed. That’s all we happen to need, though.)
