first commit

This commit is contained in:
JJBanana13
2026-02-16 14:55:56 +01:00
commit bd171e45da
3858 changed files with 974230 additions and 0 deletions

View File

@@ -0,0 +1,10 @@
# SPDX-FileCopyrightText: 2020 yuzu Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later
function(copy_citron_FFmpeg_deps target_dir)
include(WindowsCopyFiles)
set(DLL_DEST "$<TARGET_FILE_DIR:${target_dir}>/")
file(READ "${FFmpeg_PATH}/requirements.txt" FFmpeg_REQUIRED_DLLS)
string(STRIP "${FFmpeg_REQUIRED_DLLS}" FFmpeg_REQUIRED_DLLS)
windows_copy_files(${target_dir} ${FFmpeg_LIBRARY_DIR} ${DLL_DEST} ${FFmpeg_REQUIRED_DLLS})
endfunction(copy_citron_FFmpeg_deps)

View File

@@ -0,0 +1,125 @@
# SPDX-FileCopyrightText: 2016 Citra Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later
function(copy_citron_Qt5_deps target_dir)
include(WindowsCopyFiles)
if (MSVC)
set(DLL_DEST "$<TARGET_FILE_DIR:${target_dir}>/")
set(Qt5_DLL_DIR "${Qt5_DIR}/../../../bin")
else()
set(DLL_DEST "${CMAKE_BINARY_DIR}/bin/")
set(Qt5_DLL_DIR "${Qt5_DIR}/../../../lib/")
endif()
set(Qt5_PLATFORMS_DIR "${Qt5_DIR}/../../../plugins/platforms/")
set(Qt5_PLATFORMTHEMES_DIR "${Qt5_DIR}/../../../plugins/platformthemes/")
set(Qt5_PLATFORMINPUTCONTEXTS_DIR "${Qt5_DIR}/../../../plugins/platforminputcontexts/")
set(Qt5_MEDIASERVICE_DIR "${Qt5_DIR}/../../../plugins/mediaservice/")
set(Qt5_XCBGLINTEGRATIONS_DIR "${Qt5_DIR}/../../../plugins/xcbglintegrations/")
set(Qt5_STYLES_DIR "${Qt5_DIR}/../../../plugins/styles/")
set(Qt5_IMAGEFORMATS_DIR "${Qt5_DIR}/../../../plugins/imageformats/")
set(Qt5_RESOURCES_DIR "${Qt5_DIR}/../../../resources/")
set(PLATFORMS ${DLL_DEST}plugins/platforms/)
set(MEDIASERVICE ${DLL_DEST}mediaservice/)
set(STYLES ${DLL_DEST}plugins/styles/)
set(IMAGEFORMATS ${DLL_DEST}plugins/imageformats/)
if (MSVC)
windows_copy_files(${target_dir} ${Qt5_DLL_DIR} ${DLL_DEST}
Qt5Core$<$<CONFIG:Debug>:d>.*
Qt5Gui$<$<CONFIG:Debug>:d>.*
Qt5Widgets$<$<CONFIG:Debug>:d>.*
Qt5Network$<$<CONFIG:Debug>:d>.*
)
if (CITRON_USE_QT_MULTIMEDIA)
windows_copy_files(${target_dir} ${Qt5_DLL_DIR} ${DLL_DEST}
Qt5Multimedia$<$<CONFIG:Debug>:d>.*
)
endif()
if (CITRON_USE_QT_WEB_ENGINE)
windows_copy_files(${target_dir} ${Qt5_DLL_DIR} ${DLL_DEST}
Qt5Network$<$<CONFIG:Debug>:d>.*
Qt5Positioning$<$<CONFIG:Debug>:d>.*
Qt5PrintSupport$<$<CONFIG:Debug>:d>.*
Qt5Qml$<$<CONFIG:Debug>:d>.*
Qt5QmlModels$<$<CONFIG:Debug>:d>.*
Qt5Quick$<$<CONFIG:Debug>:d>.*
Qt5QuickWidgets$<$<CONFIG:Debug>:d>.*
Qt5WebChannel$<$<CONFIG:Debug>:d>.*
Qt5WebEngineCore$<$<CONFIG:Debug>:d>.*
Qt5WebEngineWidgets$<$<CONFIG:Debug>:d>.*
QtWebEngineProcess$<$<CONFIG:Debug>:d>.*
)
windows_copy_files(${target_dir} ${Qt5_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 ${Qt5_PLATFORMS_DIR} ${PLATFORMS} qwindows$<$<CONFIG:Debug>:d>.*)
windows_copy_files(citron ${Qt5_STYLES_DIR} ${STYLES} qwindowsvistastyle$<$<CONFIG:Debug>:d>.*)
windows_copy_files(citron ${Qt5_IMAGEFORMATS_DIR} ${IMAGEFORMATS}
qjpeg$<$<CONFIG:Debug>:d>.*
qgif$<$<CONFIG:Debug>:d>.*
)
windows_copy_files(citron ${Qt5_MEDIASERVICE_DIR} ${MEDIASERVICE}
dsengine$<$<CONFIG:Debug>:d>.*
wmfengine$<$<CONFIG:Debug>:d>.*
)
else()
set(Qt5_DLLS
"${Qt5_DLL_DIR}libQt5Core.so.5"
"${Qt5_DLL_DIR}libQt5DBus.so.5"
"${Qt5_DLL_DIR}libQt5Gui.so.5"
"${Qt5_DLL_DIR}libQt5Widgets.so.5"
"${Qt5_DLL_DIR}libQt5XcbQpa.so.5"
"${Qt5_DLL_DIR}libicudata.so.60"
"${Qt5_DLL_DIR}libicui18n.so.60"
"${Qt5_DLL_DIR}libicuuc.so.60"
)
set(Qt5_IMAGEFORMAT_DLLS
"${Qt5_IMAGEFORMATS_DIR}libqjpeg.so"
"${Qt5_IMAGEFORMATS_DIR}libqgif.so"
"${Qt5_IMAGEFORMATS_DIR}libqico.so"
)
set(Qt5_PLATFORMTHEME_DLLS
"${Qt5_PLATFORMTHEMES_DIR}libqgtk3.so"
"${Qt5_PLATFORMTHEMES_DIR}libqxdgdesktopportal.so"
)
set(Qt5_PLATFORM_DLLS
"${Qt5_PLATFORMS_DIR}libqxcb.so"
)
set(Qt5_PLATFORMINPUTCONTEXT_DLLS
"${Qt5_PLATFORMINPUTCONTEXTS_DIR}libcomposeplatforminputcontextplugin.so"
"${Qt5_PLATFORMINPUTCONTEXTS_DIR}libibusplatforminputcontextplugin.so"
)
set(Qt5_XCBGLINTEGRATION_DLLS
"${Qt5_XCBGLINTEGRATIONS_DIR}libqxcb-glx-integration.so"
)
foreach(LIB ${Qt5_DLLS})
file(COPY ${LIB} DESTINATION "${DLL_DEST}/lib" FOLLOW_SYMLINK_CHAIN)
endforeach()
foreach(LIB ${Qt5_IMAGEFORMAT_DLLS})
file(COPY ${LIB} DESTINATION "${DLL_DEST}plugins/imageformats/" FOLLOW_SYMLINK_CHAIN)
endforeach()
foreach(LIB ${Qt5_PLATFORMTHEME_DLLS})
file(COPY ${LIB} DESTINATION "${DLL_DEST}plugins/platformthemes/" FOLLOW_SYMLINK_CHAIN)
endforeach()
foreach(LIB ${Qt5_PLATFORM_DLLS})
file(COPY ${LIB} DESTINATION "${DLL_DEST}plugins/platforms/" FOLLOW_SYMLINK_CHAIN)
endforeach()
foreach(LIB ${Qt5_PLATFORMINPUTCONTEXT_DLLS})
file(COPY ${LIB} DESTINATION "${DLL_DEST}plugins/platforminputcontexts/" FOLLOW_SYMLINK_CHAIN)
endforeach()
foreach(LIB ${Qt5_XCBGLINTEGRATION_DLLS})
file(COPY ${LIB} DESTINATION "${DLL_DEST}plugins/xcbglintegrations/" FOLLOW_SYMLINK_CHAIN)
endforeach()
endif()
# Create an empty qt.conf file. Qt will detect that this file exists, and use the folder that its in as the root folder.
# This way it'll look for plugins in the root/plugins/ folder
add_custom_command(TARGET citron POST_BUILD
COMMAND ${CMAKE_COMMAND} -E touch ${DLL_DEST}qt.conf
)
endfunction(copy_citron_Qt5_deps)

View File

@@ -0,0 +1,68 @@
# SPDX-FileCopyrightText: 2025 citron Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
function(copy_citron_Qt6_deps target_dir)
include(WindowsCopyFiles)
if (MSVC)
set(DLL_DEST "$<TARGET_FILE_DIR:${target_dir}>/")
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_TLS_DIR "${Qt6_DIR}/../../../plugins/tls/")
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/)
set(TLS ${DLL_DEST}tls/)
if (MSVC)
windows_copy_files(${target_dir} ${Qt6_DLL_DIR} ${DLL_DEST}
Qt6Core$<$<CONFIG:Debug>:d>.*
Qt6Gui$<$<CONFIG:Debug>:d>.*
Qt6Widgets$<$<CONFIG:Debug>:d>.*
Qt6Network$<$<CONFIG:Debug>:d>.*
)
if (CITRON_USE_QT_MULTIMEDIA)
windows_copy_files(${target_dir} ${Qt6_DLL_DIR} ${DLL_DEST}
Qt6Multimedia$<$<CONFIG:Debug>:d>.*
)
endif()
if (CITRON_USE_QT_WEB_ENGINE)
windows_copy_files(${target_dir} ${Qt6_DLL_DIR} ${DLL_DEST}
Qt6WebEngineCore$<$<CONFIG:Debug>:d>.*
Qt6WebEngineWidgets$<$<CONFIG:Debug>:d>.*
QtWebEngineProcess$<$<CONFIG:Debug>: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$<$<CONFIG:Debug>:d>.*)
windows_copy_files(citron ${Qt6_STYLES_DIR} ${STYLES} qwindowsvistastyle$<$<CONFIG:Debug>:d>.*)
windows_copy_files(citron ${Qt6_IMAGEFORMATS_DIR} ${IMAGEFORMATS}
qjpeg$<$<CONFIG:Debug>:d>.*
qgif$<$<CONFIG:Debug>:d>.*
)
# Copy TLS plugins for SSL/HTTPS support (required for auto updater)
windows_copy_files(citron ${Qt6_TLS_DIR} ${TLS}
qschannelbackend$<$<CONFIG:Debug>:d>.*
qopensslbackend$<$<CONFIG:Debug>: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)

View File

@@ -0,0 +1,8 @@
# SPDX-FileCopyrightText: 2016 Citra Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later
function(copy_citron_SDL_deps target_dir)
include(WindowsCopyFiles)
set(DLL_DEST "$<TARGET_FILE_DIR:${target_dir}>/")
windows_copy_files(${target_dir} ${SDL2_DLL_DIR} ${DLL_DEST} SDL2.dll)
endfunction(copy_citron_SDL_deps)

View File

@@ -0,0 +1,262 @@
# SPDX-FileCopyrightText: 2017 yuzu Emulator Project
# SPDX-FileCopyrightText: 2025 citron Emulator Project
# 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_repo "no_platform")
set(package_extension "no_platform")
# Use yuzu-mirror GitHub repositories for external binaries (more reliable than self-hosted)
set(package_base_url "https://github.com/yuzu-mirror/")
if (WIN32)
# https://github.com/yuzu-mirror/ext-windows-bin
set(package_repo "ext-windows-bin/raw/master/")
set(package_extension ".7z")
elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
# https://github.com/yuzu-mirror/ext-linux-bin
set(package_repo "ext-linux-bin/raw/main/")
set(package_extension ".tar.xz")
elseif (ANDROID)
# https://github.com/yuzu-mirror/ext-android-bin
# Files are named with architecture suffix (e.g., ffmpeg-android-v5.1.LTS-aarch64.tar.xz)
set(package_repo "ext-android-bin/raw/main/")
set(package_extension ".tar.xz")
else()
message(FATAL_ERROR "No package available for this platform")
endif()
set(package_url "${package_base_url}${package_repo}")
set(prefix "${CMAKE_BINARY_DIR}/externals/${lib_name}")
if (NOT EXISTS "${prefix}")
set(download_url "${package_url}${remote_path}${lib_name}${package_extension}")
set(download_path "${CMAKE_BINARY_DIR}/externals/${lib_name}${package_extension}")
message(STATUS "Downloading binaries for ${lib_name} from ${download_url}...")
file(DOWNLOAD
${download_url}
${download_path}
SHOW_PROGRESS
STATUS download_status)
list(GET download_status 0 status_code)
list(GET download_status 1 status_string)
if (NOT status_code EQUAL 0)
message(FATAL_ERROR "Failed to download ${lib_name}: ${status_string} (${status_code})\nURL: ${download_url}")
endif()
# Verify the downloaded file is not empty or an error page
file(SIZE ${download_path} download_size)
if (download_size LESS 1000)
file(READ ${download_path} download_content LIMIT 500)
message(FATAL_ERROR "Downloaded file for ${lib_name} appears invalid (size: ${download_size} bytes).\nURL: ${download_url}\nContent preview: ${download_content}")
endif()
execute_process(
COMMAND ${CMAKE_COMMAND} -E tar xf ${download_path}
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/externals"
RESULT_VARIABLE extract_result)
if (NOT extract_result EQUAL 0)
message(FATAL_ERROR "Failed to extract ${lib_name} archive: ${extract_result}")
endif()
endif()
message(STATUS "Using bundled binaries at ${prefix}")
set(${prefix_var} "${prefix}" PARENT_SCOPE)
endfunction()
function(download_moltenvk_external platform version)
set(MOLTENVK_DIR "${CMAKE_BINARY_DIR}/externals/MoltenVK")
set(MOLTENVK_TAR "${CMAKE_BINARY_DIR}/externals/MoltenVK.tar")
# Use Ryujinx MoltenVK build which is compiled with an older Metal SDK
# This avoids MSL 3.2 bugs with thread_scope_subgroup and fixes text rendering issues
string(TOLOWER "${platform}" MOLTENVK_ASSET_PLATFORM)
if (NOT EXISTS ${MOLTENVK_DIR})
if (NOT EXISTS ${MOLTENVK_TAR})
file(DOWNLOAD https://github.com/V380-Ori/Ryujinx.MoltenVK/releases/download/${version}-ryujinx/MoltenVK-${MOLTENVK_ASSET_PLATFORM}.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/${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.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_result)
if (NOT aqt_result EQUAL 0)
message(WARNING "aqt install failed, trying without multimedia module")
set(install_args -c "${CURRENT_MODULE_DIR}/aqt_config.ini" install-qt --outputdir ${base_path} ${host} ${type} ${target} ${arch} --archives qttranslations qttools qtsvg qtbase)
execute_process(COMMAND ${aqt_path} ${install_args}
WORKING_DIRECTORY ${base_path})
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})
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()

View File

@@ -0,0 +1,27 @@
# SPDX-FileCopyrightText: 2022 Alexandre Bouvier <contact@amb.tf>
#
# SPDX-License-Identifier: GPL-3.0-or-later
find_path(DiscordRPC_INCLUDE_DIR discord_rpc.h)
find_library(DiscordRPC_LIBRARY discord-rpc)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(DiscordRPC
REQUIRED_VARS
DiscordRPC_LIBRARY
DiscordRPC_INCLUDE_DIR
)
if (DiscordRPC_FOUND AND NOT TARGET DiscordRPC::discord-rpc)
add_library(DiscordRPC::discord-rpc UNKNOWN IMPORTED)
set_target_properties(DiscordRPC::discord-rpc PROPERTIES
IMPORTED_LOCATION "${DiscordRPC_LIBRARY}"
INTERFACE_INCLUDE_DIRECTORIES "${DiscordRPC_INCLUDE_DIR}"
)
endif()
mark_as_advanced(
DiscordRPC_INCLUDE_DIR
DiscordRPC_LIBRARY
)

View File

@@ -0,0 +1,195 @@
# SPDX-FileCopyrightText: 2019 Citra Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later
# FindFFmpeg
# ----------
#
# Find the native FFmpeg includes and libraries
#
# This module defines the following variables:
#
# FFmpeg_INCLUDE_<component>: where to find <component>.h
# FFmpeg_LIBRARY_<component>: where to find the <component> library
# FFmpeg_INCLUDE_DIR: aggregate all the include paths
# FFmpeg_LIBRARIES: aggregate all the paths to the libraries
# FFmpeg_FOUND: True if all components have been found
#
# This module defines the following targets, which are preferred over variables:
#
# FFmpeg::<component>: Target to use <component> directly, with include path,
# library and dependencies set up. If you are using a static build, you are
# responsible for adding any external dependencies (such as zlib, bzlib...).
#
# <component> can be one of:
# avcodec
# avdevice
# avfilter
# avformat
# avutil
# postproc
# swresample
# swscale
#
set(_FFmpeg_ALL_COMPONENTS
avcodec
avdevice
avfilter
avformat
avutil
postproc
swresample
swscale
)
set(_FFmpeg_DEPS_avcodec avutil)
set(_FFmpeg_DEPS_avdevice avcodec avformat avutil)
set(_FFmpeg_DEPS_avfilter avutil)
set(_FFmpeg_DEPS_avformat avcodec avutil)
set(_FFmpeg_DEPS_postproc avutil)
set(_FFmpeg_DEPS_swresample avutil)
set(_FFmpeg_DEPS_swscale avutil)
function(find_ffmpeg LIBNAME)
if(DEFINED ENV{FFMPEG_DIR})
set(FFMPEG_DIR $ENV{FFMPEG_DIR})
endif()
if(FFMPEG_DIR)
list(APPEND INCLUDE_PATHS
${FFMPEG_DIR}
${FFMPEG_DIR}/ffmpeg
${FFMPEG_DIR}/lib${LIBNAME}
${FFMPEG_DIR}/include/lib${LIBNAME}
${FFMPEG_DIR}/include/ffmpeg
${FFMPEG_DIR}/include
NO_DEFAULT_PATH
NO_CMAKE_FIND_ROOT_PATH
)
list(APPEND LIB_PATHS
${FFMPEG_DIR}
${FFMPEG_DIR}/lib
${FFMPEG_DIR}/lib${LIBNAME}
NO_DEFAULT_PATH
NO_CMAKE_FIND_ROOT_PATH
)
else()
list(APPEND INCLUDE_PATHS
/usr/local/include/ffmpeg
/usr/local/include/lib${LIBNAME}
/usr/include/ffmpeg
/usr/include/lib${LIBNAME}
/usr/include/ffmpeg/lib${LIBNAME}
)
list(APPEND LIB_PATHS
/usr/local/lib
/usr/lib
)
endif()
find_path(FFmpeg_INCLUDE_${LIBNAME} lib${LIBNAME}/${LIBNAME}.h
HINTS ${INCLUDE_PATHS}
)
find_library(FFmpeg_LIBRARY_${LIBNAME} ${LIBNAME}
HINTS ${LIB_PATHS}
)
if(NOT FFMPEG_DIR AND (NOT FFmpeg_LIBRARY_${LIBNAME} OR NOT FFmpeg_INCLUDE_${LIBNAME}))
# Didn't find it in the usual paths, try pkg-config
find_package(PkgConfig QUIET)
pkg_check_modules(FFmpeg_PKGCONFIG_${LIBNAME} QUIET lib${LIBNAME})
find_path(FFmpeg_INCLUDE_${LIBNAME} lib${LIBNAME}/${LIBNAME}.h
${FFmpeg_PKGCONFIG_${LIBNAME}_INCLUDE_DIRS}
)
find_library(FFmpeg_LIBRARY_${LIBNAME} ${LIBNAME}
${FFmpeg_PKGCONFIG_${LIBNAME}_LIBRARY_DIRS}
)
endif()
if(FFmpeg_INCLUDE_${LIBNAME} AND FFmpeg_LIBRARY_${LIBNAME})
set(FFmpeg_INCLUDE_${LIBNAME} "${FFmpeg_INCLUDE_${LIBNAME}}" PARENT_SCOPE)
set(FFmpeg_LIBRARY_${LIBNAME} "${FFmpeg_LIBRARY_${LIBNAME}}" PARENT_SCOPE)
# Extract FFmpeg version from version.h
foreach(v MAJOR MINOR MICRO)
set(FFmpeg_${LIBNAME}_VERSION_${v} 0)
endforeach()
string(TOUPPER ${LIBNAME} LIBNAME_UPPER)
file(STRINGS "${FFmpeg_INCLUDE_${LIBNAME}}/lib${LIBNAME}/version.h" _FFmpeg_VERSION_H_CONTENTS REGEX "#define LIB${LIBNAME_UPPER}_VERSION_(MAJOR|MINOR|MICRO) ")
set(_FFmpeg_VERSION_REGEX "([0-9]+)")
foreach(v MAJOR MINOR MICRO)
if("${_FFmpeg_VERSION_H_CONTENTS}" MATCHES "#define LIB${LIBNAME_UPPER}_VERSION_${v}[\\t ]+${_FFmpeg_VERSION_REGEX}")
set(FFmpeg_${LIBNAME}_VERSION_${v} "${CMAKE_MATCH_1}")
endif()
endforeach()
set(FFmpeg_${LIBNAME}_VERSION "${FFmpeg_${LIBNAME}_VERSION_MAJOR}.${FFmpeg_${LIBNAME}_VERSION_MINOR}.${FFmpeg_${LIBNAME}_VERSION_MICRO}")
set(FFmpeg_${c}_VERSION "${FFmpeg_${LIBNAME}_VERSION}" PARENT_SCOPE)
unset(_FFmpeg_VERSION_REGEX)
unset(_FFmpeg_VERSION_H_CONTENTS)
set(FFmpeg_${c}_FOUND TRUE PARENT_SCOPE)
if(NOT FFmpeg_FIND_QUIETLY)
message("-- Found ${LIBNAME}: ${FFmpeg_INCLUDE_${LIBNAME}} ${FFmpeg_LIBRARY_${LIBNAME}} (version: ${FFmpeg_${LIBNAME}_VERSION})")
endif()
endif()
endfunction()
foreach(c ${_FFmpeg_ALL_COMPONENTS})
find_ffmpeg(${c})
endforeach()
foreach(c ${_FFmpeg_ALL_COMPONENTS})
if(FFmpeg_${c}_FOUND)
list(APPEND FFmpeg_INCLUDE_DIR ${FFmpeg_INCLUDE_${c}})
list(APPEND FFmpeg_LIBRARIES ${FFmpeg_LIBRARY_${c}})
add_library(FFmpeg::${c} IMPORTED UNKNOWN)
set_target_properties(FFmpeg::${c} PROPERTIES
IMPORTED_LOCATION ${FFmpeg_LIBRARY_${c}}
INTERFACE_INCLUDE_DIRECTORIES ${FFmpeg_INCLUDE_${c}}
)
if(_FFmpeg_DEPS_${c})
set(deps)
foreach(dep ${_FFmpeg_DEPS_${c}})
list(APPEND deps FFmpeg::${dep})
endforeach()
set_target_properties(FFmpeg::${c} PROPERTIES
INTERFACE_LINK_LIBRARIES "${deps}"
)
unset(deps)
endif()
endif()
endforeach()
if(FFmpeg_INCLUDE_DIR)
list(REMOVE_DUPLICATES FFmpeg_INCLUDE_DIR)
endif()
foreach(c ${FFmpeg_FIND_COMPONENTS})
list(APPEND _FFmpeg_REQUIRED_VARS FFmpeg_INCLUDE_${c} FFmpeg_LIBRARY_${c})
endforeach()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(FFmpeg
REQUIRED_VARS ${_FFmpeg_REQUIRED_VARS}
HANDLE_COMPONENTS
)
foreach(c ${_FFmpeg_ALL_COMPONENTS})
unset(_FFmpeg_DEPS_${c})
endforeach()
unset(_FFmpeg_ALL_COMPONENTS)
unset(_FFmpeg_REQUIRED_VARS)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(FFmpeg
REQUIRED_VARS
FFmpeg_LIBRARIES
FFmpeg_INCLUDE_DIR
HANDLE_COMPONENTS
)

View File

@@ -0,0 +1,26 @@
# SPDX-FileCopyrightText: 2023 Alexandre Bouvier <contact@amb.tf>
#
# SPDX-License-Identifier: GPL-3.0-or-later
find_package(LLVM QUIET COMPONENTS CONFIG)
if (LLVM_FOUND)
separate_arguments(LLVM_DEFINITIONS)
if (LLVMDemangle IN_LIST LLVM_AVAILABLE_LIBS)
set(LLVM_Demangle_FOUND TRUE)
endif()
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(LLVM HANDLE_COMPONENTS CONFIG_MODE)
if (LLVM_FOUND AND LLVM_Demangle_FOUND AND NOT TARGET LLVM::Demangle)
add_library(LLVM::Demangle INTERFACE IMPORTED)
target_compile_definitions(LLVM::Demangle INTERFACE ${LLVM_DEFINITIONS})
target_include_directories(LLVM::Demangle INTERFACE ${LLVM_INCLUDE_DIRS})
# prefer shared LLVM: https://github.com/llvm/llvm-project/issues/34593
# but use ugly hack because llvm_config doesn't support interface library
add_library(_dummy_lib SHARED EXCLUDE_FROM_ALL src/citron/main.cpp)
llvm_config(_dummy_lib USE_SHARED demangle)
get_target_property(LLVM_LIBRARIES _dummy_lib LINK_LIBRARIES)
target_link_libraries(LLVM::Demangle INTERFACE ${LLVM_LIBRARIES})
endif()

View File

@@ -0,0 +1,15 @@
# SPDX-FileCopyrightText: 2022 yuzu Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later
find_package(PkgConfig QUIET)
pkg_search_module(OPUS QUIET IMPORTED_TARGET opus)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Opus
REQUIRED_VARS OPUS_LINK_LIBRARIES
VERSION_VAR OPUS_VERSION
)
if (Opus_FOUND AND NOT TARGET Opus::opus)
add_library(Opus::opus ALIAS PkgConfig::OPUS)
endif()

View File

@@ -0,0 +1,19 @@
# SPDX-FileCopyrightText: 2023 Alexandre Bouvier <contact@amb.tf>
#
# SPDX-License-Identifier: GPL-3.0-or-later
find_path(RenderDoc_INCLUDE_DIR renderdoc_app.h)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(RenderDoc
REQUIRED_VARS RenderDoc_INCLUDE_DIR
)
if (RenderDoc_FOUND AND NOT TARGET RenderDoc::API)
add_library(RenderDoc::API INTERFACE IMPORTED)
set_target_properties(RenderDoc::API PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${RenderDoc_INCLUDE_DIR}"
)
endif()
mark_as_advanced(RenderDoc_INCLUDE_DIR)

View File

@@ -0,0 +1,21 @@
# SPDX-FileCopyrightText: 2023 Alexandre Bouvier <contact@amb.tf>
#
# SPDX-License-Identifier: GPL-3.0-or-later
include(FindPackageHandleStandardArgs)
find_package(SimpleIni QUIET CONFIG)
if (SimpleIni_CONSIDERED_CONFIGS)
find_package_handle_standard_args(SimpleIni CONFIG_MODE)
else()
find_package(PkgConfig QUIET)
pkg_search_module(SIMPLEINI QUIET IMPORTED_TARGET simpleini)
find_package_handle_standard_args(SimpleIni
REQUIRED_VARS SIMPLEINI_INCLUDEDIR
VERSION_VAR SIMPLEINI_VERSION
)
endif()
if (SimpleIni_FOUND AND NOT TARGET SimpleIni::SimpleIni)
add_library(SimpleIni::SimpleIni ALIAS PkgConfig::SIMPLEINI)
endif()

View File

@@ -0,0 +1,16 @@
# SPDX-FileCopyrightText: 2022 Alexandre Bouvier <contact@amb.tf>
#
# SPDX-License-Identifier: GPL-3.0-or-later
find_package(PkgConfig QUIET)
pkg_search_module(ENET QUIET IMPORTED_TARGET libenet)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(enet
REQUIRED_VARS ENET_LINK_LIBRARIES
VERSION_VAR ENET_VERSION
)
if (enet_FOUND AND NOT TARGET enet::enet)
add_library(enet::enet ALIAS PkgConfig::ENET)
endif()

View File

@@ -0,0 +1,15 @@
# SPDX-FileCopyrightText: 2023 yuzu Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later
find_package(PkgConfig QUIET)
pkg_search_module(GAMEMODE QUIET IMPORTED_TARGET gamemode)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(gamemode
REQUIRED_VARS GAMEMODE_INCLUDEDIR
VERSION_VAR GAMEMODE_VERSION
)
if (gamemode_FOUND AND NOT TARGET gamemode::headers)
add_library(gamemode::headers ALIAS PkgConfig::GAMEMODE)
endif()

View File

@@ -0,0 +1,31 @@
# SPDX-FileCopyrightText: 2022 Andrea Pappacoda <andrea@pappacoda.it>
#
# SPDX-License-Identifier: GPL-2.0-or-later
include(FindPackageHandleStandardArgs)
find_package(httplib QUIET CONFIG)
if (httplib_CONSIDERED_CONFIGS)
find_package_handle_standard_args(httplib HANDLE_COMPONENTS CONFIG_MODE)
else()
find_package(PkgConfig QUIET)
pkg_search_module(HTTPLIB QUIET IMPORTED_TARGET cpp-httplib)
if ("-DCPPHTTPLIB_OPENSSL_SUPPORT" IN_LIST HTTPLIB_CFLAGS_OTHER)
set(httplib_OpenSSL_FOUND TRUE)
endif()
if ("-DCPPHTTPLIB_ZLIB_SUPPORT" IN_LIST HTTPLIB_CFLAGS_OTHER)
set(httplib_ZLIB_FOUND TRUE)
endif()
if ("-DCPPHTTPLIB_BROTLI_SUPPORT" IN_LIST HTTPLIB_CFLAGS_OTHER)
set(httplib_Brotli_FOUND TRUE)
endif()
find_package_handle_standard_args(httplib
REQUIRED_VARS HTTPLIB_INCLUDEDIR
VERSION_VAR HTTPLIB_VERSION
HANDLE_COMPONENTS
)
endif()
if (httplib_FOUND AND NOT TARGET httplib::httplib)
add_library(httplib::httplib ALIAS PkgConfig::HTTPLIB)
endif()

View File

@@ -0,0 +1,16 @@
# SPDX-FileCopyrightText: 2022 Alexandre Bouvier <contact@amb.tf>
#
# SPDX-License-Identifier: GPL-3.0-or-later
find_package(PkgConfig QUIET)
pkg_search_module(LIBUSB QUIET IMPORTED_TARGET libusb-1.0)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(libusb
REQUIRED_VARS LIBUSB_LINK_LIBRARIES
VERSION_VAR LIBUSB_VERSION
)
if (libusb_FOUND AND NOT TARGET libusb::usb)
add_library(libusb::usb ALIAS PkgConfig::LIBUSB)
endif()

View File

@@ -0,0 +1,26 @@
# SPDX-FileCopyrightText: 2022 yuzu Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later
include(FindPackageHandleStandardArgs)
find_package(lz4 QUIET CONFIG)
if (lz4_CONSIDERED_CONFIGS)
find_package_handle_standard_args(lz4 CONFIG_MODE)
else()
find_package(PkgConfig QUIET)
pkg_search_module(LZ4 QUIET IMPORTED_TARGET liblz4)
find_package_handle_standard_args(lz4
REQUIRED_VARS LZ4_LINK_LIBRARIES
VERSION_VAR LZ4_VERSION
)
endif()
if (lz4_FOUND AND NOT TARGET lz4::lz4)
if (TARGET LZ4::lz4_shared)
add_library(lz4::lz4 ALIAS LZ4::lz4_shared)
elseif (TARGET LZ4::lz4_static)
add_library(lz4::lz4 ALIAS LZ4::lz4_static)
else()
add_library(lz4::lz4 ALIAS PkgConfig::LZ4)
endif()
endif()

View File

@@ -0,0 +1,31 @@
# SPDX-FileCopyrightText: 2023 Alexandre Bouvier <contact@amb.tf>
#
# SPDX-License-Identifier: GPL-3.0-or-later
find_path(stb_image_INCLUDE_DIR stb_image.h PATH_SUFFIXES stb)
find_path(stb_image_resize_INCLUDE_DIR stb_image_resize.h PATH_SUFFIXES stb)
find_path(stb_image_write_INCLUDE_DIR stb_image_write.h PATH_SUFFIXES stb)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(stb
REQUIRED_VARS
stb_image_INCLUDE_DIR
stb_image_resize_INCLUDE_DIR
stb_image_write_INCLUDE_DIR
)
if (stb_FOUND AND NOT TARGET stb::headers)
add_library(stb::headers INTERFACE IMPORTED)
set_property(TARGET stb::headers PROPERTY
INTERFACE_INCLUDE_DIRECTORIES
"${stb_image_INCLUDE_DIR}"
"${stb_image_resize_INCLUDE_DIR}"
"${stb_image_write_INCLUDE_DIR}"
)
endif()
mark_as_advanced(
stb_image_INCLUDE_DIR
stb_image_resize_INCLUDE_DIR
stb_image_write_INCLUDE_DIR
)

View File

@@ -0,0 +1,26 @@
# SPDX-FileCopyrightText: 2022 yuzu Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later
include(FindPackageHandleStandardArgs)
find_package(zstd QUIET CONFIG)
if (zstd_CONSIDERED_CONFIGS)
find_package_handle_standard_args(zstd CONFIG_MODE)
else()
find_package(PkgConfig QUIET)
pkg_search_module(ZSTD QUIET IMPORTED_TARGET libzstd)
find_package_handle_standard_args(zstd
REQUIRED_VARS ZSTD_LINK_LIBRARIES
VERSION_VAR ZSTD_VERSION
)
endif()
if (zstd_FOUND AND NOT TARGET zstd::zstd)
if (TARGET zstd::libzstd_shared)
add_library(zstd::zstd ALIAS zstd::libzstd_shared)
elseif (TARGET zstd::libzstd_static)
add_library(zstd::zstd ALIAS zstd::libzstd_static)
else()
add_library(zstd::zstd ALIAS PkgConfig::ZSTD)
endif()
endif()

View File

@@ -0,0 +1,79 @@
# SPDX-FileCopyrightText: 2019 yuzu Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later
# Gets a UTC timestamp and sets the provided variable to it
function(get_timestamp _var)
string(TIMESTAMP timestamp UTC)
set(${_var} "${timestamp}" PARENT_SCOPE)
endfunction()
# generate git/build information
include(GetGitRevisionDescription)
if(NOT GIT_REF_SPEC)
get_git_head_revision(GIT_REF_SPEC GIT_REV)
endif()
if(NOT GIT_DESC)
git_describe(GIT_DESC --always --long --dirty)
endif()
if (NOT GIT_BRANCH)
git_branch_name(GIT_BRANCH)
endif()
get_timestamp(BUILD_DATE)
#
# Generate build information based on the CITRON_BUILD_TYPE variable.
#
if(CITRON_BUILD_TYPE STREQUAL "Stable")
# For Stable builds, use a clean version string and an empty build name for the title bar.
set(BUILD_FULLNAME "")
# These variables are set in the root CMakeLists.txt, but we provide a fallback.
if(DEFINED CITRON_VERSION_MAJOR)
set(BUILD_VERSION "${CITRON_VERSION_MAJOR}.${CITRON_VERSION_MINOR}.${CITRON_VERSION_PATCH}")
else()
set(BUILD_VERSION "2026.2.1") # Fallback stable version
endif()
set(BUILD_ID ${DISPLAY_VERSION})
else()
# For Nightly or local developer builds, use the existing logic to generate a name and use the git hash.
set(REPO_NAME "")
set(BUILD_VERSION "0")
set(BUILD_ID ${DISPLAY_VERSION})
if (BUILD_REPOSITORY)
# regex capture the string nightly or canary into CMAKE_MATCH_1
string(REGEX MATCH "citron-emu/citron-?(.*)" OUTVAR ${BUILD_REPOSITORY})
if ("${CMAKE_MATCH_COUNT}" GREATER 0)
# capitalize the first letter of each word in the repo name.
string(REPLACE "-" ";" REPO_NAME_LIST ${CMAKE_MATCH_1})
foreach(WORD ${REPO_NAME_LIST})
string(SUBSTRING ${WORD} 0 1 FIRST_LETTER)
string(SUBSTRING ${WORD} 1 -1 REMAINDER)
string(TOUPPER ${FIRST_LETTER} FIRST_LETTER)
set(REPO_NAME "${REPO_NAME}${FIRST_LETTER}${REMAINDER}")
endforeach()
if (BUILD_TAG)
string(REGEX MATCH "${CMAKE_MATCH_1}-([0-9]+)" OUTVAR ${BUILD_TAG})
if (${CMAKE_MATCH_COUNT} GREATER 0)
set(BUILD_VERSION ${CMAKE_MATCH_1})
endif()
if (BUILD_VERSION)
# This leaves a trailing space on the last word, but we actually want that
# because of how it's styled in the title bar.
set(BUILD_FULLNAME "${REPO_NAME} ${BUILD_VERSION} ")
else()
set(BUILD_FULLNAME "")
endif()
endif()
endif()
endif()
# Add a fallback for local builds
# If BUILD_VERSION is still "0", it means the CI-specific logic was not executed.
# In that case, we should use the git description which contains the commit hash.
if (BUILD_VERSION STREQUAL "0")
set(BUILD_FULLNAME "Nightly ") # Ensure local builds are also identified as Nightly
set(BUILD_VERSION ${GIT_DESC})
endif()
endif()
configure_file(scm_rev.cpp.in scm_rev.cpp @ONLY)

View File

@@ -0,0 +1,15 @@
# SPDX-FileCopyrightText: 2022 yuzu Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
# buildcache wrapper
OPTION(USE_CCACHE "Use buildcache for compilation" OFF)
IF(USE_CCACHE)
FIND_PROGRAM(CCACHE buildcache)
IF (CCACHE)
MESSAGE(STATUS "Using buildcache found in PATH")
SET_PROPERTY(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ${CCACHE})
SET_PROPERTY(GLOBAL PROPERTY RULE_LAUNCH_LINK ${CCACHE})
ELSE(CCACHE)
MESSAGE(WARNING "USE_CCACHE enabled, but no buildcache executable found")
ENDIF(CCACHE)
ENDIF(USE_CCACHE)

View File

@@ -0,0 +1,58 @@
# SPDX-FileCopyrightText: 2022 yuzu Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
set(MINGW_PREFIX /usr/x86_64-w64-mingw32/)
set(CMAKE_SYSTEM_NAME Windows)
set(CMAKE_SYSTEM_PROCESSOR x86_64)
set(CMAKE_FIND_ROOT_PATH ${MINGW_PREFIX})
set(SDL2_PATH ${MINGW_PREFIX})
set(MINGW_TOOL_PREFIX ${CMAKE_SYSTEM_PROCESSOR}-w64-mingw32-)
# Specify the cross compiler
set(CMAKE_C_COMPILER ${MINGW_TOOL_PREFIX}clang)
set(CMAKE_CXX_COMPILER ${MINGW_TOOL_PREFIX}clang++)
set(CMAKE_RC_COMPILER ${MINGW_TOOL_PREFIX}windres)
set(CMAKE_C_COMPILER_AR ${MINGW_TOOL_PREFIX}ar)
set(CMAKE_CXX_COMPILER_AR ${MINGW_TOOL_PREFIX}ar)
set(CMAKE_C_COMPILER_RANLIB ${MINGW_TOOL_PREFIX}ranlib)
set(CMAKE_CXX_COMPILER_RANLIB ${MINGW_TOOL_PREFIX}ranlib)
# Mingw tools
set(STRIP ${MINGW_TOOL_PREFIX}strip)
set(WINDRES ${MINGW_TOOL_PREFIX}windres)
set(ENV{PKG_CONFIG} ${MINGW_TOOL_PREFIX}pkg-config)
# ccache wrapper
option(USE_CCACHE "Use ccache for compilation" OFF)
if(USE_CCACHE)
find_program(CCACHE ccache)
if(CCACHE)
message(STATUS "Using ccache found in PATH")
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ${CCACHE})
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ${CCACHE})
else(CCACHE)
message(WARNING "USE_CCACHE enabled, but no ccache found")
endif(CCACHE)
endif(USE_CCACHE)
# Search for programs in the build host directories
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# Echo modified cmake vars to screen for debugging purposes
if(NOT DEFINED ENV{MINGW_DEBUG_INFO})
message("")
message("Custom cmake vars: (blank = system default)")
message("-----------------------------------------")
message("* CMAKE_C_COMPILER : ${CMAKE_C_COMPILER}")
message("* CMAKE_CXX_COMPILER : ${CMAKE_CXX_COMPILER}")
message("* CMAKE_RC_COMPILER : ${CMAKE_RC_COMPILER}")
message("* WINDRES : ${WINDRES}")
message("* ENV{PKG_CONFIG} : $ENV{PKG_CONFIG}")
message("* STRIP : ${STRIP}")
message("* USE_CCACHE : ${USE_CCACHE}")
message("")
# So that the debug info only appears once
set(ENV{MINGW_DEBUG_INFO} SHOWN)
endif()

View File

@@ -0,0 +1,57 @@
# SPDX-FileCopyrightText: 2018 tech4me <guiwanglong@gmail.com>
# SPDX-License-Identifier: GPL-2.0-or-later
set(MINGW_PREFIX /usr/x86_64-w64-mingw32/)
set(CMAKE_SYSTEM_NAME Windows)
set(CMAKE_SYSTEM_PROCESSOR x86_64)
# Actually a hack, w/o this will cause some strange errors
set(CMAKE_HOST_WIN32 TRUE)
set(CMAKE_FIND_ROOT_PATH ${MINGW_PREFIX})
set(SDL2_PATH ${MINGW_PREFIX})
set(MINGW_TOOL_PREFIX ${CMAKE_SYSTEM_PROCESSOR}-w64-mingw32-)
# Specify the cross compiler
set(CMAKE_C_COMPILER ${MINGW_TOOL_PREFIX}gcc)
set(CMAKE_CXX_COMPILER ${MINGW_TOOL_PREFIX}g++)
set(CMAKE_RC_COMPILER ${MINGW_TOOL_PREFIX}windres)
# Mingw tools
set(STRIP ${MINGW_TOOL_PREFIX}strip)
set(WINDRES ${MINGW_TOOL_PREFIX}windres)
set(ENV{PKG_CONFIG} ${MINGW_TOOL_PREFIX}pkg-config)
# ccache wrapper
option(USE_CCACHE "Use ccache for compilation" OFF)
if(USE_CCACHE)
find_program(CCACHE ccache)
if(CCACHE)
message(STATUS "Using ccache found in PATH")
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ${CCACHE})
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ${CCACHE})
else(CCACHE)
message(WARNING "USE_CCACHE enabled, but no ccache found")
endif(CCACHE)
endif(USE_CCACHE)
# Search for programs in the build host directories
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# Echo modified cmake vars to screen for debugging purposes
if(NOT DEFINED ENV{MINGW_DEBUG_INFO})
message("")
message("Custom cmake vars: (blank = system default)")
message("-----------------------------------------")
message("* CMAKE_C_COMPILER : ${CMAKE_C_COMPILER}")
message("* CMAKE_CXX_COMPILER : ${CMAKE_CXX_COMPILER}")
message("* CMAKE_RC_COMPILER : ${CMAKE_RC_COMPILER}")
message("* WINDRES : ${WINDRES}")
message("* ENV{PKG_CONFIG} : $ENV{PKG_CONFIG}")
message("* STRIP : ${STRIP}")
message("* USE_CCACHE : ${USE_CCACHE}")
message("")
# So that the debug info only appears once
set(ENV{MINGW_DEBUG_INFO} SHOWN)
endif()

245
CMakeModules/PGO.cmake Normal file
View File

@@ -0,0 +1,245 @@
# SPDX-FileCopyrightText: 2025 citron Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later
# Profile-Guided Optimization (PGO) Support
#
# This module provides functions to enable Profile-Guided Optimization (PGO) for Citron.
# PGO is a two-stage compiler optimization technique:
# 1. GENERATE stage: Build with instrumentation to collect profiling data during runtime
# 2. USE stage: Rebuild using the collected profiling data to optimize hot paths
#
# Usage:
# set(CITRON_ENABLE_PGO_GENERATE ON) # First build: generate profiling data
# set(CITRON_ENABLE_PGO_USE ON) # Second build: use profiling data
# set(CITRON_PGO_PROFILE_DIR "${CMAKE_BINARY_DIR}/pgo-profiles") # Optional: custom profile directory
# PGO profile directory - where .pgd/.profraw/.profdata files are stored
if(NOT DEFINED CITRON_PGO_PROFILE_DIR)
set(CITRON_PGO_PROFILE_DIR "${CMAKE_BINARY_DIR}/pgo-profiles" CACHE PATH "Directory to store PGO profile data")
endif()
# Create the profile directory if it doesn't exist
file(MAKE_DIRECTORY "${CITRON_PGO_PROFILE_DIR}")
# Function to copy MSVC PGO runtime DLLs
function(citron_copy_pgo_runtime_dlls target_name)
if(NOT MSVC)
return()
endif()
# Find the Visual Studio installation directory
get_filename_component(MSVC_DIR "${CMAKE_CXX_COMPILER}" DIRECTORY)
get_filename_component(MSVC_DIR "${MSVC_DIR}" DIRECTORY)
get_filename_component(MSVC_DIR "${MSVC_DIR}" DIRECTORY)
# Common locations for PGO runtime DLLs
set(PGO_DLL_PATHS
"${MSVC_DIR}/VC/Redist/MSVC/*/x64/Microsoft.VC*.CRT/pgort140.dll"
"${MSVC_DIR}/VC/Redist/MSVC/*/x86/Microsoft.VC*.CRT/pgort140.dll"
"${MSVC_DIR}/VC/Tools/MSVC/*/bin/Hostx64/x64/pgort140.dll"
"${MSVC_DIR}/VC/Tools/MSVC/*/bin/Hostx64/x86/pgort140.dll"
"${MSVC_DIR}/VC/Tools/MSVC/*/bin/Hostx86/x64/pgort140.dll"
"${MSVC_DIR}/VC/Tools/MSVC/*/bin/Hostx86/x86/pgort140.dll"
)
# Find the PGO runtime DLL
set(PGO_DLL_FOUND FALSE)
foreach(dll_pattern ${PGO_DLL_PATHS})
file(GLOB PGO_DLL_CANDIDATES ${dll_pattern})
if(PGO_DLL_CANDIDATES)
list(GET PGO_DLL_CANDIDATES 0 PGO_DLL_PATH)
set(PGO_DLL_FOUND TRUE)
break()
endif()
endforeach()
if(PGO_DLL_FOUND)
message(STATUS " [${target_name}] Found PGO runtime DLL: ${PGO_DLL_PATH}")
# Get the target's output directory
get_target_property(TARGET_OUTPUT_DIR ${target_name} RUNTIME_OUTPUT_DIRECTORY)
if(NOT TARGET_OUTPUT_DIR)
get_target_property(TARGET_OUTPUT_DIR ${target_name} RUNTIME_OUTPUT_DIRECTORY_DEBUG)
endif()
if(NOT TARGET_OUTPUT_DIR)
set(TARGET_OUTPUT_DIR "${CMAKE_BINARY_DIR}/bin")
endif()
# Copy the DLL to the output directory
add_custom_command(TARGET ${target_name} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${PGO_DLL_PATH}"
"${TARGET_OUTPUT_DIR}/"
COMMENT "Copying PGO runtime DLL for ${target_name}"
)
else()
message(WARNING "PGO runtime DLL (pgort140.dll) not found. The instrumented build may not run properly.")
message(STATUS " Please ensure Visual Studio is properly installed with PGO support.")
message(STATUS " You may need to install the 'MSVC v143 - VS 2022 C++ x64/x86 build tools' component.")
endif()
endfunction()
# Function to configure PGO for a specific target
function(citron_configure_pgo target_name)
if(NOT TARGET ${target_name})
message(WARNING "Target ${target_name} does not exist, skipping PGO configuration")
return()
endif()
# Only configure PGO if either GENERATE or USE is enabled
if(NOT CITRON_ENABLE_PGO_GENERATE AND NOT CITRON_ENABLE_PGO_USE)
return()
endif()
# Ensure both stages are not enabled at the same time
if(CITRON_ENABLE_PGO_GENERATE AND CITRON_ENABLE_PGO_USE)
message(FATAL_ERROR "Cannot enable both CITRON_ENABLE_PGO_GENERATE and CITRON_ENABLE_PGO_USE simultaneously. Please build twice: first with GENERATE, then with USE.")
endif()
message(STATUS "Configuring PGO for target: ${target_name}")
# MSVC-specific PGO
if(MSVC)
if(CITRON_ENABLE_PGO_GENERATE)
message(STATUS " [${target_name}] MSVC PGO: GENERATE stage")
target_compile_options(${target_name} PRIVATE /GL)
target_link_options(${target_name} PRIVATE
/LTCG
/FASTGENPROFILE
/PGD:"${CITRON_PGO_PROFILE_DIR}/${target_name}.pgd"
)
citron_copy_pgo_runtime_dlls(${target_name})
elseif(CITRON_ENABLE_PGO_USE)
message(STATUS " [${target_name}] MSVC PGO: USE stage")
set(PGD_FILE "${CITRON_PGO_PROFILE_DIR}/${target_name}.pgd")
get_target_property(TARGET_OUTPUT_DIR ${target_name} RUNTIME_OUTPUT_DIRECTORY)
if(NOT TARGET_OUTPUT_DIR)
set(TARGET_OUTPUT_DIR "${CMAKE_BINARY_DIR}/bin")
endif()
set(PGD_FILE_OUTPUT "${TARGET_OUTPUT_DIR}/${target_name}.pgd")
if(EXISTS "${PGD_FILE}")
target_compile_options(${target_name} PRIVATE /GL)
file(TO_NATIVE_PATH "${PGD_FILE}" PGD_FILE_NATIVE)
target_link_options(${target_name} PRIVATE
/LTCG
"/USEPROFILE:PGD=${PGD_FILE_NATIVE}"
)
message(STATUS " [${target_name}] Using profile data: ${PGD_FILE}")
elseif(EXISTS "${PGD_FILE_OUTPUT}")
target_compile_options(${target_name} PRIVATE /GL)
file(TO_NATIVE_PATH "${PGD_FILE_OUTPUT}" PGD_FILE_NATIVE)
target_link_options(${target_name} PRIVATE
/LTCG
"/USEPROFILE:PGD=${PGD_FILE_NATIVE}"
)
message(STATUS " [${target_name}] Using profile data: ${PGD_FILE_OUTPUT}")
else()
message(WARNING "Profile data not found for ${target_name}. Checked:")
message(STATUS " - ${PGD_FILE}")
message(STATUS " - ${PGD_FILE_OUTPUT}")
message(WARNING "PGO USE stage will be skipped.")
endif()
endif()
# GCC-specific PGO
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
if(CITRON_ENABLE_PGO_GENERATE)
message(STATUS " [${target_name}] GCC PGO: GENERATE stage")
target_compile_options(${target_name} PRIVATE -fprofile-generate -fprofile-dir=${CITRON_PGO_PROFILE_DIR})
target_link_options(${target_name} PRIVATE -fprofile-generate -fprofile-dir=${CITRON_PGO_PROFILE_DIR})
elseif(CITRON_ENABLE_PGO_USE)
message(STATUS " [${target_name}] GCC PGO: USE stage")
file(GLOB profile_files "${CITRON_PGO_PROFILE_DIR}/*.gcda")
if(profile_files)
target_compile_options(${target_name} PRIVATE -fprofile-use -fprofile-correction -fprofile-dir=${CITRON_PGO_PROFILE_DIR})
target_link_options(${target_name} PRIVATE -fprofile-use -fprofile-dir=${CITRON_PGO_PROFILE_DIR})
message(STATUS " [${target_name}] Using profile data from: ${CITRON_PGO_PROFILE_DIR}")
else()
message(WARNING "No profile data found for ${target_name} in ${CITRON_PGO_PROFILE_DIR}. PGO USE stage will be skipped.")
endif()
endif()
# Clang-specific PGO
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
if(CITRON_ENABLE_PGO_GENERATE)
message(STATUS " [${target_name}] Clang PGO: GENERATE stage")
target_compile_options(${target_name} PRIVATE -fprofile-instr-generate)
target_link_options(${target_name} PRIVATE -fprofile-instr-generate)
elseif(CITRON_ENABLE_PGO_USE)
message(STATUS " [${target_name}] Clang PGO: USE stage")
set(PROFDATA_FILE "${CITRON_PGO_PROFILE_DIR}/default.profdata")
if(NOT EXISTS "${PROFDATA_FILE}")
file(GLOB profraw_files "${CITRON_PGO_PROFILE_DIR}/*.profraw")
if(profraw_files)
find_program(LLVM_PROFDATA llvm-profdata)
if(LLVM_PROFDATA)
message(STATUS " [${target_name}] Merging .profraw files into ${PROFDATA_FILE}")
execute_process(
COMMAND ${LLVM_PROFDATA} merge -output=${PROFDATA_FILE} ${profraw_files}
RESULT_VARIABLE merge_result
OUTPUT_QUIET
ERROR_QUIET
)
if(NOT merge_result EQUAL 0)
message(WARNING "Failed to merge profile data for ${target_name}. PGO USE stage will be skipped.")
return()
endif()
else()
message(WARNING "llvm-profdata not found. Cannot merge profile data. PGO USE stage will be skipped.")
return()
endif()
else()
message(WARNING "No .profraw files found in ${CITRON_PGO_PROFILE_DIR}. PGO USE stage will be skipped.")
return()
endif()
endif()
if(EXISTS "${PROFDATA_FILE}")
target_compile_options(${target_name} PRIVATE -fprofile-instr-use=${PROFDATA_FILE})
target_link_options(${target_name} PRIVATE -fprofile-instr-use=${PROFDATA_FILE})
message(STATUS " [${target_name}] Using profile data: ${PROFDATA_FILE}")
endif()
endif()
else()
message(WARNING "PGO is not supported for compiler: ${CMAKE_CXX_COMPILER_ID}")
endif()
endfunction()
# Helper function to print PGO instructions
function(citron_print_pgo_instructions)
if(CITRON_ENABLE_PGO_GENERATE)
message(STATUS "")
message(STATUS "=================================================================")
message(STATUS "PGO GENERATE Stage")
message(STATUS "=================================================================")
message(STATUS "Citron has been built with profiling instrumentation.")
message(STATUS "")
message(STATUS "Next steps:")
message(STATUS " 1. Run the built citron executable from its directory (e.g., ./build)")
message(STATUS " 2. Play games/perform typical operations to generate profile data")
message(STATUS " 3. Exit citron cleanly (use Ctrl+Q or File -> Exit)")
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
message(STATUS " 4. For Clang: Profile data (*.profraw) will be in the directory you ran citron from.")
message(STATUS " MOVE these files to the profile directory with:")
message(STATUS " mv default*.profraw ${CITRON_PGO_PROFILE_DIR}/")
message(STATUS " 5. Merge the profile data with:")
message(STATUS " llvm-profdata merge -output=${CITRON_PGO_PROFILE_DIR}/default.profdata ${CITRON_PGO_PROFILE_DIR}/*.profraw")
else()
message(STATUS " 4. Profile data will be saved to: ${CITRON_PGO_PROFILE_DIR}")
endif()
message(STATUS " 6. Rebuild with: cmake -DCITRON_ENABLE_PGO_GENERATE=OFF -DCITRON_ENABLE_PGO_USE=ON .")
message(STATUS "=================================================================")
message(STATUS "")
elseif(CITRON_ENABLE_PGO_USE)
message(STATUS "")
message(STATUS "=================================================================")
message(STATUS "PGO USE Stage")
message(STATUS "=================================================================")
message(STATUS "Citron is being optimized using profile data from: ${CITRON_PGO_PROFILE_DIR}")
message(STATUS "This build will be significantly faster than standard builds.")
message(STATUS "=================================================================")
message(STATUS "")
endif()
endfunction()

View File

@@ -0,0 +1,27 @@
# SPDX-FileCopyrightText: 2018 yuzu Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later
# This file provides the function windows_copy_files.
# This is only valid on Windows.
# Include guard
if(__windows_copy_files)
return()
endif()
set(__windows_copy_files YES)
# Any number of files to copy from SOURCE_DIR to DEST_DIR can be specified after DEST_DIR.
# This copying happens post-build.
function(windows_copy_files TARGET SOURCE_DIR DEST_DIR)
# windows commandline expects the / to be \ so switch them
string(REPLACE "/" "\\\\" SOURCE_DIR ${SOURCE_DIR})
string(REPLACE "/" "\\\\" DEST_DIR ${DEST_DIR})
# /NJH /NJS /NDL /NFL /NC /NS /NP - Silence any output
# cmake adds an extra check for command success which doesn't work too well with robocopy
# so trick it into thinking the command was successful with the || cmd /c "exit /b 0"
add_custom_command(TARGET ${TARGET} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E make_directory ${DEST_DIR}
COMMAND robocopy ${SOURCE_DIR} ${DEST_DIR} ${ARGN} /NJH /NJS /NDL /NFL /NC /NS /NP || cmd /c "exit /b 0"
)
endfunction()

View File

@@ -0,0 +1,31 @@
# SPDX-FileCopyrightText: 2025 citron Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
[aqt]
concurrency: 4
[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/