diff --git a/CMakeLists.txt b/CMakeLists.txt index f3f92194b..30c29117b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2018 yuzu Emulator Project & 2025 citron Homebrew Project +# SPDX-FileCopyrightText: 2025 Citron Homebrew Emulator Project & vampiric_x 2025 # SPDX-License-Identifier: GPL-2.0-or-later cmake_minimum_required(VERSION 3.22) @@ -12,11 +12,21 @@ include(DownloadExternals) include(CMakeDependentOption) include(CTest) +# Disable Warnings as Errors for MSVC +if (MSVC) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W3 /WX-") +endif() + +# Check if SDL2::SDL2 target exists; if not, create an alias +if (TARGET SDL2::SDL2-static) + add_library(SDL2::SDL2 ALIAS SDL2::SDL2-static) +elseif (TARGET SDL2::SDL2-shared) + add_library(SDL2::SDL2 ALIAS SDL2::SDL2-shared) +endif() + # Set bundled sdl2/qt as dependent options. -# OFF by default, but if ENABLE_SDL2 and MSVC are true then ON option(ENABLE_SDL2 "Enable the SDL2 frontend" ON) CMAKE_DEPENDENT_OPTION(CITRON_USE_BUNDLED_SDL2 "Download bundled SDL2 binaries" ON "ENABLE_SDL2;MSVC" OFF) -# On Linux system SDL2 is likely to be lacking HIDAPI support which have drawbacks but is needed for SDL motion CMAKE_DEPENDENT_OPTION(CITRON_USE_EXTERNAL_SDL2 "Compile external SDL2" ON "ENABLE_SDL2;NOT MSVC" OFF) cmake_dependent_option(ENABLE_LIBUSB "Enable the use of LibUSB" ON "NOT ANDROID" OFF) @@ -24,8 +34,6 @@ cmake_dependent_option(ENABLE_LIBUSB "Enable the use of LibUSB" ON "NOT ANDROID" option(ENABLE_OPENGL "Enable OpenGL" ON) mark_as_advanced(FORCE ENABLE_OPENGL) option(ENABLE_QT "Enable the Qt frontend" ON) -option(ENABLE_QT6 "Allow usage of Qt6 to be attempted" OFF) -set(QT6_LOCATION "" CACHE PATH "Additional Location to search for Qt6 libraries like C:/Qt/6.3.1/msvc2019_64/") option(ENABLE_QT_TRANSLATION "Enable translations for the Qt frontend" OFF) CMAKE_DEPENDENT_OPTION(CITRON_USE_BUNDLED_QT "Download bundled Qt binaries" "${MSVC}" "ENABLE_QT" OFF) @@ -73,6 +81,11 @@ CMAKE_DEPENDENT_OPTION(CITRON_USE_FASTER_LD "Check if a faster linker is availab CMAKE_DEPENDENT_OPTION(USE_SYSTEM_MOLTENVK "Use the system MoltenVK lib (instead of the bundled one)" OFF "APPLE" OFF) set(DEFAULT_ENABLE_OPENSSL ON) +if (ANDROID OR WIN32 OR APPLE) + set(DEFAULT_ENABLE_OPENSSL OFF) +endif() +option(ENABLE_OPENSSL "Enable OpenSSL backend for ISslConnection" ${DEFAULT_ENABLE_OPENSSL}) + if (ANDROID OR WIN32 OR APPLE) # - Windows defaults to the Schannel backend. # - macOS defaults to the SecureTransport backend. @@ -369,166 +382,6 @@ if(ENABLE_QT6 AND Qt6_LOCATION) list(APPEND CMAKE_PREFIX_PATH "${Qt6_LOCATION}") endif() -function(set_citron_qt_components) - # Best practice is to ask for all components at once, so they are from the same version - set(CITRON_QT_COMPONENTS2 Core Widgets Concurrent) - if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux") - list(APPEND CITRON_QT_COMPONENTS2 DBus) - endif() - if (CITRON_USE_QT_MULTIMEDIA) - list(APPEND CITRON_QT_COMPONENTS2 Multimedia) - endif() - if (CITRON_USE_QT_WEB_ENGINE) - list(APPEND CITRON_QT_COMPONENTS2 WebEngineCore WebEngineWidgets) - endif() - if (ENABLE_QT_TRANSLATION) - list(APPEND CITRON_QT_COMPONENTS2 LinguistTools) - endif() - if (USE_DISCORD_PRESENCE) - list(APPEND CITRON_QT_COMPONENTS2 Network) - endif() - set(CITRON_QT_COMPONENTS ${CITRON_QT_COMPONENTS2} PARENT_SCOPE) -endfunction(set_citron_qt_components) - -# Qt5 requires that we find components, so it doesn't fit our pretty little find package function -if(ENABLE_QT) - set(QT_VERSION 5.15) - # These are used to specify minimum versions - set(QT5_VERSION 5.15) - set(QT6_VERSION 6.3.1) - - set_citron_qt_components() - if (ENABLE_QT6) - find_package(Qt6 ${QT6_VERSION} COMPONENTS ${CITRON_QT_COMPONENTS}) - endif() - if (Qt6_FOUND) - message(STATUS "citron/CMakeLists.txt: Qt6Widgets_VERSION ${Qt6Widgets_VERSION}, setting QT_VERSION") - set(QT_VERSION ${Qt6Widgets_VERSION}) - set(QT_MAJOR_VERSION 6) - # Qt6 sets cxx_std_17 and we need to undo that - set_target_properties(Qt6::Platform PROPERTIES INTERFACE_COMPILE_FEATURES "") - else() - message(STATUS "citron/CMakeLists.txt: Qt6 not found/not selected, trying for Qt5") - # When Qt6 partially found, need this set to use Qt5 when not specifying version - set(QT_DEFAULT_MAJOR_VERSION 5) - set(QT_MAJOR_VERSION 5) - - set(CITRON_USE_QT_MULTIMEDIA ON) - # Check for system Qt on Linux, fallback to bundled Qt - if (UNIX AND NOT APPLE) - if (NOT CITRON_USE_BUNDLED_QT) - find_package(Qt5 ${QT5_VERSION} COMPONENTS Widgets DBus Multimedia) - endif() - if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux" AND (NOT Qt5_FOUND OR CITRON_USE_BUNDLED_QT)) - # Check for dependencies, then enable bundled Qt download - - # Check that the system GLIBCXX version is compatible - find_program(OBJDUMP objdump) - if (NOT OBJDUMP) - message(FATAL_ERROR "Required program `objdump` not found.") - endif() - find_library(LIBSTDCXX libstdc++.so.6) - execute_process( - COMMAND - ${OBJDUMP} -T ${LIBSTDCXX} - COMMAND - grep GLIBCXX_3.4.28 - COMMAND - sed "s/[0-9a-f]*.* //" - COMMAND - sed "s/ .*//" - COMMAND - sort -u - OUTPUT_VARIABLE - GLIBCXX_MET - ) - if (NOT GLIBCXX_MET) - message(FATAL_ERROR "Qt too old or not found, and bundled Qt package is not \ - compatible with this system. Either install Qt ${QT_VERSION}, or provide the path \ - to Qt by setting the variable Qt5_ROOT.") - endif() - - # Check for headers - find_package(PkgConfig REQUIRED) - pkg_check_modules(QT_DEP_GLU QUIET glu>=9.0.0) - if (NOT QT_DEP_GLU_FOUND) - message(FATAL_ERROR "Qt bundled package dependency `glu` not found. \ - Perhaps `libglu1-mesa-dev` needs to be installed?") - endif() - pkg_check_modules(QT_DEP_MESA QUIET dri>=20.0.8) - if (NOT QT_DEP_MESA_FOUND) - message(FATAL_ERROR "Qt bundled package dependency `dri` not found. \ - Perhaps `mesa-common-dev` needs to be installed?") - endif() - - # Check for X libraries - set(BUNDLED_QT_REQUIREMENTS - libxcb-icccm.so.4 - libxcb-image.so.0 - libxcb-keysyms.so.1 - libxcb-randr.so.0 - libxcb-render-util.so.0 - libxcb-render.so.0 - libxcb-shape.so.0 - libxcb-shm.so.0 - libxcb-sync.so.1 - libxcb-xfixes.so.0 - libxcb-xinerama.so.0 - libxcb-xkb.so.1 - libxcb.so.1 - libxkbcommon-x11.so.0 - libxkbcommon.so.0 - ) - set(UNRESOLVED_QT_DEPS "") - foreach (REQUIREMENT ${BUNDLED_QT_REQUIREMENTS}) - find_library(BUNDLED_QT_${REQUIREMENT} ${REQUIREMENT}) - if (NOT BUNDLED_QT_${REQUIREMENT}) - set(UNRESOLVED_QT_DEPS ${UNRESOLVED_QT_DEPS} ${REQUIREMENT}) - endif() - unset(BUNDLED_QT_${REQUIREMENT}) - endforeach() - unset(BUNDLED_QT_REQUIREMENTS) - - if (NOT "${UNRESOLVED_QT_DEPS}" STREQUAL "") - message(FATAL_ERROR "Bundled Qt package missing required dependencies: ${UNRESOLVED_QT_DEPS}") - endif() - - set(CITRON_USE_BUNDLED_QT ON CACHE BOOL "Download bundled Qt" FORCE) - endif() - if (CITRON_USE_BUNDLED_QT) - # Binary package currently does not support Qt webengine, so make sure it's disabled - set(CITRON_USE_QT_WEB_ENGINE OFF CACHE BOOL "Use Qt Webengine" FORCE) - endif() - endif() - - set(CITRON_QT_NO_CMAKE_SYSTEM_PATH) - - if(CITRON_USE_BUNDLED_QT) - if ((MSVC_VERSION GREATER_EQUAL 1920) AND ARCHITECTURE_x86_64) - set(QT_BUILD qt-5.15.2-msvc2019_64) - elseif ((${CMAKE_SYSTEM_NAME} STREQUAL "Linux") AND NOT MINGW AND ARCHITECTURE_x86_64) - set(QT_BUILD qt5_5_15_2) - else() - message(FATAL_ERROR "No bundled Qt binaries for your toolchain. Disable CITRON_USE_BUNDLED_QT and provide your own.") - endif() - - if (DEFINED QT_BUILD) - download_bundled_external("qt/" ${QT_BUILD} QT_PREFIX) - endif() - - set(QT_PREFIX_HINT HINTS "${QT_PREFIX}") - - set(CITRON_QT_NO_CMAKE_SYSTEM_PATH "NO_CMAKE_SYSTEM_PATH") - # Binary package for Qt5 has Qt Multimedia - set(CITRON_USE_QT_MULTIMEDIA ON CACHE BOOL "Use Qt Multimedia" FORCE) - endif() - - set_citron_qt_components() - find_package(Qt5 ${QT5_VERSION} COMPONENTS ${CITRON_QT_COMPONENTS} ${QT_PREFIX_HINT} ${CITRON_QT_NO_CMAKE_SYSTEM_PATH}) - endif() - -endif() - # find SDL2 exports a bunch of variables that are needed, so its easier to do this outside of the citron_find_package if (ENABLE_SDL2) if (CITRON_USE_BUNDLED_SDL2) @@ -558,14 +411,71 @@ if (ENABLE_SDL2) endif() endif() -# List of all FFmpeg components required -set(FFmpeg_COMPONENTS +add_subdirectory(externals) + + +if (ENABLE_QT) + if (NOT USE_SYSTEM_QT) + download_qt(6.7.3) + endif() + + find_package(Qt6 REQUIRED COMPONENTS Widgets Multimedia Concurrent) + + if (UNIX AND NOT APPLE) + find_package(Qt6 REQUIRED COMPONENTS DBus) + endif() + + if (ENABLE_QT_TRANSLATION) + find_package(Qt6 REQUIRED COMPONENTS LinguistTools) + endif() + + if (NOT DEFINED QT_TARGET_PATH) + get_target_property(qtcore_path Qt6::Core LOCATION_Release) + string(FIND "${qtcore_path}" "/bin/" qtcore_path_bin_pos REVERSE) + string(FIND "${qtcore_path}" "/lib/" qtcore_path_lib_pos REVERSE) + if (qtcore_path_bin_pos GREATER qtcore_path_lib_pos) + string(SUBSTRING "${qtcore_path}" 0 ${qtcore_path_bin_pos} QT_TARGET_PATH) + else() + string(SUBSTRING "${qtcore_path}" 0 ${qtcore_path_lib_pos} QT_TARGET_PATH) + endif() + endif() + + if (NOT DEFINED QT_HOST_PATH) + set(QT_HOST_PATH "${QT_TARGET_PATH}") + endif() + message(STATUS "Using target Qt at ${QT_TARGET_PATH}") + message(STATUS "Using host Qt at ${QT_HOST_PATH}") +endif() + +function(set_citron_qt_components) +# Best practice is to ask for all components at once, so they are from the same version +set(CITRON_QT_COMPONENTS2 Core Widgets Concurrent) +if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux") +list(APPEND CITRON_QT_COMPONENTS2 DBus) +endif() +if (CITRON_USE_QT_MULTIMEDIA) +list(APPEND CITRON_QT_COMPONENTS2 Multimedia) + endif() + if (CITRON_USE_QT_WEB_ENGINE) + list(APPEND CITRON_QT_COMPONENTS2 WebEngineCore WebEngineWidgets) + endif() + if (ENABLE_QT_TRANSLATION) + list(APPEND CITRON_QT_COMPONENTS2 LinguistTools) + endif() + if (USE_DISCORD_PRESENCE) + list(APPEND CITRON_QT_COMPONENTS2 Network) + endif() + set(CITRON_QT_COMPONENTS ${CITRON_QT_COMPONENTS2} PARENT_SCOPE) + endfunction(set_citron_qt_components) + + # List of all FFmpeg components required + set(FFmpeg_COMPONENTS avcodec avfilter avutil swscale) -if (UNIX AND NOT APPLE AND NOT ANDROID) + if (UNIX AND NOT APPLE AND NOT ANDROID) find_package(PkgConfig REQUIRED) pkg_check_modules(LIBVA libva) endif() @@ -574,6 +484,14 @@ if (NOT CITRON_USE_BUNDLED_FFMPEG) find_package(FFmpeg 4.3 REQUIRED QUIET COMPONENTS ${FFmpeg_COMPONENTS}) endif() +if(ENABLE_QT) + set_citron_qt_components() + find_package(Qt6 REQUIRED COMPONENTS ${CITRON_QT_COMPONENTS}) + set(QT_MAJOR_VERSION 6) + # Qt6 sets cxx_std_17 and we need to undo that + set_target_properties(Qt6::Platform PROPERTIES INTERFACE_COMPILE_FEATURES "") + endif() + if (WIN32 AND CITRON_CRASH_DUMPS) set(BREAKPAD_VER "breakpad-c89f9dd") download_bundled_external("breakpad/" ${BREAKPAD_VER} BREAKPAD_PREFIX) @@ -704,7 +622,25 @@ if (CITRON_USE_FASTER_LD AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU") endif() endif() -add_subdirectory(externals) +# Set runtime library to MD/MDd for all configurations +if(MSVC) + set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>DLL") + + # Force all projects (including external dependencies) to use the same runtime + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MD") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MDd") + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /MD") + set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /MDd") + + # Add this to ensure Cubeb uses the same runtime + add_compile_options( + $<$:/MDd> + $<$:/MD> + $<$:/MD> + $<$:/MD> + ) +endif() + add_subdirectory(src) # Set citron project or citron-cmd project as default StartUp Project in Visual Studio depending on whether QT is enabled or not diff --git a/CMakeModules/CopyCitronQt6Deps.cmake b/CMakeModules/CopyCitronQt6Deps.cmake new file mode 100644 index 000000000..342939f55 --- /dev/null +++ b/CMakeModules/CopyCitronQt6Deps.cmake @@ -0,0 +1,61 @@ +# SPDX-FileCopyrightText: 2024 Citron HomeBrew Emulator Project +# SPDX-FileCopyrightText: 2024 kleidis + +function(copy_citron_Qt6_deps target_dir) + include(WindowsCopyFiles) + if (MSVC) + set(DLL_DEST "$/") + set(Qt6_DLL_DIR "${Qt6_DIR}/../../../bin") + else() + set(DLL_DEST "${CMAKE_BINARY_DIR}/bin/") + set(Qt6_DLL_DIR "${Qt6_DIR}/../../../lib/") + endif() + set(Qt6_PLATFORMS_DIR "${Qt6_DIR}/../../../plugins/platforms/") + set(Qt6_STYLES_DIR "${Qt6_DIR}/../../../plugins/styles/") + set(Qt6_IMAGEFORMATS_DIR "${Qt6_DIR}/../../../plugins/imageformats/") + set(Qt6_RESOURCES_DIR "${Qt6_DIR}/../../../resources/") + set(PLATFORMS ${DLL_DEST}plugins/platforms/) + set(STYLES ${DLL_DEST}plugins/styles/) + set(IMAGEFORMATS ${DLL_DEST}plugins/imageformats/) + + if (MSVC) + windows_copy_files(${target_dir} ${Qt6_DLL_DIR} ${DLL_DEST} + Qt6Core$<$:d>.* + Qt6Gui$<$:d>.* + Qt6Widgets$<$:d>.* + Qt6Network$<$:d>.* + ) + if (CITRON_USE_QT_MULTIMEDIA) + windows_copy_files(${target_dir} ${Qt6_DLL_DIR} ${DLL_DEST} + Qt6Multimedia$<$:d>.* + ) + endif() + if (CITRON_USE_QT_WEB_ENGINE) + windows_copy_files(${target_dir} ${Qt6_DLL_DIR} ${DLL_DEST} + Qt6WebEngineCore$<$:d>.* + Qt6WebEngineWidgets$<$:d>.* + QtWebEngineProcess$<$:d>.* + ) + windows_copy_files(${target_dir} ${Qt6_RESOURCES_DIR} ${DLL_DEST} + icudtl.dat + qtwebengine_devtools_resources.pak + qtwebengine_resources.pak + qtwebengine_resources_100p.pak + qtwebengine_resources_200p.pak + ) + endif() + windows_copy_files(citron ${Qt6_PLATFORMS_DIR} ${PLATFORMS} qwindows$<$:d>.*) + windows_copy_files(citron ${Qt6_STYLES_DIR} ${STYLES} qwindowsvistastyle$<$:d>.*) + windows_copy_files(citron ${Qt6_IMAGEFORMATS_DIR} ${IMAGEFORMATS} + qjpeg$<$:d>.* + qgif$<$:d>.* + ) + else() + # Update for non-MSVC platforms if needed + endif() + + # Create an empty qt.conf file + add_custom_command(TARGET citron POST_BUILD + COMMAND ${CMAKE_COMMAND} -E touch ${DLL_DEST}qt.conf + ) +endfunction(copy_citron_Qt6_deps) diff --git a/CMakeModules/DownloadExternals.cmake b/CMakeModules/DownloadExternals.cmake index 12b337997..f188e40b6 100644 --- a/CMakeModules/DownloadExternals.cmake +++ b/CMakeModules/DownloadExternals.cmake @@ -1,10 +1,11 @@ -# SPDX-FileCopyrightText: 2017 yuzu Emulator Project & 2025 citron Homebrew Project +# SPDX-FileCopyrightText: 2025 Citron Homebrew Emulator Project & vampiric_x 2025 # SPDX-License-Identifier: GPL-2.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 prefix_var) set(package_base_url "https://github.com/yuzu-mirror/") @@ -16,7 +17,7 @@ if (WIN32) elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Linux") set(package_repo "ext-linux-bin/raw/main/") set(package_extension ".tar.xz") -elseif (ANDROID) +elseif (ANDROID) set(package_repo "ext-android-bin/raw/main/") set(package_extension ".tar.xz") else() @@ -54,3 +55,172 @@ function(download_moltenvk_external platform version) list(APPEND CMAKE_PREFIX_PATH "${MOLTENVK_DIR}/MoltenVK/dylib/${platform}") set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} PARENT_SCOPE) 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 "msvc2019_arm64") + elseif ("x86_64" IN_LIST ARCHITECTURE) + set(arch_path "msvc2019_64") + else() + message(FATAL_ERROR "Unsupported bundled Qt architecture. Enable USE_SYSTEM_QT and provide your own.") + endif() + set(arch "win64_${arch_path}") + + if (CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "AMD64") + set(host_arch_path "msvc2019_64") + elseif (CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "ARM64") + set(host_arch_path "msvc2019_64") + endif() + set(host_arch "win64_${host_arch_path}") + else() + message(FATAL_ERROR "Unsupported bundled Qt toolchain. Enable USE_SYSTEM_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 "gcc_64") + set(arch_path "linux") + 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") + set(install_args ${install_args} install-tool --outputdir ${base_path} ${host} desktop ${target}) + else() + set(prefix "${base_path}/${target}/${arch_path}") + set(install_args ${install_args} install-qt --outputdir ${base_path} ${host} ${type} ${target} ${arch} + -m qtmultimedia --archives qttranslations qttools qtsvg qtbase) + endif() + + 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.1.18") + 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}) + 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}) + else() + set(aqt_install_path "${base_path}/aqt") + file(MAKE_DIRECTORY "${aqt_install_path}") + + execute_process(COMMAND python3 -m pip install --target=${aqt_install_path} aqtinstall + WORKING_DIRECTORY ${base_path}) + execute_process(COMMAND ${CMAKE_COMMAND} -E env PYTHONPATH=${aqt_install_path} python3 -m aqt ${install_args} + WORKING_DIRECTORY ${base_path}) + 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) + + get_external_prefix(qt base_path) + 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) +set(MOLTENVK_PLATFORM "macOS") + +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/v1.2.10-rc2/MoltenVK-all.tar + ${MOLTENVK_TAR} SHOW_PROGRESS) +endif() + +execute_process(COMMAND ${CMAKE_COMMAND} -E tar xf "${MOLTENVK_TAR}" + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/externals") +endif() + +# Add the MoltenVK library path to the prefix so find_library can locate it. +list(APPEND CMAKE_PREFIX_PATH "${MOLTENVK_DIR}/MoltenVK/dylib/${MOLTENVK_PLATFORM}") +set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} PARENT_SCOPE) +endfunction() + +function(get_external_prefix lib_name prefix_var) + set(${prefix_var} "${CMAKE_BINARY_DIR}/externals/${lib_name}" PARENT_SCOPE) +endfunction() diff --git a/CMakeModules/aqt_config.ini b/CMakeModules/aqt_config.ini new file mode 100644 index 000000000..0ad399ada --- /dev/null +++ b/CMakeModules/aqt_config.ini @@ -0,0 +1,31 @@ +# SPDX-FileCopyrightText: 2024 Citron HomeBrew Emulator Project +# SPDX-FileCopyrightText: 2024 kleidis + +[aqt] +concurrency: 2 + +[mirrors] +trusted_mirrors: + https://download.qt.io +blacklist: + https://qt.mirror.constant.com + https://mirrors.ocf.berkeley.edu + https://mirrors.ustc.edu.cn + https://mirrors.tuna.tsinghua.edu.cn + https://mirrors.geekpie.club + https://mirrors-wan.geekpie.club + https://mirrors.sjtug.sjtu.edu.cn +fallbacks: + https://qtproject.mirror.liquidtelecom.com/ + https://mirrors.aliyun.com/qt/ + https://ftp.jaist.ac.jp/pub/qtproject/ + https://ftp.yz.yamagata-u.ac.jp/pub/qtproject/ + https://qt-mirror.dannhauer.de/ + https://ftp.fau.de/qtproject/ + https://mirror.netcologne.de/qtproject/ + https://mirrors.dotsrc.org/qtproject/ + https://www.nic.funet.fi/pub/mirrors/download.qt-project.org/ + https://master.qt.io/ + https://mirrors.ukfast.co.uk/sites/qt.io/ + https://ftp2.nluug.nl/languages/qt/ + https://ftp1.nluug.nl/languages/qt/ diff --git a/src/citron/CMakeLists.txt b/src/citron/CMakeLists.txt index 38f756ff1..8b0da1544 100644 --- a/src/citron/CMakeLists.txt +++ b/src/citron/CMakeLists.txt @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2018 yuzu Emulator Project & 2025 citron Homebrew Project +# SPDX-FileCopyrightText: 2025 Citron Homebrew Emulator Project & vampiric_x 2025 # SPDX-License-Identifier: GPL-2.0-or-later set(CMAKE_AUTOMOC ON) @@ -368,11 +368,7 @@ if (APPLE) elseif(WIN32) # compile as a win32 gui application instead of a console application - if (QT_VERSION VERSION_GREATER_EQUAL 6) - target_link_libraries(citron PRIVATE Qt6::EntryPointPrivate) - else() - target_link_libraries(citron PRIVATE Qt5::WinMain) - endif() + target_link_libraries(citron PRIVATE Qt6::EntryPointPrivate) if(MSVC) target_link_libraries(citron PRIVATE version.lib) set_target_properties(citron PROPERTIES LINK_FLAGS_RELEASE "/SUBSYSTEM:WINDOWS") @@ -382,15 +378,15 @@ elseif(WIN32) endif() target_link_libraries(citron PRIVATE common core input_common frontend_common network video_core) -target_link_libraries(citron PRIVATE Boost::headers glad Qt${QT_MAJOR_VERSION}::Widgets) +target_link_libraries(citron PRIVATE Boost::headers glad Qt6::Widgets) target_link_libraries(citron PRIVATE ${PLATFORM_LIBRARIES} Threads::Threads) target_link_libraries(citron PRIVATE Vulkan::Headers) if (NOT WIN32) - target_include_directories(citron PRIVATE ${Qt${QT_MAJOR_VERSION}Gui_PRIVATE_INCLUDE_DIRS}) + target_include_directories(citron PRIVATE ${Qt6Gui_PRIVATE_INCLUDE_DIRS}) endif() if (UNIX AND NOT APPLE) - target_link_libraries(citron PRIVATE Qt${QT_MAJOR_VERSION}::DBus) + target_link_libraries(citron PRIVATE Qt6::DBus) endif() target_compile_definitions(citron PRIVATE @@ -448,9 +444,9 @@ if (WIN32 AND QT_VERSION VERSION_GREATER_EQUAL 6) add_custom_command(TARGET citron POST_BUILD COMMAND ${WINDEPLOYQT_EXECUTABLE} "${CITRON_EXE_DIR}/citron.exe" --dir "${CITRON_EXE_DIR}" --libdir "${CITRON_EXE_DIR}" --plugindir "${CITRON_EXE_DIR}/plugins" --no-compiler-runtime --no-opengl-sw --no-system-d3d-compiler --no-translations --verbose 0) endif() -if (CITRON_USE_BUNDLED_QT AND QT_VERSION VERSION_LESS 6) - include(CopyCitronQt5Deps) - copy_citron_Qt5_deps(citron) +if (CITRON_USE_BUNDLED_QT) + include(CopyCitronQt6Deps) + copy_citron_Qt6_deps(citron) endif() if (ENABLE_SDL2) diff --git a/src/citron/bootmanager.cpp b/src/citron/bootmanager.cpp index 7443c7048..96d9f970f 100644 --- a/src/citron/bootmanager.cpp +++ b/src/citron/bootmanager.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2014 Citra Emulator Project & 2025 Citron Homebrew Project +// SPDX-FileCopyrightText: 2025 Citron Homebrew Emulator Project & vampiric_x 2025 // SPDX-License-Identifier: GPL-2.0-or-later #include @@ -736,19 +736,19 @@ void GRenderWindow::wheelEvent(QWheelEvent* event) { } void GRenderWindow::TouchBeginEvent(const QTouchEvent* event) { - QList touch_points = event->touchPoints(); + QList touch_points = event->points(); for (const auto& touch_point : touch_points) { - const auto [x, y] = ScaleTouch(touch_point.pos()); + const auto [x, y] = ScaleTouch(touch_point.position()); const auto [touch_x, touch_y] = MapToTouchScreen(x, y); input_subsystem->GetTouchScreen()->TouchPressed(touch_x, touch_y, touch_point.id()); } } void GRenderWindow::TouchUpdateEvent(const QTouchEvent* event) { - QList touch_points = event->touchPoints(); + QList touch_points = event->points(); input_subsystem->GetTouchScreen()->ClearActiveFlag(); for (const auto& touch_point : touch_points) { - const auto [x, y] = ScaleTouch(touch_point.pos()); + const auto [x, y] = ScaleTouch(touch_point.position()); const auto [touch_x, touch_y] = MapToTouchScreen(x, y); input_subsystem->GetTouchScreen()->TouchMoved(touch_x, touch_y, touch_point.id()); } @@ -1137,4 +1137,4 @@ bool GRenderWindow::eventFilter(QObject* object, QEvent* event) { emit MouseActivity(); } return false; -} +} \ No newline at end of file diff --git a/src/citron/configuration/configure_touch_from_button.cpp b/src/citron/configuration/configure_touch_from_button.cpp index 605e96aa0..31816bdb2 100644 --- a/src/citron/configuration/configure_touch_from_button.cpp +++ b/src/citron/configuration/configure_touch_from_button.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2020 Citra Emulator Project & 2025 Citron Homebrew Project +// SPDX-FileCopyrightText: 2025 Citron Homebrew Emulator Project & vampiric_x 2025 // SPDX-License-Identifier: GPL-2.0-or-later #include @@ -505,7 +505,7 @@ void TouchScreenPreview::mouseMoveEvent(QMouseEvent* event) { if (!coord_label) { return; } - const auto pos = MapToDeviceCoords(event->x(), event->y()); + const auto pos = MapToDeviceCoords(event->position().x(), event->position().y()); if (pos) { coord_label->setText(QStringLiteral("X: %1, Y: %2").arg(pos->x()).arg(pos->y())); } else { @@ -523,7 +523,7 @@ void TouchScreenPreview::mousePressEvent(QMouseEvent* event) { if (event->button() != Qt::MouseButton::LeftButton) { return; } - const auto pos = MapToDeviceCoords(event->x(), event->y()); + const auto pos = MapToDeviceCoords(event->position().x(), event->position().y()); if (pos) { emit DotAdded(*pos); } @@ -539,7 +539,7 @@ bool TouchScreenPreview::eventFilter(QObject* obj, QEvent* event) { emit DotSelected(obj->property(PropId).toInt()); drag_state.dot = qobject_cast(obj); - drag_state.start_pos = mouse_event->globalPos(); + drag_state.start_pos = mouse_event->globalPosition().toPoint(); return true; } case QEvent::Type::MouseMove: { @@ -549,13 +549,13 @@ bool TouchScreenPreview::eventFilter(QObject* obj, QEvent* event) { const auto mouse_event = static_cast(event); if (!drag_state.active) { drag_state.active = - (mouse_event->globalPos() - drag_state.start_pos).manhattanLength() >= + (mouse_event->globalPosition().toPoint() - drag_state.start_pos).manhattanLength() >= QApplication::startDragDistance(); if (!drag_state.active) { break; } } - auto current_pos = mapFromGlobal(mouse_event->globalPos()); + auto current_pos = mapFromGlobal(mouse_event->globalPosition().toPoint()); current_pos.setX(std::clamp(current_pos.x(), contentsMargins().left(), contentsMargins().left() + contentsRect().width() - 1)); current_pos.setY(std::clamp(current_pos.y(), contentsMargins().top(), @@ -614,4 +614,4 @@ void TouchScreenPreview::PositionDot(QLabel* const dot, const int device_x, contentsMargins().top() - static_cast(dot->height()) / 2 + 0.5f); dot->move(x_coord, y_coord); -} +} \ No newline at end of file diff --git a/src/citron/configuration/configure_ui.cpp b/src/citron/configuration/configure_ui.cpp index 60a21a4a1..207d21067 100644 --- a/src/citron/configuration/configure_ui.cpp +++ b/src/citron/configuration/configure_ui.cpp @@ -256,7 +256,7 @@ void ConfigureUi::InitializeLanguageComboBox() { locale.truncate(locale.lastIndexOf(QLatin1Char{'.'})); locale.remove(0, locale.lastIndexOf(QLatin1Char{'/'}) + 1); const QString lang = QLocale::languageToString(QLocale(locale).language()); - const QString country = QLocale::countryToString(QLocale(locale).country()); + const QString country = QLocale::territoryToString(QLocale(locale).territory()); ui->language_combobox->addItem(QStringLiteral("%1 (%2)").arg(lang, country), locale); } diff --git a/src/citron/game_list.cpp b/src/citron/game_list.cpp index 1eb27e89d..9c879b403 100644 --- a/src/citron/game_list.cpp +++ b/src/citron/game_list.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2015 Citra Emulator Project & 2025 Citron Homebrew Project +// SPDX-FileCopyrightText: 2025 Citron Homebrew Emulator Project & vampiric_x 2025 // SPDX-License-Identifier: GPL-2.0-or-later #include @@ -235,7 +235,7 @@ void GameList::OnTextChanged(const QString& new_text) { file_path.mid(file_path.lastIndexOf(QLatin1Char{'/'}) + 1) + QLatin1Char{' '} + file_title; if (ContainsAllWords(file_name, edit_filter_text) || - (file_program_id.count() == 16 && file_program_id.contains(edit_filter_text))) { + (file_program_id.size() == 16 && file_program_id.contains(edit_filter_text))) { tree_view->setRowHidden(j, folder_index, false); ++result_count; } else { diff --git a/src/citron/main.cpp b/src/citron/main.cpp index 780c23b13..9fbb8c543 100644 --- a/src/citron/main.cpp +++ b/src/citron/main.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2014 Citra Emulator Project & 2025 Citron Homebrew Project +// SPDX-FileCopyrightText: 2025 Citron Homebrew Emulator Project & vampiric_x 2025 // SPDX-License-Identifier: GPL-2.0-or-later #include @@ -5239,9 +5239,6 @@ static void SetHighDPIAttributes() { QApplication::setHighDpiScaleFactorRoundingPolicy( Qt::HighDpiScaleFactorRoundingPolicy::PassThrough); #endif - - QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); - QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); } int main(int argc, char* argv[]) {