From 73d8fb89c6897648ef9e0340793cb2487695488f Mon Sep 17 00:00:00 2001 From: BtbN Date: Sun, 4 Apr 2021 23:29:53 +0200 Subject: [PATCH 4/4] Unlock building static loader on any OS Based in parts on https://github.com/shinchiro/mpv-winbuild-cmake/blob/master/packages/vulkan-0001-cross-compile-static-linking-hacks.patch --- CMakeLists.txt | 2 -- loader/CMakeLists.txt | 23 ++++++++++++++++++++++- loader/loader.h | 3 +++ loader/loader_windows.c | 2 ++ loader/vk_loader_platform.h | 16 ++++++++++++++++ 5 files changed, 43 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 703bcb1ba..43a25d8aa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -95,9 +95,7 @@ if(BUILD_TESTS) enable_testing() endif() -if(APPLE) option(BUILD_STATIC_LOADER "Build a loader that can be statically linked" OFF) -endif() if(WIN32) # Optional: Allow specify the exact version used in the loader dll diff --git a/loader/CMakeLists.txt b/loader/CMakeLists.txt index b5bc0a98a..f74079954 100644 --- a/loader/CMakeLists.txt +++ b/loader/CMakeLists.txt @@ -251,6 +251,22 @@ if(WIN32) target_compile_options(loader-opt PUBLIC ${MSVC_LOADER_COMPILE_OPTIONS}) target_include_directories(loader-opt PRIVATE "$") + if(BUILD_STATIC_LOADER) + add_library(vulkan + STATIC + $ + $ + $ + ${CMAKE_CURRENT_SOURCE_DIR}/vulkan-1.def + ${CMAKE_CURRENT_SOURCE_DIR}/loader.rc) + set_target_properties(vulkan + PROPERTIES LINK_FLAGS_DEBUG + "/ignore:4098" + OUTPUT_NAME + vulkan-1 + PREFIX + lib) + else() add_library(vulkan SHARED $ @@ -269,6 +285,8 @@ if(WIN32) set_target_properties(vulkan PROPERTIES OUTPUT_NAME vulkan-1) + set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS LOADER_DYNAMIC_LIB) + endif() target_link_libraries(vulkan Vulkan::Headers) @@ -291,16 +309,18 @@ else() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-typedef-redefinition") endif() - if(APPLE AND BUILD_STATIC_LOADER) + if(BUILD_STATIC_LOADER) add_library(vulkan STATIC ${NORMAL_LOADER_SRCS} ${OPT_LOADER_SRCS}) else() add_library(vulkan SHARED ${NORMAL_LOADER_SRCS} ${OPT_LOADER_SRCS}) endif() add_dependencies(vulkan loader_asm_gen_files) + if (NOT BUILD_STATIC_LOADER) # set version based on LOADER_GENERATED_HEADER_VERSION used to generate the code set_target_properties(vulkan PROPERTIES SOVERSION "1" VERSION ${LOADER_GENERATED_HEADER_VERSION}) + endif() target_link_libraries(vulkan ${CMAKE_DL_LIBS} m) if (NOT ANDROID) target_link_libraries(vulkan pthread) @@ -377,6 +397,7 @@ if(PKG_CONFIG_FOUND) foreach(LIB ${CMAKE_CXX_IMPLICIT_LINK_LIBRARIES} ${PLATFORM_LIBS}) set(PRIVATE_LIBS "${PRIVATE_LIBS} -l${LIB}") endforeach() + set(PRIVATE_LIBS "${PRIVATE_LIBS} -lshlwapi -lcfgmgr32") if(WIN32) set(VULKAN_LIB_SUFFIX "-1") # Set libdir path as in cmake's FindVulkan.cmake diff --git a/loader/loader.h b/loader/loader.h index cfebfba67..62dcaeb81 100644 --- a/loader/loader.h +++ b/loader/loader.h @@ -66,6 +66,9 @@ static inline void loader_init_dispatch(void *obj, const void *data) { // Global variables used across files extern struct loader_struct loader; +#if defined(_WIN32) && !defined(LOADER_DYNAMIC_LIB) +extern LOADER_PLATFORM_THREAD_ONCE_DEFINITION(once_init); +#endif extern loader_platform_thread_mutex loader_lock; extern loader_platform_thread_mutex loader_json_lock; extern loader_platform_thread_mutex loader_preload_icd_lock; diff --git a/loader/loader_windows.c b/loader/loader_windows.c index e1579bf3a..8a7daef04 100644 --- a/loader/loader_windows.c +++ b/loader/loader_windows.c @@ -98,6 +98,7 @@ void windows_initialization(void) { #endif } +#if defined(LOADER_DYNAMIC_LIB) BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, LPVOID reserved) { switch (reason) { case DLL_PROCESS_ATTACH: @@ -114,6 +115,7 @@ BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, LPVOID reserved) { } return TRUE; } +#endif bool windows_add_json_entry(const struct loader_instance *inst, char **reg_data, // list of JSON files diff --git a/loader/vk_loader_platform.h b/loader/vk_loader_platform.h index d956e803a..fab7b44f5 100644 --- a/loader/vk_loader_platform.h +++ b/loader/vk_loader_platform.h @@ -456,9 +456,25 @@ typedef HANDLE loader_platform_thread; // The once init functionality is not used when building a DLL on Windows. This is because there is no way to clean up the // resources allocated by anything allocated by once init. This isn't a problem for static libraries, but it is for dynamic // ones. When building a DLL, we use DllMain() instead to allow properly cleaning up resources. +#if defined(LOADER_DYNAMIC_LIB) #define LOADER_PLATFORM_THREAD_ONCE_DECLARATION(var) #define LOADER_PLATFORM_THREAD_ONCE_DEFINITION(var) #define LOADER_PLATFORM_THREAD_ONCE(ctl, func) +#else +#define LOADER_PLATFORM_THREAD_ONCE_DECLARATION(var) INIT_ONCE var = INIT_ONCE_STATIC_INIT; +#define LOADER_PLATFORM_THREAD_ONCE_DEFINITION(var) INIT_ONCE var; +#define LOADER_PLATFORM_THREAD_ONCE(ctl, func) loader_platform_thread_once_fn(ctl, func) +static BOOL CALLBACK InitFuncWrapper(PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context) { + void (*func)(void) = (void (*)(void))Parameter; + func(); + return TRUE; +} +static void loader_platform_thread_once_fn(void *ctl, void (*func)(void)) { + assert(func != NULL); + assert(ctl != NULL); + InitOnceExecuteOnce((PINIT_ONCE)ctl, InitFuncWrapper, (void *)func, NULL); +} +#endif // Thread IDs: typedef DWORD loader_platform_thread_id; -- 2.25.1