From c34e3982ba40ca07f9658f6ee1d1ad147e5afcfb Mon Sep 17 00:00:00 2001 From: crueter Date: Tue, 7 Oct 2025 17:27:09 -0400 Subject: [PATCH] Update DetectArchitecture, CPM scripts/docs --- CMakeLists.txt | 8 +- CMakeModules/DetectArchitecture.cmake | 203 +++++++++++++++++++++----- 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, 204 insertions(+), 84 deletions(-) create mode 100644 docs/CPM.md delete mode 100644 docs/CPMUtil/AddCIPackage diff --git a/CMakeLists.txt b/CMakeLists.txt index f12cf5a29f..10a9374bbb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -81,14 +81,12 @@ endif() include(DetectArchitecture) +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(s): ${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; \ 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) - -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) +function(detect_architecture_symbols) + if (DEFINED ARCHITECTURE) + return() + endif() -detect_architecture("__i386" x86) -detect_architecture("__i386__" x86) -detect_architecture("_M_IX86" x86) + set(oneValueArgs ARCH) + set(multiValueArgs SYMBOLS) -detect_architecture("__ia64" ia64) -detect_architecture("__ia64__" ia64) -detect_architecture("_M_IA64" ia64) + cmake_parse_arguments(ARGS "" "${oneValueArgs}" "${multiValueArgs}" + "${ARGN}") -detect_architecture("__mips" mips) -detect_architecture("__mips__" mips) -detect_architecture("_M_MRX000" mips) + set(arch "${ARGS_ARCH}") + foreach(symbol ${ARGS_SYMBOLS}) + detect_architecture("${symbol}" "${arch}") -detect_architecture("__ppc64__" ppc64) -detect_architecture("__powerpc64__" ppc64) + 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("__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) + return() + endif() + endforeach() +endfunction() -detect_architecture("__riscv" riscv) +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() -detect_architecture("__EMSCRIPTEN__" wasm) + 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 b7b121532a..540a07e3ba 100644 --- a/docs/README.md +++ b/docs/README.md @@ -8,6 +8,6 @@ This contains documentation created by developers. This contains build instructi - **[Coding guidelines](Coding.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 4b5f3ef013..93c6338498 100644 --- a/externals/CMakeLists.txt +++ b/externals/CMakeLists.txt @@ -413,10 +413,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}") @@ -424,25 +425,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 271aaf6c4d..2c69c96641 100644 --- a/src/dynarmic/CMakeLists.txt +++ b/src/dynarmic/CMakeLists.txt @@ -53,7 +53,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) @@ -118,7 +117,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 0db869a65c..6c305ed29d 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt @@ -366,18 +366,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