# What does adding a module definition file via target\_sources do?

**URL:** https://discourse.cmake.org/t/what-does-adding-a-module-definition-file-via-target-sources-do/7610
**Category:** Usage
**Created:** [March 6, 2023, 7:11pm UTC](https://discourse.cmake.org/t/what-does-adding-a-module-definition-file-via-target-sources-do/7610 "2023-03-06T19:11:22Z")
**Posts on this page:** 8
**Page:** 1

<div class="post-metadata">

### Author: ![buildSystemPerson](https://discourse.cmake.org/user_avatar/discourse.cmake.org/buildsystemperson/32/2851_2.png) [@buildSystemPerson](https://discourse.cmake.org/u/buildSystemPerson)
#### Post date: [March 6, 2023, 7:11pm UTC](https://discourse.cmake.org/t/what-does-adding-a-module-definition-file-via-target-sources-do/7610/1 "2023-03-06T19:11:22Z")

</div>

I recently came across code like this:

```cmake
if(MSVC)
    target_link_options(foobar PRIVATE 
        /DEF:${CMAKE_CURRENT_SOURCE_DIR}/foobar.def
    )
elseif(MINGW)
    target_sources(foobar PRIVATE
        ${CMAKE_CURRENT_SOURCE_DIR}/foobar.def # ?
    )
endif()

```

But I don’t see anything in the target\_sources documentation covering this behavior?

---

<div class="post-metadata">

### Author: ![craig.scott](https://discourse.cmake.org/user_avatar/discourse.cmake.org/craig.scott/32/20_2.png) [@craig.scott](https://discourse.cmake.org/u/craig.scott)
#### Post date: [March 6, 2023, 8:26pm UTC](https://discourse.cmake.org/t/what-does-adding-a-module-definition-file-via-target-sources-do/7610/2 "2023-03-06T20:26:41Z")

</div>

I don’t think there’s anything specific about `target_sources()` here. It is just adding `foobar.def` to the list of sources for the `foobar` target. What you might be thinking about is how does a `*.def` file listed in the sources for a target end up being handled. I _think_ CMake recognises `*.def` files and uses them in place of (or maybe in addition to?) its own generated one, but I haven’t checked the code. I didn’t think that was generator-specific, but I could be wrong about that too. I don’t know if the special handling for `MSVC` in your example is necessary.

---

<div class="post-metadata">

### Author: ![buildSystemPerson](https://discourse.cmake.org/user_avatar/discourse.cmake.org/buildsystemperson/32/2851_2.png) [@buildSystemPerson](https://discourse.cmake.org/u/buildSystemPerson)
#### Post date: [March 6, 2023, 9:01pm UTC](https://discourse.cmake.org/t/what-does-adding-a-module-definition-file-via-target-sources-do/7610/3 "2023-03-06T21:01:37Z")

</div>

> What you might be thinking about is how does a `*.def` file listed in the sources for a target end up being handled.

Yes that is what I was trying to ask. I tried reading the CMake code but it was unclear to me.

> I don’t know if the special handling for `MSVC` in your example is necessary.

I’m not sure based on my past experience it seems there are minor differences between Ninja / Visual  
Studio builds on MSVC:

> [@Does adding \`.natvis\` files via target\_sources work on Ninja?](https://discourse.cmake.org/t/does-adding-natvis-files-via-target-sources-work-on-ninja/7316):
>
> According to the docs as of CMake 3.7 [Visual Studio Generators](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html#visual-studio-generators) for VS 2010 and above learned to place .natvis source files into VS project files properly. Which means the following will work correctly with Visual Studio generators. target\_sources(foobar PRIVATE foobar.natvis) Will this also work for Ninja on MSVC? Do I need to guard this with a check for MSVC?

---

<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: [March 7, 2023, 10:03pm UTC](https://discourse.cmake.org/t/what-does-adding-a-module-definition-file-via-target-sources-do/7610/4 "2023-03-07T22:03:24Z")

</div>

A `.def` file is a list of symbols to export from a library in lieu of `_EXPORT` macros in the source itself. This is just handling the compiler-specific way of telling the compiler what symbols to export from the `.dll` file.

---

<div class="post-metadata">

### Author: ![buildSystemPerson](https://discourse.cmake.org/user_avatar/discourse.cmake.org/buildsystemperson/32/2851_2.png) [@buildSystemPerson](https://discourse.cmake.org/u/buildSystemPerson)
#### Post date: [March 7, 2023, 10:38pm UTC](https://discourse.cmake.org/t/what-does-adding-a-module-definition-file-via-target-sources-do/7610/5 "2023-03-07T22:38:53Z")

</div>

So what does this code do? Because MinGW uses GCC as a compiler. But GCC doesn’t support module definition files. Does it convert it into a version-script?

```auto
if(MINGW)
    target_sources(foobar PRIVATE
        ${CMAKE_CURRENT_SOURCE_DIR}/foobar.def # ?
    )
endif()

```

---

<div class="post-metadata">

### Author: ![craig.scott](https://discourse.cmake.org/user_avatar/discourse.cmake.org/craig.scott/32/20_2.png) [@craig.scott](https://discourse.cmake.org/u/craig.scott)
#### Post date: [March 7, 2023, 10:41pm UTC](https://discourse.cmake.org/t/what-does-adding-a-module-definition-file-via-target-sources-do/7610/6 "2023-03-07T22:41:19Z")

</div>

If I had to guess, the `.def` file probably does nothing for MinGW, but all symbols get exported by default for GCC toolchains (please check this, I know this is the case on Unix-based systems, but I don’t know if MinGW does something different). If that’s true, then the code sample you provided probably isn’t doing what you thought, but things appear to work because on MinGW is exporting _everything_, not just the symbols listed in the `.def` file. EDIT: I missed this particular aspect in my previous comment.

---

<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: [March 8, 2023, 1:49am UTC](https://discourse.cmake.org/t/what-does-adding-a-module-definition-file-via-target-sources-do/7610/7 "2023-03-08T01:49:35Z")

</div>

> [@buildSystemPerson](#):
>
> But GCC doesn’t support module definition files

It kind of has to do something for symbol exporting because it’s just a part of the Windows object file format used by the runtime loader. From [this SO answer](https://stackoverflow.com/a/14167460), it looks like there is `dlltool` which does the `.def` file work. This is part of the Windows “binutils” and isn’t necessarily part of the toolchain (just like the Linux linker `ld` is not of any given toolchain; these things are much more “platform”-specified). I do see references in the GCC codebase to `dlltool`, so presumably any `.def` file support is done by passing it onto the linker implementation.

---

<div class="post-metadata">

### Author: ![buildSystemPerson](https://discourse.cmake.org/user_avatar/discourse.cmake.org/buildsystemperson/32/2851_2.png) [@buildSystemPerson](https://discourse.cmake.org/u/buildSystemPerson)
#### Post date: [March 8, 2023, 2:07am UTC](https://discourse.cmake.org/t/what-does-adding-a-module-definition-file-via-target-sources-do/7610/8 "2023-03-08T02:07:18Z")

</div>

> If I had to guess, the `.def` file probably does nothing for MinGW, but all symbols get exported by  
> default for GCC toolchains

I thought the `.def` file did nothing as well until it caused a [regression](https://github.com/KhronosGroup/Vulkan-ValidationLayers/commit/a4ed813ee6828a5390763ab87bafae643721fa54) by removing it from the MINGW build

Also we do set `CMAKE_POSITION_INDEPENDENT_CODE` to `ON` and `CMAKE_CXX_VISIBILITY_PRESET` to `hidden`.

> it looks like there is `dlltool` which does the `.def` file work. This is part of the Windows “binutils” and isn’t necessarily part of the toolchain (just like the Linux linker `ld` is not of any given toolchain; these things are much more “platform”-specified). I do see references in the GCC codebase to `dlltool`, so presumably any `.def` file support is done by passing it onto the linker implementation.

That would explain the behavior I have seen 👍
