diff --git a/.ci/license-header.sh b/.ci/license-header.sh index 784c6bac5a..d49714dae1 100755 --- a/.ci/license-header.sh +++ b/.ci/license-header.sh @@ -4,7 +4,7 @@ # SPDX-License-Identifier: GPL-3.0-or-later # specify full path if dupes may exist -EXCLUDE_FILES="CPM.cmake CPMUtil.cmake GetSCMRev.cmake renderdoc_app.h tools/cpm tools/shellcheck.sh tools/update-cpm.sh tools/windows/vcvarsall.sh externals/stb externals/glad externals/getopt externals/gamemode externals/FidelityFX-FSR externals/demangle externals/bc_decoder" +EXCLUDE_FILES="CPM.cmake CPMUtil.cmake GetSCMRev.cmake renderdoc_app.h tools/cpm tools/shellcheck.sh tools/update-cpm.sh tools/windows/vcvarsall.sh externals/stb externals/glad externals/getopt externals/gamemode externals/FidelityFX-FSR externals/demangle externals/bc_decoder externals/cmake-modules" # license header constants, please change when needed :)))) YEAR=2025 diff --git a/CMakeLists.txt b/CMakeLists.txt index 4a108e47af..1368ce3669 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,73 +5,23 @@ cmake_minimum_required(VERSION 3.22) project(yuzu) -if (${CMAKE_SYSTEM_NAME} STREQUAL "SunOS") - set(PLATFORM_SUN ON) -elseif (${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD") - set(PLATFORM_FREEBSD ON) -elseif (${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD") - set(PLATFORM_OPENBSD ON) -elseif (${CMAKE_SYSTEM_NAME} STREQUAL "NetBSD") - set(PLATFORM_NETBSD ON) -elseif (${CMAKE_SYSTEM_NAME} STREQUAL "DragonFly") - set(PLATFORM_DRAGONFLYBSD ON) -elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Haiku") - set(PLATFORM_HAIKU ON) -elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Linux") - set(PLATFORM_LINUX ON) -endif() - -# dumb heuristic to detect msys2 -if (CMAKE_COMMAND MATCHES "msys64") - set(PLATFORM_MSYS ON) -endif() - -if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") - set(CXX_CLANG ON) - if (MSVC) - set(CXX_CLANG_CL ON) - endif() -elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - set(CXX_GCC ON) -elseif (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") - set(CXX_CL ON) -elseif (CMAKE_CXX_COMPILER_ID STREQUAL "IntelLLVM") - set(CXX_ICC ON) -elseif (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") - set(CXX_APPLE ON) -endif() - list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules") list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/externals/cmake-modules") -# https://gitlab.kitware.com/cmake/cmake/-/merge_requests/11112 -# This works totally fine on MinGW64, but not CLANG{,ARM}64 -if(MINGW AND CXX_CLANG) - set(CMAKE_SYSTEM_VERSION 10.0.0) -endif() +set(CPM_SOURCE_CACHE ${CMAKE_SOURCE_DIR}/.cache/cpm) -# NB: this does not account for SPARC -# If you get Eden working on SPARC, please shoot crueter@crueter.xyz multiple emails -# and you will be hailed for eternity -if (PLATFORM_SUN) - # Terrific Solaris pkg shenanigans - list(APPEND CMAKE_PREFIX_PATH "${CMAKE_SYSROOT}/usr/lib/qt/6.6/lib/amd64/cmake") - list(APPEND CMAKE_MODULE_PATH "${CMAKE_SYSROOT}/usr/lib/qt/6.6/lib/amd64/cmake") - - # Amazing - absolutely incredible - list(APPEND CMAKE_PREFIX_PATH "${CMAKE_SYSROOT}/usr/lib/amd64/cmake") - list(APPEND CMAKE_MODULE_PATH "${CMAKE_SYSROOT}/usr/lib/amd64/cmake") - - # For some mighty reason, doing a normal release build sometimes may not trigger - # the proper -O3 switch to materialize - if (CMAKE_BUILD_TYPE MATCHES "Release") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3") - endif() - if (CMAKE_BUILD_TYPE MATCHES "RelWithDebInfo") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2") - endif() +include(DetectPlatform) +include(DetectArchitecture) +include(DefaultConfig) +include(DownloadExternals) +include(CMakeDependentOption) +include(CTest) +include(CPMUtil) + +DetectArchitecture() + +if (NOT DEFINED ARCHITECTURE) + message(FATAL_ERROR "Architecture didn't make it out of scope, did you delete DetectArchitecture.cmake?") endif() # Needed for FFmpeg w/ VAAPI and DRM @@ -90,34 +40,10 @@ if (PLATFORM_NETBSD) set(ENV{PKG_CONFIG_PATH} "${PKG_CONFIG_PATH}:${CMAKE_SYSROOT}/usr/pkg/lib/ffmpeg7/pkgconfig") endif() -# MSYS2 utilities -if (PLATFORM_MSYS) - include(FixMsysPaths) - # 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}/bin C:/msys64/usr/bin) - set(ENV{PKG_CONFIG_PATH} C:/msys64/${MSYSTEM}/lib/pkgconfig) -endif() - # static stuff option(YUZU_STATIC_BUILD "Use static libraries and executables if available" OFF) +# TODO: StaticBuild.cmake if (YUZU_STATIC_BUILD) include(StaticQtLibs) @@ -177,92 +103,6 @@ if (YUZU_STATIC_BUILD) endif() endif() -# Detect current compilation architecture and create standard definitions -# ======================================================================= - -include(CheckSymbolExists) -function(detect_architecture symbol arch) - if (NOT DEFINED ARCHITECTURE) - set(CMAKE_REQUIRED_QUIET 1) - check_symbol_exists("${symbol}" "" ARCHITECTURE_${arch}) - unset(CMAKE_REQUIRED_QUIET) - - # The output variable needs to be unique across invocations otherwise - # CMake's crazy scope rules will keep it defined - if (ARCHITECTURE_${arch}) - set(ARCHITECTURE "${arch}" PARENT_SCOPE) - set(ARCHITECTURE_${arch} 1 PARENT_SCOPE) - add_definitions("-DARCHITECTURE_${arch}=1") - endif() - endif() -endfunction() - -if (NOT ENABLE_GENERIC) - # https://sourceforge.net/p/predef/wiki/Architectures/ - # TODO: THIS IS FUCKING FLAWED ONLY THE FIRST SYMBOL THAT APPEARS WILL BE CONSIDERED :( - if (MSVC) - detect_architecture("_M_AMD64" x86_64) - detect_architecture("_M_IX86" x86) - detect_architecture("_M_ARM" arm) - detect_architecture("_M_ARM64" arm64) - else() - detect_architecture("__x86_64__" x86_64) - detect_architecture("__i386__" x86) - detect_architecture("__arm__" arm) - detect_architecture("__aarch64__" arm64) - endif() - detect_architecture("__ARM64__" arm64) - detect_architecture("__aarch64__" arm64) - detect_architecture("_M_ARM64" arm64) - - detect_architecture("__arm__" arm) - detect_architecture("__TARGET_ARCH_ARM" arm) - detect_architecture("_M_ARM" arm) - - detect_architecture("__x86_64" x86_64) - detect_architecture("__x86_64__" x86_64) - detect_architecture("__amd64" x86_64) - detect_architecture("_M_X64" x86_64) - - detect_architecture("__i386" x86) - detect_architecture("__i386__" x86) - detect_architecture("_M_IX86" x86) - - detect_architecture("__ia64" ia64) - detect_architecture("__ia64__" ia64) - detect_architecture("_M_IA64" ia64) - - detect_architecture("__mips" mips) - detect_architecture("__mips__" mips) - detect_architecture("_M_MRX000" mips) - - detect_architecture("__powerpc64__" ppc64) - detect_architecture("__ppc64__" ppc64) - detect_architecture("__PPC64__" ppc64) - detect_architecture("_ARCH_PPC64" ppc64) - - detect_architecture("__ppc__" ppc) - detect_architecture("__ppc" ppc) - detect_architecture("__powerpc__" ppc) - detect_architecture("_ARCH_COM" ppc) - detect_architecture("_ARCH_PWR" ppc) - detect_architecture("_ARCH_PPC" ppc) - detect_architecture("_M_MPPC" ppc) - detect_architecture("_M_PPC" ppc) - - detect_architecture("__riscv" riscv) - - detect_architecture("__EMSCRIPTEN__" wasm) -endif() - -if (NOT DEFINED ARCHITECTURE) - set(ARCHITECTURE "GENERIC") - set(ARCHITECTURE_GENERIC 1) - add_definitions(-DARCHITECTURE_GENERIC=1) -endif() - -message(STATUS "Target architecture: ${ARCHITECTURE}") - if (MSVC AND ARCHITECTURE_x86) message(FATAL_ERROR "Attempting to build with the x86 environment is not supported. \ This can typically happen if you used the Developer Command Prompt from the start menu; \ @@ -292,21 +132,11 @@ if (CXX_CLANG_CL) endif() endif() -set(CPM_SOURCE_CACHE ${CMAKE_SOURCE_DIR}/.cache/cpm) - -include(DownloadExternals) -include(CMakeDependentOption) -include(CTest) - # Disable Warnings as Errors for MSVC if (MSVC AND NOT CXX_CLANG) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W3 /WX-") endif() -if (PLATFORM_FREEBSD OR PLATFORM_DRAGONFLYBSD) - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${CMAKE_SYSROOT}/usr/local/lib") -endif() - # Set bundled sdl2/qt as dependent options. # On Linux system SDL2 is likely to be lacking HIDAPI support which have drawbacks but is needed for SDL motion cmake_dependent_option(ENABLE_SDL2 "Enable the SDL2 frontend" ON "NOT ANDROID" OFF) @@ -358,13 +188,7 @@ option(YUZU_TESTS "Compile tests" "${BUILD_TESTING}") option(YUZU_ENABLE_LTO "Enable link-time optimization" OFF) if(YUZU_ENABLE_LTO) - include(CheckIPOSupported) - check_ipo_supported(RESULT COMPILER_SUPPORTS_LTO) - if(NOT COMPILER_SUPPORTS_LTO) - message(FATAL_ERROR "Your compiler does not support interprocedural optimization (IPO). Re-run CMake with -DYUZU_ENABLE_LTO=OFF.") - endif() - set(CMAKE_POLICY_DEFAULT_CMP0069 NEW) - set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ${COMPILER_SUPPORTS_LTO}) + include(UseLTO) endif() option(USE_CCACHE "Use ccache for compilation" OFF) @@ -391,7 +215,6 @@ if(USE_CCACHE) endif() endif() -# TODO(crueter): CI this? option(YUZU_DOWNLOAD_ANDROID_VVL "Download validation layer binary for android" ON) option(YUZU_LEGACY "Apply patches that improve compatibility with older GPUs (e.g. Snapdragon 865) at the cost of performance" OFF) @@ -401,12 +224,12 @@ cmake_dependent_option(YUZU_ROOM_STANDALONE "Enable standalone room executable" cmake_dependent_option(YUZU_CMD "Compile the eden-cli executable" ON "ENABLE_SDL2;NOT ANDROID" OFF) -cmake_dependent_option(YUZU_CRASH_DUMPS "Compile crash dump (Minidump) support" OFF "WIN32 OR LINUX" OFF) +cmake_dependent_option(YUZU_CRASH_DUMPS "Compile crash dump (Minidump) support" OFF "WIN32 OR PLATFORM_LINUX" OFF) option(YUZU_DOWNLOAD_TIME_ZONE_DATA "Always download time zone binaries" ON) set(YUZU_TZDB_PATH "" CACHE STRING "Path to a pre-downloaded timezone database") -cmake_dependent_option(YUZU_USE_FASTER_LD "Check if a faster linker is available" ON "LINUX" OFF) +cmake_dependent_option(YUZU_USE_FASTER_LD "Check if a faster linker is available" ON "PLATFORM_LINUX" OFF) cmake_dependent_option(YUZU_USE_BUNDLED_MOLTENVK "Download bundled MoltenVK lib" ON "APPLE" OFF) @@ -438,41 +261,15 @@ endif() # TODO(crueter): CPM this if (ANDROID AND YUZU_DOWNLOAD_ANDROID_VVL) - set(vvl_version "1.4.328.0") - set(vvl_zip_file "${CMAKE_BINARY_DIR}/externals/vvl-android-${vvl_version}.zip") - if (NOT EXISTS "${vvl_zip_file}") - # Download and extract validation layer release to externals directory - set(vvl_base_url "https://github.com/KhronosGroup/Vulkan-ValidationLayers/releases/download") - file(DOWNLOAD "${vvl_base_url}/vulkan-sdk-${vvl_version}/android-binaries-${vvl_version}.zip" - "${vvl_zip_file}" SHOW_PROGRESS) - execute_process(COMMAND ${CMAKE_COMMAND} -E tar xf "${vvl_zip_file}" - WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/externals") - endif() + AddJsonPackage(vulkan-validation-layers) - # Copy the arm64 binary to src/android/app/main/jniLibs - if (ARCHITECTURE_arm64) - set(vvl_abi arm64-v8a) - elseif(ARCHITECTURE_x86_64) - set(vvl_abi x86_64) - endif() + set(abi ${CMAKE_ANDROID_ARCH_ABI}) - set(vvl_lib_path "${CMAKE_CURRENT_SOURCE_DIR}/src/android/app/src/main/jniLibs/${vvl_abi}/") - file(COPY "${CMAKE_BINARY_DIR}/externals/android-binaries-${vvl_version}/${vvl_abi}/libVkLayer_khronos_validation.so" + set(vvl_lib_path "${CMAKE_CURRENT_SOURCE_DIR}/src/android/app/src/main/jniLibs/${abi}/") + file(COPY "${VVL_SOURCE_DIR}/${abi}/libVkLayer_khronos_validation.so" DESTINATION "${vvl_lib_path}") endif() -if (ANDROID) - set(CMAKE_SKIP_INSTALL_RULES ON) - set(CMAKE_POLICY_VERSION_MINIMUM 3.5) # Workaround for Oboe -endif() - -# Default to a Release build -get_property(IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) -if (NOT IS_MULTI_CONFIG AND NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." FORCE) - message(STATUS "Defaulting to a Release build") -endif() - if(EXISTS ${PROJECT_SOURCE_DIR}/hooks/pre-commit AND NOT EXISTS ${PROJECT_SOURCE_DIR}/.git/hooks/pre-commit) if (EXISTS ${PROJECT_SOURCE_DIR}/.git/) message(STATUS "Copying pre-commit hook") @@ -480,25 +277,23 @@ if(EXISTS ${PROJECT_SOURCE_DIR}/hooks/pre-commit AND NOT EXISTS ${PROJECT_SOURCE endif() endif() -configure_file(${PROJECT_SOURCE_DIR}/dist/compatibility_list/compatibility_list.qrc - ${PROJECT_BINARY_DIR}/dist/compatibility_list/compatibility_list.qrc +set(compat_base dist/compatibility_list/compatibility_list) +set(compat_qrc ${compat_base}.qrc) +set(compat_json ${compat_base}.json) + +configure_file(${PROJECT_SOURCE_DIR}/${compat_qrc} + ${PROJECT_BINARY_DIR}/${compat_qrc} COPYONLY) -if (EXISTS ${PROJECT_SOURCE_DIR}/dist/compatibility_list/compatibility_list.json) - configure_file("${PROJECT_SOURCE_DIR}/dist/compatibility_list/compatibility_list.json" - "${PROJECT_BINARY_DIR}/dist/compatibility_list/compatibility_list.json" +if (EXISTS ${PROJECT_SOURCE_DIR}/${compat_json}) + configure_file("${PROJECT_SOURCE_DIR}/${compat_json}" + "${PROJECT_BINARY_DIR}/${compat_json}" COPYONLY) endif() -if (ENABLE_COMPATIBILITY_LIST_DOWNLOAD AND NOT EXISTS ${PROJECT_BINARY_DIR}/dist/compatibility_list/compatibility_list.json) - message(STATUS "Downloading compatibility list for yuzu...") - file(DOWNLOAD - https://api.yuzu-emu.org/gamedb/ - "${PROJECT_BINARY_DIR}/dist/compatibility_list/compatibility_list.json" SHOW_PROGRESS) -endif() - -if (NOT EXISTS ${PROJECT_BINARY_DIR}/dist/compatibility_list/compatibility_list.json) - file(WRITE ${PROJECT_BINARY_DIR}/dist/compatibility_list/compatibility_list.json "") +# TODO: Compat list download +if (NOT EXISTS ${PROJECT_BINARY_DIR}/${compat_json}) + file(WRITE ${PROJECT_BINARY_DIR}/${compat_json} "") endif() if (YUZU_LEGACY) @@ -580,8 +375,6 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin) # System imported libraries # ======================================================================= -include(CPMUtil) - # openssl funniness if (ENABLE_OPENSSL) if (YUZU_USE_BUNDLED_OPENSSL) @@ -673,6 +466,7 @@ if (YUZU_USE_CPM) add_library(Opus::opus ALIAS opus) endif() else() + # TODO: we can probably just use CPM for this... right? # Enforce the search mode of non-required packages for better and shorter failure messages find_package(fmt 8 REQUIRED) @@ -737,10 +531,9 @@ endfunction() if (APPLE) # Umbrella framework for everything GUI-related - find_library(COCOA_LIBRARY Cocoa) + find_library(COCOA_LIBRARY Cocoa REQUIRED) + find_library(IOKIT_LIBRARY IOKit REQUIRED) set(PLATFORM_LIBRARIES ${COCOA_LIBRARY} ${IOKIT_LIBRARY} ${COREVIDEO_LIBRARY}) - # find_library(ICONV_LIBRARY iconv REQUIRED) - # list(APPEND PLATFORM_LIBRARIES ${ICONV_LIBRARY}) elseif (WIN32) # Target Windows 10 add_compile_definitions(_WIN32_WINNT=0x0A00 WINVER=0x0A00) @@ -881,11 +674,6 @@ if(ENABLE_QT) set_target_properties(Qt6::Platform PROPERTIES INTERFACE_COMPILE_FEATURES "") endif() -if (UNIX AND NOT APPLE AND NOT ANDROID) - find_package(PkgConfig REQUIRED) - pkg_check_modules(LIBVA libva) -endif() - if (NOT (YUZU_USE_BUNDLED_FFMPEG OR YUZU_USE_EXTERNAL_FFMPEG)) # Use system installed FFmpeg find_package(FFmpeg REQUIRED QUIET COMPONENTS ${FFmpeg_COMPONENTS}) @@ -912,54 +700,6 @@ endif() set(THREADS_PREFER_PTHREAD_FLAG ON) find_package(Threads REQUIRED) -# Setup a custom clang-format target (if clang-format can be found) that will run -# against all the src files. This should be used before making a pull request. -# ======================================================================= - -set(CLANG_FORMAT_POSTFIX "-15") -find_program(CLANG_FORMAT - NAMES clang-format${CLANG_FORMAT_POSTFIX} - clang-format - PATHS ${PROJECT_BINARY_DIR}/externals) -# if find_program doesn't find it, try to download from externals -if (NOT CLANG_FORMAT) - if (WIN32 AND NOT CMAKE_CROSSCOMPILING) - message(STATUS "Clang format not found! Downloading...") - set(CLANG_FORMAT "${PROJECT_BINARY_DIR}/externals/clang-format${CLANG_FORMAT_POSTFIX}.exe") - file(DOWNLOAD - https://github.com/eden-emulator/ext-windows-bin/raw/master/clang-format${CLANG_FORMAT_POSTFIX}.exe - "${CLANG_FORMAT}" SHOW_PROGRESS - STATUS DOWNLOAD_SUCCESS) - if (NOT DOWNLOAD_SUCCESS EQUAL 0) - message(WARNING "Could not download clang format! Disabling the clang format target") - file(REMOVE ${CLANG_FORMAT}) - unset(CLANG_FORMAT) - endif() - else() - message(WARNING "Clang format not found! Disabling the clang format target") - endif() -endif() - -if (CLANG_FORMAT) - set(SRCS ${PROJECT_SOURCE_DIR}/src) - set(CCOMMENT "Running clang format against all the .h and .cpp files in src/") - if (WIN32) - add_custom_target(clang-format - COMMAND powershell.exe -Command "Get-ChildItem '${SRCS}/*' -Include *.cpp,*.h -Recurse | Foreach {&'${CLANG_FORMAT}' -i $_.fullname}" - COMMENT ${CCOMMENT}) - elseif(MINGW) - add_custom_target(clang-format - COMMAND find `cygpath -u ${SRCS}` -iname *.h -o -iname *.cpp | xargs `cygpath -u ${CLANG_FORMAT}` -i - COMMENT ${CCOMMENT}) - else() - add_custom_target(clang-format - COMMAND find ${SRCS} -iname *.h -o -iname *.cpp | xargs ${CLANG_FORMAT} -i - COMMENT ${CCOMMENT}) - endif() - unset(SRCS) - unset(CCOMMENT) -endif() - # Include source code # =================== @@ -993,47 +733,8 @@ if (MSVC AND CXX_CLANG) link_libraries(llvm-mingw-runtime) endif() -#[[ - search order: - - gold (GCC only) - the best, generally, but unfortunately not packaged anymore - - mold (GCC only) - generally does well on GCC - - ldd - preferred on clang - - bfd - the final fallback - - If none are found (macOS uses ld.prime, etc) just use the default linker -]] if (YUZU_USE_FASTER_LD) - find_program(LINKER_BFD bfd) - if (LINKER_BFD) - set(LINKER bfd) - endif() - - find_program(LINKER_LLD lld) - if (LINKER_LLD) - set(LINKER lld) - endif() - - if (CXX_GCC) - find_program(LINKER_MOLD mold) - if (LINKER_MOLD AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "12.1") - set(LINKER mold) - endif() - - find_program(LINKER_GOLD gold) - if (LINKER_GOLD) - set(LINKER gold) - endif() - endif() - - if (LINKER) - message(NOTICE "Selecting ${LINKER} as linker") - add_link_options("-fuse-ld=${LINKER}") - else() - message(WARNING "No faster linker found--using default") - endif() - - if (LINKER STREQUAL "lld" AND CXX_GCC) - message(WARNING "Using lld on GCC may cause issues with certain LTO settings. If the program fails to compile, disable YUZU_USE_FASTER_LD, or install mold or GNU gold.") - endif() + include(FasterLinker) endif() # Set runtime library to MD/MDd for all configurations @@ -1055,14 +756,6 @@ if(MSVC) ) endif() -if (MINGW) - # This saves a truly ridiculous amount of time during linking - # In my tests, without this it takes 2 mins, with it takes 3-5 seconds - # or on GitHub Actions, 10 minutes -> 3 seconds - set(MINGW_FLAGS "-Wl,--strip-all -Wl,--gc-sections") - set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} ${MINGW_FLAGS}") -endif() - add_subdirectory(src) # Set yuzu project or yuzu-cmd project as default StartUp Project in Visual Studio depending on whether QT is enabled or not diff --git a/CMakeModules/GetSCMRev.cmake b/CMakeModules/GetSCMRev.cmake deleted file mode 100644 index ee5ce6a91c..0000000000 --- a/CMakeModules/GetSCMRev.cmake +++ /dev/null @@ -1,49 +0,0 @@ -# SPDX-FileCopyrightText: 2025 crueter -# SPDX-License-Identifier: GPL-3.0-or-later - -include(GetGitRevisionDescription) - -function(trim var) - string(REGEX REPLACE "\n" "" new "${${var}}") - set(${var} ${new} PARENT_SCOPE) -endfunction() - -set(TAG_FILE ${CMAKE_SOURCE_DIR}/GIT-TAG) -set(REF_FILE ${CMAKE_SOURCE_DIR}/GIT-REFSPEC) -set(COMMIT_FILE ${CMAKE_SOURCE_DIR}/GIT-COMMIT) -set(RELEASE_FILE ${CMAKE_SOURCE_DIR}/GIT-RELEASE) - -if (EXISTS ${REF_FILE} AND EXISTS ${COMMIT_FILE}) - file(READ ${REF_FILE} GIT_REFSPEC) - file(READ ${COMMIT_FILE} GIT_COMMIT) -else() - get_git_head_revision(GIT_REFSPEC GIT_COMMIT) - git_branch_name(GIT_REFSPEC) - if (GIT_REFSPEC MATCHES "NOTFOUND") - set(GIT_REFSPEC 1.0.0) - set(GIT_COMMIT stable) - endif() -endif() - -if (EXISTS ${TAG_FILE}) - file(READ ${TAG_FILE} GIT_TAG) -else() - git_describe(GIT_TAG --tags --abbrev=0) - if (GIT_TAG MATCHES "NOTFOUND") - set(GIT_TAG "${GIT_REFSPEC}") - endif() -endif() - -if (EXISTS ${RELEASE_FILE}) - file(READ ${RELEASE_FILE} GIT_RELEASE) - trim(GIT_RELEASE) - message(STATUS "Git release: ${GIT_RELEASE}") -endif() - -trim(GIT_REFSPEC) -trim(GIT_COMMIT) -trim(GIT_TAG) - -message(STATUS "Git commit: ${GIT_COMMIT}") -message(STATUS "Git tag: ${GIT_TAG}") -message(STATUS "Git refspec: ${GIT_REFSPEC}") diff --git a/cpmfile.json b/cpmfile.json index c00f955087..d4bf2a5b20 100644 --- a/cpmfile.json +++ b/cpmfile.json @@ -25,9 +25,9 @@ "fmt": { "repo": "fmtlib/fmt", "tag": "%VERSION%", - "hash": "c4ab814c20fbad7e3f0ae169125a4988a2795631194703251481dc36b18da65c886c4faa9acd046b0a295005217b3689eb0126108a9ba5aac2ca909aae263c2f", + "hash": "f0da82c545b01692e9fd30fdfb613dbb8dd9716983dcd0ff19ac2a8d36f74beb5540ef38072fdecc1e34191b3682a8542ecbf3a61ef287dbba0a2679d4e023f2", "version": "8", - "git_version": "12.0.0" + "git_version": "12.1.0" }, "lz4": { "name": "lz4", @@ -91,5 +91,13 @@ "version": "20250828", "artifact": "clang-rt-builtins.tar.zst", "hash": "d902392caf94e84f223766e2cc51ca5fab6cae36ab8dc6ef9ef6a683ab1c483bfcfe291ef0bd38ab16a4ecc4078344fa8af72da2f225ab4c378dee23f6186181" + }, + "vulkan-validation-layers": { + "package": "VVL", + "repo": "KhronosGroup/Vulkan-ValidationLayers", + "tag": "vulkan-sdk-%VERSION%", + "git_version": "1.4.328.1", + "artifact": "android-binaries-%VERSION%.zip", + "hash": "5ec895a453cb7c2f156830b9766953a0c2bd44dea99e6a3dac4160305041ccd3e87534b4ce0bd102392178d2a8eca48411856298f9395e60117cdfe89f72137e" } } diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt index d19feb0b52..28b34d56ac 100644 --- a/externals/CMakeLists.txt +++ b/externals/CMakeLists.txt @@ -392,3 +392,17 @@ if (ANDROID) add_library(oboe::oboe ALIAS oboe) endif() + +# moltenvk +if (NOT YUZU_USE_BUNDLED_MOLTENVK) + find_library(MOLTENVK_LIBRARY MoltenVK) +else() + unset(MOLTENVK_LIBRARY) +endif() + +# TODO: kosmickrisp? +if (NOT MOLTENVK_LIBRARY) + AddJsonPackage(moltenvk) + + set(MOLTENVK_LIBRARY "${moltenvk_SOURCE_DIR}/MoltenVK/dylib/macOS/libMoltenVK.dylib" CACHE STRING "" FORCE) +endif() diff --git a/externals/cmake-modules/DefaultConfig.cmake b/externals/cmake-modules/DefaultConfig.cmake new file mode 100644 index 0000000000..eb5bb3cdef --- /dev/null +++ b/externals/cmake-modules/DefaultConfig.cmake @@ -0,0 +1,17 @@ +# SPDX-FileCopyrightText: Copyright 2025 crueter +# SPDX-License-Identifier: GPL-3.0-or-later + +## DefaultConfig ## + +# Generally, you will always want "some" default configuration for your project. +# This module does nothing but enforce that. :) + +set(CMAKE_BUILD_TYPE_DEFAULT "Release" CACHE STRING "Default build type") + +get_property(IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +if (NOT IS_MULTI_CONFIG AND NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE "${CMAKE_BUILD_TYPE_DEFAULT}" + CACHE STRING "Choose the type of build." FORCE) + message(STATUS "[DefaultConfig] Defaulting to a " + "${CMAKE_BUILD_TYPE_DEFAULT} build") +endif() diff --git a/externals/cmake-modules/DetectArchitecture.cmake b/externals/cmake-modules/DetectArchitecture.cmake new file mode 100644 index 0000000000..82dce31878 --- /dev/null +++ b/externals/cmake-modules/DetectArchitecture.cmake @@ -0,0 +1,225 @@ +# SPDX-FileCopyrightText: Copyright 2025 crueter +# SPDX-License-Identifier: GPL-3.0-or-later + +## DetectArchitecture ## +#[[ +Does exactly as it sounds. Detects common symbols defined for different architectures and +adds compile definitions thereof. Namely: +- arm64 +- arm +- x86_64 +- x86 +- ia64 +- mips64 +- mips +- ppc64 +- ppc +- riscv +- riscv64 +- loongarch64 +- wasm + +Unsupported architectures: +- ARMv2-6 +- m68k +- PIC + +This file WILL NOT detect endian-ness for you. + +This file is based off of Yuzu and Dynarmic. +]] + +# multiarch builds are a special case and also very difficult +# this is what I have for now, but it's not ideal + +# Do note that situations where multiple architectures are defined +# should NOT be too dependent on the architecture +# otherwise, you may end up with duplicate code +if (CMAKE_OSX_ARCHITECTURES) + set(MULTIARCH_BUILD 1) + set(ARCHITECTURE "${CMAKE_OSX_ARCHITECTURES}") + + # hope and pray the architecture names match + foreach(ARCH IN ${CMAKE_OSX_ARCHITECTURES}) + set(ARCHITECTURE_${ARCH} 1 PARENT_SCOPE) + add_definitions(-DARCHITECTURE_${ARCH}=1) + endforeach() + + return() +endif() + +include(CheckSymbolExists) +function(detect_architecture symbol arch) + # The output variable needs to be unset between invocations otherwise + # CMake's crazy scope rules will keep it defined + unset(SYMBOL_EXISTS CACHE) + + if (NOT DEFINED ARCHITECTURE) + set(CMAKE_REQUIRED_QUIET 1) + check_symbol_exists("${symbol}" "" SYMBOL_EXISTS) + unset(CMAKE_REQUIRED_QUIET) + + if (SYMBOL_EXISTS) + set(ARCHITECTURE "${arch}" PARENT_SCOPE) + set(ARCHITECTURE_${arch} 1 PARENT_SCOPE) + add_definitions(-DARCHITECTURE_${arch}=1) + endif() + endif() +endfunction() + +function(detect_architecture_symbols) + if (DEFINED ARCHITECTURE) + return() + endif() + + set(oneValueArgs ARCH) + set(multiValueArgs SYMBOLS) + + cmake_parse_arguments(ARGS "" "${oneValueArgs}" "${multiValueArgs}" + "${ARGN}") + + set(arch "${ARGS_ARCH}") + foreach(symbol ${ARGS_SYMBOLS}) + detect_architecture("${symbol}" "${arch}") + + if (ARCHITECTURE_${arch}) + message(DEBUG "[DetectArchitecture] Found architecture symbol ${symbol} for ${arch}") + set(ARCHITECTURE "${arch}" PARENT_SCOPE) + set(ARCHITECTURE_${arch} 1 PARENT_SCOPE) + add_definitions(-DARCHITECTURE_${arch}=1) + + return() + endif() + endforeach() +endfunction() + +function(DetectArchitecture) + # arches here are put in a sane default order of importance + # notably, amd64, arm64, and riscv (in order) are BY FAR the most common + # mips is pretty popular in embedded + # ppc64 is pretty popular in supercomputing + # sparc is uh + # ia64 exists + # the rest exist, but are probably less popular than ia64 + + detect_architecture_symbols( + ARCH arm64 + SYMBOLS + "__ARM64__" + "__aarch64__" + "_M_ARM64") + + detect_architecture_symbols( + ARCH x86_64 + SYMBOLS + "__x86_64" + "__x86_64__" + "__amd64" + "_M_X64" + "_M_AMD64") + + # riscv is interesting since it generally does not define a riscv64-specific symbol + # We can, however, check for the rv32 zcf extension which is good enough of a heuristic on GCC + detect_architecture_symbols( + ARCH riscv + SYMBOLS + "__riscv_zcf") + + # if zcf doesn't exist we can safely assume it's riscv64 + detect_architecture_symbols( + ARCH riscv64 + SYMBOLS + "__riscv") + + detect_architecture_symbols( + ARCH x86 + SYMBOLS + "__i386" + "__i386__" + "_M_IX86") + + detect_architecture_symbols( + ARCH arm + SYMBOLS + "__arm__" + "__TARGET_ARCH_ARM" + "_M_ARM") + + detect_architecture_symbols( + ARCH ia64 + SYMBOLS + "__ia64" + "__ia64__" + "_M_IA64") + + # mips is probably the least fun to detect due to microMIPS + # Because microMIPS is such cancer I'm considering it out of scope for now + detect_architecture_symbols( + ARCH mips64 + SYMBOLS + "__mips64") + + detect_architecture_symbols( + ARCH mips + SYMBOLS + "__mips" + "__mips__" + "_M_MRX000") + + detect_architecture_symbols( + ARCH ppc64 + SYMBOLS + "__ppc64__" + "__powerpc64__" + "_ARCH_PPC64" + "_M_PPC64") + + detect_architecture_symbols( + ARCH ppc + SYMBOLS + "__ppc__" + "__ppc" + "__powerpc__" + "_ARCH_COM" + "_ARCH_PWR" + "_ARCH_PPC" + "_M_MPPC" + "_M_PPC") + + detect_architecture_symbols( + ARCH sparc64 + SYMBOLS + "__sparc_v9__") + + detect_architecture_symbols( + ARCH sparc + SYMBOLS + "__sparc__" + "__sparc") + + # I don't actually know about loongarch32 since crossdev does not support it, only 64 + detect_architecture_symbols( + ARCH loongarch64 + SYMBOLS + "__loongarch__" + "__loongarch64") + + detect_architecture_symbols( + ARCH wasm + SYMBOLS + "__EMSCRIPTEN__") + + # "generic" target + # If you have reached this point, you're on some as-of-yet unsupported architecture. + # See the docs up above for known unsupported architectures + # If you're not in the list... I think you know what you're doing. + if (NOT DEFINED ARCHITECTURE) + set(ARCHITECTURE "GENERIC") + set(ARCHITECTURE_GENERIC 1) + add_definitions(-DARCHITECTURE_GENERIC=1) + endif() + + message(STATUS "[DetectArchitecture] Target architecture: ${ARCHITECTURE}") + set(ARCHITECTURE "${ARCHITECTURE}" PARENT_SCOPE) + set(ARCHITECTURE_${ARCHITECTURE} 1 PARENT_SCOPE) +endfunction() diff --git a/externals/cmake-modules/DetectPlatform.cmake b/externals/cmake-modules/DetectPlatform.cmake new file mode 100644 index 0000000000..25b324a674 --- /dev/null +++ b/externals/cmake-modules/DetectPlatform.cmake @@ -0,0 +1,151 @@ +# SPDX-FileCopyrightText: Copyright 2025 crueter +# SPDX-License-Identifier: GPL-3.0-or-later + +## DetectPlatform ## + +# This is a small helper that sets PLATFORM_ variables for various +# operating systems and distributions. Note that Apple, Windows, Android, etc. +# are not covered, as CMake already does that for us. + +# It also sets CXX_ for the C++ compiler. + +# Furthermore, some platforms have really silly requirements/quirks, so this +# also does a few of those. + +# This module contains contributions from the Eden Emulator Project, +# notably from crueter and Lizzie. + +if (${CMAKE_SYSTEM_NAME} STREQUAL "SunOS") + set(PLATFORM_SUN ON) +elseif (${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD") + set(PLATFORM_FREEBSD ON) +elseif (${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD") + set(PLATFORM_OPENBSD ON) +elseif (${CMAKE_SYSTEM_NAME} STREQUAL "NetBSD") + set(PLATFORM_NETBSD ON) +elseif (${CMAKE_SYSTEM_NAME} STREQUAL "DragonFly") + set(PLATFORM_DRAGONFLYBSD ON) +elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Haiku") + set(PLATFORM_HAIKU ON) +elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Linux") + set(PLATFORM_LINUX ON) +endif() + +# dumb heuristic to detect msys2 +if (CMAKE_COMMAND MATCHES "msys64") + set(PLATFORM_MSYS ON) +endif() + +if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + set(CXX_CLANG ON) + if (MSVC) + set(CXX_CLANG_CL ON) + endif() +elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + set(CXX_GCC ON) +elseif (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") + set(CXX_CL ON) +elseif (CMAKE_CXX_COMPILER_ID STREQUAL "IntelLLVM") + set(CXX_ICC ON) +elseif (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") + set(CXX_APPLE ON) +endif() + +# https://gitlab.kitware.com/cmake/cmake/-/merge_requests/11112 +# This works totally fine on MinGW64, but not CLANG{,ARM}64 +if(MINGW AND CXX_CLANG) + set(CMAKE_SYSTEM_VERSION 10.0.0) +endif() + +# NB: this does not account for SPARC +if (PLATFORM_SUN) + # Terrific OpenIndiana pkg shenanigans + list(APPEND CMAKE_PREFIX_PATH + "${CMAKE_SYSROOT}/usr/lib/qt/6.6/lib/amd64/cmake") + list(APPEND CMAKE_MODULE_PATH + "${CMAKE_SYSROOT}/usr/lib/qt/6.6/lib/amd64/cmake") + + # Amazing - absolutely incredible + list(APPEND CMAKE_PREFIX_PATH "${CMAKE_SYSROOT}/usr/lib/amd64/cmake") + list(APPEND CMAKE_MODULE_PATH "${CMAKE_SYSROOT}/usr/lib/amd64/cmake") + + # For some mighty reason, doing a normal release build sometimes + # may not trigger the proper -O3 switch to materialize + if (CMAKE_BUILD_TYPE MATCHES "Release") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3") + endif() + if (CMAKE_BUILD_TYPE MATCHES "RelWithDebInfo") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2") + endif() +endif() + +# MSYS2 utilities + +# Sometimes, PkgConfig modules will incorrectly reference / when CMake +# wants you to reference it as C:/msys64/. This function corrects that. +# Example in a Find module: +#[[ + if (PLATFORM_MSYS) + FixMsysPath(PkgConfig::OPUS) + endif() +]] + +function(FixMsysPath target) + get_target_property(include_dir ${target} INTERFACE_INCLUDE_DIRECTORIES) + + if (NOT (include_dir MATCHES "^/")) + return() + endif() + + set(root_default $ENV{MSYS2_LOCATION}) + if (root_default STREQUAL "") + set(root_default "C:/msys64") + endif() + + set(MSYS_ROOT_PATH ${root_default} + CACHE STRING "Location of the MSYS2 root") + + set(include_dir "C:/msys64${include_dir}") + set_target_properties(${target} PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES ${include_dir}) +endfunction() + +# MSYSTEM handling + program_path +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}/bin C:/msys64/usr/bin) + set(ENV{PKG_CONFIG_PATH} C:/msys64/${MSYSTEM}/lib/pkgconfig) +endif() + +# This saves a truly ridiculous amount of time during linking +# In my tests, without this, Eden takes 2 mins, with this, it takes 3-5 seconds +# or on GitHub Actions, 10 minutes -> 3 seconds +if (MINGW) + set(MINGW_FLAGS "-Wl,--strip-all -Wl,--gc-sections") + set(CMAKE_EXE_LINKER_FLAGS_RELEASE + "${CMAKE_EXE_LINKER_FLAGS_RELEASE} ${MINGW_FLAGS}") +endif() + +# awesome +if (PLATFORM_FREEBSD OR PLATFORM_DRAGONFLYBSD) + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${CMAKE_SYSROOT}/usr/local/lib") +endif() \ No newline at end of file diff --git a/externals/cmake-modules/FasterLinker.cmake b/externals/cmake-modules/FasterLinker.cmake new file mode 100644 index 0000000000..6b472a4f0f --- /dev/null +++ b/externals/cmake-modules/FasterLinker.cmake @@ -0,0 +1,58 @@ +# SPDX-FileCopyrightText: Copyright 2025 crueter +# SPDX-License-Identifier: GPL-3.0-or-later + +## FasterLinker ## + +# This finds a faster linker for your compiler, if available. +# Only really tested on Linux. I would not recommend this on MSYS2. + +#[[ + search order: + - gold (GCC only) - the best, generally, but not packaged anymore + - mold (GCC only) - generally does well on GCC + - lld - preferred on clang + - bfd - the final fallback + - If none are found (macOS uses ld.prime, etc) just use the default linker +]] + +# This module is based on the work of Yuzu, specifically Liam White, +# and later extended by crueter. + +if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + set(CXX_GCC ON) +endif() + +find_program(LINKER_BFD bfd) +if (LINKER_BFD) + set(LINKER bfd) +endif() + +find_program(LINKER_LLD lld) +if (LINKER_LLD) + set(LINKER lld) +endif() + +if (CXX_GCC) + find_program(LINKER_MOLD mold) + if (LINKER_MOLD AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "12.1") + set(LINKER mold) + endif() + + find_program(LINKER_GOLD gold) + if (LINKER_GOLD) + set(LINKER gold) + endif() +endif() + +if (LINKER) + message(NOTICE "[FasterLinker] Selecting ${LINKER} as linker") + add_link_options("-fuse-ld=${LINKER}") +else() + message(WARNING "[FasterLinker] No faster linker found--using default") +endif() + +if (LINKER STREQUAL "lld" AND CXX_GCC) + message(WARNING + "[FasterLinker] Using lld on GCC may cause issues " + "with certain LTO settings.") +endif() diff --git a/externals/cmake-modules/GetGitRevisionDescription.cmake b/externals/cmake-modules/GetGitRevisionDescription.cmake deleted file mode 100644 index dab1347753..0000000000 --- a/externals/cmake-modules/GetGitRevisionDescription.cmake +++ /dev/null @@ -1,162 +0,0 @@ -# SPDX-FileCopyrightText: 2009 Iowa State University -# SPDX-FileContributor: Ryan Pavlik -# SPDX-License-Identifier: BSL-1.0 - -# - Returns a version string from Git -# -# These functions force a re-configure on each git commit so that you can -# trust the values of the variables in your build system. -# -# get_git_head_revision( [ ...]) -# -# Returns the refspec and sha hash of the current head revision -# -# git_describe( [ ...]) -# -# Returns the results of git describe on the source tree, and adjusting -# the output so that it tests false if an error occurs. -# -# git_get_exact_tag( [ ...]) -# -# Returns the results of git describe --exact-match on the source tree, -# and adjusting the output so that it tests false if there was no exact -# matching tag. -# -# Requires CMake 2.6 or newer (uses the 'function' command) -# -# Original Author: -# 2009-2010 Ryan Pavlik -# http://academic.cleardefinition.com -# Iowa State University HCI Graduate Program/VRAC -# -# Copyright Iowa State University 2009-2010. -# Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE_1_0.txt or copy at -# http://www.boost.org/LICENSE_1_0.txt) - -if(__get_git_revision_description) - return() -endif() -set(__get_git_revision_description YES) - -# We must run the following at "include" time, not at function call time, -# to find the path to this module rather than the path to a calling list file -get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH) - -function(get_git_head_revision _refspecvar _hashvar) - set(GIT_PARENT_DIR "${CMAKE_CURRENT_SOURCE_DIR}") - set(GIT_DIR "${GIT_PARENT_DIR}/.git") - while(NOT EXISTS "${GIT_DIR}") # .git dir not found, search parent directories - set(GIT_PREVIOUS_PARENT "${GIT_PARENT_DIR}") - get_filename_component(GIT_PARENT_DIR ${GIT_PARENT_DIR} PATH) - if(GIT_PARENT_DIR STREQUAL GIT_PREVIOUS_PARENT) - # We have reached the root directory, we are not in git - set(${_refspecvar} "GITDIR-NOTFOUND" PARENT_SCOPE) - set(${_hashvar} "GITDIR-NOTFOUND" PARENT_SCOPE) - return() - endif() - set(GIT_DIR "${GIT_PARENT_DIR}/.git") - endwhile() - # check if this is a submodule - if(NOT IS_DIRECTORY ${GIT_DIR}) - file(READ ${GIT_DIR} submodule) - string(REGEX REPLACE "gitdir: (.*)\n$" "\\1" GIT_DIR_RELATIVE ${submodule}) - get_filename_component(SUBMODULE_DIR ${GIT_DIR} PATH) - get_filename_component(GIT_DIR ${SUBMODULE_DIR}/${GIT_DIR_RELATIVE} ABSOLUTE) - endif() - set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data") - if(NOT EXISTS "${GIT_DATA}") - file(MAKE_DIRECTORY "${GIT_DATA}") - endif() - - if(NOT EXISTS "${GIT_DIR}/HEAD") - return() - endif() - set(HEAD_FILE "${GIT_DATA}/HEAD") - configure_file("${GIT_DIR}/HEAD" "${HEAD_FILE}" COPYONLY) - - configure_file("${_gitdescmoddir}/GetGitRevisionDescription.cmake.in" - "${GIT_DATA}/grabRef.cmake" - @ONLY) - include("${GIT_DATA}/grabRef.cmake") - - set(${_refspecvar} "${HEAD_REF}" PARENT_SCOPE) - set(${_hashvar} "${HEAD_HASH}" PARENT_SCOPE) -endfunction() - -function(git_branch_name _var) - if(NOT GIT_FOUND) - find_package(Git QUIET) - endif() - - if(NOT GIT_FOUND) - set(${_var} "GIT-NOTFOUND" PARENT_SCOPE) - return() - endif() - - execute_process(COMMAND - "${GIT_EXECUTABLE}" - rev-parse --abbrev-ref HEAD - WORKING_DIRECTORY - "${CMAKE_SOURCE_DIR}" - RESULT_VARIABLE - res - OUTPUT_VARIABLE - out - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE) - if(NOT res EQUAL 0) - set(out "${out}-${res}-NOTFOUND") - endif() - - set(${_var} "${out}" PARENT_SCOPE) -endfunction() - -function(git_describe _var) - if(NOT GIT_FOUND) - find_package(Git QUIET) - endif() - #get_git_head_revision(refspec hash) - if(NOT GIT_FOUND) - set(${_var} "GIT-NOTFOUND" PARENT_SCOPE) - return() - endif() - #if(NOT hash) - # set(${_var} "HEAD-HASH-NOTFOUND" PARENT_SCOPE) - # return() - #endif() - - # TODO sanitize - #if((${ARGN}" MATCHES "&&") OR - # (ARGN MATCHES "||") OR - # (ARGN MATCHES "\\;")) - # message("Please report the following error to the project!") - # message(FATAL_ERROR "Looks like someone's doing something nefarious with git_describe! Passed arguments ${ARGN}") - #endif() - - #message(STATUS "Arguments to execute_process: ${ARGN}") - - execute_process(COMMAND - "${GIT_EXECUTABLE}" - describe - ${hash} - ${ARGN} - WORKING_DIRECTORY - "${CMAKE_SOURCE_DIR}" - RESULT_VARIABLE - res - OUTPUT_VARIABLE - out - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE) - if(NOT res EQUAL 0) - set(out "${out}-${res}-NOTFOUND") - endif() - - set(${_var} "${out}" PARENT_SCOPE) -endfunction() - -function(git_get_exact_tag _var) - git_describe(out --exact-match ${ARGN}) - set(${_var} "${out}" PARENT_SCOPE) -endfunction() diff --git a/externals/cmake-modules/GetGitRevisionDescription.cmake.in b/externals/cmake-modules/GetGitRevisionDescription.cmake.in deleted file mode 100644 index 868e032efb..0000000000 --- a/externals/cmake-modules/GetGitRevisionDescription.cmake.in +++ /dev/null @@ -1,45 +0,0 @@ -# SPDX-FileCopyrightText: 2009 Iowa State University -# SPDX-FileContributor: Ryan Pavlik -# SPDX-License-Identifier: BSL-1.0 - -# Internal file for GetGitRevisionDescription.cmake -# -# Requires CMake 2.6 or newer (uses the 'function' command) -# -# Original Author: -# 2009-2010 Ryan Pavlik -# http://academic.cleardefinition.com -# Iowa State University HCI Graduate Program/VRAC -# -# Copyright Iowa State University 2009-2010. -# Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE_1_0.txt or copy at -# http://www.boost.org/LICENSE_1_0.txt) - -set(HEAD_HASH) - -file(READ "@HEAD_FILE@" HEAD_CONTENTS LIMIT 1024) - -string(STRIP "${HEAD_CONTENTS}" HEAD_CONTENTS) -if(HEAD_CONTENTS MATCHES "ref") - # named branch - string(REPLACE "ref: " "" HEAD_REF "${HEAD_CONTENTS}") - if(EXISTS "@GIT_DIR@/${HEAD_REF}") - configure_file("@GIT_DIR@/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY) - elseif(EXISTS "@GIT_DIR@/logs/${HEAD_REF}") - configure_file("@GIT_DIR@/logs/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY) - set(HEAD_HASH "${HEAD_REF}") - endif() -else() - # detached HEAD - configure_file("@GIT_DIR@/HEAD" "@GIT_DATA@/head-ref" COPYONLY) -endif() - -if(NOT HEAD_HASH) - if(EXISTS "@GIT_DATA@/head-ref") - file(READ "@GIT_DATA@/head-ref" HEAD_HASH LIMIT 1024) - string(STRIP "${HEAD_HASH}" HEAD_HASH) - else() - set(HEAD_HASH "Unknown") - endif() -endif() diff --git a/externals/cmake-modules/GetSCMRev.cmake b/externals/cmake-modules/GetSCMRev.cmake new file mode 100644 index 0000000000..4b144584e8 --- /dev/null +++ b/externals/cmake-modules/GetSCMRev.cmake @@ -0,0 +1,85 @@ +# SPDX-FileCopyrightText: Copyright 2025 crueter +# SPDX-License-Identifier: GPL-3.0-or-later + +## GetSCMRev ## +# Name is self explanatory. Gets revision information from files, OR from git. +# Prioritizes GIT-TAG, GIT-REFSPEC, GIT-COMMIT, GIT-RELEASE files within the root directory, +# otherwise grabs stuff from Git. + +# loosely based on Ryan Pavlik's work +find_package(Git QUIET) + +# commit: git rev-parse HEAD +# tag: git describe --tags --abbrev=0 +# branch: git rev-parse --abbrev-ref=HEAD + +function(run_git_command variable) + if(NOT GIT_FOUND) + set(${variable} "GIT-NOTFOUND" PARENT_SCOPE) + return() + endif() + + execute_process(COMMAND + "${GIT_EXECUTABLE}" + ${ARGN} + WORKING_DIRECTORY + "${CMAKE_SOURCE_DIR}" + RESULT_VARIABLE + res + OUTPUT_VARIABLE + out + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + + if(NOT res EQUAL 0) + set(out "${out}-${res}-NOTFOUND") + endif() + + set(${variable} "${out}" PARENT_SCOPE) +endfunction() + +function(trim var) + string(REGEX REPLACE "\n" "" new "${${var}}") + set(${var} ${new} PARENT_SCOPE) +endfunction() + +set(TAG_FILE ${CMAKE_SOURCE_DIR}/GIT-TAG) +set(REF_FILE ${CMAKE_SOURCE_DIR}/GIT-REFSPEC) +set(COMMIT_FILE ${CMAKE_SOURCE_DIR}/GIT-COMMIT) +set(RELEASE_FILE ${CMAKE_SOURCE_DIR}/GIT-RELEASE) + +if (EXISTS ${REF_FILE} AND EXISTS ${COMMIT_FILE}) + file(READ ${REF_FILE} GIT_REFSPEC) + file(READ ${COMMIT_FILE} GIT_COMMIT) +else() + run_git_command(GIT_COMMIT rev-parse HEAD) + run_git_command(GIT_REFSPEC rev-parse --abbrev-ref HEAD) + + if (GIT_REFSPEC MATCHES "NOTFOUND") + set(GIT_REFSPEC 1.0.0) + set(GIT_COMMIT stable) + endif() +endif() + +if (EXISTS ${TAG_FILE}) + file(READ ${TAG_FILE} GIT_TAG) +else() + run_git_command(GIT_TAG describe --tags --abbrev=0) + if (GIT_TAG MATCHES "NOTFOUND") + set(GIT_TAG "${GIT_REFSPEC}") + endif() +endif() + +if (EXISTS ${RELEASE_FILE}) + file(READ ${RELEASE_FILE} GIT_RELEASE) + trim(GIT_RELEASE) + message(STATUS "[GetSCMRev] Git release: ${GIT_RELEASE}") +endif() + +trim(GIT_REFSPEC) +trim(GIT_COMMIT) +trim(GIT_TAG) + +message(STATUS "[GetSCMRev] Git commit: ${GIT_COMMIT}") +message(STATUS "[GetSCMRev] Git tag: ${GIT_TAG}") +message(STATUS "[GetSCMRev] Git refspec: ${GIT_REFSPEC}") diff --git a/externals/cmake-modules/UseCcache.cmake b/externals/cmake-modules/UseCcache.cmake new file mode 100644 index 0000000000..8caea18fe0 --- /dev/null +++ b/externals/cmake-modules/UseCcache.cmake @@ -0,0 +1,34 @@ +# SPDX-FileCopyrightText: Copyright 2025 crueter +# SPDX-License-Identifier: GPL-3.0-or-later + +## UseCcache ## + +# Adds an option to enable CCache and uses it if provided. +# Also does some debug info downgrading to make it easier. +# Credit to DraVee for his work on this + +option(USE_CCACHE "Use ccache for compilation" OFF) +set(CCACHE_PATH "ccache" CACHE STRING "Path to ccache binary") +if(USE_CCACHE) + find_program(CCACHE_BINARY ${CCACHE_PATH}) + if(CCACHE_BINARY) + message(STATUS "[UseCcache] Found ccache at: ${CCACHE_BINARY}") + set(CMAKE_C_COMPILER_LAUNCHER ${CCACHE_BINARY}) + set(CMAKE_CXX_COMPILER_LAUNCHER ${CCACHE_BINARY}) + else() + message(FATAL_ERROR "[UseCcache] USE_CCACHE enabled, but no " + "executable found at: ${CCACHE_PATH}") + endif() + # Follow SCCache recommendations: + # + if(WIN32) + string(REPLACE "/Zi" "/Z7" CMAKE_CXX_FLAGS_DEBUG + "${CMAKE_CXX_FLAGS_DEBUG}") + string(REPLACE "/Zi" "/Z7" CMAKE_C_FLAGS_DEBUG + "${CMAKE_C_FLAGS_DEBUG}") + string(REPLACE "/Zi" "/Z7" CMAKE_CXX_FLAGS_RELWITHDEBINFO + "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}") + string(REPLACE "/Zi" "/Z7" CMAKE_C_FLAGS_RELWITHDEBINFO + "${CMAKE_C_FLAGS_RELWITHDEBINFO}") + endif() +endif() diff --git a/externals/cmake-modules/UseLTO.cmake b/externals/cmake-modules/UseLTO.cmake new file mode 100644 index 0000000000..d1603aba1c --- /dev/null +++ b/externals/cmake-modules/UseLTO.cmake @@ -0,0 +1,17 @@ +# SPDX-FileCopyrightText: Copyright 2025 crueter +# SPDX-License-Identifier: GPL-3.0-or-later + +## UseLTO ## + +# Enable Interprocedural Optimization (IPO). +# Self-explanatory. + +include(CheckIPOSupported) +check_ipo_supported(RESULT COMPILER_SUPPORTS_LTO) +if(NOT COMPILER_SUPPORTS_LTO) + message(FATAL_ERROR + "Your compiler does not support interprocedural optimization" + " (IPO).") +endif() +set(CMAKE_POLICY_DEFAULT_CMP0069 NEW) +set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ${COMPILER_SUPPORTS_LTO}) diff --git a/externals/cpmfile.json b/externals/cpmfile.json index 7f5af5dfce..067a824b64 100644 --- a/externals/cpmfile.json +++ b/externals/cpmfile.json @@ -28,8 +28,8 @@ "httplib": { "repo": "yhirose/cpp-httplib", "tag": "v%VERSION%", - "hash": "b364500f76e2ecb0fe21b032d831272e3f1dfeea71af74e325f8fc4ce9dcdb3c941b97a5b422bdeafb9facd058597b90f8bfc284fb9afe3c33fefa15dd5a010b", - "git_version": "0.26.0", + "hash": "e7a8877d489c97669a8ee536e1498575be921e558ed947253013fe6b67a49d4569eedd01f543caa70183b92d8ac0e8687d662a70d880954412e387317008a239", + "git_version": "0.28.0", "find_args": "MODULE GLOBAL", "patches": [ "0001-mingw.patch" @@ -89,9 +89,9 @@ "package": "unordered_dense", "repo": "martinus/unordered_dense", "tag": "v%VERSION%", - "hash": "f9c819e28e1c1a387acfee09277d6af5e366597a0d39acf1c687acf0608a941ba966af8aaebdb8fba0126c7360269c4a51754ef4cab17c35c01a30215f953368", + "hash": "b98b5d4d96f8e0081b184d6c4c1181fae4e41723b54bed4296717d7f417348b48fad0bbcc664cac142b8c8a47e95aa57c1eb1cf6caa855fd782fad3e3ab99e5e", "find_args": "CONFIG", - "git_version": "4.5.0" + "git_version": "4.8.1" }, "mbedtls": { "package": "MbedTLS", @@ -188,9 +188,9 @@ "package": "SimpleIni", "repo": "brofield/simpleini", "tag": "v%VERSION%", - "hash": "6c198636816a0018adbf7f735d402c64245c6fcd540b7360d4388d46f007f3a520686cdaec4705cb8cb31401b2cb4797a80b42ea5d08a6a5807c0848386f7ca1", + "hash": "b937c18a7b6277d77ca7ebfb216af4984810f77af4c32d101b7685369a4bd5eb61406223f82698e167e6311a728d07415ab59639fdf19eff71ad6dc2abfda989", "find_args": "MODULE", - "git_version": "4.22" + "git_version": "4.25" }, "sdl2_generic": { "package": "SDL2", @@ -210,5 +210,13 @@ "key": "steamdeck", "bundled": true, "skip_updates": "true" + }, + "moltenvk": { + "repo": "KhronosGroup/MoltenVK", + "tag": "v%VERSION%", + "git_version": "1.4.1", + "artifact": "MoltenVK-macOS.tar", + "hash": "a394329f390a11d1052d2efeef5f7f33860465eea4d7e9e1faf808e616d533a283b9c55074fb833ef95ef40067fc319470eab07dc72ac63e6464dc26cbe34905", + "bundled": true } } diff --git a/src/dynarmic/CMakeLists.txt b/src/dynarmic/CMakeLists.txt index 6328d4c90d..6d19c4355a 100644 --- a/src/dynarmic/CMakeLists.txt +++ b/src/dynarmic/CMakeLists.txt @@ -33,12 +33,6 @@ option(DYNARMIC_INSTALL "Install dynarmic headers and CMake files" OFF) option(DYNARMIC_USE_BUNDLED_EXTERNALS "Use all bundled externals (useful when e.g. cross-compiling)" OFF) option(DYNARMIC_ENABLE_LTO "Enable LTO" OFF) -# Default to a Release build -if (NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." FORCE) - message(STATUS "Defaulting to a Release build") -endif() - # Set hard requirements for C++ set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) @@ -54,12 +48,6 @@ endif() # Add the module directory to the list of paths list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/CMakeModules") -# Arch detection -if (NOT DEFINED ARCHITECTURE) - message(FATAL_ERROR "Unsupported architecture encountered. Ending CMake generation.") -endif() -message(STATUS "Target architecture: ${ARCHITECTURE}") - # Compiler flags if (MSVC) set(DYNARMIC_CXX_FLAGS @@ -119,7 +107,7 @@ else() endif() find_package(Boost 1.57 REQUIRED) -find_package(fmt 9 CONFIG) +find_package(fmt 8 CONFIG) # Pull in externals CMakeLists for libs where available add_subdirectory(externals) diff --git a/src/dynarmic/CMakeModules/TargetArchitectureSpecificSources.cmake b/src/dynarmic/CMakeModules/TargetArchitectureSpecificSources.cmake index f08911c6f2..7af6cc518b 100644 --- a/src/dynarmic/CMakeModules/TargetArchitectureSpecificSources.cmake +++ b/src/dynarmic/CMakeModules/TargetArchitectureSpecificSources.cmake @@ -1,5 +1,8 @@ +# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +# SPDX-License-Identifier: GPL-3.0-or-later + function(target_architecture_specific_sources project arch) - if (NOT DYNARMIC_MULTIARCH_BUILD) + if (NOT MULTIARCH_BUILD) target_sources("${project}" PRIVATE ${ARGN}) return() endif() diff --git a/src/dynarmic/tests/CMakeLists.txt b/src/dynarmic/tests/CMakeLists.txt index a77c681f31..4124ca975b 100644 --- a/src/dynarmic/tests/CMakeLists.txt +++ b/src/dynarmic/tests/CMakeLists.txt @@ -56,7 +56,7 @@ if ("x86_64" IN_LIST ARCHITECTURE) native/preserve_xmm.cpp ) - if (NOT MSVC AND NOT DYNARMIC_MULTIARCH_BUILD) + if (NOT MSVC AND NOT MULTIARCH_BUILD) target_sources(dynarmic_tests PRIVATE rsqrt_test.cpp rsqrt_test_fn.s diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index e505319b3c..8abeb90086 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt @@ -375,12 +375,6 @@ if (APPLE) set_target_properties(yuzu PROPERTIES MACOSX_BUNDLE TRUE) set_target_properties(yuzu PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist) - if (YUZU_USE_BUNDLED_MOLTENVK) - set(MOLTENVK_PLATFORM "macOS") - set(MOLTENVK_VERSION "v1.4.0") - download_moltenvk(${MOLTENVK_PLATFORM} ${MOLTENVK_VERSION}) - endif() - set(CMAKE_FIND_LIBRARY_SUFFIXES ".dylib") find_library(MOLTENVK_LIBRARY MoltenVK REQUIRED) message(STATUS "Using MoltenVK at ${MOLTENVK_LIBRARY}.") diff --git a/tools/cpm/check-updates.sh b/tools/cpm/check-updates.sh index 5fc7836199..189c520690 100755 --- a/tools/cpm/check-updates.sh +++ b/tools/cpm/check-updates.sh @@ -8,10 +8,14 @@ RETURN=0 -filter() { +filter_out() { TAGS=$(echo "$TAGS" | jq "[.[] | select(.name | test(\"$1\"; \"i\") | not)]") } +filter_in() { + TAGS=$(echo "$TAGS" | jq "[.[] | select(.name | test(\"$1\"; \"i\"))]") +} + usage() { cat << EOF Usage: $0 [uf] [PACKAGE]... @@ -83,19 +87,27 @@ while true; do # filter out some commonly known annoyances # TODO add more - filter vulkan-sdk # vulkan - filter yotta # mbedtls + if [ "$PACKAGE" = "vulkan-validation-layers" ]; then + filter_in vulkan-sdk + else + filter_out vulkan-sdk + fi + + [ "$CI" = "true" ] && filter_in "-" + + filter_out yotta # mbedtls # ignore betas/alphas (remove if needed) - filter alpha - filter beta - filter rc + filter_out alpha + filter_out beta + filter_out rc # Add package-specific overrides here, e.g. here for fmt: - [ "$PACKAGE" = fmt ] && filter v0.11 + [ "$PACKAGE" = fmt ] && filter_out v0.11 LATEST=$(echo "$TAGS" | jq -r '.[0].name') + [ "$LATEST" = "null" ] && echo "-- * Up-to-date" && continue [ "$LATEST" = "$TAG" ] && [ "$FORCE" != "true" ] && echo "-- * Up-to-date" && continue RETURN=1 diff --git a/tools/cpm/download.sh b/tools/cpm/download.sh index bc436ba0f1..c8a1d637e0 100755 --- a/tools/cpm/download.sh +++ b/tools/cpm/download.sh @@ -20,10 +20,13 @@ download_package() { ACTUAL_HASH=$("${HASH_ALGO}"sum "$OUTFILE" | cut -d" " -f1) [ "$ACTUAL_HASH" != "$HASH" ] && echo "!! $FILENAME did not match expected hash; expected $HASH but got $ACTUAL_HASH" && exit 1 + TMPDIR="$TMP/extracted" mkdir -p "$OUTDIR" + mkdir -p "$TMPDIR" PREVDIR="$PWD" - cd "$OUTDIR" + mkdir -p "$TMPDIR" + cd "$TMPDIR" case "$FILENAME" in (*.7z) @@ -44,11 +47,16 @@ download_package() { # thanks gnu if [ "$(echo "$DIRS" | wc -l)" -eq 2 ]; then SUBDIR=$(find . -maxdepth 1 -type d -not -name ".") - mv "$SUBDIR"/* . - mv "$SUBDIR"/.* . 2>/dev/null || true + mv "$SUBDIR"/* "$OUTDIR" + mv "$SUBDIR"/.* "$OUTDIR" 2>/dev/null || true rmdir "$SUBDIR" + else + mv ./* "$OUTDIR" + mv ./.* "$OUTDIR" 2>/dev/null || true fi + cd "$OUTDIR" + if echo "$JSON" | grep -e "patches" > /dev/null; then PATCHES=$(echo "$JSON" | jq -r '.patches | join(" ")') for patch in $PATCHES; do