diff --git a/CMakeLists.txt b/CMakeLists.txt index f436c0a183..96209292db 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,7 +31,6 @@ elseif (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") endif() list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules") -list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/externals/cmake-modules") # NB: this does not account for SPARC # If you get Eden working on SPARC, please shoot crueter@crueter.xyz multiple emails @@ -64,45 +63,14 @@ 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) +include(DetectArchitecture) - # 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) - 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() -endif() +DetectArchitecture() if (NOT DEFINED ARCHITECTURE) - set(ARCHITECTURE "GENERIC") - set(ARCHITECTURE_GENERIC 1) - add_definitions(-DARCHITECTURE_GENERIC=1) + message(FATAL_ERROR "Architecture didn't make it out of scope, did you delete DetectArchitecture.cmake?") 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; \ @@ -134,7 +102,8 @@ endif() set(CPM_SOURCE_CACHE ${CMAKE_SOURCE_DIR}/.cache/cpm) -include(DownloadExternals) +include(DownloadQt) +include(CPMUtil) include(CMakeDependentOption) include(CTest) @@ -198,6 +167,7 @@ if (YUZU_USE_PRECOMPILED_HEADERS) message(STATUS "Using Precompiled Headers.") set(CMAKE_PCH_INSTANTIATE_TEMPLATES ON) endif() + option(YUZU_ENABLE_LTO "Enable link-time optimization" OFF) if(YUZU_ENABLE_LTO) include(CheckIPOSupported) @@ -208,8 +178,10 @@ if(YUZU_ENABLE_LTO) set(CMAKE_POLICY_DEFAULT_CMP0069 NEW) set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ${COMPILER_SUPPORTS_LTO}) endif() + 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) @@ -264,29 +236,14 @@ if (ENABLE_OPENSSL) endif() if (ANDROID AND YUZU_DOWNLOAD_ANDROID_VVL) - # TODO(crueter): CPM this - set(vvl_version "1.4.321.0") - set(vvl_zip_file "${CMAKE_BINARY_DIR}/externals/vvl-android.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 set(vvl_lib_path "${CMAKE_CURRENT_SOURCE_DIR}/src/android/app/src/main/jniLibs/arm64-v8a/") - file(COPY "${CMAKE_BINARY_DIR}/externals/android-binaries-${vvl_version}/arm64-v8a/libVkLayer_khronos_validation.so" + file(COPY "${VVL_SOURCE_DIR}/arm64-v8a/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) @@ -399,8 +356,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) @@ -686,17 +641,17 @@ if(ENABLE_QT) set_target_properties(Qt6::Platform PROPERTIES INTERFACE_COMPILE_FEATURES "") endif() -if (WIN32 AND YUZU_CRASH_DUMPS) - set(BREAKPAD_VER "breakpad-c89f9dd") - download_bundled_external("breakpad/" ${BREAKPAD_VER} "breakpad-win" BREAKPAD_PREFIX "c89f9dd") +# if (WIN32 AND YUZU_CRASH_DUMPS) +# set(BREAKPAD_VER "breakpad-c89f9dd") +# download_bundled_external("breakpad/" ${BREAKPAD_VER} "breakpad-win" BREAKPAD_PREFIX "c89f9dd") - set(BREAKPAD_CLIENT_INCLUDE_DIR "${BREAKPAD_PREFIX}/include") - set(BREAKPAD_CLIENT_LIBRARY "${BREAKPAD_PREFIX}/lib/libbreakpad_client.lib") +# set(BREAKPAD_CLIENT_INCLUDE_DIR "${BREAKPAD_PREFIX}/include") +# set(BREAKPAD_CLIENT_LIBRARY "${BREAKPAD_PREFIX}/lib/libbreakpad_client.lib") - add_library(libbreakpad_client INTERFACE IMPORTED) - target_link_libraries(libbreakpad_client INTERFACE "${BREAKPAD_CLIENT_LIBRARY}") - target_include_directories(libbreakpad_client INTERFACE "${BREAKPAD_CLIENT_INCLUDE_DIR}") -endif() +# add_library(libbreakpad_client INTERFACE IMPORTED) +# target_link_libraries(libbreakpad_client INTERFACE "${BREAKPAD_CLIENT_LIBRARY}") +# target_include_directories(libbreakpad_client INTERFACE "${BREAKPAD_CLIENT_INCLUDE_DIR}") +# endif() # Prefer the -pthread flag on Linux. set(THREADS_PREFER_PTHREAD_FLAG ON) diff --git a/CMakeModules/CPM.cmake b/CMakeModules/CPM.cmake index 5544d8eefe..2d97f5493c 100644 --- a/CMakeModules/CPM.cmake +++ b/CMakeModules/CPM.cmake @@ -1,3 +1,8 @@ +# SPDX-FileCopyrightText: Copyright 2025 crueter +# SPDX-License-Identifier: GPL-3.0-or-later + +# This is a slightly modified version of CPM.cmake + # CPM.cmake - CMake's missing package manager # =========================================== # See https://github.com/cpm-cmake/CPM.cmake for usage and update instructions. diff --git a/CMakeModules/DetectArchitecture.cmake b/CMakeModules/DetectArchitecture.cmake new file mode 100644 index 0000000000..b9194a8037 --- /dev/null +++ b/CMakeModules/DetectArchitecture.cmake @@ -0,0 +1,225 @@ +# SPDX-FileCopyrightText: 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/CMakeModules/DownloadExternals.cmake b/CMakeModules/DownloadQt.cmake similarity index 68% rename from CMakeModules/DownloadExternals.cmake rename to CMakeModules/DownloadQt.cmake index f6e3aaa4ad..373a698dab 100644 --- a/CMakeModules/DownloadExternals.cmake +++ b/CMakeModules/DownloadQt.cmake @@ -1,62 +1,6 @@ # SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project # SPDX-License-Identifier: GPL-3.0-or-later -# This function downloads a binary library package from our external repo. -# Params: -# remote_path: path to the file to download, relative to the remote repository root -# prefix_var: name of a variable which will be set with the path to the extracted contents -set(CURRENT_MODULE_DIR ${CMAKE_CURRENT_LIST_DIR}) -function(download_bundled_external remote_path lib_name cpm_key prefix_var version) - set(package_base_url "https://github.com/eden-emulator/") - set(package_repo "no_platform") - set(package_extension "no_platform") - set(CACHE_KEY "") - - # TODO(crueter): Need to convert ffmpeg to a CI. - if (WIN32 OR FORCE_WIN_ARCHIVES) - if (ARCHITECTURE_arm64) - set(CACHE_KEY "windows") - set(package_repo "ext-windows-arm64-bin/raw/master/") - set(package_extension ".zip") - elseif(ARCHITECTURE_x86_64) - set(CACHE_KEY "windows") - set(package_repo "ext-windows-bin/raw/master/") - set(package_extension ".7z") - endif() - elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Linux") - set(CACHE_KEY "linux") - set(package_repo "ext-linux-bin/raw/master/") - set(package_extension ".tar.xz") - elseif (ANDROID) - set(CACHE_KEY "android") - set(package_repo "ext-android-bin/raw/master/") - set(package_extension ".tar.xz") - else() - message(FATAL_ERROR "No package available for this platform") - endif() - string(CONCAT package_url "${package_base_url}" "${package_repo}") - string(CONCAT full_url "${package_url}" "${remote_path}" "${lib_name}" "${package_extension}") - message(STATUS "Resolved bundled URL: ${full_url}") - - # TODO(crueter): DELETE THIS ENTIRELY, GLORY BE TO THE CI! - AddPackage( - NAME ${cpm_key} - VERSION ${version} - URL ${full_url} - DOWNLOAD_ONLY YES - KEY ${CACHE_KEY} - BUNDLED_PACKAGE ON - # TODO(crueter): hash - ) - - if (DEFINED ${cpm_key}_SOURCE_DIR) - set(${prefix_var} "${${cpm_key}_SOURCE_DIR}" PARENT_SCOPE) - message(STATUS "Using bundled binaries at ${${cpm_key}_SOURCE_DIR}") - else() - message(FATAL_ERROR "AddPackage did not set ${cpm_key}_SOURCE_DIR") - endif() -endfunction() - # Determine installation parameters for OS, architecture, and compiler function(determine_qt_parameters target host_out type_out arch_out arch_path_out host_type_out host_arch_out host_arch_path_out) if (WIN32) @@ -237,35 +181,3 @@ function(download_qt target) list(APPEND CMAKE_PREFIX_PATH "${prefix}") set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} PARENT_SCOPE) endfunction() - -function(download_moltenvk version platform) - if(NOT version) - message(FATAL_ERROR "download_moltenvk: version argument is required") - endif() - if(NOT platform) - message(FATAL_ERROR "download_moltenvk: platform argument is required") - endif() - - set(MOLTENVK_DIR "${CMAKE_BINARY_DIR}/externals/MoltenVK") - set(MOLTENVK_TAR "${CMAKE_BINARY_DIR}/externals/MoltenVK.tar") - - if(NOT EXISTS "${MOLTENVK_DIR}") - if(NOT EXISTS "${MOLTENVK_TAR}") - file(DOWNLOAD "https://github.com/KhronosGroup/MoltenVK/releases/download/${version}/MoltenVK-${platform}.tar" - "${MOLTENVK_TAR}" SHOW_PROGRESS) - endif() - - execute_process( - COMMAND ${CMAKE_COMMAND} -E tar xf "${MOLTENVK_TAR}" - WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/externals" - RESULT_VARIABLE tar_res - ERROR_VARIABLE tar_err - ) - if(NOT tar_res EQUAL 0) - message(FATAL_ERROR "Extracting MoltenVK failed: ${tar_err}") - endif() - endif() - list(APPEND CMAKE_PREFIX_PATH "${MOLTENVK_DIR}/MoltenVK/dylib/${platform}") - set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} PARENT_SCOPE) -endfunction() - diff --git a/CMakeModules/GetSCMRev.cmake b/CMakeModules/GetSCMRev.cmake index ee5ce6a91c..c15f933c88 100644 --- a/CMakeModules/GetSCMRev.cmake +++ b/CMakeModules/GetSCMRev.cmake @@ -1,11 +1,41 @@ # SPDX-FileCopyrightText: 2025 crueter # SPDX-License-Identifier: GPL-3.0-or-later -include(GetGitRevisionDescription) +# 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) + string(REGEX REPLACE "\n" "" new "${${var}}") + set(${var} ${new} PARENT_SCOPE) endfunction() set(TAG_FILE ${CMAKE_SOURCE_DIR}/GIT-TAG) @@ -14,36 +44,37 @@ 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) + 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() + 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) + 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() + 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 "Git release: ${GIT_RELEASE}") + 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 "Git commit: ${GIT_COMMIT}") -message(STATUS "Git tag: ${GIT_TAG}") -message(STATUS "Git refspec: ${GIT_REFSPEC}") +message(STATUS "[GetSCMRev] Git commit: ${GIT_COMMIT}") +message(STATUS "[GetSCMRev] Git tag: ${GIT_TAG}") +message(STATUS "[GetSCMRev] Git refspec: ${GIT_REFSPEC}") diff --git a/cpmfile.json b/cpmfile.json index e9e53ed326..6f4a2be65c 100644 --- a/cpmfile.json +++ b/cpmfile.json @@ -94,5 +94,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.321.0", + "artifact": "android-binaries-%VERSION%.zip", + "hash": "0a977711101c8f82a9762cee919e05fc48968e41e9c93a6c006971d3b4e348707c98c6f9c865fa2b97eb12654906ee659f29867f40cf643eb5dca1e93d8af73d" } } diff --git a/docs/CPM.md b/docs/CPM.md new file mode 100644 index 0000000000..779515ae7e --- /dev/null +++ b/docs/CPM.md @@ -0,0 +1,14 @@ +# CPMUtil + +CPMUtil is a wrapper around CPM that aims to reduce boilerplate and add useful utility functions to make dependency management a piece of cake. + +See more in [its repository](https://git.crueter.xyz/CMake/CPMUtil) + +Eden-specific options: + +- `YUZU_USE_CPM` is set by default on MSVC and Android. Other platforms should use this if certain "required" system dependencies (e.g. OpenSSL) are broken or missing + * If this is `OFF`, required system dependencies will be searched via `find_package`, although most externals use CPM regardless. + +## Tooling + +See the [tooling docs](../tools/cpm) \ No newline at end of file diff --git a/docs/CPMUtil.md b/docs/CPMUtil.md index 779515ae7e..0cff9411fe 100644 --- a/docs/CPMUtil.md +++ b/docs/CPMUtil.md @@ -2,13 +2,259 @@ CPMUtil is a wrapper around CPM that aims to reduce boilerplate and add useful utility functions to make dependency management a piece of cake. -See more in [its repository](https://git.crueter.xyz/CMake/CPMUtil) +Global Options: -Eden-specific options: +- `CPMUTIL_FORCE_SYSTEM` (default `OFF`): Require all CPM dependencies to use system packages. NOT RECOMMENDED! + * Many packages, e.g. mcl, sirit, xbyak, discord-rpc, are not generally available as a system package. + * You may optionally override these (see CPMUtil section) +- `CPMUTIL_FORCE_BUNDLED` (default `ON` on MSVC and Android, `OFF` elsewhere): Require all CPM dependencies to use bundled packages. -- `YUZU_USE_CPM` is set by default on MSVC and Android. Other platforms should use this if certain "required" system dependencies (e.g. OpenSSL) are broken or missing - * If this is `OFF`, required system dependencies will be searched via `find_package`, although most externals use CPM regardless. +## AddPackage -## Tooling +The core of CPMUtil is the `AddPackage` function. `AddPackage` itself is fully CMake-based, and largely serves as an interface between CPM and the rest of CPMUtil. -See the [tooling docs](../tools/cpm) \ No newline at end of file +**Identification/Fetching** + +- `NAME` (required): The package name (must be the same as the `find_package` name if applicable) +- `VERSION`: The minimum version of this package that can be used on the system +- `GIT_VERSION`: The "version" found within git +- `URL`: The URL to fetch. +- `REPO`: The GitHub repo to use (`owner/repo`). + * Only GitHub is supported for now, though other platforms will see support at some point +- `TAG`: The tag to fetch, if applicable. +- `ARTIFACT`: The name of the artifact, if applicable. +- `SHA`: Commit sha to fetch, if applicable. +- `BRANCH`: Branch to fetch, if applicable. + +The following configurations are supported, in descending order of precedence: + +- `URL`: Bare URL download, useful for custom artifacts + * If this is set, `GIT_URL` or `REPO` should be set to allow the dependency viewer to link to the project's Git repository. + * If this is NOT set, `REPO` must be defined. +- `REPO + TAG + ARTIFACT`: GitHub release artifact + * The final download URL will be `https://github.com/${REPO}/releases/download/${TAG}/${ARTIFACT}` + * Useful for prebuilt libraries and prefetched archives +- `REPO + TAG`: GitHub tag archive + * The final download URL will be `https://github.com/${REPO}/archive/refs/tags/${TAG}.tar.gz` + * Useful for pinning to a specific tag, better for build identification +- `REPO + SHA`: GitHub commit archive + * The final download URL will be `https://github.com/${REPO}/archive/${SHA}.zip` + * Useful for pinning to a specific commit +- `REPO + BRANCH`: GitHub branch archive + * The final download URL will be `https://github.com/${REPO}/archive/refs/heads/${BRANCH}.zip` + * Generally not recommended unless the branch is frozen +- `REPO`: GitHub master archive + * The final download URL will be `https://github.com/${REPO}/archive/refs/heads/master.zip` + * Generally not recommended unless the project is dead + +**Hashing** + +Hashing is used for verifying downloads. It's highly recommended to use these. + +- `HASH_ALGO` (default `SHA512`): Hash algorithm to use + +Hashing strategies, descending order of precedence: + +- `HASH`: Bare hash verification, useful for static downloads e.g. commit archives +- `HASH_SUFFIX`: Download the hash as `${DOWNLOAD_URL}.${HASH_SUFFIX}` + * The downloaded hash *must* match the hash algorithm and contain nothing but the hash; no filenames or extra content. +- `HASH_URL`: Download the hash from a separate URL + +**Additional Options** + +- `KEY`: Custom cache key to use (stored as `.cache/cpm/${packagename_lower}/${key}`) + * Default is based on, in descending order of precedence: + - First 4 characters of the sha + - `GIT_VERSION` + - Tag + - `VERSION` + - Otherwise, CPM defaults will be used. This is not recommended as it doesn't produce reproducible caches +- `DOWNLOAD_ONLY`: Whether or not to configure the downloaded package via CMake + * Useful to turn `OFF` if the project doesn't use CMake +- `SOURCE_SUBDIR`: Subdirectory of the project containing a CMakeLists.txt file +- `FIND_PACKAGE_ARGUMENTS`: Arguments to pass to the `find_package` call +- `BUNDLED_PACKAGE`: Set to `ON` to default to the bundled package +- `FORCE_BUNDLED_PACKAGE`: Set to `ON` to force the usage of the bundled package, regardless of CPMUTIL_FORCE_SYSTEM or `_FORCE_SYSTEM` +- `OPTIONS`: Options to pass to the configuration of the package +- `PATCHES`: Patches to apply to the package, stored in `.patch/${packagename_lower}/0001-patch-name.patch` and so on +- Other arguments can be passed to CPM as well + +**Extra Variables** + +For each added package, users may additionally force usage of the system/bundled package. + +- `${package}_FORCE_SYSTEM`: Require the package to be installed on the system +- `${package}_FORCE_BUNDLED`: Force the package to be fetched and use the bundled version + +**Bundled/System Switching** + +Descending order of precedence: +- If `${package}_FORCE_SYSTEM` is true, requires the package to be on the system +- If `${package}_FORCE_BUNDLED` is true, forcefully uses the bundled package +- If `CPMUTIL_FORCE_SYSTEM` is true, requires the package to be on the system +- If `CPMUTIL_FORCE_BUNDLED` is true, forcefully uses the bundled package +- If the `BUNDLED_PACKAGE` argument is true, forcefully uses the bundled package +- Otherwise, CPM will search for the package first, and if not found, will use the bundled package + +**Identification** + +All dependencies must be identifiable in some way for usage in the dependency viewer. Lists are provided in descending order of precedence. + +URLs: + +- `GIT_URL` +- `REPO` as a Git repository + * You may optionally specify `GIT_HOST` to use a custom host, e.g. `GIT_HOST git.crueter.xyz`. Note that the git host MUST be GitHub-like in its artifact/archive downloads, e.g. Forgejo + * If `GIT_HOST` is unspecified, defaults to `github.com` +- `URL` + +Versions (bundled): + +- `SHA` +- `GIT_VERSION` +- `VERSION` +- `TAG` +- "unknown" + +If the package is a system package, AddPackage will attempt to determine the package version and append ` (system)` to the identifier. Otherwise, it will be marked as `unknown (system)` + +## AddCIPackage + +Adds a package that follows [crueter's CI repository spec](https://github.com/crueter-ci). + +- `VERSION` (required): The version to get (the tag will be `v${VERSION}`) +- `NAME` (required): Name used within the artifacts +- `REPO` (required): CI repository, e.g. `crueter-ci/OpenSSL` +- `PACKAGE` (required): `find_package` package name +- `EXTENSION`: Artifact extension (default `tar.zst`) +- `MIN_VERSION`: Minimum version for `find_package`. Only used if platform does not support this package as a bundled artifact +- `DISABLED_PLATFORMS`: List of platforms that lack artifacts for this package. Options: + * `windows-amd64` + * `windows-arm64` + * `android` + * `solaris-amd64` + * `freebsd-amd64` + * `linux-amd64` + * `linux-aarch64` + * `macos-universal` + +## AddJsonPackage + +This is the recommended method of usage for CPMUtil. In each directory that utilizes `CPMUtil`, there must be a `cpmfile.json` that defines dependencies in a similar manner to the individual calls. + +The cpmfile is an object of objects, with each sub-object being named according to the package's identifier, e.g. `openssl`, which can then be fetched with `AddJsonPackage()`. Options are designed to map closely to the argument names, and are always strings unless otherwise specified. + +- `package` -> `NAME` (`PACKAGE` for CI), defaults to the object key +- `repo` -> `REPO` +- `version` -> `VERSION` +- `ci` (bool) + +If `ci` is `false`: + +- `hash` -> `HASH` +- `hash_suffix` -> `HASH_SUFFIX` +- `sha` -> `SHA` +- `key` -> `KEY` +- `tag` -> `TAG` + * If the tag contains `%VERSION%`, that part will be replaced by the `git_version`, OR `version` if `git_version` is not specified +- `url` -> `URL` +- `artifact` -> `ARTIFACT` + * If the artifact contains `%VERSION%`, that part will be replaced by the `git_version`, OR `version` if `git_version` is not specified + * If the artifact contains `%TAG%`, that part will be replaced by the `tag` (with its replacement already done) +- `git_version` -> `GIT_VERSION` +- `git_host` -> `GIT_HOST` +- `source_subdir` -> `SOURCE_SUBDIR` +- `bundled` -> `BUNDLED_PACKAGE` +- `find_args` -> `FIND_PACKAGE_ARGUMENTS` +- `patches` -> `PATCHES` (array) +- `options` -> `OPTIONS` (array) + +Other arguments aren't currently supported. If you wish to add them, see the `AddJsonPackage` function in `CMakeModules/CPMUtil.cmake`. + +If `ci` is `true`: + +- `name` -> `NAME`, defaults to the object key +- `extension` -> `EXTENSION`, defaults to `tar.zst` +- `min_version` -> `MIN_VERSION` +- `extension` -> `EXTENSION` +- `disabled_platforms` -> `DISABLED_PLATFORMS` (array) + +## Examples + +In order: OpenSSL CI, Boost (tag + artifact), Opus (options + find_args), discord-rpc (sha + options + patches) + +```json +{ + "openssl": { + "ci": true, + "package": "OpenSSL", + "name": "openssl", + "repo": "crueter-ci/OpenSSL", + "version": "3.6.0", + "min_version": "1.1.1", + "disabled_platforms": [ + "macos-universal" + ] + }, + "boost": { + "package": "Boost", + "repo": "boostorg/boost", + "tag": "boost-%VERSION%", + "artifact": "%TAG%-cmake.7z", + "hash": "e5b049e5b61964480ca816395f63f95621e66cb9bcf616a8b10e441e0e69f129e22443acb11e77bc1e8170f8e4171b9b7719891efc43699782bfcd4b3a365f01", + "git_version": "1.88.0", + "version": "1.57" + }, + "opus": { + "package": "Opus", + "repo": "xiph/opus", + "sha": "5ded705cf4", + "hash": "0dc89e58ddda1f3bc6a7037963994770c5806c10e66f5cc55c59286fc76d0544fe4eca7626772b888fd719f434bc8a92f792bdb350c807968b2ac14cfc04b203", + "version": "1.3", + "find_args": "MODULE", + "options": [ + "OPUS_BUILD_TESTING OFF", + "OPUS_BUILD_PROGRAMS OFF", + "OPUS_INSTALL_PKG_CONFIG_MODULE OFF", + "OPUS_INSTALL_CMAKE_CONFIG_MODULE OFF" + ] + }, + "discord-rpc": { + "repo": "discord/discord-rpc", + "sha": "963aa9f3e5", + "hash": "386e1344e9a666d730f2d335ee3aef1fd05b1039febefd51aa751b705009cc764411397f3ca08dffd46205c72f75b235c870c737b2091a4ed0c3b061f5919bde", + "options": [ + "BUILD_EXAMPLES OFF" + ], + "patches": [ + "0001-cmake-version.patch", + "0002-no-clang-format.patch", + "0003-fix-cpp17.patch" + ] + }, +} +``` + +## Inclusion + +To include CPMUtil: + +```cmake +include(CPMUtil) +``` + +## Lists + +CPMUtil will create three lists of dependencies where `AddPackage` or similar was used. Each is in order of addition. + +- `CPM_PACKAGE_NAMES`: The names of packages included by CPMUtil +- `CPM_PACKAGE_URLS`: The URLs to project/repo pages of packages +- `CPM_PACKAGE_SHAS`: Short version identifiers for each package + * If the package was included as a system package, ` (system)` is appended thereafter + * Packages whose versions can't be deduced will be left as `unknown`. + +For an example of how this might be implemented in an application, see Eden's implementation: + +- [`dep_hashes.h.in`](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/src/dep_hashes.h.in) +- [`GenerateDepHashes.cmake`](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CMakeModules/GenerateDepHashes.cmake) +- [`deps_dialog.cpp`](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/src/yuzu/deps_dialog.cpp) \ No newline at end of file diff --git a/docs/README.md b/docs/README.md index 686cfe8ea0..f7f795ac23 100644 --- a/docs/README.md +++ b/docs/README.md @@ -5,6 +5,6 @@ This contains documentation created by developers. This contains build instructi - **[General Build Instructions](Build.md)** - **[Development Guidelines](Development.md)** - **[Dependencies](Deps.md)** -- **[CPM - CMake Package Manager](CPMUtil.md)** +- **[CMake Dependency Management](CPM.md)** - **[Platform-Specific Caveats](Caveats.md)** -- **[User Handbook](User.md)** \ No newline at end of file +- **[User Handbook](User.md)** diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt index 434e6fb100..c071de0b8a 100644 --- a/externals/CMakeLists.txt +++ b/externals/CMakeLists.txt @@ -398,3 +398,36 @@ if (ARCHITECTURE_arm64 AND NOT TARGET sse2neon) add_library(sse2neon INTERFACE) target_include_directories(sse2neon INTERFACE sse2neon) endif() + +# MoltenVK +if (APPLE) + find_library(MOLTENVK_LIBRARY MoltenVK) + + if (NOT MOLTENVK_LIBRARY OR YUZU_USE_BUNDLED_MOLTENVK) + message(STATUS "Using bundled MoltenVK") + AddJsonPackage(moltenvk) + + # TODO: is this portable? + set(MVK_STATIC "${moltenvk_SOURCE_DIR}/MoltenVK/static/MoltenVK.xcframework/macos-arm64_x86_64/libMoltenVK.a") + set(MVK_DYLIB "${moltenvk_SOURCE_DIR}/MoltenVK/dylib/${platform}/libMoltenVK.dylib") + + # prefer static lib if it exists for smaller executable size + if (EXISTS "${MVK_STATIC}") + # Using static MoltenVK requires linking to a few Apple frameworks + find_library(IOSURFACE_LIBRARY IOSurface REQUIRED) + find_library(QUARTZCORE_LIBRARY QuartzCore REQUIRED) + + add_library(MoltenVK::MoltenVK STATIC IMPORTED GLOBAL) + set_target_properties(MoltenVK::MoltenVK PROPERTIES + IMPORTED_LOCATION "${MVK_STATIC}" + ) + + target_link_libraries(MoltenVK::MoltenVK INTERFACE ${IOSURFACE_LIBRARY} ${QUARTZCORE_LIBRARY}) + else() + add_library(MoltenVK::MoltenVK SHARED IMPORTED GLOBAL) + set_target_properties(MoltenVK::MoltenVK PROPERTIES + IMPORTED_LOCATION "${MVK_DYLIB}" + ) + endif() + endif() +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/cpmfile.json b/externals/cpmfile.json index dde8c22d5f..a1fcbd4090 100644 --- a/externals/cpmfile.json +++ b/externals/cpmfile.json @@ -198,5 +198,12 @@ "key": "steamdeck", "bundled": true, "skip_updates": "true" + }, + "moltenvk": { + "repo": "KhronosGroup/MoltenVK", + "tag": "v%VERSION%", + "git_version": "1.4.0", + "artifact": "MoltenVK-macOS.tar", + "hash": "63721377503bbfaa9c8df79e7ebc3dc43577d38fa0f4a986c50a56a3904f9629b4cf9001d9c95c184228b574cd06608ff29ab89c14549cb6be8a7fb9cbe1e95a" } } diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 96ea429e5a..dcc70c9ac7 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -276,4 +276,13 @@ if(YUZU_USE_PRECOMPILED_HEADERS) target_precompile_headers(common PRIVATE precompiled_headers.h) endif() +# IOPS (needed for power state) requires linking to IOKit +if (APPLE) + find_library(IOKIT_LIBRARY IOKit) + if(NOT IOKIT_LIBRARY) + message(FATAL_ERROR "IOKit not found, did you install XCode tools?") + endif() + target_link_libraries(common PRIVATE ${IOKIT_LIBRARY}) +endif() + create_target_directory_groups(common) diff --git a/src/dynarmic/CMakeLists.txt b/src/dynarmic/CMakeLists.txt index 6b3308fb54..6661e94d47 100644 --- a/src/dynarmic/CMakeLists.txt +++ b/src/dynarmic/CMakeLists.txt @@ -39,7 +39,7 @@ 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") + message(STATUS "[dynarmic] Defaulting to a Release build") endif() # Set hard requirements for C++ @@ -58,11 +58,9 @@ endif() list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/CMakeModules") # Arch detection -include(DetectArchitecture) if (NOT DEFINED ARCHITECTURE) - message(FATAL_ERROR "Unsupported architecture encountered. Ending CMake generation.") + message(FATAL_ERROR "[dynarmic] Unsupported architecture encountered. Ending CMake generation.") endif() -message(STATUS "Target architecture: ${ARCHITECTURE}") # Compiler flags if (MSVC) @@ -144,7 +142,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/DetectArchitecture.cmake b/src/dynarmic/CMakeModules/DetectArchitecture.cmake deleted file mode 100644 index 28bd1ef263..0000000000 --- a/src/dynarmic/CMakeModules/DetectArchitecture.cmake +++ /dev/null @@ -1,62 +0,0 @@ -include(CheckSymbolExists) - -if (CMAKE_OSX_ARCHITECTURES) - set(DYNARMIC_MULTIARCH_BUILD 1) - set(ARCHITECTURE "${CMAKE_OSX_ARCHITECTURES}") - return() -endif() - -function(detect_architecture symbol arch) - if (NOT DEFINED ARCHITECTURE) - set(CMAKE_REQUIRED_QUIET YES) - check_symbol_exists("${symbol}" "" DETECT_ARCHITECTURE_${arch}) - unset(CMAKE_REQUIRED_QUIET) - - if (DETECT_ARCHITECTURE_${arch}) - set(ARCHITECTURE "${arch}" PARENT_SCOPE) - endif() - - unset(DETECT_ARCHITECTURE_${arch} CACHE) - endif() -endfunction() - -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("__ppc64__" ppc64) -detect_architecture("__powerpc64__" 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) diff --git a/src/dynarmic/CMakeModules/TargetArchitectureSpecificSources.cmake b/src/dynarmic/CMakeModules/TargetArchitectureSpecificSources.cmake index f08911c6f2..1a2dbc1326 100644 --- a/src/dynarmic/CMakeModules/TargetArchitectureSpecificSources.cmake +++ b/src/dynarmic/CMakeModules/TargetArchitectureSpecificSources.cmake @@ -1,5 +1,5 @@ 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/src/dynarmic/CMakeLists.txt b/src/dynarmic/src/dynarmic/CMakeLists.txt index 8aa0f41afa..3932496436 100644 --- a/src/dynarmic/src/dynarmic/CMakeLists.txt +++ b/src/dynarmic/src/dynarmic/CMakeLists.txt @@ -313,7 +313,7 @@ elseif (APPLE) message(WARNING "macOS fastmem disabled: unable to find mach/mach_exc.defs") target_sources(dynarmic PRIVATE backend/exception_handler_generic.cpp) else() - message(STATUS "mach/mach_exc.defs location: ${MACH_EXC_DEFS_DIR}") + message(STATUS "[dynarmic] mach/mach_exc.defs location: ${MACH_EXC_DEFS_DIR}") execute_process( COMMAND mkdir -p "${CMAKE_CURRENT_SOURCE_DIR}/backend/x64/mig" diff --git a/src/dynarmic/tests/CMakeLists.txt b/src/dynarmic/tests/CMakeLists.txt index df90168a52..27d9f0af33 100644 --- a/src/dynarmic/tests/CMakeLists.txt +++ b/src/dynarmic/tests/CMakeLists.txt @@ -57,7 +57,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 c03f7a3abf..31f73928fd 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt @@ -366,18 +366,19 @@ 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.3.0") - download_moltenvk(${MOLTENVK_PLATFORM} ${MOLTENVK_VERSION}) - endif() - find_library(MOLTENVK_LIBRARY MoltenVK REQUIRED) - message(STATUS "Using MoltenVK at ${MOLTENVK_LIBRARY}.") - set_source_files_properties(${MOLTENVK_LIBRARY} PROPERTIES MACOSX_PACKAGE_LOCATION Frameworks - XCODE_FILE_ATTRIBUTES "CodeSignOnCopy") - target_sources(yuzu PRIVATE ${MOLTENVK_LIBRARY}) + if (TARGET MoltenVK::MoltenVK) + target_link_libraries(yuzu PRIVATE MoltenVK::MoltenVK) + else() + find_library(MOLTENVK_LIBRARY MoltenVK) + message(STATUS "Using MoltenVK at ${MOLTENVK_LIBRARY}.") + set_source_files_properties(${MOLTENVK_LIBRARY} PROPERTIES MACOSX_PACKAGE_LOCATION Frameworks + XCODE_FILE_ATTRIBUTES "CodeSignOnCopy") -elseif(WIN32) + target_sources(yuzu PRIVATE "${MOLTENVK_LIBRARY}") + endif() +endif() + +if(WIN32) # compile as a win32 gui application instead of a console application target_link_libraries(yuzu PRIVATE Qt6::EntryPointPrivate) if(MSVC) diff --git a/tools/cpm/download.sh b/tools/cpm/download.sh index 426f1f51e6..a930069463 100755 --- a/tools/cpm/download.sh +++ b/tools/cpm/download.sh @@ -16,6 +16,7 @@ download_package() { LOWER_PACKAGE=$(echo "$PACKAGE_NAME" | tr '[:upper:]' '[:lower:]') OUTDIR="${CPM_SOURCE_CACHE}/${LOWER_PACKAGE}/${KEY}" + TMPDIR="$TMP/extracted" [ -d "$OUTDIR" ] && return curl "$DOWNLOAD" -sS -L -o "$OUTFILE" @@ -26,7 +27,8 @@ download_package() { mkdir -p "$OUTDIR" PREVDIR="$PWD" - cd "$OUTDIR" + mkdir -p "$TMPDIR" + cd "$TMPDIR" case "$FILENAME" in (*.7z) @@ -47,11 +49,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 diff --git a/tools/shellcheck.sh b/tools/shellcheck.sh index 719c717cf2..832b7496c7 100755 --- a/tools/shellcheck.sh +++ b/tools/shellcheck.sh @@ -1,6 +1,6 @@ #!/bin/sh -e -# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +# SPDX-FileCopyrightText: Copyright 2025 crueter # SPDX-License-Identifier: GPL-3.0-or-later # fd is slightly faster on NVMe (the syntax sux though) diff --git a/tools/update-cpm.sh b/tools/update-cpm.sh index 8bd8df2b83..6ca23fc2d6 100755 --- a/tools/update-cpm.sh +++ b/tools/update-cpm.sh @@ -1,6 +1,16 @@ #!/bin/sh -e -# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +# SPDX-FileCopyrightText: Copyright 2025 crueter # SPDX-License-Identifier: GPL-3.0-or-later -wget -O CMakeModules/CPM.cmake https://github.com/cpm-cmake/CPM.cmake/releases/latest/download/CPM.cmake +# updates CPMUtil, its docs, and related tools from the latest release + +if command -v zstd > /dev/null; then + EXT=tar.zst +else + EXT=tar.gz +fi + +wget "https://git.crueter.xyz/CMake/CPMUtil/releases/download/continuous/CPMUtil.$EXT" +tar xf "CPMUtil.$EXT" +rm "CPMUtil.$EXT"