From 52cc25ccbf5faf3ae0ee33e9e28e998440f5c424 Mon Sep 17 00:00:00 2001 From: lat9nq <22451773+lat9nq@users.noreply.github.com> Date: Wed, 19 May 2021 17:18:33 -0400 Subject: [PATCH] cmake: Download Qt binaries on Linux if needed If the local version of Qt is older than the minimum version required by yuzu, download a pre-built binary package from yuzu-emu/ext-linux-bin and build yuzu with it, instead. This also requires linking yuzu to the correct libraries after building it, and copying over the required binaries when building yuzu. This sets the Qt requirement to 5.12, which is intentionally behind the versions used by our toolchains since they are not all updated yet to 5.15. --- CMakeLists.txt | 32 +++++-- CMakeModules/CopyYuzuQt5Deps.cmake | 135 +++++++++++++++++++++-------- src/yuzu/CMakeLists.txt | 13 ++- 3 files changed, 134 insertions(+), 46 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e70f29636b..b17bc9c0f1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,7 +17,7 @@ CMAKE_DEPENDENT_OPTION(YUZU_ALLOW_SYSTEM_SDL2 "Try using system SDL2 before fall option(ENABLE_QT "Enable the Qt frontend" ON) option(ENABLE_QT_TRANSLATION "Enable translations for the Qt frontend" OFF) -CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_QT "Download bundled Qt binaries" ON "ENABLE_QT;MSVC" OFF) +CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_QT "Download bundled Qt binaries" MSVC "ENABLE_QT" OFF) option(ENABLE_WEB_SERVICE "Enable web services (telemetry, etc.)" ON) @@ -240,6 +240,7 @@ yuzu_find_packages() # Qt5 requires that we find components, so it doesn't fit our pretty little find package function if(ENABLE_QT) + set(QT_VERSION 5.12) # We want to load the generated conan qt config so that we get the QT_ROOT var so that we can use the official # Qt5Config inside the root folder instead of the conan generated one. if(EXISTS ${CMAKE_BINARY_DIR}/qtConfig.cmake) @@ -247,22 +248,40 @@ if(ENABLE_QT) list(APPEND CMAKE_MODULE_PATH "${CONAN_QT_ROOT_RELEASE}") list(APPEND CMAKE_PREFIX_PATH "${CONAN_QT_ROOT_RELEASE}") endif() + + # Check for system Qt on Linux, fallback to bundled Qt + if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux") + if (NOT YUZU_USE_BUNDLED_QT) + find_package(Qt5 ${QT_VERSION} COMPONENTS Widgets QUIET) + if (NOT Qt5_FOUND) + set(YUZU_USE_BUNDLED_QT ON CACHE BOOL "Download bundled Qt" FORCE) + endif() + endif() + if (YUZU_USE_BUNDLED_QT) + # Binary package currently does not support Qt webengine, so make sure it's disabled + set(YUZU_USE_QT_WEB_ENGINE OFF CACHE BOOL "Use Qt Webengine" FORCE) + endif() + endif() + # Workaround for an issue where conan tries to build Qt from scratch instead of download prebuilt binaries set(QT_PREFIX_HINT) + if(YUZU_USE_BUNDLED_QT) if ((MSVC_VERSION GREATER_EQUAL 1910 AND MSVC_VERSION LESS 1930) AND ARCHITECTURE_x86_64) - set(QT_VER qt-5.12.8-msvc2017_64) + set(QT_BUILD qt-5.12.8-msvc2017_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 YUZU_USE_BUNDLED_QT and provide your own.") endif() - if (DEFINED QT_VER) - download_bundled_external("qt/" ${QT_VER} QT_PREFIX) + if (DEFINED QT_BUILD) + download_bundled_external("qt/" ${QT_BUILD} QT_PREFIX) endif() set(QT_PREFIX_HINT HINTS "${QT_PREFIX}") endif() - find_package(Qt5 5.9 COMPONENTS Widgets ${QT_PREFIX_HINT}) + find_package(Qt5 ${QT_VERSION} REQUIRED COMPONENTS Widgets ${QT_PREFIX_HINT} NO_CMAKE_SYSTEM_PATH) if (YUZU_USE_QT_WEB_ENGINE) find_package(Qt5 COMPONENTS WebEngineCore WebEngineWidgets) endif() @@ -271,6 +290,7 @@ if(ENABLE_QT) find_package(Qt5 REQUIRED COMPONENTS LinguistTools ${QT_PREFIX_HINT}) endif() endif() + # find SDL2 exports a bunch of variables that are needed, so its easier to do this outside of the yuzu_find_package if (ENABLE_SDL2) if (YUZU_USE_BUNDLED_SDL2) @@ -379,7 +399,7 @@ if (CONAN_REQUIRED_LIBS) if(ENABLE_QT) list(APPEND CMAKE_MODULE_PATH "${CONAN_QT_ROOT_RELEASE}") list(APPEND CMAKE_PREFIX_PATH "${CONAN_QT_ROOT_RELEASE}") - find_package(Qt5 5.9 REQUIRED COMPONENTS Widgets) + find_package(Qt5 5.12 REQUIRED COMPONENTS Widgets) if (YUZU_USE_QT_WEB_ENGINE) find_package(Qt5 REQUIRED COMPONENTS WebEngineCore WebEngineWidgets) endif() diff --git a/CMakeModules/CopyYuzuQt5Deps.cmake b/CMakeModules/CopyYuzuQt5Deps.cmake index 59343b1ca8..4a6aeebbb3 100644 --- a/CMakeModules/CopyYuzuQt5Deps.cmake +++ b/CMakeModules/CopyYuzuQt5Deps.cmake @@ -1,52 +1,111 @@ function(copy_yuzu_Qt5_deps target_dir) include(WindowsCopyFiles) - set(DLL_DEST "${CMAKE_BINARY_DIR}/bin/$/") - set(Qt5_DLL_DIR "${Qt5_DIR}/../../../bin") + if (MSVC) + set(DLL_DEST "${CMAKE_BINARY_DIR}/bin/$/") + 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_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(STYLES ${DLL_DEST}plugins/styles/) set(IMAGEFORMATS ${DLL_DEST}plugins/imageformats/) - windows_copy_files(${target_dir} ${Qt5_DLL_DIR} ${DLL_DEST} - icudt*.dll - icuin*.dll - icuuc*.dll - Qt5Core$<$:d>.* - Qt5Gui$<$:d>.* - Qt5Widgets$<$:d>.* - ) - - if (YUZU_USE_QT_WEB_ENGINE) - windows_copy_files(${target_dir} ${Qt5_DLL_DIR} ${DLL_DEST} - Qt5Network$<$:d>.* - Qt5Positioning$<$:d>.* - Qt5PrintSupport$<$:d>.* - Qt5Qml$<$:d>.* - Qt5Quick$<$:d>.* - Qt5QuickWidgets$<$:d>.* - Qt5WebChannel$<$:d>.* - Qt5WebEngine$<$:d>.* - Qt5WebEngineCore$<$:d>.* - Qt5WebEngineWidgets$<$:d>.* - QtWebEngineProcess$<$:d>.* + if (MSVC) + windows_copy_files(${target_dir} ${Qt5_DLL_DIR} ${DLL_DEST} + icudt*.dll + icuin*.dll + icuuc*.dll + Qt5Core$<$:d>.* + Qt5Gui$<$:d>.* + Qt5Widgets$<$:d>.* ) - windows_copy_files(${target_dir} ${Qt5_RESOURCES_DIR} ${DLL_DEST} - qtwebengine_resources.pak - qtwebengine_devtools_resources.pak - qtwebengine_resources_100p.pak - qtwebengine_resources_200p.pak - icudtl.dat - ) - endif () - windows_copy_files(yuzu ${Qt5_PLATFORMS_DIR} ${PLATFORMS} qwindows$<$:d>.*) - windows_copy_files(yuzu ${Qt5_STYLES_DIR} ${STYLES} qwindowsvistastyle$<$:d>.*) - windows_copy_files(yuzu ${Qt5_IMAGEFORMATS_DIR} ${IMAGEFORMATS} - qjpeg$<$:d>.* - qgif$<$:d>.* - ) + if (YUZU_USE_QT_WEB_ENGINE) + windows_copy_files(${target_dir} ${Qt5_DLL_DIR} ${DLL_DEST} + Qt5Network$<$:d>.* + Qt5Positioning$<$:d>.* + Qt5PrintSupport$<$:d>.* + Qt5Qml$<$:d>.* + Qt5Quick$<$:d>.* + Qt5QuickWidgets$<$:d>.* + Qt5WebChannel$<$:d>.* + Qt5WebEngine$<$:d>.* + Qt5WebEngineCore$<$:d>.* + Qt5WebEngineWidgets$<$:d>.* + QtWebEngineProcess$<$:d>.* + ) + + windows_copy_files(${target_dir} ${Qt5_RESOURCES_DIR} ${DLL_DEST} + qtwebengine_resources.pak + qtwebengine_devtools_resources.pak + qtwebengine_resources_100p.pak + qtwebengine_resources_200p.pak + icudtl.dat + ) + endif () + windows_copy_files(yuzu ${Qt5_PLATFORMS_DIR} ${PLATFORMS} qwindows$<$:d>.*) + windows_copy_files(yuzu ${Qt5_STYLES_DIR} ${STYLES} qwindowsvistastyle$<$:d>.*) + windows_copy_files(yuzu ${Qt5_IMAGEFORMATS_DIR} ${IMAGEFORMATS} + qjpeg$<$:d>.* + qgif$<$: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 yuzu POST_BUILD diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index cc0790e077..634fe66a5c 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt @@ -4,6 +4,12 @@ set(CMAKE_AUTOUIC ON) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/CMakeModules) +# Set the RPATH for Qt Libraries +# This must be done before the `yuzu` target is created +if (YUZU_USE_BUNDLED_QT AND (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")) + set(CMAKE_BUILD_RPATH "${CMAKE_BINARY_DIR}/bin/lib/") +endif() + add_executable(yuzu Info.plist about_dialog.cpp @@ -278,11 +284,14 @@ if(UNIX AND NOT APPLE) install(TARGETS yuzu RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}/bin") endif() -if (MSVC) +if (YUZU_USE_BUNDLED_QT) include(CopyYuzuQt5Deps) + copy_yuzu_Qt5_deps(yuzu) +endif() + +if (MSVC) include(CopyYuzuSDLDeps) include(CopyYuzuFFmpegDeps) - copy_yuzu_Qt5_deps(yuzu) copy_yuzu_SDL_deps(yuzu) copy_yuzu_FFmpeg_deps(yuzu) endif()