From 04bb1ee5dac2c856a542e79ec2cdabaa2026e271 Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Fri, 17 Sep 2021 14:20:38 +0200 Subject: [PATCH] Fix QtProjectImporter test for Qt 6.2 versions in PATH In Qt 5, qmake is statically linked to the bootstrap library, so just copying qmake somewhere results in a runnable executable. In Qt 6 this changed, and qmake depends on the dynamic QtCore library, and on Linux also on ICU. Copy these in addition to the qmake executable. Keep the directory structure as in Qt, so the dynamic linker finds them. Change-Id: Ie4f6b617bc91d847b1e4fe38dc8a1c603eae4087 Reviewed-by: Christian Kandeler --- src/plugins/qtsupport/qtprojectimporter.cpp | 51 ++++++++++++++++++--- 1 file changed, 45 insertions(+), 6 deletions(-) diff --git a/src/plugins/qtsupport/qtprojectimporter.cpp b/src/plugins/qtsupport/qtprojectimporter.cpp index 19e9054fb43..d3b25312f2b 100644 --- a/src/plugins/qtsupport/qtprojectimporter.cpp +++ b/src/plugins/qtsupport/qtprojectimporter.cpp @@ -33,7 +33,8 @@ #include #include -#include +#include +#include #include #include @@ -41,6 +42,7 @@ #include using namespace ProjectExplorer; +using namespace Utils; namespace QtSupport { @@ -269,14 +271,51 @@ void TestQtProjectImporter::deleteDirectoryData(void *directoryData) const delete static_cast(directoryData); } +static QStringList additionalFilesToCopy(const BaseQtVersion *qt) +{ + // This is a hack and only works with local, "standard" installations of Qt + const int major = qt->qtVersion().majorVersion; + if (major >= 6) { + if (HostOsInfo::isMacHost()) { + return {"lib/QtCore.framework/Versions/A/QtCore"}; + } else if (HostOsInfo::isWindowsHost()) { + const QString release = QString("bin/Qt%1Core.dll").arg(major); + const QString debug = QString("bin/Qt%1Cored.dll").arg(major); + const FilePath base = qt->qmakeFilePath().parentDir().parentDir(); + if (base.pathAppended(release).exists()) + return {release}; + if (base.pathAppended(debug).exists()) + return {debug}; + return {release}; + } else if (HostOsInfo::isLinuxHost()) { + const QString core = QString("lib/libQt%1Core.so.%1").arg(major); + const QDir base(qt->qmakeFilePath().parentDir().parentDir().pathAppended("lib").toString()); + const QStringList icuLibs = Utils::transform(base.entryList({"libicu*.so.*"}), [](const QString &lib) { return QString("lib/" + lib); }); + return QStringList(core) + icuLibs; + } + } + return {}; +} + static Utils::FilePath setupQmake(const BaseQtVersion *qt, const QString &path) { - const QFileInfo fi = QFileInfo(qt->qmakeFilePath().toFileInfo().canonicalFilePath()); - const QString qmakeFile = path + "/" + fi.fileName(); - if (!QFile::copy(fi.absoluteFilePath(), qmakeFile)) - return Utils::FilePath(); + // This is a hack and only works with local, "standard" installations of Qt + const FilePath qmake = qt->qmakeFilePath().canonicalPath(); + const QString qmakeFile = "bin/" + qmake.fileName(); + const FilePath source = qmake.parentDir().parentDir(); + const FilePath target = FilePath::fromString(path); - return Utils::FilePath::fromString(qmakeFile); + const QStringList filesToCopy = QStringList(qmakeFile) + additionalFilesToCopy(qt); + for (const QString &file : filesToCopy) { + const FilePath sourceFile = source.pathAppended(file); + const FilePath targetFile = target.pathAppended(file); + if (!targetFile.parentDir().ensureWritableDir() || !sourceFile.copyFile(targetFile)) { + qDebug() << "Failed to copy" << sourceFile.toString() << "to" << targetFile.toString(); + return {}; + } + } + + return target.pathAppended(qmakeFile); } void QtSupportPlugin::testQtProjectImporter_oneProject_data()