Browse Source

[cmake] allow fully static MinGW builds + (theoretical) clangarm64

Requires qt6-static, obviously... at least for eden. eden-cli also can
be built fully static
Notable challenges n such:
1. VkMemAlloc conflicts with Qt, since it embeds vk_mem_alloc.h in
   qrhivulkan; we can get around this by conditionally defining
   VMA_IMPLEMENTATION; that is, define it in the SDL2 frontend and undef
   it in the Qt frontend. It's not ideal, but I mean... it works, no?
2. find_library, pkgconfig, and some Config modules will always look for
   a .dll, so we have to tell CMake to look for .a
3. In spite of this, some will end up using .dll.a (implib) as their
   link targets; this is, well, bad, so we create a find_library hook
   that rejects dll.a
4. Some libraries have specific configs (boost lol)
5. Some libraries use _static targets (zstd, mbedtls)
6. Some extra libraries need to be linked, i.e. jbig, lzma, etc
7. QuaZip is sad

Needs testing on all platforms, and for both frontends on desktop, to
ensure Vulkan still works as expected.

Signed-off-by: crueter <crueter@eden-emu.dev>
pull/2994/head
crueter 3 months ago
parent
commit
dda1431d8b
No known key found for this signature in database GPG Key ID: 425ACD2D4830EBC6
  1. 84
      CMakeLists.txt
  2. 26
      CMakeModules/Findzstd.cmake
  3. 8
      src/CMakeLists.txt
  4. 2
      src/common/CMakeLists.txt
  5. 2
      src/core/CMakeLists.txt
  6. 2
      src/dedicated_room/CMakeLists.txt
  7. 4
      src/video_core/CMakeLists.txt
  8. 6
      src/video_core/vulkan_common/vma.cpp
  9. 5
      src/yuzu/main_window.cpp
  10. 7
      src/yuzu_cmd/CMakeLists.txt
  11. 6
      src/yuzu_cmd/yuzu.cpp

84
CMakeLists.txt

@ -21,6 +21,11 @@ elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
set(PLATFORM_LINUX ON) set(PLATFORM_LINUX ON)
endif() endif()
# dumb heuristic to detect msys2
if (CMAKE_COMMAND MATCHES "msys64")
set(PLATFORM_MSYS ON)
endif()
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
set(CXX_CLANG ON) set(CXX_CLANG ON)
if (MSVC) if (MSVC)
@ -85,6 +90,84 @@ if (PLATFORM_NETBSD)
set(ENV{PKG_CONFIG_PATH} "${PKG_CONFIG_PATH}:${CMAKE_SYSROOT}/usr/pkg/lib/ffmpeg7/pkgconfig") set(ENV{PKG_CONFIG_PATH} "${PKG_CONFIG_PATH}:${CMAKE_SYSROOT}/usr/pkg/lib/ffmpeg7/pkgconfig")
endif() endif()
# MSYS2 utilities
if (PLATFORM_MSYS)
# really, really dumb heuristic to detect what environment we are in
macro(system var)
if (CMAKE_COMMAND MATCHES ${var})
set(MSYSTEM ${var})
endif()
endmacro()
system(mingw64)
system(clang64)
system(clangarm64)
system(ucrt64)
if (NOT DEFINED MSYSTEM)
set(MSYSTEM msys2)
endif()
# we (generally) want to prioritize environment-specific binaries if possible
# some, like autoconf, are not present on environments besides msys2 though
set(CMAKE_PROGRAM_PATH C:/msys64/${MSYSTEM}/usr/bin C:/msys64/usr/bin)
endif()
# static stuff
option(YUZU_STATIC_BUILD "Use static libraries and executables if available" OFF)
if (YUZU_STATIC_BUILD)
# lol
set(Boost_USE_STATIC_LIBS ON)
set(BUILD_SHARED_LIBS OFF)
## find .a libs first (static, usually)
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
## some libraries define a Library::Name_static alternative ##
set(YUZU_STATIC_SUFFIX _static)
## some libraries use CMAKE_IMPORT_LIBRARY_SUFFIX e.g. Harfbuzz ##
set(CMAKE_IMPORT_LIBRARY_SUFFIX ".a")
# simple hook to reject ".dll.a" libraries
function(find_library var)
# also skip previously-found libraries cuz... yaknow
if (${var})
return()
endif()
_find_library(${var} ${ARGN})
if (${var})
get_filename_component(lib_name "${${var}}" NAME)
if (lib_name MATCHES "dll\\.a$")
unset(${var} CACHE)
set(${var} "${var}-NOTFOUND" CACHE INTERNAL "" FORCE)
endif()
endif()
endfunction()
## other hooks needed ##
macro(extra_libs)
foreach(lib ${ARGN})
find_library(${lib}_LIBRARY ${lib} REQUIRED)
link_libraries(${${lib}_LIBRARY})
endforeach()
endmacro()
# libtiff.a
extra_libs(jbig lzma deflate)
# libfreetype.a
extra_libs(bz2 Lerc)
# libharfbuzz.a
extra_libs(graphite2 rpcrt4)
# msys2 quazip does not build a static lib
set(QuaZip-Qt6_FORCE_BUNDLED ON)
endif()
# Detect current compilation architecture and create standard definitions # Detect current compilation architecture and create standard definitions
# ======================================================================= # =======================================================================
@ -582,6 +665,7 @@ else()
find_package(stb MODULE) find_package(stb MODULE)
find_package(Opus 1.3 MODULE REQUIRED) find_package(Opus 1.3 MODULE REQUIRED)
find_package(ZLIB 1.2 REQUIRED) find_package(ZLIB 1.2 REQUIRED)
find_package(zstd 1.5 REQUIRED MODULE) find_package(zstd 1.5 REQUIRED MODULE)

26
CMakeModules/Findzstd.cmake

@ -6,22 +6,28 @@
include(FindPackageHandleStandardArgs) include(FindPackageHandleStandardArgs)
find_package(PkgConfig QUIET)
pkg_search_module(ZSTD QUIET IMPORTED_TARGET libzstd)
find_package_handle_standard_args(zstd
REQUIRED_VARS ZSTD_LINK_LIBRARIES
VERSION_VAR ZSTD_VERSION
)
find_package(zstd QUIET CONFIG)
if (zstd_CONSIDERED_CONFIGS)
find_package_handle_standard_args(zstd CONFIG_MODE)
else()
find_package(PkgConfig QUIET)
pkg_search_module(ZSTD QUIET IMPORTED_TARGET libzstd)
find_package_handle_standard_args(zstd
REQUIRED_VARS ZSTD_LINK_LIBRARIES
VERSION_VAR ZSTD_VERSION
)
endif()
if (zstd_FOUND AND NOT TARGET zstd::zstd) if (zstd_FOUND AND NOT TARGET zstd::zstd)
if (TARGET zstd::libzstd_shared)
if (TARGET zstd::libzstd_shared AND NOT YUZU_STATIC_BUILD)
add_library(zstd::zstd ALIAS zstd::libzstd_shared) add_library(zstd::zstd ALIAS zstd::libzstd_shared)
add_library(zstd::libzstd ALIAS zstd::libzstd_shared)
elseif (TARGET zstd::libzstd_static) elseif (TARGET zstd::libzstd_static)
add_library(zstd::zstd ALIAS zstd::libzstd_static) add_library(zstd::zstd ALIAS zstd::libzstd_static)
add_library(zstd::libzstd ALIAS zstd::libzstd_static)
else() else()
add_library(zstd::zstd ALIAS PkgConfig::ZSTD) add_library(zstd::zstd ALIAS PkgConfig::ZSTD)
add_library(zstd::libzstd ALIAS PkgConfig::ZSTD)
endif() endif()
endif() endif()
if (NOT TARGET zstd::libzstd)
add_library(zstd::libzstd ALIAS zstd::zstd)
endif()

8
src/CMakeLists.txt

@ -178,13 +178,15 @@ else()
if (MINGW) if (MINGW)
add_compile_definitions(MINGW_HAS_SECURE_API) add_compile_definitions(MINGW_HAS_SECURE_API)
# Only windows has this requirement, thanks windows # Only windows has this requirement, thanks windows
if (WIN32)
if (WIN32 AND ARCHITECTURE_x86_64)
add_compile_options("-msse4.1") add_compile_options("-msse4.1")
endif() endif()
if (MINGW_STATIC_BUILD)
if (YUZU_STATIC_BUILD)
add_compile_definitions(QT_STATICPLUGIN) add_compile_definitions(QT_STATICPLUGIN)
add_compile_options("-static")
add_compile_options(-static)
endif() endif()
endif() endif()

2
src/common/CMakeLists.txt

@ -252,7 +252,7 @@ if(CXX_CLANG)
endif() endif()
if (BOOST_NO_HEADERS) if (BOOST_NO_HEADERS)
target_link_libraries(common PUBLIC Boost::algorithm Boost::icl Boost::pool Boost::filesystem)
target_link_libraries(common PUBLIC Boost::algorithm Boost::icl Boost::pool)
else() else()
target_link_libraries(common PUBLIC Boost::headers) target_link_libraries(common PUBLIC Boost::headers)
endif() endif()

2
src/core/CMakeLists.txt

@ -1199,7 +1199,7 @@ else()
target_link_libraries(core PUBLIC Boost::headers) target_link_libraries(core PUBLIC Boost::headers)
endif() endif()
target_link_libraries(core PRIVATE fmt::fmt nlohmann_json::nlohmann_json RenderDoc::API MbedTLS::mbedcrypto MbedTLS::mbedtls)
target_link_libraries(core PRIVATE fmt::fmt nlohmann_json::nlohmann_json RenderDoc::API MbedTLS::mbedcrypto${YUZU_STATIC_SUFFIX} MbedTLS::mbedtls${YUZU_STATIC_SUFFIX})
if (MINGW) if (MINGW)
target_link_libraries(core PRIVATE ws2_32 mswsock wlanapi) target_link_libraries(core PRIVATE ws2_32 mswsock wlanapi)
endif() endif()

2
src/dedicated_room/CMakeLists.txt

@ -19,7 +19,7 @@ if (ENABLE_WEB_SERVICE)
target_link_libraries(yuzu-room PRIVATE web_service) target_link_libraries(yuzu-room PRIVATE web_service)
endif() endif()
target_link_libraries(yuzu-room PRIVATE MbedTLS::mbedcrypto MbedTLS::mbedtls)
target_link_libraries(yuzu-room PRIVATE MbedTLS::mbedcrypto${YUZU_STATIC_SUFFIX} MbedTLS::mbedtls${YUZU_STATIC_SUFFIX})
if (MSVC) if (MSVC)
target_link_libraries(yuzu-room PRIVATE getopt) target_link_libraries(yuzu-room PRIVATE getopt)
endif() endif()

4
src/video_core/CMakeLists.txt

@ -312,7 +312,6 @@ add_library(video_core STATIC
vulkan_common/vulkan_wrapper.h vulkan_common/vulkan_wrapper.h
vulkan_common/nsight_aftermath_tracker.cpp vulkan_common/nsight_aftermath_tracker.cpp
vulkan_common/nsight_aftermath_tracker.h vulkan_common/nsight_aftermath_tracker.h
vulkan_common/vma.cpp
vulkan_common/vma.h vulkan_common/vma.h
vulkan_common/vulkan.h vulkan_common/vulkan.h
) )
@ -369,9 +368,6 @@ else()
# xbyak # xbyak
set_source_files_properties(macro/macro_jit_x64.cpp PROPERTIES COMPILE_OPTIONS "-Wno-conversion;-Wno-shadow") set_source_files_properties(macro/macro_jit_x64.cpp PROPERTIES COMPILE_OPTIONS "-Wno-conversion;-Wno-shadow")
# VMA
set_source_files_properties(vulkan_common/vma.cpp PROPERTIES COMPILE_OPTIONS "-Wno-conversion;-Wno-unused-variable;-Wno-unused-parameter;-Wno-missing-field-initializers")
# Get around GCC failing with intrinsics in Debug # Get around GCC failing with intrinsics in Debug
if (CXX_GCC AND CMAKE_BUILD_TYPE MATCHES "Debug") if (CXX_GCC AND CMAKE_BUILD_TYPE MATCHES "Debug")
set_source_files_properties(host1x/vic.cpp PROPERTIES COMPILE_OPTIONS "-O2") set_source_files_properties(host1x/vic.cpp PROPERTIES COMPILE_OPTIONS "-O2")

6
src/video_core/vulkan_common/vma.cpp

@ -1,6 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#define VMA_IMPLEMENTATION
#include "video_core/vulkan_common/vma.h"

5
src/yuzu/main_window.cpp

@ -1,6 +1,10 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
#ifdef QT_STATICPLUGIN
#undef VMA_IMPLEMENTATION
#endif
#include "common/fs/ryujinx_compat.h" #include "common/fs/ryujinx_compat.h"
#include "main_window.h" #include "main_window.h"
#include "network/network.h" #include "network/network.h"
@ -263,6 +267,7 @@ using namespace Common::Literals;
#endif #endif
#ifdef QT_STATICPLUGIN #ifdef QT_STATICPLUGIN
#include <QtPlugin>
Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin); Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin);
#endif #endif

7
src/yuzu_cmd/CMakeLists.txt

@ -56,3 +56,10 @@ if(WIN32)
endif() endif()
create_target_directory_groups(yuzu-cmd) create_target_directory_groups(yuzu-cmd)
if (YUZU_STATIC_BUILD)
# yuzu-cmd requires us to explicitly link libpthread, libgcc, and libstdc++ as static
# At a guess, it's probably because Qt handles the Qt executable for us
target_link_options(yuzu-cmd PRIVATE -static -lpthread)
target_link_options(yuzu-cmd PRIVATE -static-libgcc -static-libstdc++)
endif()

6
src/yuzu_cmd/yuzu.cpp

@ -4,12 +4,13 @@
// SPDX-FileCopyrightText: 2014 Citra Emulator Project // SPDX-FileCopyrightText: 2014 Citra Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include <chrono>
#define VMA_IMPLEMENTATION
#include "video_core/vulkan_common/vma.h"
#include <iostream> #include <iostream>
#include <memory> #include <memory>
#include <regex> #include <regex>
#include <string> #include <string>
#include <thread>
#include <fmt/ostream.h> #include <fmt/ostream.h>
@ -17,7 +18,6 @@
#include "common/logging/backend.h" #include "common/logging/backend.h"
#include "common/logging/log.h" #include "common/logging/log.h"
#include "common/scm_rev.h" #include "common/scm_rev.h"
#include "common/scope_exit.h"
#include "common/settings.h" #include "common/settings.h"
#include "common/string_util.h" #include "common/string_util.h"
#include "core/core.h" #include "core/core.h"

Loading…
Cancel
Save