Previously, #ifdef _WIN32 was used to check for Windows, and then __declspec(dllexport) and __declspec(dllimport) were used to declare the public API as exported / imported from DLLs. GCC/MinGW also supports those attributes, and everything worked fine.
That specific commit (without any explanation why this was broken before) now changed that to detect just MSVC, and not any Windows system. This is problematic, because
There are other compilers than MSVC and MinGW on Windows, and to my knowledge all support the __declspec Syntax for DLLs.
MinGW now uses __attribute__((visibility("default"))), which as no effect at all.
This means that on MinGW after this change no public APIs are marked as exported in the DLL.
Now due to a quirk of GCC this doesn't mean the DLL doesn't work at all, because if GCC compiles a DLL that contains no symbols that are exported, it will assume that all symbols are exported. But this also means that symbols that were not explicitly marked as exported are now exported on MinGW (while they aren't on MSVC).
To demonstrate the behavior, I've created the following test program:
CMakeLists.txt:
cmake_minimum_required(VERSION 3.15)
project(link_test VERSION 1.0)
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
set(CMAKE_VISIBILITY_INLINES_HIDDEN YES)
option(NO_DECLSPEC_MINGW "Don't use __declspec(dllimport/dllexport) on MinGW" OFF)
add_library(link_test link_test.cpp link_test.h)
target_compile_definitions(link_test
PUBLIC $<$<BOOL:${NO_DECLSPEC_MINGW}>:NO_DECLSPEC_MINGW>
INTERFACE $<$<BOOL:${BUILD_SHARED_LIBS}>:LINK_TEST_IMPORT>
)
set_target_properties(link_test PROPERTIES DEFINE_SYMBOL "LINK_TEST_EXPORT")
The DLL compiled with __attribute__((visibility("default"))) exports the following symbols:
In the future this could be even more problematic: if GCC decides to stop exporting all symbols in DLLs without an explicit dllexport marking at some point in the future (don't know if that's planned at all or why GCC behaves like this currently, but it could happen), then the current logic would mean that tinyxml2's DLL would then export no symbols at all.
In my eyes the previous check #ifdef _WIN32 was correct, and I have compiled tinyxml2 on MinGW as a DLL for a couple of years now, without any issues. I think this change should therefore be reverted.
The commit https://github.com/leethomason/tinyxml2/commit/cc4c1df7ec28101eaacc6388cd8a0a857bffd297 caused a huge change in how DLLs are built on MinGW.
Previously,
#ifdef _WIN32
was used to check for Windows, and then__declspec(dllexport)
and__declspec(dllimport)
were used to declare the public API as exported / imported from DLLs. GCC/MinGW also supports those attributes, and everything worked fine.That specific commit (without any explanation why this was broken before) now changed that to detect just MSVC, and not any Windows system. This is problematic, because
__declspec
Syntax for DLLs.__attribute__((visibility("default")))
, which as no effect at all.This means that on MinGW after this change no public APIs are marked as exported in the DLL.
Now due to a quirk of GCC this doesn't mean the DLL doesn't work at all, because if GCC compiles a DLL that contains no symbols that are exported, it will assume that all symbols are exported. But this also means that symbols that were not explicitly marked as exported are now exported on MinGW (while they aren't on MSVC).
To demonstrate the behavior, I've created the following test program:
CMakeLists.txt
:link_test.h
:link_test.cpp
:The DLL compiled with
__declspec(dllexport)
exports the following symbols (using https://github.com/lucasg/Dependencies):The DLL compiled with
__attribute__((visibility("default")))
exports the following symbols:In the future this could be even more problematic: if GCC decides to stop exporting all symbols in DLLs without an explicit
dllexport
marking at some point in the future (don't know if that's planned at all or why GCC behaves like this currently, but it could happen), then the current logic would mean that tinyxml2's DLL would then export no symbols at all.In my eyes the previous check
#ifdef _WIN32
was correct, and I have compiled tinyxml2 on MinGW as a DLL for a couple of years now, without any issues. I think this change should therefore be reverted.