From a13b6a9694a174c4056fca09e941e2d5bf98a703 Mon Sep 17 00:00:00 2001 From: crueter Date: Tue, 7 Oct 2025 13:10:12 -0400 Subject: [PATCH 1/5] WIP: [cmake] allow static MoltenVK, fix IOKit link Signed-off-by: crueter --- CMakeModules/DownloadExternals.cmake | 42 +++++++++++++++++++++++++--- src/common/CMakeLists.txt | 9 ++++++ src/yuzu/CMakeLists.txt | 26 +++++++++-------- 3 files changed, 62 insertions(+), 15 deletions(-) diff --git a/CMakeModules/DownloadExternals.cmake b/CMakeModules/DownloadExternals.cmake index f6e3aaa4ad..90336b193b 100644 --- a/CMakeModules/DownloadExternals.cmake +++ b/CMakeModules/DownloadExternals.cmake @@ -238,7 +238,7 @@ function(download_qt target) set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} PARENT_SCOPE) endfunction() -function(download_moltenvk version platform) +function(download_moltenvk platform version) if(NOT version) message(FATAL_ERROR "download_moltenvk: version argument is required") endif() @@ -249,12 +249,17 @@ function(download_moltenvk version platform) set(MOLTENVK_DIR "${CMAKE_BINARY_DIR}/externals/MoltenVK") set(MOLTENVK_TAR "${CMAKE_BINARY_DIR}/externals/MoltenVK.tar") + message(STATUS "Using bundled MoltenVK") + if(NOT EXISTS "${MOLTENVK_DIR}") if(NOT EXISTS "${MOLTENVK_TAR}") + message(STATUS "Downloading MoltenVK ${version}") file(DOWNLOAD "https://github.com/KhronosGroup/MoltenVK/releases/download/${version}/MoltenVK-${platform}.tar" "${MOLTENVK_TAR}" SHOW_PROGRESS) endif() + message(STATUS "Extracting MoltenVK tarball at ${MOLTENVK_TAR}") + execute_process( COMMAND ${CMAKE_COMMAND} -E tar xf "${MOLTENVK_TAR}" WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/externals" @@ -265,7 +270,36 @@ function(download_moltenvk version platform) 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() + # TODO: is this portable? + set(MVK_STATIC "${MOLTENVK_DIR}/MoltenVK/static/MoltenVK.xcframework/macos-arm64_x86_64/libMoltenVK.a") + set(MVK_DYLIB "${MOLTENVK_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 extra libraries + find_library(IOSURFACE_LIBRARY IOSurface) + if(NOT IOSURFACE_LIBRARY) + message(FATAL_ERROR "IOSurface not found, did you install XCode tools?") + endif() + + find_library(QUARTZCORE_LIBRARY QuartzCore) + if(NOT QUARTZCORE_LIBRARY) + message(FATAL_ERROR "QuartzCore not found, did you install XCode tools?") + endif() + + add_library(moltenvk STATIC IMPORTED) + set_target_properties(moltenvk PROPERTIES + IMPORTED_LOCATION "${MVK_STATIC}" + ) + + target_link_libraries(moltenvk INTERFACE ${IOSURFACE_LIBRARY} ${QUARTZCORE_LIBRARY}) + else() + add_library(moltenvk SHARED IMPORTED) + set_target_properties(moltenvk PROPERTIES + IMPORTED_LOCATION "${MVK_DYLIB}" + ) + endif() + + add_library(MoltenVK::MoltenVK ALIAS moltenvk) +endfunction() diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 21f2ab4ed4..b4120c4e46 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -274,4 +274,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/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index e86f007cce..3625657f09 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt @@ -367,18 +367,22 @@ 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}) + find_library(MOLTENVK_LIBRARY MoltenVK) -elseif(WIN32) + if (NOT MOLTENVK_LIBRARY OR YUZU_USE_BUNDLED_MOLTENVK) + set(MOLTENVK_PLATFORM "macos") + set(MOLTENVK_VERSION "v1.4.0") + download_moltenvk(${MOLTENVK_PLATFORM} ${MOLTENVK_VERSION}) + target_link_libraries(yuzu PRIVATE MoltenVK::MoltenVK) + else() + message(STATUS "Using MoltenVK at ${MOLTENVK_LIBRARY}.") + set_source_files_properties(${MOLTENVK_LIBRARY} PROPERTIES MACOSX_PACKAGE_LOCATION Frameworks + XCODE_FILE_ATTRIBUTES "CodeSignOnCopy") + target_link_libraries(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) From da0a031f06ee9330462cd3c7bab7072138ce7d03 Mon Sep 17 00:00:00 2001 From: crueter Date: Tue, 7 Oct 2025 17:10:37 -0400 Subject: [PATCH 2/5] CMake reorg, use my updated modules, CI vvl Signed-off-by: crueter --- CMakeLists.txt | 79 ++------- .../DetectArchitecture.cmake | 46 ++++- ...wnloadExternals.cmake => DownloadQt.cmake} | 122 ------------- CMakeModules/GetSCMRev.cmake | 75 +++++--- cpmfile.json | 8 + externals/CMakeLists.txt | 40 +++++ .../GetGitRevisionDescription.cmake | 162 ------------------ .../GetGitRevisionDescription.cmake.in | 45 ----- externals/cpmfile.json | 7 + src/dynarmic/CMakeLists.txt | 11 +- .../TargetArchitectureSpecificSources.cmake | 2 +- src/dynarmic/src/dynarmic/CMakeLists.txt | 2 +- src/dynarmic/tests/CMakeLists.txt | 2 +- 13 files changed, 174 insertions(+), 427 deletions(-) rename {src/dynarmic/CMakeModules => CMakeModules}/DetectArchitecture.cmake (56%) rename CMakeModules/{DownloadExternals.cmake => DownloadQt.cmake} (61%) delete mode 100644 externals/cmake-modules/GetGitRevisionDescription.cmake delete mode 100644 externals/cmake-modules/GetGitRevisionDescription.cmake.in diff --git a/CMakeLists.txt b/CMakeLists.txt index c0c117fcf1..7828a993e6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,7 +35,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 @@ -80,36 +79,7 @@ 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) - 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() +include(DetectArchitecture) if (NOT DEFINED ARCHITECTURE) set(ARCHITECTURE "GENERIC") @@ -117,7 +87,7 @@ if (NOT DEFINED ARCHITECTURE) add_definitions(-DARCHITECTURE_GENERIC=1) endif() -message(STATUS "Target architecture: ${ARCHITECTURE}") +message(STATUS "Target architecture(s): ${ARCHITECTURE}") if (MSVC AND ARCHITECTURE_x86) message(FATAL_ERROR "Attempting to build with the x86 environment is not supported. \ @@ -150,7 +120,8 @@ endif() set(CPM_SOURCE_CACHE ${CMAKE_SOURCE_DIR}/.cache/cpm) -include(DownloadExternals) +include(DownloadQt) +include(CPMUtil) include(CMakeDependentOption) include(CTest) @@ -217,6 +188,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) @@ -227,8 +199,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) @@ -287,29 +261,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() - # We need to downgrade debug info (/Zi -> /Z7) to use an older but more cacheable format # See https://github.com/nanoant/CMakePCHCompiler/issues/21 if(WIN32 AND (CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")) @@ -429,8 +388,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) @@ -716,17 +673,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/src/dynarmic/CMakeModules/DetectArchitecture.cmake b/CMakeModules/DetectArchitecture.cmake similarity index 56% rename from src/dynarmic/CMakeModules/DetectArchitecture.cmake rename to CMakeModules/DetectArchitecture.cmake index 28bd1ef263..09a56ae283 100644 --- a/src/dynarmic/CMakeModules/DetectArchitecture.cmake +++ b/CMakeModules/DetectArchitecture.cmake @@ -1,22 +1,56 @@ +# 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 +- mips +- ppc64 +- ppc +- riscv +- wasm + +This file is based off of Yuzu and Dynarmic. +TODO: add SPARC +]] include(CheckSymbolExists) +# 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(DYNARMIC_MULTIARCH_BUILD 1) + 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() function(detect_architecture symbol arch) if (NOT DEFINED ARCHITECTURE) - set(CMAKE_REQUIRED_QUIET YES) - check_symbol_exists("${symbol}" "" DETECT_ARCHITECTURE_${arch}) + set(CMAKE_REQUIRED_QUIET 1) + check_symbol_exists("${symbol}" "" ARCHITECTURE_${arch}) unset(CMAKE_REQUIRED_QUIET) - if (DETECT_ARCHITECTURE_${arch}) + if (ARCHITECTURE_${arch}) set(ARCHITECTURE "${arch}" PARENT_SCOPE) + set(ARCHITECTURE_${arch} 1 PARENT_SCOPE) + add_definitions(-DARCHITECTURE_${arch}=1) endif() - - unset(DETECT_ARCHITECTURE_${arch} CACHE) endif() endfunction() diff --git a/CMakeModules/DownloadExternals.cmake b/CMakeModules/DownloadQt.cmake similarity index 61% rename from CMakeModules/DownloadExternals.cmake rename to CMakeModules/DownloadQt.cmake index 90336b193b..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,69 +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 platform version) - 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") - - message(STATUS "Using bundled MoltenVK") - - if(NOT EXISTS "${MOLTENVK_DIR}") - if(NOT EXISTS "${MOLTENVK_TAR}") - message(STATUS "Downloading MoltenVK ${version}") - file(DOWNLOAD "https://github.com/KhronosGroup/MoltenVK/releases/download/${version}/MoltenVK-${platform}.tar" - "${MOLTENVK_TAR}" SHOW_PROGRESS) - endif() - - message(STATUS "Extracting MoltenVK tarball at ${MOLTENVK_TAR}") - - 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() - - # TODO: is this portable? - set(MVK_STATIC "${MOLTENVK_DIR}/MoltenVK/static/MoltenVK.xcframework/macos-arm64_x86_64/libMoltenVK.a") - set(MVK_DYLIB "${MOLTENVK_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 extra libraries - find_library(IOSURFACE_LIBRARY IOSurface) - if(NOT IOSURFACE_LIBRARY) - message(FATAL_ERROR "IOSurface not found, did you install XCode tools?") - endif() - - find_library(QUARTZCORE_LIBRARY QuartzCore) - if(NOT QUARTZCORE_LIBRARY) - message(FATAL_ERROR "QuartzCore not found, did you install XCode tools?") - endif() - - add_library(moltenvk STATIC IMPORTED) - set_target_properties(moltenvk PROPERTIES - IMPORTED_LOCATION "${MVK_STATIC}" - ) - - target_link_libraries(moltenvk INTERFACE ${IOSURFACE_LIBRARY} ${QUARTZCORE_LIBRARY}) - else() - add_library(moltenvk SHARED IMPORTED) - set_target_properties(moltenvk PROPERTIES - IMPORTED_LOCATION "${MVK_DYLIB}" - ) - endif() - - add_library(MoltenVK::MoltenVK ALIAS moltenvk) -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 abb80c1dd7..b9f393d15a 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/externals/CMakeLists.txt b/externals/CMakeLists.txt index 43778118d8..fae7b48aad 100644 --- a/externals/CMakeLists.txt +++ b/externals/CMakeLists.txt @@ -405,3 +405,43 @@ 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") + + # TODO: is this portable? + set(MVK_STATIC "${MOLTENVK_DIR}/MoltenVK/static/MoltenVK.xcframework/macos-arm64_x86_64/libMoltenVK.a") + set(MVK_DYLIB "${MOLTENVK_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) + 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) + set_target_properties(MoltenVK::MoltenVK PROPERTIES + IMPORTED_LOCATION "${MVK_DYLIB}" + ) + endif() + + target_link_libraries(yuzu PRIVATE MoltenVK::MoltenVK) + else() + 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 ${MOLTENVK_LIBRARY}) + 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 6056a5be24..9a974e0d52 100644 --- a/externals/cpmfile.json +++ b/externals/cpmfile.json @@ -210,5 +210,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/dynarmic/CMakeLists.txt b/src/dynarmic/CMakeLists.txt index e5345ef458..f288833359 100644 --- a/src/dynarmic/CMakeLists.txt +++ b/src/dynarmic/CMakeLists.txt @@ -35,7 +35,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++ @@ -54,11 +54,10 @@ 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}") +message(STATUS "[dynarmic] Target architecture(s): ${ARCHITECTURE}") # Compiler flags if (MSVC) @@ -143,8 +142,8 @@ else() endif() endif() -find_package(Boost 1.57 REQUIRED) -find_package(fmt 9 CONFIG) +find_package(Boost 1.57 CONFIG REQUIRED) +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..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 f21000044e..34fcbe3762 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 From 359720fa994510de1fb6c3ad87c26cd2c14ea17d Mon Sep 17 00:00:00 2001 From: crueter Date: Tue, 7 Oct 2025 17:27:09 -0400 Subject: [PATCH 3/5] Update DetectArchitecture, CPM scripts/docs --- CMakeLists.txt | 10 +- CMakeModules/DetectArchitecture.cmake | 199 +++++++++++++++++++++----- docs/CPM.md | 14 ++ docs/CPMUtil/AddCIPackage | 17 --- docs/README.md | 2 +- externals/CMakeLists.txt | 17 +-- src/dynarmic/CMakeLists.txt | 3 +- src/yuzu/CMakeLists.txt | 11 +- tools/cpm/download.sh | 13 +- 9 files changed, 203 insertions(+), 83 deletions(-) create mode 100644 docs/CPM.md delete mode 100644 docs/CPMUtil/AddCIPackage diff --git a/CMakeLists.txt b/CMakeLists.txt index 7828a993e6..07799fc99c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -81,13 +81,11 @@ endif() include(DetectArchitecture) -if (NOT DEFINED ARCHITECTURE) - set(ARCHITECTURE "GENERIC") - set(ARCHITECTURE_GENERIC 1) - add_definitions(-DARCHITECTURE_GENERIC=1) -endif() +DetectArchitecture() -message(STATUS "Target architecture(s): ${ARCHITECTURE}") +if (NOT DEFINED ARCHITECTURE) + message(FATAL_ERROR "Architecture didn't make it out of scope, did you delete DetectArchitecture.cmake?") +endif() if (MSVC AND ARCHITECTURE_x86) message(FATAL_ERROR "Attempting to build with the x86 environment is not supported. \ diff --git a/CMakeModules/DetectArchitecture.cmake b/CMakeModules/DetectArchitecture.cmake index 09a56ae283..b9194a8037 100644 --- a/CMakeModules/DetectArchitecture.cmake +++ b/CMakeModules/DetectArchitecture.cmake @@ -10,16 +10,24 @@ adds compile definitions thereof. Namely: - 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. -TODO: add SPARC ]] -include(CheckSymbolExists) # multiarch builds are a special case and also very difficult # this is what I have for now, but it's not ideal @@ -40,13 +48,18 @@ if (CMAKE_OSX_ARCHITECTURES) 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}" "" ARCHITECTURE_${arch}) + check_symbol_exists("${symbol}" "" SYMBOL_EXISTS) unset(CMAKE_REQUIRED_QUIET) - if (ARCHITECTURE_${arch}) + if (SYMBOL_EXISTS) set(ARCHITECTURE "${arch}" PARENT_SCOPE) set(ARCHITECTURE_${arch} 1 PARENT_SCOPE) add_definitions(-DARCHITECTURE_${arch}=1) @@ -54,43 +67,159 @@ function(detect_architecture symbol arch) endif() endfunction() -detect_architecture("__ARM64__" arm64) -detect_architecture("__aarch64__" arm64) -detect_architecture("_M_ARM64" arm64) +function(detect_architecture_symbols) + if (DEFINED ARCHITECTURE) + return() + endif() -detect_architecture("__arm__" arm) -detect_architecture("__TARGET_ARCH_ARM" arm) -detect_architecture("_M_ARM" arm) + set(oneValueArgs ARCH) + set(multiValueArgs SYMBOLS) -detect_architecture("__x86_64" x86_64) -detect_architecture("__x86_64__" x86_64) -detect_architecture("__amd64" x86_64) -detect_architecture("_M_X64" x86_64) + cmake_parse_arguments(ARGS "" "${oneValueArgs}" "${multiValueArgs}" + "${ARGN}") -detect_architecture("__i386" x86) -detect_architecture("__i386__" x86) -detect_architecture("_M_IX86" x86) + set(arch "${ARGS_ARCH}") + foreach(symbol ${ARGS_SYMBOLS}) + detect_architecture("${symbol}" "${arch}") -detect_architecture("__ia64" ia64) -detect_architecture("__ia64__" ia64) -detect_architecture("_M_IA64" ia64) + 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) -detect_architecture("__mips" mips) -detect_architecture("__mips__" mips) -detect_architecture("_M_MRX000" mips) + return() + endif() + endforeach() +endfunction() -detect_architecture("__ppc64__" ppc64) -detect_architecture("__powerpc64__" ppc64) +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("__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_symbols( + ARCH arm64 + SYMBOLS + "__ARM64__" + "__aarch64__" + "_M_ARM64") -detect_architecture("__riscv" riscv) + detect_architecture_symbols( + ARCH x86_64 + SYMBOLS + "__x86_64" + "__x86_64__" + "__amd64" + "_M_X64" + "_M_AMD64") -detect_architecture("__EMSCRIPTEN__" wasm) + # 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/docs/CPM.md b/docs/CPM.md new file mode 100644 index 0000000000..53cdfaebcf --- /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) or [locally](./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/AddCIPackage b/docs/CPMUtil/AddCIPackage deleted file mode 100644 index 559db69ea9..0000000000 --- a/docs/CPMUtil/AddCIPackage +++ /dev/null @@ -1,17 +0,0 @@ -# AddPackage - -- `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` \ No newline at end of file diff --git a/docs/README.md b/docs/README.md index 9ce0857563..91055808c9 100644 --- a/docs/README.md +++ b/docs/README.md @@ -7,6 +7,6 @@ This contains documentation created by developers. This contains build instructi - **[Development Guidelines](Development.md)** - **[Dependencies](Deps.md)** - **[Debug Guidelines](./Debug.md)** -- **[CPM - CMake Package Manager](CPMUtil.md)** +- **[CMake Dependency Management](CPM.md)** - **[Platform-Specific Caveats](Caveats.md)** - **[User Handbook](User.md)** diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt index fae7b48aad..f55ebeb1c1 100644 --- a/externals/CMakeLists.txt +++ b/externals/CMakeLists.txt @@ -412,10 +412,11 @@ if (APPLE) if (NOT MOLTENVK_LIBRARY OR YUZU_USE_BUNDLED_MOLTENVK) message(STATUS "Using bundled MoltenVK") + AddJsonPackage(moltenvk) # TODO: is this portable? - set(MVK_STATIC "${MOLTENVK_DIR}/MoltenVK/static/MoltenVK.xcframework/macos-arm64_x86_64/libMoltenVK.a") - set(MVK_DYLIB "${MOLTENVK_DIR}/MoltenVK/dylib/${platform}/libMoltenVK.dylib") + 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}") @@ -423,25 +424,17 @@ if (APPLE) find_library(IOSURFACE_LIBRARY IOSurface REQUIRED) find_library(QUARTZCORE_LIBRARY QuartzCore REQUIRED) - add_library(MoltenVK::MoltenVK STATIC IMPORTED) + 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) + add_library(MoltenVK::MoltenVK SHARED IMPORTED GLOBAL) set_target_properties(MoltenVK::MoltenVK PROPERTIES IMPORTED_LOCATION "${MVK_DYLIB}" ) endif() - - target_link_libraries(yuzu PRIVATE MoltenVK::MoltenVK) - else() - 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 ${MOLTENVK_LIBRARY}) endif() endif() diff --git a/src/dynarmic/CMakeLists.txt b/src/dynarmic/CMakeLists.txt index f288833359..351e622995 100644 --- a/src/dynarmic/CMakeLists.txt +++ b/src/dynarmic/CMakeLists.txt @@ -57,7 +57,6 @@ list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/CMakeModules") if (NOT DEFINED ARCHITECTURE) message(FATAL_ERROR "[dynarmic] Unsupported architecture encountered. Ending CMake generation.") endif() -message(STATUS "[dynarmic] Target architecture(s): ${ARCHITECTURE}") # Compiler flags if (MSVC) @@ -142,7 +141,7 @@ else() endif() endif() -find_package(Boost 1.57 CONFIG REQUIRED) +find_package(Boost 1.57 REQUIRED) find_package(fmt 8 CONFIG) # Pull in externals CMakeLists for libs where available diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index 3625657f09..86b4a6909b 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt @@ -367,18 +367,15 @@ 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) - find_library(MOLTENVK_LIBRARY MoltenVK) - - if (NOT MOLTENVK_LIBRARY OR YUZU_USE_BUNDLED_MOLTENVK) - set(MOLTENVK_PLATFORM "macos") - set(MOLTENVK_VERSION "v1.4.0") - download_moltenvk(${MOLTENVK_PLATFORM} ${MOLTENVK_VERSION}) + 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") - target_link_libraries(yuzu PRIVATE ${MOLTENVK_LIBRARY}) + + target_sources(yuzu PRIVATE "${MOLTENVK_LIBRARY}") endif() endif() diff --git a/tools/cpm/download.sh b/tools/cpm/download.sh index 315f01d54b..68f1eb4040 100755 --- a/tools/cpm/download.sh +++ b/tools/cpm/download.sh @@ -13,6 +13,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" @@ -23,7 +24,8 @@ download_package() { mkdir -p "$OUTDIR" PREVDIR="$PWD" - cd "$OUTDIR" + mkdir -p "$TMPDIR" + cd "$TMPDIR" case "$FILENAME" in (*.7z) @@ -44,11 +46,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 From a60f59810eefe1970168766750a39fa905eb84bf Mon Sep 17 00:00:00 2001 From: crueter Date: Wed, 15 Oct 2025 16:06:31 -0400 Subject: [PATCH 4/5] [cmake] do not allow static moltenVK Conflicts with sys moltenvk Signed-off-by: crueter --- externals/CMakeLists.txt | 23 +++++------------------ src/yuzu/CMakeLists.txt | 1 + 2 files changed, 6 insertions(+), 18 deletions(-) diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt index f55ebeb1c1..e508920d61 100644 --- a/externals/CMakeLists.txt +++ b/externals/CMakeLists.txt @@ -414,27 +414,14 @@ if (APPLE) 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 SHARED IMPORTED) + set_target_properties(moltenvk PROPERTIES + IMPORTED_LOCATION "${MVK_DYLIB}" + ) - 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() + add_library(MoltenVK::MoltenVK ALIAS moltenvk) endif() endif() diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index 86b4a6909b..79a1ecaa23 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt @@ -376,6 +376,7 @@ if (APPLE) XCODE_FILE_ATTRIBUTES "CodeSignOnCopy") target_sources(yuzu PRIVATE "${MOLTENVK_LIBRARY}") + target_link_libraries(yuzu PRIVATE "${MOLTENVK_LIBRARY}") endif() endif() From 13ada189ccee5b46dabc5f9d4561797e6d7b0332 Mon Sep 17 00:00:00 2001 From: crueter Date: Tue, 21 Oct 2025 23:00:59 -0400 Subject: [PATCH 5/5] fix license Signed-off-by: crueter --- .ci/license-header.sh | 2 +- .../CMakeModules/TargetArchitectureSpecificSources.cmake | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.ci/license-header.sh b/.ci/license-header.sh index 874f29aa45..73712108df 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 sse2neon.h renderdoc_app.h tools/cpm tools/shellcheck.sh tools/update-cpm.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 DetectArchitecture.cmake sse2neon.h renderdoc_app.h tools/cpm tools/shellcheck.sh tools/update-cpm.sh externals/stb externals/glad externals/getopt externals/gamemode externals/FidelityFX-FSR externals/demangle externals/bc_decoder" # license header constants, please change when needed :)))) YEAR=2025 diff --git a/src/dynarmic/CMakeModules/TargetArchitectureSpecificSources.cmake b/src/dynarmic/CMakeModules/TargetArchitectureSpecificSources.cmake index 1a2dbc1326..7af6cc518b 100644 --- a/src/dynarmic/CMakeModules/TargetArchitectureSpecificSources.cmake +++ b/src/dynarmic/CMakeModules/TargetArchitectureSpecificSources.cmake @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +# SPDX-License-Identifier: GPL-3.0-or-later + function(target_architecture_specific_sources project arch) if (NOT MULTIARCH_BUILD) target_sources("${project}" PRIVATE ${ARGN})