From 474cd6b1c7dc7b8f338d914ec89bc79f0fbe9361 Mon Sep 17 00:00:00 2001 From: Dale Glass Date: Mon, 21 Dec 2020 20:58:11 +0100 Subject: [PATCH] Improve Qt handling in CMake Support 3 options: * VIRCADIA_USE_SYSTEM_QT is set -- use system's Qt * VIRCADIA_QT_PATH is set -- use Qt found in that dir * Otherwise -- use downloaded Qt package This removes these variables: * VIRCADIA_USE_QT_VERSION * VIRCADIA_USE_PREBUILT_QT * HIFI_QT_BASE --- cmake/macros/SetupQt.cmake | 14 +++ hifi_qt.py | 100 +++++++++++++++--- interface/CMakeLists.txt | 32 +++--- .../src/controllers/UserInputMapper.cpp | 4 + tools/nitpick/CMakeLists.txt | 2 +- tools/skeleton-dump/src/SkeletonDumpApp.cpp | 5 + 6 files changed, 126 insertions(+), 31 deletions(-) diff --git a/cmake/macros/SetupQt.cmake b/cmake/macros/SetupQt.cmake index 6f31a3994c..35a22ecb4d 100644 --- a/cmake/macros/SetupQt.cmake +++ b/cmake/macros/SetupQt.cmake @@ -25,6 +25,9 @@ function(calculate_qt5_version result _QT_DIR) set(_QT_CORE_DIR "${_QT_DIR}/lib/QtCore.framework/Versions/5/Headers") else() set(_QT_CORE_DIR "${_QT_DIR}/include/QtCore") + if(NOT EXISTS "${_QT_CORE_DIR}") + set(_QT_CORE_DIR "${_QT_DIR}/include/qt5/QtCore") + endif() endif() if(NOT EXISTS "${_QT_CORE_DIR}") message(FATAL_ERROR "Could not find 'include/QtCore' in '${_QT_DIR}'") @@ -78,6 +81,17 @@ macro(setup_qt) message(FATAL_ERROR "Unable to locate Qt5CoreConfig.cmake in '${QT_CMAKE_PREFIX_PATH}'") endif() + set(RCC_BINARY "${QT_DIR}/bin/rcc") + + if(NOT EXISTS "${RCC_BINARY}") + set(RCC_BINARY "${QT_DIR}/bin/rcc-qt5") + endif() + + if(NOT EXISTS "${RCC_BINARY}") + message(FATAL_ERROR "Unable to locate rcc '${QT_DIR}'") + endif() + + message(STATUS "Using Qt build in : '${QT_DIR}' with version ${QT_VERSION}") # Instruct CMake to run moc automatically when needed. diff --git a/hifi_qt.py b/hifi_qt.py index 7ee8a787b5..dbff6319ff 100644 --- a/hifi_qt.py +++ b/hifi_qt.py @@ -28,18 +28,83 @@ endif() self.args = args self.configFilePath = os.path.join(args.build_root, 'qt.cmake') self.version = os.getenv('VIRCADIA_USE_QT_VERSION', '5.15.2') - self.assets_url = hifi_utils.readEnviromentVariableFromFile(args.build_root, 'EXTERNAL_BUILD_ASSETS') - defaultBasePath = os.path.expanduser('~/hifi/qt') - self.basePath = os.getenv('HIFI_QT_BASE', defaultBasePath) - if (not os.path.isdir(self.basePath)): - os.makedirs(self.basePath) - self.path = os.path.join(self.basePath, self.version) - self.fullPath = os.path.join(self.path, 'qt5-install') - self.cmakePath = os.path.join(self.fullPath, 'lib/cmake') + # OS dependent information + system = platform.system() - print("Using qt path {}".format(self.path)) + qt_found = False + + # Here we handle the 3 possible cases of dealing with Qt: + if os.getenv('VIRCADIA_USE_SYSTEM_QT'): + # 1. Using the system provided Qt. This is only recommended for Qt 5.15.0 and above, + # as it includes a required fix on Linux. + # + # This path only works on Linux as neither Windows nor OSX ship Qt. + + if system != "Linux": + raise Exception("Using the system Qt is only supported on Linux") + + cmake_paths = [ "lib64/cmake", "lib/cmake" ] + cmake_path_ok = False + + # This makes the lockFile stuff happy. Needs to be writable. + self.path = tempfile.mkdtemp() + + self.fullPath = '/usr' + + # Find the cmake directory + for cp in cmake_paths: + self.cmakePath = os.path.join(self.fullPath, cp) + if os.path.isdir(self.cmakePath): + cmake_path_ok = True + break + + if not cmake_path_ok: + raise Exception("Failed to find cmake directory. Looked under " + self.fullPath + " in " + (', '.join(cmake_paths))) + + qt_found = True + print("Using system Qt") + + elif os.getenv('VIRCADIA_QT_PATH'): + # 2. Using an user-provided directory. + # VIRCADIA_QT_PATH must point to a directory with a Qt install in it. + + self.path = os.getenv('VIRCADIA_QT_PATH') + self.fullPath = self.path + self.cmakePath = os.path.join(self.fullPath, 'lib/cmake') + + qt_found = True + print("Using Qt from " + self.fullPath) + + else: + # 3. Using a pre-built Qt. + # + # This works somewhat differently from above, notice how path and fullPath are + # used differently in this case. + # + # In the case of an user-provided directory, we just use the user-supplied directory. + # + # For a pre-built qt, however, we have to unpack it. The archive is required to contain + # a qt5-install directory in it. + + self.path = os.path.expanduser("~/vircadia-files/qt") + self.fullPath = os.path.join(self.path, 'qt5-install') + self.cmakePath = os.path.join(self.fullPath, 'lib/cmake') + + if (not os.path.isdir(self.path)): + os.makedirs(self.path) + + qt_found = os.path.isdir(self.fullPath) + print("Using a packaged Qt") + + if qt_found: + # Sanity check, ensure we have a good cmake directory + if not os.path.isdir(os.path.join(self.cmakePath, "Qt5")): + raise Exception("Failed to find Qt5 directory under " + self.cmakePath) + + # I'm not sure why this is needed. It's used by hifi_singleton. + # Perhaps it stops multiple build processes from interferring? lockDir, lockName = os.path.split(self.path) lockName += '.lock' if not os.path.isdir(lockDir): @@ -47,21 +112,16 @@ endif() self.lockFile = os.path.join(lockDir, lockName) - if (os.getenv('VIRCADIA_USE_PREBUILT_QT')): - print("Using pre-built Qt5") + if qt_found: + print("Found pre-built Qt5") return - # OS dependent information - system = platform.system() - cpu_architecture = platform.machine() - if 'Windows' == system: self.qtUrl = self.assets_url + '/dependencies/vcpkg/qt5-install-5.15.2-windows.tar.gz' elif 'Darwin' == system: self.qtUrl = self.assets_url + '/dependencies/vcpkg/qt5-install-5.15.2-macos.tar.gz' elif 'Linux' == system: import distro - dist = distro.linux_distribution() if 'x86_64' == cpu_architecture: if distro.id() == 'ubuntu': @@ -124,6 +184,14 @@ endif() print("Machine : " + platform.machine()) raise Exception('UNKNOWN OPERATING SYSTEM!!!') + def showQtBuildInfo(self): + print("") + print("It's also possible to build Qt for your distribution, please see the documentation at:") + print("https://github.com/vircadia/vircadia/tree/master/tools/qt-builder") + print("") + print("Alternatively, you can try building against the system Qt by setting the VIRCADIA_USE_SYSTEM_QT environment variable.") + print("You'll need to install the development packages, and to have Qt 5.15.0 or newer. ") + def writeConfig(self): print("Writing cmake config to {}".format(self.configFilePath)) # Write out the configuration for use by CMake diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index c307c63142..142fda15ce 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -34,14 +34,14 @@ if (ANDROID) add_custom_command( OUTPUT ${RESOURCES_RCC} DEPENDS ${RESOURCES_QRC} ${GENERATE_QRC_DEPENDS} - COMMAND "${QT_DIR}/bin/rcc" + COMMAND "${RCC_BINARY}" ARGS ${RESOURCES_QRC} -no-compress -binary -o ${RESOURCES_RCC} ) else () add_custom_command( OUTPUT ${RESOURCES_RCC} DEPENDS ${RESOURCES_QRC} ${GENERATE_QRC_DEPENDS} - COMMAND "${QT_DIR}/bin/rcc" + COMMAND "${RCC_BINARY}" ARGS ${RESOURCES_QRC} -binary -o ${RESOURCES_RCC} ) endif() @@ -199,6 +199,8 @@ endif() if (WIN32 OR APPLE) add_dependencies(${TARGET_NAME} resources) +if (WIN32 OR APPLE OR UNIX) + add_dependencies(${TARGET_NAME} resources screenshare) endif() if (SCREENSHARE) @@ -435,18 +437,20 @@ else() endif() endif() -if (DEV_BUILD AND (APPLE OR UNIX)) - # create a qt.conf file to override hard-coded search paths in Qt libs - set(QT_LIB_PATH "${QT_CMAKE_PREFIX_PATH}/../..") - if (APPLE) - set(QT_CONF_FILE "${RESOURCES_DEV_DIR}/../Resources/qt.conf") - else () - set(QT_CONF_FILE "${INTERFACE_EXEC_DIR}/qt.conf") - endif () - file(GENERATE - OUTPUT "${QT_CONF_FILE}" - CONTENT "[Paths]\nPrefix=${QT_LIB_PATH}\n" - ) +if (NOT $ENV{VIRCADIA_USE_SYSTEM_QT}) + if (DEV_BUILD AND (APPLE OR UNIX)) + # create a qt.conf file to override hard-coded search paths in Qt libs + set(QT_LIB_PATH "${QT_CMAKE_PREFIX_PATH}/../..") + if (APPLE) + set(QT_CONF_FILE "${RESOURCES_DEV_DIR}/../Resources/qt.conf") + else () + set(QT_CONF_FILE "${INTERFACE_EXEC_DIR}/qt.conf") + endif () + file(GENERATE + OUTPUT "${QT_CONF_FILE}" + CONTENT "[Paths]\nPrefix=${QT_LIB_PATH}\n" + ) + endif() endif() if (SCRIPTS_INSTALL_DIR) diff --git a/libraries/controllers/src/controllers/UserInputMapper.cpp b/libraries/controllers/src/controllers/UserInputMapper.cpp index 6333792b3f..b5e07d5691 100755 --- a/libraries/controllers/src/controllers/UserInputMapper.cpp +++ b/libraries/controllers/src/controllers/UserInputMapper.cpp @@ -44,6 +44,10 @@ #include "impl/Route.h" #include "impl/Mapping.h" +#if QT_VERSION > QT_VERSION_CHECK(5, 13, 0) +// FIXME: Remove this after Qt 5.15 upgrade +#define endl Qt::endl +#endif namespace controller { const uint16_t UserInputMapper::STANDARD_DEVICE = 0; diff --git a/tools/nitpick/CMakeLists.txt b/tools/nitpick/CMakeLists.txt index 8b4a5d03df..18ee84c0e5 100644 --- a/tools/nitpick/CMakeLists.txt +++ b/tools/nitpick/CMakeLists.txt @@ -12,7 +12,7 @@ generate_qrc(OUTPUT ${RESOURCES_QRC} PATH ${CMAKE_CURRENT_SOURCE_DIR}/resources add_custom_command( OUTPUT ${RESOURCES_RCC} DEPENDS ${RESOURCES_QRC} ${GENERATE_QRC_DEPENDS} - COMMAND "${QT_DIR}/bin/rcc" + COMMAND "${RCC_BINARY}" ARGS ${RESOURCES_QRC} -binary -o ${RESOURCES_RCC} ) diff --git a/tools/skeleton-dump/src/SkeletonDumpApp.cpp b/tools/skeleton-dump/src/SkeletonDumpApp.cpp index 42a1c78090..e3169098d6 100644 --- a/tools/skeleton-dump/src/SkeletonDumpApp.cpp +++ b/tools/skeleton-dump/src/SkeletonDumpApp.cpp @@ -15,6 +15,11 @@ #include #include +#if QT_VERSION > QT_VERSION_CHECK(5, 13, 0) +// FIXME: Remove this after Qt 5.15 upgrade +#define endl Qt::endl +#endif + SkeletonDumpApp::SkeletonDumpApp(int argc, char* argv[]) : QCoreApplication(argc, argv) { // parse command-line