Symbols from linked static library are not visible in executable module definition file (Windows)
We have a setup where an executable has ENABLE_EXPORTS and WINDOWS_EXPORT_ALL_SYMBOLS set in order to allow a MODULE target to link to the executable it will be dynamically loaded from. However, the executable in question links in symbols from several STATIC library targets, and we expect the symbols imported from those static libraries to be visible in the .def file generated in the build directory. Currently, this is not the case. This works as expected on MacOS, but not on Windows.
We'd like a way for WINDOWS_EXPORT_ALL_SYMBOLS to also export symbols linked in statically, not just from .obj sources. This issue is related: #16473 (closed), but we don't want to manually specify .def files.
The reason for wanting this with static libraries and not the workaround (see below) is that we run into some symbol conflicts if using object files as opposed to linking to a static library.
Here's a minimal example, with a workaround to use OBJECT files:
cmake_minimum_required(VERSION 3.14)
project("Test")
add_executable(MyExecutable WIN32 main.cpp)
set_target_properties(MyExecutable PROPERTIES ENABLE_EXPORTS 1)
set_target_properties(MyExecutable PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS TRUE)
# Results in exports.def not containing ClassContainer symbols
# Can be fixed by linking PUBLIC, but this would make the Plugin (bottom) link to its dependencies and include any static libraries that ClassContainer linked to
add_library(ClassContainer STATIC exported_class.cpp)
target_link_libraries(MyExecutable PRIVATE ClassContainer)
# Works
#add_library(ClassContainer OBJECT exported_class.cpp)
#target_sources(MyExecutable PRIVATE $<TARGET_OBJECTS:ClassContainer>)
#target_link_libraries(MyExecutable PRIVATE $<TARGET_PROPERTY:ClassContainer,LINK_LIBRARIES>)
add_library(Plugin MODULE plugin.cpp)
target_link_libraries(Plugin MyExecutable)
main.cpp:
#include <Windows.h>
#include "exported_class.h"
int APIENTRY wWinMain(HINSTANCE, HINSTANCE, LPWSTR commandLine, int)
{
MyClass myClass;
myClass.Foo();
return 0;
}
plugin.cpp:
#include "exported_class.h"
void Bar()
{
MyClass myClass;
myClass.Foo();
}
exported_class.h:
#pragma once
class MyClass
{
public:
void Foo();
};
exported_class.cpp:
#include "exported_class.h"
void MyClass::Foo()
{
}