diff --git a/CMakeLists.txt b/CMakeLists.txt index 5479865cf..6488c8bfb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -347,6 +347,15 @@ cmake_dependent_option(MAGNUM_BUILD_GL_TESTS "Build unit tests for OpenGL code" cmake_dependent_option(MAGNUM_BUILD_AL_TESTS "Build unit tests for OpenAL code" ON "MAGNUM_BUILD_TESTS;MAGNUM_WITH_AUDIO" OFF) cmake_dependent_option(MAGNUM_BUILD_VK_TESTS "Build unit tests for Vulkan code" OFF "MAGNUM_BUILD_TESTS;MAGNUM_TARGET_VK" OFF) +if(CORRADE_TARGET_WINDOWS AND NOT CORRADE_TARGET_WINDOWS_RT) + # TODO is there some cmake_dependent_option() but for strings? I.e., to + # hide this if a static build isn't enabled? I don't want to repeat the + # complicated logic from inside cmake_dependent_option() just for a + # single option. + set(MAGNUM_BUILD_STATIC_UNIQUE_GLOBALS_DLL_NAME "" + CACHE STRING "Name of a DLL in which to search for unique globals symbols if MAGNUM_BUILD_STATIC_UNIQUE_GLOBALS is enabled") +endif() + # OpenGLTester / VulkanTester libraries, built by default only if GL / VK tests # are enabled cmake_dependent_option(MAGNUM_WITH_OPENGLTESTER "Build OpenGLTester library" OFF "NOT MAGNUM_BUILD_GL_TESTS" ON) diff --git a/doc/building.dox b/doc/building.dox index b749c0d8e..0230cd269 100644 --- a/doc/building.dox +++ b/doc/building.dox @@ -675,6 +675,12 @@ Options controlling the build: Enabled by default for static builds. May introduce additional overhead on some platforms, disable if you will only link static libraries to one final executable and won't use any dynamic plugins. +- `MAGNUM_BUILD_STATIC_UNIQUE_GLOBALS_DLL_NAME` --- Name of a DLL in which to + search for unique globals symbols. By default, the main executable is + searched, which works in most cases except when Corrade is only linked to a + DLL, such as in Python modules. The name is expected to be just a filename + without any path. Used only on Windows and only if + `MAGNUM_BUILD_STATIC_UNIQUE_GLOBALS` is enabled. - `MAGNUM_BUILD_PLUGINS_STATIC` --- Build plugins as static. By default, plugins are built as dynamic. Independent of the `MAGNUM_BUILD_STATIC` option to allow having static libraries with dynamic plugins and vice diff --git a/doc/changelog.dox b/doc/changelog.dox index 6f9f6456d..1a6d50883 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -881,6 +881,10 @@ See also: - Fixed various variable shadowing warings on MSVC (see [mosra/magnum#611](https://github.com/mosra/magnum/issues/611)) - Fixed compilation on a non-deprecated build (see [mosra/magnum#612](https://github.com/mosra/magnum/pull/612)) - Fixed build of the @ref Vk library with @ref CORRADE_STANDARD_ASSERT +- On Windows there's a new `MAGNUM_BUILD_STATIC_UNIQUE_GLOBALS_DLL_NAME` + @ref building-features "CMake option" to aid + @ref MAGNUM_BUILD_STATIC_UNIQUE_GLOBALS in cases where Corrade is only + linked to a DLL but not the main executable. @subsection changelog-latest-bugfixes Bug fixes diff --git a/src/Magnum/CMakeLists.txt b/src/Magnum/CMakeLists.txt index 2baa45ca1..776a831de 100644 --- a/src/Magnum/CMakeLists.txt +++ b/src/Magnum/CMakeLists.txt @@ -31,6 +31,19 @@ set(CMAKE_FOLDER "Magnum") configure_file(${CMAKE_CURRENT_SOURCE_DIR}/configure.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/configure.h) +# The Implementation/configure.h is used by +# Implementation/WindowsWeakSymbol.cpp which is used only if +# MAGNUM_BUILD_STATIC AND MAGNUM_BUILD_STATIC_UNIQUE_GLOBALS is defined. +if(CORRADE_TARGET_WINDOWS AND NOT CORRADE_TARGET_WINDOWS_RT AND MAGNUM_BUILD_STATIC_UNIQUE_GLOBALS AND MAGNUM_BUILD_STATIC) + if(MAGNUM_BUILD_STATIC_UNIQUE_GLOBALS_DLL_NAME) + set(WINDOWS_WEAK_SYMBOL_DLL_NAME "\"${MAGNUM_BUILD_STATIC_UNIQUE_GLOBALS_DLL_NAME}\"") + else() + set(WINDOWS_WEAK_SYMBOL_DLL_NAME nullptr) + endif() + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Implementation/configure.h.cmake + ${CMAKE_CURRENT_BINARY_DIR}/Implementation/configure.h) +endif() + # Generate version header. If Git is found and this is a Git working copy, # extract values from there, otherwise use just MAGNUM_VERSION_YEAR/MONTH that # are set in project root CMakeLists. diff --git a/src/Magnum/Implementation/WindowsWeakSymbol.cpp b/src/Magnum/Implementation/WindowsWeakSymbol.cpp index 3b1923c09..3fafbbf33 100644 --- a/src/Magnum/Implementation/WindowsWeakSymbol.cpp +++ b/src/Magnum/Implementation/WindowsWeakSymbol.cpp @@ -31,11 +31,13 @@ #define VC_EXTRALEAN #include +#include "Magnum/Implementation/configure.h" + namespace Magnum { namespace Implementation { void* windowsWeakSymbol(const char* name, void* backup) { /* FARPROC?! I want either a function pointer or a variable pointer */ - void* address = reinterpret_cast(GetProcAddress(GetModuleHandleA(nullptr), name)); + void* address = reinterpret_cast(GetProcAddress(GetModuleHandleA(WINDOWS_WEAK_SYMBOL_DLL_NAME), name)); /* This shouldn't fail, except in Python, where it's a sad, sad misery. */ if(!address) { std::fprintf(stderr, "Cannot query global symbol %s and make it unique\n" diff --git a/src/Magnum/Implementation/configure.h.cmake b/src/Magnum/Implementation/configure.h.cmake new file mode 100644 index 000000000..66b59ca71 --- /dev/null +++ b/src/Magnum/Implementation/configure.h.cmake @@ -0,0 +1,29 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020, 2021, 2022, 2023 Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +/* Either a nullptr literal or a string literal with the DLL name. Windows + only. */ +#define WINDOWS_WEAK_SYMBOL_DLL_NAME ${WINDOWS_WEAK_SYMBOL_DLL_NAME} + diff --git a/src/Magnum/Magnum.h b/src/Magnum/Magnum.h index a53d21f7d..71074ee9e 100644 --- a/src/Magnum/Magnum.h +++ b/src/Magnum/Magnum.h @@ -117,8 +117,10 @@ Defined if built as static libraries. Default are shared libraries. @brief Static library build with globals unique across shared libraries @m_since{2020,06} -Enabled by default in a static build. -@see @ref building, @ref cmake +Enabled by default in a static build. On Windows see also the +`MAGNUM_BUILD_STATIC_UNIQUE_GLOBALS_DLL_NAME` +@ref building-features "CMake option". +@see @ref cmake */ #define MAGNUM_BUILD_STATIC_UNIQUE_GLOBALS #undef MAGNUM_BUILD_STATIC_UNIQUE_GLOBALS