# msvc how to handle declspecs

**URL:** https://discourse.cmake.org/t/msvc-how-to-handle-declspecs/9779
**Category:** Usage
**Tags:** os:windows
**Created:** [January 5, 2024, 5:05pm UTC](https://discourse.cmake.org/t/msvc-how-to-handle-declspecs/9779 "2024-01-05T17:05:28Z")
**Posts on this page:** 7
**Page:** 1

<div class="post-metadata">

### Author: ![JuliusCaesar](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/j/85e7bf/32.png) [@JuliusCaesar](https://discourse.cmake.org/u/JuliusCaesar)
#### Post date: [January 5, 2024, 5:05pm UTC](https://discourse.cmake.org/t/msvc-how-to-handle-declspecs/9779/1 "2024-01-05T17:05:28Z")

</div>

Hey guys,  
I’m struggling to get msvc to work for my project.  
I’m getting some undefined symbol linker errors for some const global data.

I’m using Cmake 3.27 with latest MSVC 17 and  
`set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)`  
However according to the docs this does not work for global data.

That’s why I did come up with

```auto
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
project ("declspec")

set(LIB_NAME "otherLib")
set(LIB_SOURCES "otherLib/libTest.h" "otherLib/libTest.c")
add_library(${LIB_NAME} ${LIB_SOURCES})
if (MSVC)
   target_compile_definitions(${LIB_NAME}
    PRIVATE 
      DECL_SPEC_DATA=__declspec\(dllimport\)
      FOO_VAR=0
    PUBLIC
      DECL_SPEC_DATA=__declspec\(dllexport\)
      FOO_VAR=1
   )
endif()

set(EXE_NAME declspec)
add_executable (${EXE_NAME} "declspec.cpp" "declspec.h")
target_link_libraries(${EXE_NAME} PRIVATE ${LIB_NAME})

```

[//mylib.h](https://mylib.h)

```auto
  typedef struct _some_struct {
    int dummyInt;
    float dummyFloat;
  } some_struct_t;

  DECL_SPEC_DATA extern const some_struct_t g_someStruct;

```

//my lib.c

```auto
const some_struct_t g_someStruct = {
  .dummyInt = 10,
  .dummyFloat = 10.0f
};

```

The Idea: For all sources compiled within the lib DECL\_SPEC\_DATA is set to import. For all sources from the exe DECL\_SPEC\_DATA is set to export.  
However i still run into linker errors.  
I did some digging:

after adding

```auto
#if (FOO_VAR != 0)
#error "FOO_VAR is not private"
#endif // (FOO_VAR != 0)

```

to libTest.c I’m getting a compiler error.

Looks like PUBLIC and PRIVATE definitions are getting messed up.

Can I not mix public and private in this way?  
How would you handle the decl specs.Iis there any nicer way?

Thx for your help guys 🙂

---

<div class="post-metadata">

### Author: ![jtxa](https://discourse.cmake.org/user_avatar/discourse.cmake.org/jtxa/32/1535_2.png) [@jtxa](https://discourse.cmake.org/u/jtxa)
#### Post date: [January 5, 2024, 9:08pm UTC](https://discourse.cmake.org/t/msvc-how-to-handle-declspecs/9779/2 "2024-01-05T21:08:56Z")

</div>

Haven’t read the details in your question. But there is a basic misunderstanding.  
`PUBLIC` is the same as specifying `PRIVATE` and `INTERFACE`.  
So you wanted to use `INTERFACE` instead of `PUBLIC`.

---

<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: [January 5, 2024, 9:19pm UTC](https://discourse.cmake.org/t/msvc-how-to-handle-declspecs/9779/3 "2024-01-05T21:19:03Z")

</div>

The `PRIVATE`, `PUBLIC` and `INTERFACE` keywords in `target_link_libraries()` don’t change the visibility of any symbols, at least not directly.

The `CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS` approach is at best a stop-gap measure, it shouldn’t be seen as a long term solution. I suggest you take a look at the [GenerateExportHeader](https://cmake.org/cmake/help/latest/module/GenerateExportHeader.html) module as a much better way of handling which symbols you want to export and make visible. I won’t repeat all the details here, I’ll instead suggest you watch the first 13 minutes or so of my CppCon 2019 talk, which goes through this: [https://youtu.be/m0DwB4OvDXk](https://youtu.be/m0DwB4OvDXk)

---

<div class="post-metadata">

### Author: ![JuliusCaesar](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/j/85e7bf/32.png) [@JuliusCaesar](https://discourse.cmake.org/u/JuliusCaesar)
#### Post date: [January 11, 2024, 9:40pm UTC](https://discourse.cmake.org/t/msvc-how-to-handle-declspecs/9779/4 "2024-01-11T21:40:24Z")

</div>

Hey @jtxa , thx that did work in my particular case 🙂

@craig.scott  
Thx for this interesting input. This is a 3rd party, therefore I’d like to export everything ;).  
So if i got this correctly generate\_export\_header() creates a new header which all the available functions. I can make cmake annotate all functions by using CMAKE\_CXX\_VISIBILITY\_PRESET or CMAKE\_VISIBILITY\_INLINES\_HIDDEN

Is this correct?

---

<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: [January 12, 2024, 9:55am UTC](https://discourse.cmake.org/t/msvc-how-to-handle-declspecs/9779/5 "2024-01-12T09:55:40Z")

</div>

The `CMAKE_CXX_VISIBILITY_PRESET` and `CMAKE_VISIBILITY_INLINES_HIDDEN` variables are for setting the overall default visibility behavior, and normally you only set them when you want to hide things by default (already the default behavior with Visual Studio toolchains, but not the default with pretty much everything else). `generate_export_header()` is then used to provide a header that gives you macros you can use to annotate each thing you want to export. It isn’t for exporting all things in a blanket way.

---

<div class="post-metadata">

### Author: ![JuliusCaesar](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/j/85e7bf/32.png) [@JuliusCaesar](https://discourse.cmake.org/u/JuliusCaesar)
#### Post date: [January 12, 2024, 2:07pm UTC](https://discourse.cmake.org/t/msvc-how-to-handle-declspecs/9779/6 "2024-01-12T14:07:30Z")

</div>

ah thx for the clarification. I’ll have a look at that 🙂

---

<div class="post-metadata">

### Author: ![Albrecht-S](https://discourse.cmake.org/user_avatar/discourse.cmake.org/albrecht-s/32/1407_2.png) [@Albrecht-S](https://discourse.cmake.org/u/Albrecht-S)
#### Post date: [January 12, 2024, 6:21pm UTC](https://discourse.cmake.org/t/msvc-how-to-handle-declspecs/9779/7 "2024-01-12T18:21:34Z")

</div>

I believe the original CMake code does the opposite of what it should do. To clarify: if you compile the library you must **export** the data/functions, and if you compile the executable program you must **import** them. Together with the wrong `PUBLIC` (vs. `INTERFACE`) setting, the partially corrected code should IMHO read:

```auto
if (MSVC)
   target_compile_definitions(${LIB_NAME}
    PRIVATE 
      DECL_SPEC_DATA=__declspec\(dllexport\) # build setting for the library: export
      FOO_VAR=0
    INTERFACE
      DECL_SPEC_DATA=__declspec\(dllimport\) # for the consumer: import
      FOO_VAR=1
   )
endif()

```

That said, what Craig Scott said would be a better long term solution but I wanted to “fix” the IMHO wrong code anyway. Unless **I** am now mixing this up.
