diff --git a/CMakeLists.txt b/CMakeLists.txt index 5b0630c85d..4ac1456ba1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,13 +13,13 @@ set(CPM_SOURCE_CACHE ${CMAKE_SOURCE_DIR}/.cache/cpm) include(DetectPlatform) include(DetectArchitecture) include(DefaultConfig) -include(DownloadExternals) +include(UseLTO) +include(FasterLinker) +include(UseCcache) include(CMakeDependentOption) include(CTest) include(CPMUtil) -DetectArchitecture() - if (NOT DEFINED ARCHITECTURE) message(FATAL_ERROR "Architecture didn't make it out of scope, did you delete DetectArchitecture.cmake?") endif() @@ -41,6 +41,7 @@ if (PLATFORM_NETBSD) set(ENV{PKG_CONFIG_PATH} "${PKG_CONFIG_PATH}:${CMAKE_SYSROOT}/usr/pkg/lib/ffmpeg7/pkgconfig") endif() +# TODO: does mingw need any of this anymore # static stuff option(YUZU_STATIC_BUILD "Use static libraries and executables if available" OFF) @@ -150,10 +151,10 @@ cmake_dependent_option(YUZU_USE_BUNDLED_SDL2 "Download bundled SDL2 build" "${MS option(ENABLE_QT "Enable the Qt frontend" ON) option(ENABLE_QT_TRANSLATION "Enable translations for the Qt frontend" OFF) option(ENABLE_UPDATE_CHECKER "Enable update checker (for Qt and Android)" OFF) -cmake_dependent_option(YUZU_USE_BUNDLED_QT "Download bundled Qt binaries" "${MSVC}" "ENABLE_QT" OFF) option(YUZU_USE_QT_MULTIMEDIA "Use QtMultimedia for Camera" OFF) -option(YUZU_USE_QT_WEB_ENGINE "Use QtWebEngine for web applet implementation" OFF) +cmake_dependent_option(YUZU_USE_QT_WEB_ENGINE "Use QtWebEngine for web applet implementation" OFF "NOT YUZU_USE_BUNDLED_QT" OFF) set(YUZU_QT_MIRROR "" CACHE STRING "What mirror to use for downloading the bundled Qt libraries") +cmake_dependent_option(YUZU_USE_BUNDLED_QT "Download bundled Qt binaries" "${MSVC}" "ENABLE_QT" OFF) option(ENABLE_CUBEB "Enables the cubeb audio backend" ON) @@ -187,35 +188,6 @@ cmake_dependent_option(USE_DISCORD_PRESENCE "Enables Discord Rich Presence" OFF option(YUZU_TESTS "Compile tests" "${BUILD_TESTING}") -option(YUZU_ENABLE_LTO "Enable link-time optimization" OFF) -if(YUZU_ENABLE_LTO) - include(UseLTO) -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) - message(STATUS "Found ccache at: ${CCACHE_BINARY}") - set(CMAKE_C_COMPILER_LAUNCHER ${CCACHE_BINARY}) - set(CMAKE_CXX_COMPILER_LAUNCHER ${CCACHE_BINARY}) - else() - message(FATAL_ERROR "USE_CCACHE enabled, but no executable found at: ${CCACHE_PATH}") - endif() - # Follow SCCache recommendations: - # - if(WIN32) - if(CMAKE_BUILD_TYPE STREQUAL "Debug") - string(REPLACE "/Zi" "/Z7" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}") - string(REPLACE "/Zi" "/Z7" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}") - elseif(CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") - string(REPLACE "/Zi" "/Z7" CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}") - string(REPLACE "/Zi" "/Z7" CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}") - endif() - endif() -endif() - option(YUZU_DOWNLOAD_ANDROID_VVL "Download validation layer binary for android" ON) option(YUZU_LEGACY "Apply patches that improve compatibility with older GPUs (e.g. Snapdragon 865) at the cost of performance" OFF) @@ -230,8 +202,6 @@ cmake_dependent_option(YUZU_CRASH_DUMPS "Compile crash dump (Minidump) support" option(YUZU_DOWNLOAD_TIME_ZONE_DATA "Always download time zone binaries" ON) set(YUZU_TZDB_PATH "" CACHE STRING "Path to a pre-downloaded timezone database") -cmake_dependent_option(YUZU_USE_FASTER_LD "Check if a faster linker is available" ON "PLATFORM_LINUX" OFF) - cmake_dependent_option(YUZU_USE_BUNDLED_MOLTENVK "Download bundled MoltenVK lib" ON "APPLE" OFF) option(YUZU_DISABLE_LLVM "Disable LLVM (useful for CI)" OFF) @@ -260,7 +230,6 @@ if (ENABLE_OPENSSL) option(YUZU_USE_BUNDLED_OPENSSL "Download bundled OpenSSL build" ${DEFAULT_YUZU_USE_BUNDLED_OPENSSL}) endif() -# TODO(crueter): CPM this if (ANDROID AND YUZU_DOWNLOAD_ANDROID_VVL) AddJsonPackage(vulkan-validation-layers) @@ -362,6 +331,7 @@ if (PLATFORM_LINUX OR CXX_CLANG) endif() # Other presets, e.g. steamdeck +# TODO(crueter): Just have every Linux/Windows use old sdl2 set(YUZU_SYSTEM_PROFILE "generic" CACHE STRING "CMake and Externals profile to use. One of: generic, steamdeck") # Configure C++ standard @@ -541,10 +511,6 @@ elseif (WIN32) endif() elseif (PLATFORM_HAIKU) # Haiku is so special :) - # Some fucking genius decided to name an entire module "network" in 2019 - # this caused great disaster amongst the Haiku community who had came first with - # their "libnetwork.so"; since CMake doesn't do magic, we have to use an ABSOLUTE PATH - # to the library itself, otherwise it will think we are linking to... our network thing set(PLATFORM_LIBRARIES bsd /boot/system/lib/libnetwork.so) elseif (CMAKE_SYSTEM_NAME MATCHES "^(Linux|kFreeBSD|GNU|SunOS)$") set(PLATFORM_LIBRARIES rt) @@ -569,11 +535,6 @@ if (ARCHITECTURE_x86 OR ARCHITECTURE_x86_64) find_package(xbyak) endif() -if (ENABLE_WEB_SERVICE OR ENABLE_QT_UPDATE_CHECKER) - # Workaround: httplib will kill itself if you attempt to do a find_package propagation - # find_package(httplib CONFIG) -endif() - if (ENABLE_WEB_SERVICE OR ENABLE_UPDATE_CHECKER) find_package(cpp-jwt) endif() @@ -600,7 +561,7 @@ endif() if (ENABLE_QT) if (YUZU_USE_BUNDLED_QT) - download_qt(6.8.3) + AddQt(6.9.3) else() message(STATUS "Using system Qt") if (NOT Qt6_DIR) @@ -683,15 +644,16 @@ if (NOT (YUZU_USE_BUNDLED_FFMPEG OR YUZU_USE_EXTERNAL_FFMPEG)) endif() if (WIN32 AND YUZU_CRASH_DUMPS) - set(BREAKPAD_VER "breakpad-c89f9dd") - download_bundled_external("breakpad/" ${BREAKPAD_VER} "breakpad-win" BREAKPAD_PREFIX "c89f9dd") + message(STATUS "YUZU_CRASH_DUMPS is unimplemented on Windows. Check back later.") + # 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}") + # 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. @@ -725,16 +687,11 @@ if (MSVC AND CXX_CLANG) add_library(llvm-mingw-runtime STATIC IMPORTED) set_target_properties(llvm-mingw-runtime PROPERTIES - IMPORTED_LOCATION "${LIB_PATH}" - ) + IMPORTED_LOCATION "${LIB_PATH}") link_libraries(llvm-mingw-runtime) endif() -if (YUZU_USE_FASTER_LD) - include(FasterLinker) -endif() - # Set runtime library to MD/MDd for all configurations if(MSVC) set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>DLL") diff --git a/CMakeModules/CPM.cmake b/CMakeModules/CPM.cmake index 2d97f5493c..5544d8eefe 100644 --- a/CMakeModules/CPM.cmake +++ b/CMakeModules/CPM.cmake @@ -1,8 +1,3 @@ -# 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/CPMUtil.cmake b/CMakeModules/CPMUtil.cmake index 6f36871b92..31a9f10fb5 100644 --- a/CMakeModules/CPMUtil.cmake +++ b/CMakeModules/CPMUtil.cmake @@ -1,5 +1,5 @@ -# SPDX-FileCopyrightText: Copyright 2025 crueter -# SPDX-License-Identifier: GPL-3.0-or-later +# SPDX-FileCopyrightText: Copyright 2026 crueter +# SPDX-License-Identifier: LGPL-3.0-or-later set(CPM_SOURCE_CACHE "${PROJECT_SOURCE_DIR}/.cache/cpm" CACHE STRING "" FORCE) @@ -124,8 +124,7 @@ function(AddJsonPackage) PACKAGE ${package} EXTENSION ${extension} MIN_VERSION ${min_version} - DISABLED_PLATFORMS ${disabled_platforms} - ) + DISABLED_PLATFORMS ${disabled_platforms}) # pass stuff to parent scope set(${package}_ADDED "${${package}_ADDED}" @@ -223,8 +222,7 @@ function(AddJsonPackage) GIT_HOST ${git_host} ARTIFACT ${artifact} - TAG ${tag} - ) + TAG ${tag}) # pass stuff to parent scope set(${package}_ADDED "${${package}_ADDED}" @@ -280,8 +278,7 @@ function(AddPackage) KEY BUNDLED_PACKAGE FORCE_BUNDLED_PACKAGE - FIND_PACKAGE_ARGUMENTS - ) + FIND_PACKAGE_ARGUMENTS) set(multiValueArgs OPTIONS PATCHES) @@ -343,7 +340,7 @@ function(AddPackage) cpm_utils_message(FATAL_ERROR ${PKG_ARGS_NAME} "No URL or repository defined") endif() - cpm_utils_message(STATUS ${PKG_ARGS_NAME} "Download URL is ${pkg_url}") + cpm_utils_message(DEBUG ${PKG_ARGS_NAME} "Download URL is ${pkg_url}") if(NOT DEFINED PKG_ARGS_KEY) if(DEFINED PKG_ARGS_SHA) @@ -453,8 +450,7 @@ function(AddPackage) if(DEFINED PKG_ARGS_VERSION) list(APPEND EXTRA_ARGS - VERSION ${PKG_ARGS_VERSION} - ) + VERSION ${PKG_ARGS_VERSION}) endif() CPMAddPackage( @@ -471,8 +467,7 @@ function(AddPackage) ${EXTRA_ARGS} - ${PKG_ARGS_UNPARSED_ARGUMENTS} - ) + ${PKG_ARGS_UNPARSED_ARGUMENTS}) set_property(GLOBAL APPEND PROPERTY CPM_PACKAGE_NAMES ${PKG_ARGS_NAME}) set_property(GLOBAL APPEND PROPERTY CPM_PACKAGE_URLS ${pkg_git_url}) @@ -516,24 +511,6 @@ function(AddPackage) endfunction() -function(add_ci_package key) - set(ARTIFACT ${ARTIFACT_NAME}-${key}-${ARTIFACT_VERSION}.${ARTIFACT_EXT}) - - AddPackage( - NAME ${ARTIFACT_PACKAGE} - REPO ${ARTIFACT_REPO} - TAG v${ARTIFACT_VERSION} - GIT_VERSION ${ARTIFACT_VERSION} - ARTIFACT ${ARTIFACT} - - KEY ${key}-${ARTIFACT_VERSION} - HASH_SUFFIX sha512sum - FORCE_BUNDLED_PACKAGE ON - ) - - set(ARTIFACT_DIR ${${ARTIFACT_PACKAGE}_SOURCE_DIR} PARENT_SCOPE) -endfunction() - # TODO(crueter): we could do an AddMultiArchPackage, multiplatformpackage? # name is the artifact name, package is for find_package override function(AddCIPackage) @@ -543,12 +520,13 @@ function(AddCIPackage) REPO PACKAGE EXTENSION - MIN_VERSION - ) + MIN_VERSION) set(multiValueArgs DISABLED_PLATFORMS) - cmake_parse_arguments(PKG_ARGS "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + set(optionArgs MODULE) + + cmake_parse_arguments(PKG_ARGS "${optionArgs}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) if(NOT DEFINED PKG_ARGS_VERSION) message(FATAL_ERROR "[CPMUtil] VERSION is required") @@ -589,55 +567,73 @@ function(AddCIPackage) set(ARTIFACT_REPO ${PKG_ARGS_REPO}) set(ARTIFACT_PACKAGE ${PKG_ARGS_PACKAGE}) - if((MSVC AND ARCHITECTURE_x86_64) AND NOT "windows-amd64" IN_LIST DISABLED_PLATFORMS) - add_ci_package(windows-amd64) - endif() - - if((MSVC AND ARCHITECTURE_arm64) AND NOT "windows-arm64" IN_LIST DISABLED_PLATFORMS) - add_ci_package(windows-arm64) - endif() - - if((MINGW AND ARCHITECTURE_x86_64) AND NOT "mingw-amd64" IN_LIST DISABLED_PLATFORMS) - add_ci_package(mingw-amd64) - endif() - - if((MINGW AND ARCHITECTURE_arm64) AND NOT "mingw-arm64" IN_LIST DISABLED_PLATFORMS) - add_ci_package(mingw-arm64) - endif() + if(MSVC AND ARCHITECTURE_x86_64) + set(pkgname windows-amd64) + elseif(MSVC AND ARCHITECTURE_arm64) + set(pkgname windows-arm64) + elseif(MINGW AND ARCHITECTURE_x86_64) + set(pkgname mingw-amd64) + elseif(MINGW AND ARCHITECTURE_arm64) + set(pkgname mingw-arm64) + elseif(ANDROID AND ARCHITECTURE_x86_64) + set(pkgname android-x86_64) + elseif(ANDROID AND ARCHITECTURE_arm64) + set(pkgname android-aarch64) + elseif(PLATFORM_SUN) + set(pkgname solaris-amd64) + elseif(PLATFORM_FREEBSD) + set(pkgname freebsd-amd64) + elseif(PLATFORM_LINUX AND ARCHITECTURE_x86_64) + set(pkgname linux-amd64) + elseif(PLATFORM_LINUX AND ARCHITECTURE_arm64) + set(pkgname linux-aarch64) + elseif(APPLE) + set(pkgname macos-universal) + endif() + + if (DEFINED pkgname AND NOT "${pkgname}" IN_LIST DISABLED_PLATFORMS) + set(ARTIFACT "${ARTIFACT_NAME}-${pkgname}-${ARTIFACT_VERSION}.${ARTIFACT_EXT}") + + AddPackage( + NAME ${ARTIFACT_PACKAGE} + REPO ${ARTIFACT_REPO} + TAG "v${ARTIFACT_VERSION}" + GIT_VERSION ${ARTIFACT_VERSION} + ARTIFACT ${ARTIFACT} + + KEY "${pkgname}-${ARTIFACT_VERSION}" + HASH_SUFFIX sha512sum + FORCE_BUNDLED_PACKAGE ON + DOWNLOAD_ONLY ${PKG_ARGS_MODULE}) - if((ANDROID AND ARCHITECTURE_x86_64) AND NOT "android-x86_64" IN_LIST DISABLED_PLATFORMS) - add_ci_package(android-x86_64) - endif() - - if((ANDROID AND ARCHITECTURE_arm64) AND NOT "android-aarch64" IN_LIST DISABLED_PLATFORMS) - add_ci_package(android-aarch64) - endif() - - if(PLATFORM_SUN AND NOT "solaris-amd64" IN_LIST DISABLED_PLATFORMS) - add_ci_package(solaris-amd64) - endif() - - if(PLATFORM_FREEBSD AND NOT "freebsd-amd64" IN_LIST DISABLED_PLATFORMS) - add_ci_package(freebsd-amd64) - endif() + set(${ARTIFACT_PACKAGE}_ADDED TRUE PARENT_SCOPE) + set(${ARTIFACT_PACKAGE}_SOURCE_DIR "${${ARTIFACT_PACKAGE}_SOURCE_DIR}" PARENT_SCOPE) - if((PLATFORM_LINUX AND ARCHITECTURE_x86_64) AND NOT "linux-amd64" IN_LIST DISABLED_PLATFORMS) - add_ci_package(linux-amd64) + if (PKG_ARGS_MODULE) + list(PREPEND CMAKE_PREFIX_PATH "${${ARTIFACT_PACKAGE}_SOURCE_DIR}") + set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} PARENT_SCOPE) + endif() + else() + find_package(${ARTIFACT_PACKAGE} ${ARTIFACT_MIN_VERSION} REQUIRED) endif() +endfunction() - if((PLATFORM_LINUX AND ARCHITECTURE_arm64) AND NOT "linux-aarch64" IN_LIST DISABLED_PLATFORMS) - add_ci_package(linux-aarch64) +# Utility function for Qt +function(AddQt version) + if (NOT DEFINED version) + message(FATAL_ERROR "[CPMUtil] AddQt: version is required") endif() - # TODO(crueter): macOS amd64/aarch64 split mayhaps - if(APPLE AND NOT "macos-universal" IN_LIST DISABLED_PLATFORMS) - add_ci_package(macos-universal) - endif() + AddCIPackage( + NAME Qt + PACKAGE Qt6 + VERSION 6.9.3 + MIN_VERSION 6 + REPO crueter-ci/Qt + DISABLED_PLATFORMS + android-x86_64 android-aarch64 + freebsd-amd64 solaris-amd64 openbsd-amd64 + MODULE) - if(DEFINED ARTIFACT_DIR) - set(${ARTIFACT_PACKAGE}_ADDED TRUE PARENT_SCOPE) - set(${ARTIFACT_PACKAGE}_SOURCE_DIR "${ARTIFACT_DIR}" PARENT_SCOPE) - else() - find_package(${ARTIFACT_PACKAGE} ${ARTIFACT_MIN_VERSION} REQUIRED) - endif() + set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} PARENT_SCOPE) endfunction() diff --git a/CMakeModules/DownloadExternals.cmake b/CMakeModules/DownloadExternals.cmake deleted file mode 100644 index f6e3aaa4ad..0000000000 --- a/CMakeModules/DownloadExternals.cmake +++ /dev/null @@ -1,271 +0,0 @@ -# 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) - set(host "windows") - set(type "desktop") - - if (NOT tool) - if (MINGW) - set(arch "win64_mingw") - set(arch_path "mingw_64") - elseif (MSVC) - if ("arm64" IN_LIST ARCHITECTURE) - set(arch_path "msvc2022_arm64") - elseif ("x86_64" IN_LIST ARCHITECTURE) - set(arch_path "msvc2022_64") - else() - message(FATAL_ERROR "Unsupported bundled Qt architecture. Disable YUZU_USE_BUNDLED_QT and provide your own.") - endif() - set(arch "win64_${arch_path}") - - if (CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "AMD64") - set(host_arch_path "msvc2022_64") - elseif (CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "ARM64") - set(host_arch_path "msvc2022_arm64") - endif() - set(host_arch "win64_${host_arch_path}") - else() - message(FATAL_ERROR "Unsupported bundled Qt toolchain. Disable YUZU_USE_BUNDLED_QT and provide your own.") - endif() - endif() - elseif (APPLE) - set(host "mac") - set(type "desktop") - set(arch "clang_64") - set(arch_path "macos") - else() - set(host "linux") - set(type "desktop") - set(arch "linux_gcc_64") - set(arch_path "gcc_64") - endif() - - set(${host_out} "${host}" PARENT_SCOPE) - set(${type_out} "${type}" PARENT_SCOPE) - set(${arch_out} "${arch}" PARENT_SCOPE) - set(${arch_path_out} "${arch_path}" PARENT_SCOPE) - if (DEFINED host_type) - set(${host_type_out} "${host_type}" PARENT_SCOPE) - else() - set(${host_type_out} "${type}" PARENT_SCOPE) - endif() - if (DEFINED host_arch) - set(${host_arch_out} "${host_arch}" PARENT_SCOPE) - else() - set(${host_arch_out} "${arch}" PARENT_SCOPE) - endif() - if (DEFINED host_arch_path) - set(${host_arch_path_out} "${host_arch_path}" PARENT_SCOPE) - else() - set(${host_arch_path_out} "${arch_path}" PARENT_SCOPE) - endif() -endfunction() - -# Download Qt binaries for a specific configuration. -function(download_qt_configuration prefix_out target host type arch arch_path base_path) - if (target MATCHES "tools_.*") - set(tool ON) - else() - set(tool OFF) - endif() - - set(install_args -c "${CURRENT_MODULE_DIR}/aqt_config.ini") - if (tool) - set(prefix "${base_path}/Tools") - list(APPEND install_args install-tool --outputdir "${base_path}" "${host}" desktop "${target}") - else() - set(prefix "${base_path}/${target}/${arch_path}") - list(APPEND install_args install-qt --outputdir "${base_path}" "${host}" "${type}" "${target}" "${arch}" -m qt_base) - - if (YUZU_USE_QT_MULTIMEDIA) - list(APPEND install_args qtmultimedia) - endif() - - if (YUZU_USE_QT_WEB_ENGINE) - list(APPEND install_args qtpositioning qtwebchannel qtwebengine) - endif() - - if (NOT "${YUZU_QT_MIRROR}" STREQUAL "") - message(STATUS "Using Qt mirror ${YUZU_QT_MIRROR}") - list(APPEND install_args -b "${YUZU_QT_MIRROR}") - endif() - endif() - - message(STATUS "Install Args: ${install_args}") - - if (NOT EXISTS "${prefix}") - message(STATUS "Downloading Qt binaries for ${target}:${host}:${type}:${arch}:${arch_path}") - set(AQT_PREBUILD_BASE_URL "https://github.com/miurahr/aqtinstall/releases/download/v3.3.0") - if (WIN32) - set(aqt_path "${base_path}/aqt.exe") - if (NOT EXISTS "${aqt_path}") - file(DOWNLOAD "${AQT_PREBUILD_BASE_URL}/aqt.exe" "${aqt_path}" SHOW_PROGRESS) - endif() - execute_process(COMMAND "${aqt_path}" ${install_args} - WORKING_DIRECTORY "${base_path}" - RESULT_VARIABLE aqt_res - OUTPUT_VARIABLE aqt_out - ERROR_VARIABLE aqt_err) - if (NOT aqt_res EQUAL 0) - message(FATAL_ERROR "aqt.exe failed: ${aqt_err}") - endif() - elseif (APPLE) - set(aqt_path "${base_path}/aqt-macos") - if (NOT EXISTS "${aqt_path}") - file(DOWNLOAD "${AQT_PREBUILD_BASE_URL}/aqt-macos" "${aqt_path}" SHOW_PROGRESS) - endif() - execute_process(COMMAND chmod +x "${aqt_path}") - execute_process(COMMAND "${aqt_path}" ${install_args} - WORKING_DIRECTORY "${base_path}" - RESULT_VARIABLE aqt_res - ERROR_VARIABLE aqt_err) - if (NOT aqt_res EQUAL 0) - message(FATAL_ERROR "aqt-macos failed: ${aqt_err}") - endif() - else() - find_program(PYTHON3_EXECUTABLE python3) - if (NOT PYTHON3_EXECUTABLE) - message(FATAL_ERROR "python3 is required to install Qt using aqt (pip mode).") - endif() - set(aqt_install_path "${base_path}/aqt") - file(MAKE_DIRECTORY "${aqt_install_path}") - - execute_process(COMMAND "${PYTHON3_EXECUTABLE}" -m pip install --target="${aqt_install_path}" aqtinstall - WORKING_DIRECTORY "${base_path}" - RESULT_VARIABLE pip_res - ERROR_VARIABLE pip_err) - if (NOT pip_res EQUAL 0) - message(FATAL_ERROR "pip install aqtinstall failed: ${pip_err}") - endif() - - execute_process(COMMAND "${CMAKE_COMMAND}" -E env PYTHONPATH="${aqt_install_path}" "${PYTHON3_EXECUTABLE}" -m aqt ${install_args} - WORKING_DIRECTORY "${base_path}" - RESULT_VARIABLE aqt_res - ERROR_VARIABLE aqt_err) - if (NOT aqt_res EQUAL 0) - message(FATAL_ERROR "aqt (python) failed: ${aqt_err}") - endif() - endif() - - message(STATUS "Downloaded Qt binaries for ${target}:${host}:${type}:${arch}:${arch_path} to ${prefix}") - endif() - - set(${prefix_out} "${prefix}" PARENT_SCOPE) -endfunction() - -# This function downloads Qt using aqt. -# The path of the downloaded content will be added to the CMAKE_PREFIX_PATH. -# QT_TARGET_PATH is set to the Qt for the compile target platform. -# QT_HOST_PATH is set to a host-compatible Qt, for running tools. -# Params: -# target: Qt dependency to install. Specify a version number to download Qt, or "tools_(name)" for a specific build tool. -function(download_qt target) - determine_qt_parameters("${target}" host type arch arch_path host_type host_arch host_arch_path) - - set(base_path "${CMAKE_BINARY_DIR}/externals/qt") - file(MAKE_DIRECTORY "${base_path}") - - download_qt_configuration(prefix "${target}" "${host}" "${type}" "${arch}" "${arch_path}" "${base_path}") - if (DEFINED host_arch_path AND NOT "${host_arch_path}" STREQUAL "${arch_path}") - download_qt_configuration(host_prefix "${target}" "${host}" "${host_type}" "${host_arch}" "${host_arch_path}" "${base_path}") - else() - set(host_prefix "${prefix}") - endif() - - set(QT_TARGET_PATH "${prefix}" CACHE STRING "") - set(QT_HOST_PATH "${host_prefix}" CACHE STRING "") - - 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/docs/CPMUtil/AddQt.md b/docs/CPMUtil/AddQt.md new file mode 100644 index 0000000000..2c8c2624fb --- /dev/null +++ b/docs/CPMUtil/AddQt.md @@ -0,0 +1,28 @@ +# AddQt + +Simply call `AddQt()` before any Qt `find_package` calls and everything will be set up for you. On Linux, the bundled Qt library is built as a shared library, and provided you have OpenSSL and X11, everything should just work. + +On Windows, MinGW, and MacOS, Qt is bundled as a static library. No further action is needed, as the provided libraries automatically integrate the Windows/Cocoa plugins, alongside the corresponding Multimedia and Network plugins. + +## Modules + +The following modules are bundled into these Qt builds: + +- Base (Gui, Core, Widgets, Network) +- Multimedia +- Declarative (Quick, QML) +- Linux: Wayland client + +Each platform has the corresponding QPA built in and set as the default as well. This means you don't need to add `Q_IMPORT_PLUGIN`! + +## Example + +See an example in the [`tests/qt`](https://git.crueter.xyz/CMake/CPMUtil/src/branch/master/tests/qt/CMakeLists.txt) directory. + +## Versions + +The following versions have available builds: + +- 6.9.3 + +See [here](https://github.com/crueter-ci/Qt) for an updated list at any time. \ No newline at end of file diff --git a/docs/CPMUtil/README.md b/docs/CPMUtil/README.md index 3f0cb2c741..4ce6e1bf92 100644 --- a/docs/CPMUtil/README.md +++ b/docs/CPMUtil/README.md @@ -13,6 +13,7 @@ You are highly encouraged to read AddPackage first, even if you plan to only int - [AddPackage](#addpackage) - [AddCIPackage](#addcipackage) - [AddJsonPackage](#addjsonpackage) +- [AddQt](#addqt) - [Lists](#lists) - [For Packagers](#for-packagers) - [Network Sandbox](#network-sandbox) @@ -30,6 +31,10 @@ The core of CPMUtil is the [`AddPackage`](./AddPackage.md) function. [`AddPackag [`AddJsonPackage`](./AddJsonPackage.md) is the recommended method of usage for CPMUtil. +## AddQt + +[`AddQt`](./AddQt.md) adds a specific version of Qt to your project. + ## Lists CPMUtil will create three lists of dependencies where `AddPackage` or similar was used. Each is in order of addition. diff --git a/externals/cmake-modules/DefaultConfig.cmake b/externals/cmake-modules/DefaultConfig.cmake index eb5bb3cdef..81e93f6c2e 100644 --- a/externals/cmake-modules/DefaultConfig.cmake +++ b/externals/cmake-modules/DefaultConfig.cmake @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: Copyright 2025 crueter -# SPDX-License-Identifier: GPL-3.0-or-later +# SPDX-License-Identifier: LGPL-3.0-or-later ## DefaultConfig ## diff --git a/externals/cmake-modules/DetectArchitecture.cmake b/externals/cmake-modules/DetectArchitecture.cmake index 82dce31878..105963c8c2 100644 --- a/externals/cmake-modules/DetectArchitecture.cmake +++ b/externals/cmake-modules/DetectArchitecture.cmake @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: Copyright 2025 crueter -# SPDX-License-Identifier: GPL-3.0-or-later +# SPDX-License-Identifier: LGPL-3.0-or-later ## DetectArchitecture ## #[[ @@ -93,133 +93,129 @@ function(detect_architecture_symbols) 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() +# 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() +message(STATUS "[DetectArchitecture] Target architecture: ${ARCHITECTURE}") \ No newline at end of file diff --git a/externals/cmake-modules/DetectPlatform.cmake b/externals/cmake-modules/DetectPlatform.cmake index 25b324a674..0ad695066b 100644 --- a/externals/cmake-modules/DetectPlatform.cmake +++ b/externals/cmake-modules/DetectPlatform.cmake @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: Copyright 2025 crueter -# SPDX-License-Identifier: GPL-3.0-or-later +# SPDX-License-Identifier: LGPL-3.0-or-later ## DetectPlatform ## @@ -147,5 +147,6 @@ endif() # awesome if (PLATFORM_FREEBSD OR PLATFORM_DRAGONFLYBSD) - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${CMAKE_SYSROOT}/usr/local/lib") + set(CMAKE_EXE_LINKER_FLAGS + "${CMAKE_EXE_LINKER_FLAGS} -L${CMAKE_SYSROOT}/usr/local/lib") endif() \ No newline at end of file diff --git a/externals/cmake-modules/FasterLinker.cmake b/externals/cmake-modules/FasterLinker.cmake index 6b472a4f0f..37d8bca33b 100644 --- a/externals/cmake-modules/FasterLinker.cmake +++ b/externals/cmake-modules/FasterLinker.cmake @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: Copyright 2025 crueter -# SPDX-License-Identifier: GPL-3.0-or-later +# SPDX-License-Identifier: LGPL-3.0-or-later ## FasterLinker ## @@ -12,47 +12,45 @@ - mold (GCC only) - generally does well on GCC - lld - preferred on clang - bfd - the final fallback - - If none are found (macOS uses ld.prime, etc) just use the default linker + - If none are found just use the default linker ]] # This module is based on the work of Yuzu, specifically Liam White, # and later extended by crueter. -if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - set(CXX_GCC ON) -endif() - -find_program(LINKER_BFD bfd) -if (LINKER_BFD) - set(LINKER bfd) -endif() - -find_program(LINKER_LLD lld) -if (LINKER_LLD) - set(LINKER lld) -endif() - -if (CXX_GCC) - find_program(LINKER_MOLD mold) - if (LINKER_MOLD AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "12.1") - set(LINKER mold) +option(USE_FASTER_LINKER "Attempt to use a faster linker program" OFF) + +if (USE_FASTER_LINKER) + macro(find_linker ld) + find_program(LINKER_${ld} ld.${ld}) + if (LINKER_${ld}) + set(LINKER ${ld}) + endif() + endmacro() + + find_linker(bfd) + find_linker(lld) + + if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + find_program(LINKER_MOLD mold) + if (LINKER_MOLD AND + CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "12.1") + set(LINKER mold) + endif() + + find_linker(gold) + + if (LINKER STREQUAL "lld") + message(WARNING + "[FasterLinker] Using lld on GCC may cause issues.\ + Install mold, gold, or disable USE_FASTER_LINKER.") + endif() endif() - find_program(LINKER_GOLD gold) - if (LINKER_GOLD) - set(LINKER gold) + if (LINKER) + message(NOTICE "[FasterLinker] Selecting ${LINKER} as linker") + add_link_options("-fuse-ld=${LINKER}") + else() + message(WARNING "[FasterLinker] No faster linker found--using default") endif() -endif() - -if (LINKER) - message(NOTICE "[FasterLinker] Selecting ${LINKER} as linker") - add_link_options("-fuse-ld=${LINKER}") -else() - message(WARNING "[FasterLinker] No faster linker found--using default") -endif() - -if (LINKER STREQUAL "lld" AND CXX_GCC) - message(WARNING - "[FasterLinker] Using lld on GCC may cause issues " - "with certain LTO settings.") -endif() +endif() \ No newline at end of file diff --git a/externals/cmake-modules/GetSCMRev.cmake b/externals/cmake-modules/GetSCMRev.cmake index 4b144584e8..74c32097da 100644 --- a/externals/cmake-modules/GetSCMRev.cmake +++ b/externals/cmake-modules/GetSCMRev.cmake @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: Copyright 2025 crueter -# SPDX-License-Identifier: GPL-3.0-or-later +# SPDX-License-Identifier: LGPL-3.0-or-later ## GetSCMRev ## # Name is self explanatory. Gets revision information from files, OR from git. @@ -13,6 +13,8 @@ find_package(Git QUIET) # tag: git describe --tags --abbrev=0 # branch: git rev-parse --abbrev-ref=HEAD +# TODO: string overrides + function(run_git_command variable) if(NOT GIT_FOUND) set(${variable} "GIT-NOTFOUND" PARENT_SCOPE) diff --git a/externals/cmake-modules/UseCcache.cmake b/externals/cmake-modules/UseCcache.cmake index 8caea18fe0..34a9de3cf2 100644 --- a/externals/cmake-modules/UseCcache.cmake +++ b/externals/cmake-modules/UseCcache.cmake @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: Copyright 2025 crueter -# SPDX-License-Identifier: GPL-3.0-or-later +# SPDX-License-Identifier: LGPL-3.0-or-later ## UseCcache ## diff --git a/externals/cmake-modules/UseLTO.cmake b/externals/cmake-modules/UseLTO.cmake index d1603aba1c..b364ef22d8 100644 --- a/externals/cmake-modules/UseLTO.cmake +++ b/externals/cmake-modules/UseLTO.cmake @@ -1,17 +1,21 @@ # SPDX-FileCopyrightText: Copyright 2025 crueter -# SPDX-License-Identifier: GPL-3.0-or-later +# SPDX-License-Identifier: LGPL-3.0-or-later ## UseLTO ## # Enable Interprocedural Optimization (IPO). # Self-explanatory. -include(CheckIPOSupported) -check_ipo_supported(RESULT COMPILER_SUPPORTS_LTO) -if(NOT COMPILER_SUPPORTS_LTO) - message(FATAL_ERROR - "Your compiler does not support interprocedural optimization" - " (IPO).") -endif() -set(CMAKE_POLICY_DEFAULT_CMP0069 NEW) -set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ${COMPILER_SUPPORTS_LTO}) +option(ENABLE_LTO "Enable Link-Time Optimization (LTO)" OFF) + +if (ENABLE_LTO) + include(CheckIPOSupported) + check_ipo_supported(RESULT COMPILER_SUPPORTS_LTO) + if(NOT COMPILER_SUPPORTS_LTO) + message(FATAL_ERROR + "Your compiler does not support interprocedural optimization" + " (IPO). Disable ENABLE_LTO and try again.") + endif() + set(CMAKE_POLICY_DEFAULT_CMP0069 NEW) + set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ${COMPILER_SUPPORTS_LTO}) +endif() \ No newline at end of file diff --git a/tools/cpm/common.sh b/tools/cpm/common.sh index 436b2cedee..97a2fed003 100755 --- a/tools/cpm/common.sh +++ b/tools/cpm/common.sh @@ -1,6 +1,6 @@ #!/bin/sh -e -# SPDX-FileCopyrightText: Copyright 2025 crueter +# SPDX-FileCopyrightText: Copyright 2026 crueter # SPDX-License-Identifier: LGPL-3.0-or-later ################################## @@ -9,6 +9,14 @@ # TODO: cache cpmfile defs +must_install() { + for cmd in "$@"; do + command -v "$cmd" >/dev/null 2>&1 || { echo "-- $cmd must be installed" && exit 1; } + done +} + +must_install jq find mktemp tar 7z unzip sha512sum git patch curl xargs + # How many levels to go (3 is 2 subdirs max) MAXDEPTH=3 diff --git a/tools/cpm/migrate.sh b/tools/cpm/migrate.sh index adf72bd0bb..b24bbfbbbf 100755 --- a/tools/cpm/migrate.sh +++ b/tools/cpm/migrate.sh @@ -1,11 +1,10 @@ #!/bin/sh -e -# SPDX-FileCopyrightText: Copyright 2025 crueter +# SPDX-FileCopyrightText: Copyright 2026 crueter # SPDX-License-Identifier: LGPL-3.0-or-later SUBMODULES="$(git submodule status --recursive | cut -c2-)" - -[ -z "$SUBMODULES" ] && echo "No submodules defined!" && exit 0 +: "${SUBMODULES:?No submodules defined!}" tmp=$(mktemp) printf '{}' >"$tmp" @@ -22,7 +21,7 @@ for i in $SUBMODULES; do remote=$(git -C "$path" remote get-url origin) host=$(echo "$remote" | cut -d"/" -f3) - [ "$host" = github.com ] && host= + [ "$host" != github.com ] || host= repo=$(echo "$remote" | cut -d"/" -f4-5 | cut -d'.' -f1) diff --git a/tools/cpm/package.sh b/tools/cpm/package.sh index f64f40a3d2..474a2f351e 100755 --- a/tools/cpm/package.sh +++ b/tools/cpm/package.sh @@ -1,6 +1,6 @@ #!/bin/sh -e -# SPDX-FileCopyrightText: Copyright 2025 crueter +# SPDX-FileCopyrightText: Copyright 2026 crueter # SPDX-License-Identifier: LGPL-3.0-or-later RETURN=0 @@ -31,48 +31,12 @@ export SCRIPTS while :; do case "$1" in - hash) + hash | update | fetch | add | rm | version | which | download) + cmd="$1" shift - "$SCRIPTS"/hash.sh "$@" + "$SCRIPTS/$cmd".sh "$@" break ;; - update) - shift - "$SCRIPTS"/update.sh "$@" - break - ;; - fetch) - shift - "$SCRIPTS"/fetch.sh "$@" - break - ;; - add) - shift - "$SCRIPTS"/add.sh "$@" - break - ;; - rm) - shift - "$SCRIPTS"/rm.sh "$@" - break - ;; - version) - shift - "$SCRIPTS"/version.sh "$@" - break - ;; - which) - shift - "$SCRIPTS"/which.sh "$@" - break - ;; - download) - shift - "$SCRIPTS"/download.sh "$@" - break - ;; - -h | --help) usage ;; - "") usage ;; *) usage ;; esac diff --git a/tools/cpm/package/add.sh b/tools/cpm/package/add.sh index 975e6fbae2..f8071ee1bd 100755 --- a/tools/cpm/package/add.sh +++ b/tools/cpm/package/add.sh @@ -1,6 +1,6 @@ #!/bin/sh -e -# SPDX-FileCopyrightText: Copyright 2025 crueter +# SPDX-FileCopyrightText: Copyright 2026 crueter # SPDX-License-Identifier: LGPL-3.0-or-later RETURN=0 @@ -30,7 +30,7 @@ die() { } _cpmfile() { - [ -z "$1" ] && die "You must specify a valid cpmfile." + [ -n "$1" ] || die "You must specify a valid cpmfile." CPMFILE="$1" } @@ -70,7 +70,7 @@ done : "${CPMFILE:=$PWD/cpmfile.json}" -[ -z "$PKG" ] && die "You must specify a package name." +[ -n "$PKG" ] || die "You must specify a package name." export PKG export CPMFILE diff --git a/tools/cpm/package/download.sh b/tools/cpm/package/download.sh index c541426084..2a6125e74d 100755 --- a/tools/cpm/package/download.sh +++ b/tools/cpm/package/download.sh @@ -1,6 +1,6 @@ #!/bin/sh -e -# SPDX-FileCopyrightText: Copyright 2025 crueter +# SPDX-FileCopyrightText: Copyright 2026 crueter # SPDX-License-Identifier: LGPL-3.0-or-later usage() { @@ -29,8 +29,8 @@ while :; do shift done -[ "$ALL" = 1 ] && packages="${LIBS:-$packages}" -[ -z "$packages" ] && usage +[ "$ALL" != 1 ] || packages="${LIBS:-$packages}" +[ -n "$packages" ] || usage for pkg in $packages; do PACKAGE="$pkg" diff --git a/tools/cpm/package/fetch.sh b/tools/cpm/package/fetch.sh index a1f3dc0cf1..a846f34b88 100755 --- a/tools/cpm/package/fetch.sh +++ b/tools/cpm/package/fetch.sh @@ -1,6 +1,6 @@ #!/bin/sh -e -# SPDX-FileCopyrightText: Copyright 2025 crueter +# SPDX-FileCopyrightText: Copyright 2026 crueter # SPDX-License-Identifier: LGPL-3.0-or-later : "${CPM_SOURCE_CACHE:=$PWD/.cache/cpm}" @@ -73,11 +73,12 @@ download_package() { } ci_package() { - [ "$REPO" = null ] && echo "-- ! No repo defined" && return + [ "$REPO" != null ] || echo "-- ! No repo defined" && return echo "-- CI package $PACKAGE_NAME" - for platform in windows-amd64 windows-arm64 \ + for platform in \ + windows-amd64 windows-arm64 \ mingw-amd64 mingw-arm64 \ android-aarch64 android-x86_64 \ solaris-amd64 freebsd-amd64 openbsd-amd64 \ @@ -90,7 +91,6 @@ ci_package() { echo "-- * -- disabled" continue ;; - *) ;; esac FILENAME="${NAME}-${platform}-${VERSION}.${EXT}" @@ -102,7 +102,7 @@ ci_package() { [ -d "$OUTDIR" ] && continue HASH_ALGO=$(echo "$JSON" | jq -r ".hash_algo") - [ "$HASH_ALGO" = null ] && HASH_ALGO=sha512 + [ "$HASH_ALGO" != null ] || HASH_ALGO=sha512 HASH_SUFFIX="${HASH_ALGO}sum" HASH_URL="${DOWNLOAD}.${HASH_SUFFIX}" @@ -137,8 +137,8 @@ while :; do shift done -[ "$ALL" = 1 ] && packages="${LIBS:-$packages}" -[ -z "$packages" ] && usage +[ "$ALL" != 1 ] || packages="${LIBS:-$packages}" +[ -n "$packages" ] || usage for PACKAGE in $packages; do export PACKAGE diff --git a/tools/cpm/package/hash.sh b/tools/cpm/package/hash.sh index 8a23894617..57bc1fee10 100755 --- a/tools/cpm/package/hash.sh +++ b/tools/cpm/package/hash.sh @@ -1,6 +1,6 @@ #!/bin/sh -e -# SPDX-FileCopyrightText: Copyright 2025 crueter +# SPDX-FileCopyrightText: Copyright 2026 crueter # SPDX-License-Identifier: LGPL-3.0-or-later RETURN=0 @@ -52,9 +52,9 @@ while :; do shift done -[ "$ALL" = 1 ] && packages="${LIBS:-$packages}" +[ "$ALL" != 1 ] || packages="${LIBS:-$packages}" [ "$DRY" = 1 ] && UPDATE=false || UPDATE=true -[ -z "$packages" ] && usage +[ -n "$packages" ] || usage export UPDATE diff --git a/tools/cpm/package/rm.sh b/tools/cpm/package/rm.sh index 4af163492f..8b1ab94295 100755 --- a/tools/cpm/package/rm.sh +++ b/tools/cpm/package/rm.sh @@ -1,6 +1,6 @@ #!/bin/sh -e -# SPDX-FileCopyrightText: Copyright 2025 crueter +# SPDX-FileCopyrightText: Copyright 2026 crueter # SPDX-License-Identifier: LGPL-3.0-or-later RETURN=0 @@ -16,7 +16,7 @@ EOF exit $RETURN } -[ $# -lt 1 ] && usage +[ $# -ge 1 ] || usage for pkg in "$@"; do JSON=$("$SCRIPTS"/which.sh "$pkg") || { diff --git a/tools/cpm/package/update.sh b/tools/cpm/package/update.sh index 362d4c14e0..be6a0fbbef 100755 --- a/tools/cpm/package/update.sh +++ b/tools/cpm/package/update.sh @@ -1,6 +1,6 @@ #!/bin/sh -e -# SPDX-FileCopyrightText: Copyright 2025 crueter +# SPDX-FileCopyrightText: Copyright 2026 crueter # SPDX-License-Identifier: LGPL-3.0-or-later filter_out() { @@ -37,13 +37,13 @@ while :; do case "$char" in a) ALL=1 ;; - n) DRY=1 ;; + n) UPDATE=false ;; h) usage ;; *) die "Invalid option -$char" ;; esac done ;; - --dry-run) DRY=1 ;; + --dry-run) UPDATE=false ;; --all) ALL=1 ;; --help) usage ;; "$0") break ;; @@ -54,9 +54,9 @@ while :; do shift done -[ "$ALL" = 1 ] && packages="${LIBS:-$packages}" -[ "$DRY" = 1 ] && UPDATE=false || UPDATE=true -[ -z "$packages" ] && usage +[ "$ALL" != 1 ] || packages="${LIBS:-$packages}" +: "${UPDATE:=true}" +[ -n "$packages" ] || usage for pkg in $packages; do PACKAGE="$pkg" @@ -66,15 +66,15 @@ for pkg in $packages; do SKIP=$(value "skip_updates") - [ "$SKIP" = "true" ] && continue + [ "$SKIP" != "true" ] || continue - [ "$REPO" = null ] && continue - [ "$GIT_HOST" != "github.com" ] && continue # TODO + [ "$REPO" != null ] || continue + [ "$GIT_HOST" = "github.com" ] || continue # TODO - [ "$CI" = "true" ] && continue + [ "$CI" != "true" ] || continue # shellcheck disable=SC2153 - [ "$TAG" = null ] && continue + [ "$TAG" != null ] || continue echo "-- Package $PACKAGE" @@ -99,12 +99,15 @@ for pkg in $packages; do filter_out rc # Add package-specific overrides here, e.g. here for fmt: - [ "$PACKAGE" = fmt ] && filter_out v0.11 + [ "$PACKAGE" != fmt ] || filter_out v0.11 LATEST=$(echo "$TAGS" | jq -r '.[0].name') - [ "$LATEST" = "null" ] && echo "-- * Up-to-date" && continue - [ "$LATEST" = "$TAG" ] && [ "$FORCE" != "true" ] && echo "-- * Up-to-date" && continue + if [ "$LATEST" = "null" ] || + { [ "$LATEST" = "$TAG" ] && [ "$FORCE" != "true" ]; }; then + echo "-- * Up-to-date" + continue + fi if [ "$HAS_REPLACE" = "true" ]; then # this just extracts the tag prefix diff --git a/tools/cpm/package/util/fix-hash.sh b/tools/cpm/package/util/fix-hash.sh index 5d8dd0e163..e142428f75 100755 --- a/tools/cpm/package/util/fix-hash.sh +++ b/tools/cpm/package/util/fix-hash.sh @@ -1,6 +1,6 @@ #!/bin/sh -e -# SPDX-FileCopyrightText: Copyright 2025 crueter +# SPDX-FileCopyrightText: Copyright 2026 crueter # SPDX-License-Identifier: LGPL-3.0-or-later : "${PACKAGE:=$1}" @@ -13,7 +13,7 @@ [ "$HASH_URL" = null ] || exit 0 [ "$HASH_SUFFIX" = null ] || exit 0 -[ "$HASH" = null ] && echo "-- * Package has no hash specified" && exit 0 +[ "$HASH" != null ] || echo "-- * Package has no hash specified" && exit 0 ACTUAL=$("$SCRIPTS"/util/url-hash.sh "$DOWNLOAD") diff --git a/tools/cpm/package/util/interactive.sh b/tools/cpm/package/util/interactive.sh index 974228488a..99db77e20d 100755 --- a/tools/cpm/package/util/interactive.sh +++ b/tools/cpm/package/util/interactive.sh @@ -1,6 +1,6 @@ #!/bin/sh -e -# SPDX-FileCopyrightText: Copyright 2025 crueter +# SPDX-FileCopyrightText: Copyright 2026 crueter # SPDX-License-Identifier: LGPL-3.0-or-later # This reads a single-line input from the user and also gives them @@ -13,7 +13,7 @@ read_single() { while :; do printf -- "-- %s" "$1" - [ -n "$2" ] && printf " (? for help, %s)" "$3" + [ -z "$2" ] || printf " (? for help, %s)" "$3" printf ": " if ! IFS= read -r reply; then echo @@ -113,7 +113,7 @@ tag v1.3.0, then set this to 1.3.0 and set the tag to v%VERSION%." "Most commonly this will be something like v%VERSION% or release-%VERSION%, or just %VERSION%." TAGNAME="$reply" - [ -z "$TAGNAME" ] && TAGNAME="%VERSION%" + [ -n "$TAGNAME" ] || TAGNAME="%VERSION%" optional "Name of the release artifact to download, if applicable. -- %VERSION% is replaced by the numeric version and %TAG% is replaced by the tag name" \ @@ -160,9 +160,9 @@ fi jq_input='{repo: "'"$REPO"'"}' # common trivial fields -[ -n "$PACKAGE" ] && jq_input="$jq_input + {package: \"$PACKAGE\"}" -[ -n "$MIN_VERSION" ] && jq_input="$jq_input + {min_version: \"$MIN_VERSION\"}" -[ -n "$FIND_ARGS" ] && jq_input="$jq_input + {find_args: \"$FIND_ARGS\"}" +[ -z "$PACKAGE" ] || jq_input="$jq_input + {package: \"$PACKAGE\"}" +[ -z "$MIN_VERSION" ] || jq_input="$jq_input + {min_version: \"$MIN_VERSION\"}" +[ -z "$FIND_ARGS" ] || jq_input="$jq_input + {find_args: \"$FIND_ARGS\"}" if [ "$CI" = "true" ]; then jq_input="$jq_input + { @@ -177,7 +177,7 @@ if [ "$CI" = "true" ]; then jq_input="$jq_input + {disabled_platforms: $disabled_json}" fi else - [ -n "$MIN_VERSION" ] && jq_input="$jq_input + {version: \"$MIN_VERSION\"}" + [ -z "$MIN_VERSION" ] || jq_input="$jq_input + {version: \"$MIN_VERSION\"}" jq_input="$jq_input + {hash: \"\"}" # options @@ -194,8 +194,8 @@ else # versioning stuff if [ -n "$GIT_VERSION" ]; then jq_input="$jq_input + {git_version: \"$GIT_VERSION\"}" - [ -n "$TAGNAME" ] && jq_input="$jq_input + {tag: \"$TAGNAME\"}" - [ -n "$ARTIFACT" ] && jq_input="$jq_input + {artifact: \"$ARTIFACT\"}" + [ -z "$TAGNAME" ] || jq_input="$jq_input + {tag: \"$TAGNAME\"}" + [ -z "$ARTIFACT" ] || jq_input="$jq_input + {artifact: \"$ARTIFACT\"}" else jq_input="$jq_input + {sha: \"$SHA\"}" fi diff --git a/tools/cpm/package/vars.sh b/tools/cpm/package/vars.sh index 71bbb3e041..b7e76ac047 100755 --- a/tools/cpm/package/vars.sh +++ b/tools/cpm/package/vars.sh @@ -1,6 +1,6 @@ #!/bin/sh -e -# SPDX-FileCopyrightText: Copyright 2025 crueter +# SPDX-FileCopyrightText: Copyright 2026 crueter # SPDX-License-Identifier: LGPL-3.0-or-later # shellcheck disable=SC1091 @@ -9,12 +9,15 @@ value() { echo "$JSON" | jq -r ".$1" } -[ -z "$PACKAGE" ] && echo "Package was not specified" && exit 0 +[ -n "$PACKAGE" ] || echo "Package was not specified" && exit 0 # shellcheck disable=SC2153 JSON=$(echo "$PACKAGES" | jq -r ".\"$PACKAGE\" | select( . != null )") -[ -z "$JSON" ] && echo "!! No cpmfile definition for $PACKAGE" >&2 && exit 1 +if [ -z "$JSON" ]; then + echo "!! No cpmfile definition for $PACKAGE" >&2 + exit 1 +fi # unset stuff export PACKAGE_NAME="null" @@ -48,10 +51,10 @@ REPO=$(value "repo") CI=$(value "ci") PACKAGE_NAME=$(value "package") -[ "$PACKAGE_NAME" = null ] && PACKAGE_NAME="$PACKAGE" +[ "$PACKAGE_NAME" != null ] || PACKAGE_NAME="$PACKAGE" GIT_HOST=$(value "git_host") -[ "$GIT_HOST" = null ] && GIT_HOST=github.com +[ "$GIT_HOST" != null ] || GIT_HOST=github.com export PACKAGE_NAME export REPO @@ -66,12 +69,12 @@ VERSION=$(value "version") if [ "$CI" = "true" ]; then EXT=$(value "extension") - [ "$EXT" = null ] && EXT="tar.zst" + [ "$EXT" != null ] || EXT="tar.zst" NAME=$(value "name") DISABLED=$(echo "$JSON" | jq -j '.disabled_platforms') - [ "$NAME" = null ] && NAME="$PACKAGE_NAME" + [ "$NAME" != null ] || NAME="$PACKAGE_NAME" export EXT export NAME @@ -90,7 +93,7 @@ ARTIFACT=$(value "artifact") SHA=$(value "sha") GIT_VERSION=$(value "git_version") -[ "$GIT_VERSION" = null ] && GIT_VERSION="$VERSION" +[ "$GIT_VERSION" != null ] || GIT_VERSION="$VERSION" if [ "$GIT_VERSION" != null ]; then VERSION_REPLACE="$GIT_VERSION" @@ -98,8 +101,11 @@ else VERSION_REPLACE="$VERSION" fi -echo "$TAG" | grep -e "%VERSION%" >/dev/null && - HAS_REPLACE=true || HAS_REPLACE=false +if echo "$TAG" | grep -e "%VERSION%" >/dev/null; then + HAS_REPLACE=true +else + HAS_REPLACE=false +fi ORIGINAL_TAG="$TAG" @@ -145,7 +151,7 @@ export KEY ################ HASH_ALGO=$(value "hash_algo") -[ "$HASH_ALGO" = null ] && HASH_ALGO=sha512 +[ "$HASH_ALGO" != null ] || HASH_ALGO=sha512 HASH=$(value "hash") diff --git a/tools/cpm/package/version.sh b/tools/cpm/package/version.sh index b92098f532..fef78124a0 100755 --- a/tools/cpm/package/version.sh +++ b/tools/cpm/package/version.sh @@ -1,6 +1,6 @@ #!/bin/sh -e -# SPDX-FileCopyrightText: Copyright 2025 crueter +# SPDX-FileCopyrightText: Copyright 2026 crueter # SPDX-License-Identifier: LGPL-3.0-or-later # shellcheck disable=SC1091 @@ -20,14 +20,14 @@ EOF PACKAGE="$1" NEW_VERSION="$2" -[ -z "$PACKAGE" ] && usage -[ -z "$NEW_VERSION" ] && usage +[ -n "$PACKAGE" ] || usage +[ -n "$NEW_VERSION" ] || usage export PACKAGE . "$SCRIPTS"/vars.sh -[ "$REPO" = null ] && exit 0 +[ "$REPO" != null ] || exit 0 if [ "$HAS_REPLACE" = "true" ]; then # this just extracts the tag prefix @@ -54,7 +54,7 @@ fi echo "-- * -- Updating $PACKAGE to version $NEW_VERSION" "$SCRIPTS"/util/replace.sh "$PACKAGE" "$NEW_JSON" -[ "$CI" = "true" ] && exit 0 +[ "$CI" != "true" ] || exit 0 echo "-- * -- Fixing hash" . "$ROOTDIR"/common.sh UPDATE=true QUIET=true "$SCRIPTS"/util/fix-hash.sh diff --git a/tools/cpm/package/which.sh b/tools/cpm/package/which.sh index de3ca41c02..650e725c64 100755 --- a/tools/cpm/package/which.sh +++ b/tools/cpm/package/which.sh @@ -1,12 +1,12 @@ #!/bin/sh -e -# SPDX-FileCopyrightText: Copyright 2025 crueter +# SPDX-FileCopyrightText: Copyright 2026 crueter # SPDX-License-Identifier: LGPL-3.0-or-later # check which file a package is in JSON=$(echo "$CPMFILES" | xargs grep -l "\"$1\"") -[ -z "$JSON" ] && echo "!! No cpmfile definition for $1" >&2 && exit 1 +[ -n "$JSON" ] || echo "!! No cpmfile definition for $1" >&2 && exit 1 echo "$JSON" diff --git a/tools/cpm/update.sh b/tools/cpm/update.sh index 81bb84c80a..15fd937242 100755 --- a/tools/cpm/update.sh +++ b/tools/cpm/update.sh @@ -1,16 +1,19 @@ #!/bin/sh -e -# SPDX-FileCopyrightText: Copyright 2025 crueter +# SPDX-FileCopyrightText: Copyright 2026 crueter # SPDX-License-Identifier: LGPL-3.0-or-later # updates CPMUtil, its docs, and related tools from the latest release -if command -v zstd >/dev/null; then +if command -v zstd >/dev/null 2>&1; 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" +file=CPMUtil.$EXT +url="https://git.crueter.xyz/CMake/CPMUtil/releases/download/continuous/$file" + +curl -L "$url" -o "$file" +tar xf "$file" +rm "$file" diff --git a/tools/cpmutil.sh b/tools/cpmutil.sh index 52afba2623..cec758a726 100755 --- a/tools/cpmutil.sh +++ b/tools/cpmutil.sh @@ -1,6 +1,6 @@ #!/bin/sh -e -# SPDX-FileCopyrightText: Copyright 2025 crueter +# SPDX-FileCopyrightText: Copyright 2026 crueter # SPDX-License-Identifier: LGPL-3.0-or-later # shellcheck disable=SC1091 @@ -49,26 +49,18 @@ export ROOTDIR while :; do case "$1" in - -h | --help) usage ;; ls) echo "$CPMFILES" | tr ' ' '\n' break ;; - format) - "$SCRIPTS"/format.sh - break - ;; - update) - "$SCRIPTS"/update.sh - break - ;; - migrate) - "$SCRIPTS"/migrate.sh + format | update | migrate) + "$SCRIPTS/$1".sh break ;; package) + cmd="$1" shift - "$SCRIPTS"/package.sh "$@" + "$SCRIPTS/$cmd".sh "$@" break ;; *) usage ;;