CMake: rework for Qt6 support

This PR rearranges things in the CMake system to make compiling with Qt6 possible

1. Camera API has changed in Qt6, so the camera feature is disabled
2. A previous fix involving QLocale is now version gated.
3. QRegExp replaced with QRegularExpression, see #5343
4. Qt6_LOCATION option added to specify a location to search for Qt6
  (see examples below)
5. windeployqt is used to copy Qt6 files into the build directory on Windows

Notes for Arch Linux
Arch install happened to have qt6-base qt6-declarative qt6-translations installed

mkdir build && cd build
cmake .. -GNinja -DYUZU_USE_BUNDLED_VCPKG=ON -DYUZU_TESTS=OFF -DENABLE_QT6=YES -DYUZU_USE_BUNDLED_QT=NO

Windows (MSVC)
Qt wants users to download precompiled libraries via an online installer,
it is worth noting that the GPL/LGPL takes precendence over any ...

In the Qt Maintenance tool, under a version, such as 6.3.1
Select "MSVC 2019 64-bit"
Under Additional Libraries Qt Multimedia may be of use for Camera support

For the Web Applet I had to select the following:
PDF Positioning WebChannel WebEngine

mkdir build && cd build
cmake -G "Visual Studio 16 2019" -DQt6_LOCATION=C:/Qt/6.4.0/msvc2019_64/ \
-DENABLE_COMPATIBILITY_LIST_DOWNLOAD=YES -DYUZU_USE_BUNDLED_QT=NO \
-DENABLE_QT_TRANSLATION=YES -DENABLE_QT6=YES ..

Some numbers for reference (msvc2019_64)
Qt5 (slimmed down) 508 MB
Qt5.15.2 all in    929 MB
Qt6.3.1           1.71 GB
Qt6.3.2           1.73 GB
Qt6.4.0-beta3     1.83 GB
Qt6.4.0           1.67 GB
This commit is contained in:
Kyle Kienapfel 2022-10-17 16:55:40 -07:00
parent d23a35dfbd
commit a75542ad2d
5 changed files with 192 additions and 130 deletions

View File

@ -19,6 +19,9 @@ CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_SDL2 "Download bundled SDL2 binaries" ON
CMAKE_DEPENDENT_OPTION(YUZU_USE_EXTERNAL_SDL2 "Compile external SDL2" ON "ENABLE_SDL2;NOT MSVC" OFF) CMAKE_DEPENDENT_OPTION(YUZU_USE_EXTERNAL_SDL2 "Compile external SDL2" ON "ENABLE_SDL2;NOT MSVC" OFF)
option(ENABLE_QT "Enable the Qt frontend" ON) 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) option(ENABLE_QT_TRANSLATION "Enable translations for the Qt frontend" OFF)
CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_QT "Download bundled Qt binaries" "${MSVC}" "ENABLE_QT" OFF) CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_QT "Download bundled Qt binaries" "${MSVC}" "ENABLE_QT" OFF)
@ -28,6 +31,8 @@ option(YUZU_USE_BUNDLED_LIBUSB "Compile bundled libusb" OFF)
option(YUZU_USE_BUNDLED_FFMPEG "Download/Build bundled FFmpeg" "${WIN32}") option(YUZU_USE_BUNDLED_FFMPEG "Download/Build bundled FFmpeg" "${WIN32}")
option(YUZU_USE_QT_MULTIMEDIA "Use QtMultimedia for Camera" OFF)
option(YUZU_USE_QT_WEB_ENGINE "Use QtWebEngine for web applet implementation" OFF) option(YUZU_USE_QT_WEB_ENGINE "Use QtWebEngine for web applet implementation" OFF)
option(ENABLE_CUBEB "Enables the cubeb audio backend" ON) option(ENABLE_CUBEB "Enables the cubeb audio backend" ON)
@ -213,21 +218,64 @@ if (MINGW)
find_library(MSWSOCK_LIBRARY mswsock REQUIRED) find_library(MSWSOCK_LIBRARY mswsock REQUIRED)
endif() endif()
# Please consider this as a stub
if(ENABLE_QT6 AND Qt6_LOCATION)
list(APPEND CMAKE_PREFIX_PATH "${Qt6_LOCATION}")
endif()
function(set_yuzu_qt_components)
# Best practice is to ask for all components at once, so they are from the same version
set(YUZU_QT_COMPONENTS2 Core Widgets Concurrent)
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
list(APPEND YUZU_QT_COMPONENTS2 DBus)
endif()
if (YUZU_USE_QT_MULTIMEDIA)
list(APPEND YUZU_QT_COMPONENTS2 Multimedia)
endif()
if (YUZU_USE_QT_WEB_ENGINE)
list(APPEND YUZU_QT_COMPONENTS2 WebEngineCore WebEngineWidgets)
endif()
if (ENABLE_QT_TRANSLATION)
list(APPEND YUZU_QT_COMPONENTS2 LinguistTools)
endif()
set(YUZU_QT_COMPONENTS ${YUZU_QT_COMPONENTS2} PARENT_SCOPE)
endfunction(set_yuzu_qt_components)
# Qt5 requires that we find components, so it doesn't fit our pretty little find package function # Qt5 requires that we find components, so it doesn't fit our pretty little find package function
if(ENABLE_QT) if(ENABLE_QT)
set(QT_VERSION 5.15) set(QT_VERSION 5.15)
# These are used to specify minimum versions
set(QT5_VERSION 5.15)
set(QT6_VERSION 6.3.1)
set_yuzu_qt_components()
if (ENABLE_QT6)
find_package(Qt6 ${QT6_VERSION} COMPONENTS ${YUZU_QT_COMPONENTS})
endif()
if (Qt6_FOUND)
message(STATUS "yuzu/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 "yuzu/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(YUZU_USE_QT_MULTIMEDIA ON)
# Check for system Qt on Linux, fallback to bundled Qt # Check for system Qt on Linux, fallback to bundled Qt
if (UNIX AND NOT APPLE) if (UNIX AND NOT APPLE)
if (NOT YUZU_USE_BUNDLED_QT) if (NOT YUZU_USE_BUNDLED_QT)
find_package(Qt5 ${QT_VERSION} COMPONENTS Widgets DBus Multimedia) find_package(Qt5 ${QT5_VERSION} COMPONENTS Widgets DBus Multimedia)
endif() endif()
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux" AND (NOT Qt5_FOUND OR YUZU_USE_BUNDLED_QT)) if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux" AND (NOT Qt5_FOUND OR YUZU_USE_BUNDLED_QT))
# Check for dependencies, then enable bundled Qt download # Check for dependencies, then enable bundled Qt download
# Check that the system GLIBCXX version is compatible # Check that the system GLIBCXX version is compatible
find_program(OBJDUMP objdump) find_program(OBJDUMP objdump)
if ("${OBJDUMP}" STREQUAL "OBJDUMP-NOTFOUND") if (NOT OBJDUMP)
message(FATAL_ERROR "Required program `objdump` not found.") message(FATAL_ERROR "Required program `objdump` not found.")
endif() endif()
find_library(LIBSTDCXX libstdc++.so.6) find_library(LIBSTDCXX libstdc++.so.6)
@ -285,7 +333,7 @@ if(ENABLE_QT)
set(UNRESOLVED_QT_DEPS "") set(UNRESOLVED_QT_DEPS "")
foreach (REQUIREMENT ${BUNDLED_QT_REQUIREMENTS}) foreach (REQUIREMENT ${BUNDLED_QT_REQUIREMENTS})
find_library(BUNDLED_QT_${REQUIREMENT} ${REQUIREMENT}) find_library(BUNDLED_QT_${REQUIREMENT} ${REQUIREMENT})
if ("${BUNDLED_QT_${REQUIREMENT}}" STREQUAL "BUNDLED_QT_${REQUIREMENT}-NOTFOUND") if (NOT BUNDLED_QT_${REQUIREMENT})
set(UNRESOLVED_QT_DEPS ${UNRESOLVED_QT_DEPS} ${REQUIREMENT}) set(UNRESOLVED_QT_DEPS ${UNRESOLVED_QT_DEPS} ${REQUIREMENT})
endif() endif()
unset(BUNDLED_QT_${REQUIREMENT}) unset(BUNDLED_QT_${REQUIREMENT})
@ -322,19 +370,14 @@ if(ENABLE_QT)
set(QT_PREFIX_HINT HINTS "${QT_PREFIX}") set(QT_PREFIX_HINT HINTS "${QT_PREFIX}")
set(YUZU_QT_NO_CMAKE_SYSTEM_PATH "NO_CMAKE_SYSTEM_PATH") set(YUZU_QT_NO_CMAKE_SYSTEM_PATH "NO_CMAKE_SYSTEM_PATH")
endif() # Binary package for Qt5 has Qt Multimedia
if (UNIX AND NOT APPLE AND YUZU_USE_BUNDLED_QT) set(YUZU_USE_QT_MULTIMEDIA ON CACHE BOOL "Use Qt Multimedia" FORCE)
find_package(Qt5 ${QT_VERSION} REQUIRED COMPONENTS Widgets Concurrent Multimedia DBus ${QT_PREFIX_HINT} ${YUZU_QT_NO_CMAKE_SYSTEM_PATH})
else()
find_package(Qt5 ${QT_VERSION} REQUIRED COMPONENTS Widgets Concurrent Multimedia ${QT_PREFIX_HINT} ${YUZU_QT_NO_CMAKE_SYSTEM_PATH})
endif()
if (YUZU_USE_QT_WEB_ENGINE)
find_package(Qt5 REQUIRED COMPONENTS WebEngineCore WebEngineWidgets)
endif() endif()
if (ENABLE_QT_TRANSLATION) set_yuzu_qt_components()
find_package(Qt5 REQUIRED COMPONENTS LinguistTools ${QT_PREFIX_HINT}) find_package(Qt5 ${QT5_VERSION} COMPONENTS ${YUZU_QT_COMPONENTS} ${QT_PREFIX_HINT} ${YUZU_QT_NO_CMAKE_SYSTEM_PATH})
endif() endif()
endif() endif()
# find SDL2 exports a bunch of variables that are needed, so its easier to do this outside of the yuzu_find_package # find SDL2 exports a bunch of variables that are needed, so its easier to do this outside of the yuzu_find_package

View File

@ -27,10 +27,13 @@ function(copy_yuzu_Qt5_deps target_dir)
Qt5Core$<$<CONFIG:Debug>:d>.* Qt5Core$<$<CONFIG:Debug>:d>.*
Qt5Gui$<$<CONFIG:Debug>:d>.* Qt5Gui$<$<CONFIG:Debug>:d>.*
Qt5Widgets$<$<CONFIG:Debug>:d>.* Qt5Widgets$<$<CONFIG:Debug>:d>.*
Qt5Multimedia$<$<CONFIG:Debug>:d>.*
Qt5Network$<$<CONFIG:Debug>:d>.* Qt5Network$<$<CONFIG:Debug>:d>.*
) )
if (YUZU_USE_QT_MULTIMEDIA)
windows_copy_files(${target_dir} ${Qt5_DLL_DIR} ${DLL_DEST}
Qt5Multimedia$<$<CONFIG:Debug>:d>.*
)
endif()
if (YUZU_USE_QT_WEB_ENGINE) if (YUZU_USE_QT_WEB_ENGINE)
windows_copy_files(${target_dir} ${Qt5_DLL_DIR} ${DLL_DEST} windows_copy_files(${target_dir} ${Qt5_DLL_DIR} ${DLL_DEST}
Qt5Network$<$<CONFIG:Debug>:d>.* Qt5Network$<$<CONFIG:Debug>:d>.*

View File

@ -292,7 +292,7 @@ if (APPLE)
set_target_properties(yuzu PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist) set_target_properties(yuzu PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist)
elseif(WIN32) elseif(WIN32)
# compile as a win32 gui application instead of a console application # compile as a win32 gui application instead of a console application
if (QT_VERSION VERSION_GREATER 6) if (QT_VERSION VERSION_GREATER_EQUAL 6)
target_link_libraries(yuzu PRIVATE Qt6::EntryPointPrivate) target_link_libraries(yuzu PRIVATE Qt6::EntryPointPrivate)
else() else()
target_link_libraries(yuzu PRIVATE Qt5::WinMain) target_link_libraries(yuzu PRIVATE Qt5::WinMain)
@ -308,15 +308,15 @@ endif()
create_target_directory_groups(yuzu) create_target_directory_groups(yuzu)
target_link_libraries(yuzu PRIVATE common core input_common network video_core) target_link_libraries(yuzu PRIVATE common core input_common network video_core)
target_link_libraries(yuzu PRIVATE Boost::boost glad Qt::Widgets Qt::Multimedia) target_link_libraries(yuzu PRIVATE Boost::boost glad Qt${QT_MAJOR_VERSION}::Widgets)
target_link_libraries(yuzu PRIVATE ${PLATFORM_LIBRARIES} Threads::Threads) target_link_libraries(yuzu PRIVATE ${PLATFORM_LIBRARIES} Threads::Threads)
target_include_directories(yuzu PRIVATE ../../externals/Vulkan-Headers/include) target_include_directories(yuzu PRIVATE ../../externals/Vulkan-Headers/include)
if (NOT WIN32) if (NOT WIN32)
target_include_directories(yuzu PRIVATE ${Qt5Gui_PRIVATE_INCLUDE_DIRS}) target_include_directories(yuzu PRIVATE ${Qt${QT_MAJOR_VERSION}Gui_PRIVATE_INCLUDE_DIRS})
endif() endif()
if (UNIX AND NOT APPLE) if (UNIX AND NOT APPLE)
target_link_libraries(yuzu PRIVATE Qt::DBus) target_link_libraries(yuzu PRIVATE Qt${QT_MAJOR_VERSION}::DBus)
endif() endif()
target_compile_definitions(yuzu PRIVATE target_compile_definitions(yuzu PRIVATE
@ -355,8 +355,13 @@ if (ENABLE_WEB_SERVICE)
target_compile_definitions(yuzu PRIVATE -DENABLE_WEB_SERVICE) target_compile_definitions(yuzu PRIVATE -DENABLE_WEB_SERVICE)
endif() endif()
if (YUZU_USE_QT_MULTIMEDIA)
target_link_libraries(yuzu PRIVATE Qt${QT_MAJOR_VERSION}::Multimedia)
target_compile_definitions(yuzu PRIVATE -DYUZU_USE_QT_MULTIMEDIA)
endif ()
if (YUZU_USE_QT_WEB_ENGINE) if (YUZU_USE_QT_WEB_ENGINE)
target_link_libraries(yuzu PRIVATE Qt::WebEngineCore Qt::WebEngineWidgets) target_link_libraries(yuzu PRIVATE Qt${QT_MAJOR_VERSION}::WebEngineCore Qt${QT_MAJOR_VERSION}::WebEngineWidgets)
target_compile_definitions(yuzu PRIVATE -DYUZU_USE_QT_WEB_ENGINE) target_compile_definitions(yuzu PRIVATE -DYUZU_USE_QT_WEB_ENGINE)
endif () endif ()
@ -364,7 +369,16 @@ if(UNIX AND NOT APPLE)
install(TARGETS yuzu) install(TARGETS yuzu)
endif() endif()
if (YUZU_USE_BUNDLED_QT) if (WIN32 AND QT_VERSION VERSION_GREATER_EQUAL 6)
if (MSVC AND NOT ${CMAKE_GENERATOR} STREQUAL "Ninja")
set(YUZU_EXE_DIR "${CMAKE_BINARY_DIR}/bin/$<CONFIG>")
else()
set(YUZU_EXE_DIR "${CMAKE_BINARY_DIR}/bin")
endif()
add_custom_command(TARGET yuzu POST_BUILD COMMAND ${WINDEPLOYQT_EXECUTABLE} "${YUZU_EXE_DIR}/yuzu.exe" --dir "${YUZU_EXE_DIR}" --libdir "${YUZU_EXE_DIR}" --plugindir "${YUZU_EXE_DIR}/plugins" --no-compiler-runtime --no-opengl-sw --no-system-d3d-compiler --no-translations --verbose 0)
endif()
if (YUZU_USE_BUNDLED_QT AND QT_VERSION VERSION_LESS 6)
include(CopyYuzuQt5Deps) include(CopyYuzuQt5Deps)
copy_yuzu_Qt5_deps(yuzu) copy_yuzu_Qt5_deps(yuzu)
endif() endif()

View File

@ -4,7 +4,7 @@
#include <QComboBox> #include <QComboBox>
#include <QFuture> #include <QFuture>
#include <QIntValidator> #include <QIntValidator>
#include <QRegExpValidator> #include <QRegularExpressionValidator>
#include <QString> #include <QString>
#include <QtConcurrent/QtConcurrentRun> #include <QtConcurrent/QtConcurrentRun>
#include "common/settings.h" #include "common/settings.h"

View File

@ -3,7 +3,7 @@
#pragma once #pragma once
#include <QRegExp> #include <QRegularExpression>
#include <QString> #include <QString>
#include <QValidator> #include <QValidator>
@ -29,19 +29,21 @@ public:
private: private:
/// room name can be alphanumeric and " " "_" "." and "-" and must have a size of 4-20 /// room name can be alphanumeric and " " "_" "." and "-" and must have a size of 4-20
QRegExp room_name_regex = QRegExp(QStringLiteral("^[a-zA-Z0-9._- ]{4,20}$")); QRegularExpression room_name_regex =
QRegExpValidator room_name; QRegularExpression(QStringLiteral("^[a-zA-Z0-9._ -]{4,20}"));
QRegularExpressionValidator room_name;
/// nickname can be alphanumeric and " " "_" "." and "-" and must have a size of 4-20 /// nickname can be alphanumeric and " " "_" "." and "-" and must have a size of 4-20
QRegExp nickname_regex = QRegExp(QStringLiteral("^[a-zA-Z0-9._- ]{4,20}$")); const QRegularExpression nickname_regex =
QRegExpValidator nickname; QRegularExpression(QStringLiteral("^[a-zA-Z0-9._ -]{4,20}"));
QRegularExpressionValidator nickname;
/// ipv4 address only /// ipv4 address only
// TODO remove this when we support hostnames in direct connect // TODO remove this when we support hostnames in direct connect
QRegExp ip_regex = QRegExp(QStringLiteral( QRegularExpression ip_regex = QRegularExpression(QStringLiteral(
"(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|" "(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|"
"2[0-4][0-9]|25[0-5])")); "2[0-4][0-9]|25[0-5])"));
QRegExpValidator ip; QRegularExpressionValidator ip;
/// port must be between 0 and 65535 /// port must be between 0 and 65535
QIntValidator port; QIntValidator port;