diff --git a/share/qtcreator/translations/qtcreator_cs.ts b/share/qtcreator/translations/qtcreator_cs.ts index b7e0efc99e3..086b2dfea0b 100644 --- a/share/qtcreator/translations/qtcreator_cs.ts +++ b/share/qtcreator/translations/qtcreator_cs.ts @@ -32121,16 +32121,16 @@ Spustil jste Qemu? Qt %1 (%2) - qmake does not exist or is not executable - Soubor qmake neexistuje nebo není spustitelný + %1 does not exist or is not executable + Soubor %1 neexistuje nebo není spustitelný Qt version is not properly installed, please run make install Verze Qt není správně nainstalována. Proveďte, prosím, příkaz "make install" - Could not determine the path to the binaries of the Qt installation, maybe the qmake path is wrong? - Cestu ke spustitelným souborům instalace Qt se nepodařilo určit. Možná je cesta k qmake chybná? + Could not determine the path to the binaries of the Qt installation, maybe the %1 path is wrong? + Cestu ke spustitelným souborům instalace Qt se nepodařilo určit. Možná je cesta k %1 chybná? The default mkspec symlink is broken. diff --git a/share/qtcreator/translations/qtcreator_da.ts b/share/qtcreator/translations/qtcreator_da.ts index 4cfd3841b60..21dd2fad82d 100644 --- a/share/qtcreator/translations/qtcreator_da.ts +++ b/share/qtcreator/translations/qtcreator_da.ts @@ -35382,16 +35382,16 @@ For flere detaljer, se /etc/sysctl.d/10-ptrace.conf Ingen qmake-sti sat - qmake does not exist or is not executable - qmake findes ikke eller er ikke eksekverbar + %1 does not exist or is not executable + %1 findes ikke eller er ikke eksekverbar Qt version is not properly installed, please run make install Qt version er ikke ordentligt installeret, kør venligst make install - Could not determine the path to the binaries of the Qt installation, maybe the qmake path is wrong? - Kunne ikke beslutte stien til binærene af Qt installationen, måske er qmake-stien forkert? + Could not determine the path to the binaries of the Qt installation, maybe the %1 path is wrong? + Kunne ikke beslutte stien til binærene af Qt installationen, måske er %1-stien forkert? The default mkspec symlink is broken. diff --git a/share/qtcreator/translations/qtcreator_de.ts b/share/qtcreator/translations/qtcreator_de.ts index 8013bb9b20e..49d5e966da9 100644 --- a/share/qtcreator/translations/qtcreator_de.ts +++ b/share/qtcreator/translations/qtcreator_de.ts @@ -10113,8 +10113,8 @@ Dies ist unabhängig vom Wert der Eigenschaft "visible" in QML.Es ist keine qmake-Pfad gesetzt - qmake does not exist or is not executable - Die qmake-Datei existiert nicht oder ist nicht ausführbar + %1 does not exist or is not executable + Die %1-Datei existiert nicht oder ist nicht ausführbar Qt version has no name @@ -10141,8 +10141,8 @@ Dies ist unabhängig vom Wert der Eigenschaft "visible" in QML.Die Qt-Version ist nicht richtig installiert, führen Sie bitte make install aus - Could not determine the path to the binaries of the Qt installation, maybe the qmake path is wrong? - Der Pfad zu den ausführbaren Dateien der Qt-Installation konnte nicht bestimmt werden, möglicherweise ist der Pfad zu qmake falsch? + Could not determine the path to the binaries of the Qt installation, maybe the %1 path is wrong? + Der Pfad zu den ausführbaren Dateien der Qt-Installation konnte nicht bestimmt werden, möglicherweise ist der Pfad zu %1 falsch? The default mkspec symlink is broken. diff --git a/share/qtcreator/translations/qtcreator_fr.ts b/share/qtcreator/translations/qtcreator_fr.ts index ec42c365792..2e632c21390 100644 --- a/share/qtcreator/translations/qtcreator_fr.ts +++ b/share/qtcreator/translations/qtcreator_fr.ts @@ -33604,8 +33604,8 @@ Nous allons essayer de travailler avec cela mais vous pourrez rencontrer des pro Chemin de qmake non spécifié - qmake does not exist or is not executable - qmake n'existe pas ou n'est pas exécutable + %1 does not exist or is not executable + %1 n'existe pas ou n'est pas exécutable Qt version has no name @@ -33633,8 +33633,8 @@ Nous allons essayer de travailler avec cela mais vous pourrez rencontrer des pro La version de Qt n'est pas correctement installée, veuillez exécuter make install - Could not determine the path to the binaries of the Qt installation, maybe the qmake path is wrong? - Impossible de déterminer le chemin vers les programmes de Qt, peut-être que le chemin vers qmake est faux ? + Could not determine the path to the binaries of the Qt installation, maybe the %1 path is wrong? + Impossible de déterminer le chemin vers les programmes de Qt, peut-être que le chemin vers %1 est faux ? The default mkspec symlink is broken. diff --git a/share/qtcreator/translations/qtcreator_hr.ts b/share/qtcreator/translations/qtcreator_hr.ts index e7a14f06a9c..c60ce6f3c59 100644 --- a/share/qtcreator/translations/qtcreator_hr.ts +++ b/share/qtcreator/translations/qtcreator_hr.ts @@ -41628,7 +41628,7 @@ Saving failed. - qmake does not exist or is not executable + %1 does not exist or is not executable @@ -41636,7 +41636,7 @@ Saving failed. - Could not determine the path to the binaries of the Qt installation, maybe the qmake path is wrong? + Could not determine the path to the binaries of the Qt installation, maybe the %1 path is wrong? diff --git a/share/qtcreator/translations/qtcreator_ja.ts b/share/qtcreator/translations/qtcreator_ja.ts index c65ccab4138..017e3ebc611 100644 --- a/share/qtcreator/translations/qtcreator_ja.ts +++ b/share/qtcreator/translations/qtcreator_ja.ts @@ -26108,16 +26108,16 @@ Do you want to save the data first? qmake のパスが設定されていません - qmake does not exist or is not executable - qmake が存在しないか実行可能ではありません + %1 does not exist or is not executable + %1 が存在しないか実行可能ではありません Qt version is not properly installed, please run make install Qt バージョンが正しくインストールされていません。make install を実行してください - Could not determine the path to the binaries of the Qt installation, maybe the qmake path is wrong? - Qt インストール先のパスが特定できませんでした。qmake のパスが間違っていませんか? + Could not determine the path to the binaries of the Qt installation, maybe the %1 path is wrong? + Qt インストール先のパスが特定できませんでした。%1 のパスが間違っていませんか? The default mkspec symlink is broken. diff --git a/share/qtcreator/translations/qtcreator_pl.ts b/share/qtcreator/translations/qtcreator_pl.ts index 4bd2dfddc49..288c0333976 100644 --- a/share/qtcreator/translations/qtcreator_pl.ts +++ b/share/qtcreator/translations/qtcreator_pl.ts @@ -12382,8 +12382,8 @@ Dla projektów CMake, upewnij się, że zmienna QML_IMPORT_PATH jest obecna w CM Nie ustawiono ścieżki do qmake - qmake does not exist or is not executable - Brak qmake lub nie jest on plikiem wykonywalnym + %1 does not exist or is not executable + Brak %1 lub nie jest on plikiem wykonywalnym Qt version has no name @@ -12410,8 +12410,8 @@ Dla projektów CMake, upewnij się, że zmienna QML_IMPORT_PATH jest obecna w CM Wersja Qt zainstalowana niepoprawnie, uruchom komendę: make install - Could not determine the path to the binaries of the Qt installation, maybe the qmake path is wrong? - Nie można określić ścieżki do plików binarnych instalacji Qt. Sprawdź ścieżkę do qmake. + Could not determine the path to the binaries of the Qt installation, maybe the %1 path is wrong? + Nie można określić ścieżki do plików binarnych instalacji Qt. Sprawdź ścieżkę do %1. The default mkspec symlink is broken. diff --git a/share/qtcreator/translations/qtcreator_ru.ts b/share/qtcreator/translations/qtcreator_ru.ts index ca1e07984e3..038c8b7d562 100644 --- a/share/qtcreator/translations/qtcreator_ru.ts +++ b/share/qtcreator/translations/qtcreator_ru.ts @@ -45319,8 +45319,8 @@ For more details, see /etc/sysctl.d/10-ptrace.conf Путь к qmake не указан - qmake does not exist or is not executable - qmake отсутствует или не запускается + %1 does not exist or is not executable + %1 отсутствует или не запускается Qt version has no name @@ -45347,8 +45347,8 @@ For more details, see /etc/sysctl.d/10-ptrace.conf Профиль Qt не установлен, пожалуйста выполните make install - Could not determine the path to the binaries of the Qt installation, maybe the qmake path is wrong? - Не удалось определить путь к утилитам Qt. Может путь к qmake неверен? + Could not determine the path to the binaries of the Qt installation, maybe the %1 path is wrong? + Не удалось определить путь к утилитам Qt. Может путь к %1 неверен? The default mkspec symlink is broken. diff --git a/share/qtcreator/translations/qtcreator_sl.ts b/share/qtcreator/translations/qtcreator_sl.ts index ca8f7d46bb3..ed9bf70dfb4 100644 --- a/share/qtcreator/translations/qtcreator_sl.ts +++ b/share/qtcreator/translations/qtcreator_sl.ts @@ -21803,8 +21803,8 @@ Projekte programov QML izvede pregledovalnik QML in jih ni potrebno zgraditi. - qmake does not exist or is not executable - Datoteka »qmake« ne obstaja ali pa ni izvršljiva + %1 does not exist or is not executable + Datoteka »%1« ne obstaja ali pa ni izvršljiva @@ -21813,8 +21813,8 @@ Projekte programov QML izvede pregledovalnik QML in jih ni potrebno zgraditi. - Could not determine the path to the binaries of the Qt installation, maybe the qmake path is wrong? - Ni bilo moč ugotoviti poti do programov namestitve Qt. Morda je pot do qmake napačna? + Could not determine the path to the binaries of the Qt installation, maybe the %1 path is wrong? + Ni bilo moč ugotoviti poti do programov namestitve Qt. Morda je pot do %1 napačna? diff --git a/share/qtcreator/translations/qtcreator_uk.ts b/share/qtcreator/translations/qtcreator_uk.ts index 7ed2f44691f..b3c68dd579c 100644 --- a/share/qtcreator/translations/qtcreator_uk.ts +++ b/share/qtcreator/translations/qtcreator_uk.ts @@ -22711,8 +22711,8 @@ For more details, see /etc/sysctl.d/10-ptrace.conf Шлях до qmake не задано - qmake does not exist or is not executable - qmake не існує або не є виконуваним модулем + %1 does not exist or is not executable + %1 не існує або не є виконуваним модулем ABI detection failed: Make sure to use a matching compiler when building. @@ -22763,8 +22763,8 @@ For more details, see /etc/sysctl.d/10-ptrace.conf Версія Qt не встановлена як слід, будь ласка, запустіть make install - Could not determine the path to the binaries of the Qt installation, maybe the qmake path is wrong? - Не вдалось визначити шлях до виконуваних модулів встановлення Qt, можливо, шлях до qmake помилковий? + Could not determine the path to the binaries of the Qt installation, maybe the %1 path is wrong? + Не вдалось визначити шлях до виконуваних модулів встановлення Qt, можливо, шлях до %1 помилковий? The default mkspec symlink is broken. diff --git a/share/qtcreator/translations/qtcreator_zh_CN.ts b/share/qtcreator/translations/qtcreator_zh_CN.ts index 8e6d46bd95c..64fa094ec3c 100644 --- a/share/qtcreator/translations/qtcreator_zh_CN.ts +++ b/share/qtcreator/translations/qtcreator_zh_CN.ts @@ -27948,8 +27948,8 @@ Did you start Qemu? 没有设置qmake路径 - qmake does not exist or is not executable - qmake不存在或者不可执行 + %1 does not exist or is not executable + %1不存在或者不可执行 Qt version has no name @@ -27976,8 +27976,8 @@ Did you start Qemu? Qt没有被正确安装,请运行make install - Could not determine the path to the binaries of the Qt installation, maybe the qmake path is wrong? - 无法确定Qt安装的二进制所在的路径,或许qmake的路径设置出现了错误? + Could not determine the path to the binaries of the Qt installation, maybe the %1 path is wrong? + 无法确定Qt安装的二进制所在的路径,或许%1的路径设置出现了错误? The default mkspec symlink is broken. diff --git a/share/qtcreator/translations/qtcreator_zh_TW.ts b/share/qtcreator/translations/qtcreator_zh_TW.ts index 253df6a4499..3aa3e0d04ff 100644 --- a/share/qtcreator/translations/qtcreator_zh_TW.ts +++ b/share/qtcreator/translations/qtcreator_zh_TW.ts @@ -15636,8 +15636,8 @@ Requires <b>Qt 4.7.4</b> or newer. 沒有設定 qmake 路徑 - qmake does not exist or is not executable - qmake 不存在或無法執行 + %1 does not exist or is not executable + %1 不存在或無法執行 Qt version has no name @@ -15664,8 +15664,8 @@ Requires <b>Qt 4.7.4</b> or newer. Qt 沒有被正確安裝,請執行 make install - Could not determine the path to the binaries of the Qt installation, maybe the qmake path is wrong? - 無法決定 Qt 安裝版的路徑。也許是 qmake 的路徑設定有錯誤? + Could not determine the path to the binaries of the Qt installation, maybe the %1 path is wrong? + 無法決定 Qt 安裝版的路徑。也許是 %1 的路徑設定有錯誤? The default mkspec symlink is broken. diff --git a/src/libs/utils/buildablehelperlibrary.cpp b/src/libs/utils/buildablehelperlibrary.cpp index c1030fd5e78..0ad53e52a73 100644 --- a/src/libs/utils/buildablehelperlibrary.cpp +++ b/src/libs/utils/buildablehelperlibrary.cpp @@ -41,7 +41,61 @@ bool BuildableHelperLibrary::isQtChooser(const FilePath &filePath) return filePath.symLinkTarget().endsWith("/qtchooser"); } -FilePath BuildableHelperLibrary::qtChooserToQmakePath(const FilePath &qtChooser) +static const QStringList &queryToolNames() +{ + static const QStringList names = {"qmake", "qtpaths"}; + return names; +} + +static bool isQueryTool(FilePath path) +{ + if (path.isEmpty()) + return false; + if (BuildableHelperLibrary::isQtChooser(path)) + path = BuildableHelperLibrary::qtChooserToQueryToolPath(path.symLinkTarget()); + if (!path.exists()) + return false; + QtcProcess proc; + proc.setCommand({path, {"-query"}}); + proc.runBlocking(); + if (proc.result() != ProcessResult::FinishedWithSuccess) + return false; + const QString output = proc.stdOut(); + // Exemplary output of "[qmake|qtpaths] -query": + // QT_SYSROOT:... + // QT_INSTALL_PREFIX:... + // [...] + // QT_VERSION:6.4.0 + return output.contains("QT_VERSION:"); +} + +static FilePath findQueryToolInDir(const FilePath &dir) +{ + if (dir.isEmpty()) + return {}; + + for (const QString &queryTool : queryToolNames()) { + FilePath queryToolPath = dir.pathAppended(queryTool).withExecutableSuffix(); + if (queryToolPath.exists()) { + if (isQueryTool(queryToolPath)) + return queryToolPath; + } + + // Prefer qmake-qt5 to qmake-qt4 by sorting the filenames in reverse order. + const FilePaths candidates = dir.dirEntries( + {BuildableHelperLibrary::possibleQtQueryTools(queryTool), QDir::Files}, + QDir::Name | QDir::Reversed); + for (const FilePath &candidate : candidates) { + if (candidate == queryToolPath) + continue; + if (isQueryTool(candidate)) + return candidate; + } + } + return {}; +} + +FilePath BuildableHelperLibrary::qtChooserToQueryToolPath(const FilePath &qtChooser) { const QString toolDir = QLatin1String("QTTOOLDIR=\""); QtcProcess proc; @@ -51,6 +105,10 @@ FilePath BuildableHelperLibrary::qtChooserToQmakePath(const FilePath &qtChooser) if (proc.result() != ProcessResult::FinishedWithSuccess) return {}; const QString output = proc.stdOut(); + // Exemplary output of "qtchooser -print-env": + // QT_SELECT="default" + // QTTOOLDIR="/usr/lib/qt5/bin" + // QTLIBDIR="/usr/lib/x86_64-linux-gnu" int pos = output.indexOf(toolDir); if (pos == -1) return {}; @@ -59,44 +117,13 @@ FilePath BuildableHelperLibrary::qtChooserToQmakePath(const FilePath &qtChooser) if (end == -1) return {}; - FilePath qmake = qtChooser; - qmake.setPath(output.mid(pos, end - pos) + "/qmake"); - return qmake; -} - -static bool isQmake(FilePath path) -{ - if (path.isEmpty()) - return false; - if (BuildableHelperLibrary::isQtChooser(path)) - path = BuildableHelperLibrary::qtChooserToQmakePath(path.symLinkTarget()); - if (!path.exists()) - return false; - return !BuildableHelperLibrary::qtVersionForQMake(path).isEmpty(); -} - -static FilePath findQmakeInDir(const FilePath &dir) -{ - if (dir.isEmpty()) - return {}; - - FilePath qmakePath = dir.pathAppended("qmake").withExecutableSuffix(); - if (qmakePath.exists()) { - if (isQmake(qmakePath)) - return qmakePath; + FilePath queryToolPath = qtChooser; + for (const QString &queryTool : queryToolNames()) { + queryToolPath.setPath(output.mid(pos, end - pos) + "/" + queryTool); + if (queryToolPath.exists()) + return queryToolPath; } - - // Prefer qmake-qt5 to qmake-qt4 by sorting the filenames in reverse order. - const FilePaths candidates = dir.dirEntries( - {BuildableHelperLibrary::possibleQMakeCommands(), QDir::Files}, - QDir::Name | QDir::Reversed); - for (const FilePath &candidate : candidates) { - if (candidate == qmakePath) - continue; - if (isQmake(candidate)) - return candidate; - } - return {}; + return queryToolPath; } FilePath BuildableHelperLibrary::findSystemQt(const Environment &env) @@ -107,86 +134,55 @@ FilePath BuildableHelperLibrary::findSystemQt(const Environment &env) FilePaths BuildableHelperLibrary::findQtsInEnvironment(const Environment &env, int maxCount) { - FilePaths qmakeList; + FilePaths queryToolList; std::set canonicalEnvPaths; const FilePaths paths = env.path(); for (const FilePath &path : paths) { if (!canonicalEnvPaths.insert(path.toFileInfo().canonicalFilePath()).second) continue; - const FilePath qmake = findQmakeInDir(path); - if (qmake.isEmpty()) + const FilePath queryTool = findQueryToolInDir(path); + if (queryTool.isEmpty()) continue; - qmakeList << qmake; - if (maxCount != -1 && qmakeList.size() == maxCount) + queryToolList << queryTool; + if (maxCount != -1 && queryToolList.size() == maxCount) break; } - return qmakeList; + return queryToolList; } -QString BuildableHelperLibrary::qtVersionForQMake(const FilePath &qmakePath) +QString BuildableHelperLibrary::filterForQtQueryToolsFileDialog() { - if (qmakePath.isEmpty()) - return QString(); - - QtcProcess qmake; - qmake.setTimeoutS(5); - qmake.setCommand({qmakePath, {"--version"}}); - qmake.runBlocking(); - if (qmake.result() != ProcessResult::FinishedWithSuccess) { - qWarning() << qmake.exitMessage(); - return QString(); + QStringList toolFilters; + for (const QString &queryTool : queryToolNames()) { + for (const QString &tool: BuildableHelperLibrary::possibleQtQueryTools(queryTool)) { + QString toolFilter; + if (HostOsInfo::isMacHost()) + // work around QTBUG-7739 that prohibits filters that don't start with * + toolFilter += QLatin1Char('*'); + toolFilter += tool; + if (HostOsInfo::isAnyUnixHost() && !HostOsInfo::isMacHost()) + // kde bug, we need at least one wildcard character + // see QTCREATORBUG-7771 + toolFilter += QLatin1Char('*'); + toolFilters.append(toolFilter); + } } - - const QString output = qmake.allOutput(); - static const QRegularExpression regexp("(QMake version:?)[\\s]*([\\d.]*)", - QRegularExpression::CaseInsensitiveOption); - const QRegularExpressionMatch match = regexp.match(output); - const QString qmakeVersion = match.captured(2); - if (qmakeVersion.startsWith(QLatin1String("2.")) - || qmakeVersion.startsWith(QLatin1String("3."))) { - static const QRegularExpression regexp2("Using Qt version[\\s]*([\\d\\.]*)", - QRegularExpression::CaseInsensitiveOption); - const QRegularExpressionMatch match2 = regexp2.match(output); - const QString version = match2.captured(1); - return version; - } - return QString(); + return queryToolNames().join(", ") + " (" + toolFilters.join(" ") + ")"; } -QString BuildableHelperLibrary::filterForQmakeFileDialog() +QStringList BuildableHelperLibrary::possibleQtQueryTools(const QString &tool) { - QString filter = QLatin1String("qmake ("); - const QStringList commands = possibleQMakeCommands(); - for (int i = 0; i < commands.size(); ++i) { - if (i) - filter += QLatin1Char(' '); - if (HostOsInfo::isMacHost()) - // work around QTBUG-7739 that prohibits filters that don't start with * - filter += QLatin1Char('*'); - filter += commands.at(i); - if (HostOsInfo::isAnyUnixHost() && !HostOsInfo::isMacHost()) - // kde bug, we need at least one wildcard character - // see QTCREATORBUG-7771 - filter += QLatin1Char('*'); - } - filter += QLatin1Char(')'); - return filter; -} - - -QStringList BuildableHelperLibrary::possibleQMakeCommands() -{ - // On Windows it is always "qmake.exe" + // On Windows it is ".exe" or ".bat" // On Unix some distributions renamed qmake with a postfix to avoid clashes // On OS X, Qt 4 binary packages also has renamed qmake. There are also symbolic links that are - // named "qmake", but the file dialog always checks against resolved links (native Cocoa issue) - QStringList commands(HostOsInfo::withExecutableSuffix("qmake*")); + // named , but the file dialog always checks against resolved links (native Cocoa issue) + QStringList tools(HostOsInfo::withExecutableSuffix(tool + "*")); // Qt 6 CMake built targets, such as Android, are dependent on the host installation - // and use a script wrapper around the host qmake executable + // and use a script wrapper around the host queryTool executable if (HostOsInfo::isWindowsHost()) - commands.append("qmake*.bat"); - return commands; + tools.append(tool + "*.bat"); + return tools; } } // namespace Utils diff --git a/src/libs/utils/buildablehelperlibrary.h b/src/libs/utils/buildablehelperlibrary.h index 8b47bef1012..2b07ac009e9 100644 --- a/src/libs/utils/buildablehelperlibrary.h +++ b/src/libs/utils/buildablehelperlibrary.h @@ -45,12 +45,11 @@ public: static FilePath findSystemQt(const Environment &env); static FilePaths findQtsInEnvironment(const Environment &env, int maxCount = -1); static bool isQtChooser(const FilePath &filePath); - static FilePath qtChooserToQmakePath(const FilePath &path); - // return true if the qmake at qmakePath is a Qt (used by QtVersion) - static QString qtVersionForQMake(const FilePath &qmakePath); - // returns something like qmake4, qmake, qmake-qt4 or whatever distributions have chosen (used by QtVersion) - static QStringList possibleQMakeCommands(); - static QString filterForQmakeFileDialog(); + static FilePath qtChooserToQueryToolPath(const FilePath &path); + // returns something like qmake4, qmake, qmake-qt4, qtpaths + // or whatever distributions have chosen (used by QtVersion) + static QStringList possibleQtQueryTools(const QString &tool); + static QString filterForQtQueryToolsFileDialog(); }; } // Utils diff --git a/src/plugins/cmakeprojectmanager/cmakekitinformation.cpp b/src/plugins/cmakeprojectmanager/cmakekitinformation.cpp index 6c39ddef419..1c4112f882c 100644 --- a/src/plugins/cmakeprojectmanager/cmakekitinformation.cpp +++ b/src/plugins/cmakeprojectmanager/cmakekitinformation.cpp @@ -1196,7 +1196,7 @@ Tasks CMakeConfigurationKitAspect::validate(const Kit *k) const if (!version || !version->isValid()) { addWarning(tr("CMake configuration has a path to a qmake binary set, " "even though the kit has no valid Qt version.")); - } else if (qmakePath != version->qmakeFilePath() && isQt4) { + } else if (qmakePath != version->queryToolFilePath() && isQt4) { addWarning(tr("CMake configuration has a path to a qmake binary set " "that does not match the qmake binary path " "configured in the Qt version.")); diff --git a/src/plugins/docker/kitdetector.cpp b/src/plugins/docker/kitdetector.cpp index 5e0c2e86598..474322a6043 100644 --- a/src/plugins/docker/kitdetector.cpp +++ b/src/plugins/docker/kitdetector.cpp @@ -214,10 +214,10 @@ QtVersions KitDetectorPrivate::autoDetectQtVersions() const QString error; const auto handleQmake = [this, &qtVersions, &error](const FilePath &qmake) { - if (QtVersion *qtVersion = QtVersionFactory::createQtVersionFromQMakePath(qmake, - false, - m_sharedId, - &error)) { + if (QtVersion *qtVersion = QtVersionFactory::createQtVersionFromQueryToolPath(qmake, + false, + m_sharedId, + &error)) { if (qtVersion->isValid()) { if (!Utils::anyOf(qtVersions, [qtVersion](QtVersion* other) { @@ -227,7 +227,7 @@ QtVersions KitDetectorPrivate::autoDetectQtVersions() const qtVersions.append(qtVersion); QtVersionManager::addVersion(qtVersion); emit q->logOutput( - tr("Found \"%1\"").arg(qtVersion->qmakeFilePath().toUserOutput())); + tr("Found \"%1\"").arg(qtVersion->queryToolFilePath().toUserOutput())); } } } diff --git a/src/plugins/qbsprojectmanager/qbsprofilemanager.cpp b/src/plugins/qbsprojectmanager/qbsprofilemanager.cpp index 7909de1981e..0fbfa346816 100644 --- a/src/plugins/qbsprojectmanager/qbsprofilemanager.cpp +++ b/src/plugins/qbsprojectmanager/qbsprofilemanager.cpp @@ -181,7 +181,7 @@ void QbsProfileManager::addProfileFromKit(const ProjectExplorer::Kit *k) data = provider->properties(k, data); } if (const QtSupport::QtVersion * const qt = QtSupport::QtKitAspect::qtVersion(k)) - data.insert("moduleProviders.Qt.qmakeFilePaths", qt->qmakeFilePath().toString()); + data.insert("moduleProviders.Qt.qmakeFilePaths", qt->queryToolFilePath().toString()); if (QbsSettings::qbsVersion() < QVersionNumber({1, 20})) { const QString keyPrefix = "profiles." + name + "."; diff --git a/src/plugins/qmakeprojectmanager/qmakeproject.cpp b/src/plugins/qmakeprojectmanager/qmakeproject.cpp index c77f468ae23..d292f1fb5a5 100644 --- a/src/plugins/qmakeprojectmanager/qmakeproject.cpp +++ b/src/plugins/qmakeprojectmanager/qmakeproject.cpp @@ -745,6 +745,9 @@ Tasks QmakeProject::projectIssues(const Kit *k) const result.append(createProjectTask(Task::TaskType::Error, tr("Qt version is invalid."))); if (!ToolChainKitAspect::cxxToolChain(k)) result.append(createProjectTask(Task::TaskType::Error, tr("No C++ compiler set in kit."))); + if (!qtFromKit->qmakeFilePath().isExecutableFile()) + result.append(createProjectTask(Task::TaskType::Error, + tr("Qmake was not found or is not executable."))); // A project can be considered part of more than one Qt version, for instance if it is an // example shipped via the installer. diff --git a/src/plugins/qmakeprojectmanager/qmakestep.cpp b/src/plugins/qmakeprojectmanager/qmakestep.cpp index 2502297ef00..2444303cb4d 100644 --- a/src/plugins/qmakeprojectmanager/qmakestep.cpp +++ b/src/plugins/qmakeprojectmanager/qmakestep.cpp @@ -103,7 +103,8 @@ QMakeStep::QMakeStep(BuildStepList *bsl, Id id) auto updateSummary = [this] { QtVersion *qtVersion = QtKitAspect::qtVersion(target()->kit()); if (!qtVersion) - return tr("qmake: No Qt version set. Cannot run qmake."); + return tr("Query tool: No Qt version set. " + "Cannot run neither qmake nor qtpaths."); const QString program = qtVersion->qmakeFilePath().fileName(); return tr("qmake: %1 %2").arg(program, project()->projectFilePath().fileName()); }; @@ -164,7 +165,7 @@ QString QMakeStep::allArguments(const QtVersion *v, ArgumentFlags flags) const QString args = ProcessArgs::joinArgs(arguments); // User arguments ProcessArgs::addArgs(&args, userArguments()); - for (QString arg : qAsConst(m_extraArgs)) + for (const QString &arg : qAsConst(m_extraArgs)) ProcessArgs::addArgs(&args, arg); return (flags & ArgumentFlag::Expand) ? bc->macroExpander()->expand(args) : args; } @@ -214,7 +215,8 @@ bool QMakeStep::init() else workingDirectory = qmakeBc->buildDirectory(); - m_qmakeCommand = CommandLine{qtVersion->qmakeFilePath(), allArguments(qtVersion), CommandLine::Raw}; + m_qmakeCommand = + CommandLine{qtVersion->qmakeFilePath(), allArguments(qtVersion), CommandLine::Raw}; m_runMakeQmake = (qtVersion->qtVersion() >= QtVersionNumber(5, 0 ,0)); // The Makefile is used by qmake and make on the build device, from that diff --git a/src/plugins/qmldesigner/designercore/instances/puppetcreator.cpp b/src/plugins/qmldesigner/designercore/instances/puppetcreator.cpp index 38c88a1cee1..6f511472057 100644 --- a/src/plugins/qmldesigner/designercore/instances/puppetcreator.cpp +++ b/src/plugins/qmldesigner/designercore/instances/puppetcreator.cpp @@ -610,7 +610,7 @@ QString PuppetCreator::qmakeCommand() const { QtSupport::QtVersion *currentQtVersion = QtSupport::QtKitAspect::qtVersion(m_target->kit()); if (currentQtVersion) - return currentQtVersion->qmakeFilePath().toString(); + return currentQtVersion->queryToolFilePath().toString(); return QString(); } diff --git a/src/plugins/qtsupport/baseqtversion.cpp b/src/plugins/qtsupport/baseqtversion.cpp index 1aafe1f575c..324add0e7c6 100644 --- a/src/plugins/qtsupport/baseqtversion.cpp +++ b/src/plugins/qtsupport/baseqtversion.cpp @@ -81,6 +81,7 @@ const char QTVERSIONAUTODETECTED[] = "isAutodetected"; const char QTVERSIONDETECTIONSOURCE[] = "autodetectionSource"; const char QTVERSION_OVERRIDE_FEATURES[] = "overrideFeatures"; const char QTVERSIONQMAKEPATH[] = "QMakePath"; +const char QTVERSIONQUERYTOOLPATH[] = "QueryToolPath"; const char QTVERSIONSOURCEPATH[] = "SourcePath"; const char QTVERSION_ABIS[] = "Abis"; @@ -187,19 +188,19 @@ public: FilePath findHostBinary(HostBinaries binary) const; void updateMkspec(); QHash versionInfo(); - static bool queryQMakeVariables(const FilePath &binary, - const Environment &env, - QHash *versionInfo, - QString *error = nullptr); + static bool queryQtPaths(const FilePath &queryTool, + const Environment &env, + QHash *versionInfo, + QString *error = nullptr); enum PropertyVariant { PropertyVariantDev, PropertyVariantGet, PropertyVariantSrc }; QString qmakeProperty(const QByteArray &name, PropertyVariant variant = PropertyVariantGet); static QString qmakeProperty(const QHash &versionInfo, const QByteArray &name, PropertyVariant variant = PropertyVariantGet); static FilePath mkspecDirectoryFromVersionInfo(const QHash &versionInfo, - const FilePath &qmakeCommand); + const FilePath &queryTool); static FilePath mkspecFromVersionInfo(const QHash &versionInfo, - const FilePath &qmakeCommand); + const FilePath &queryTool); static FilePath sourcePath(const QHash &versionInfo); void setId(int id); // used by the qtversionmanager for legacy restore // and by the qtoptionspage to replace Qt versions @@ -221,7 +222,7 @@ public: bool m_defaultConfigIsDebugAndRelease = true; bool m_frameworkBuild = false; bool m_versionInfoUpToDate = false; - bool m_qmakeIsExecutable = true; + bool m_queryToolIsExecutable = true; QString m_detectionSource; QSet m_overrideFeatures; @@ -233,6 +234,7 @@ public: QHash m_versionInfo; + FilePath m_queryTool; FilePath m_qmakeCommand; FilePath m_rccPath; @@ -346,12 +348,12 @@ QtVersion::~QtVersion() QString QtVersion::defaultUnexpandedDisplayName() const { QString location; - if (qmakeFilePath().isEmpty()) { + if (queryToolFilePath().isEmpty()) { location = QCoreApplication::translate("QtVersion", ""); } else { // Deduce a description from '/foo/qt-folder/[qtbase]/bin/qmake' -> '/foo/qt-folder'. // '/usr' indicates System Qt 4.X on Linux. - for (FilePath dir = qmakeFilePath().parentDir(); !dir.isEmpty(); dir = dir.parentDir()) { + for (FilePath dir = queryToolFilePath().parentDir(); !dir.isEmpty(); dir = dir.parentDir()) { const QString dirName = dir.fileName(); if (dirName == "usr") { // System-installed Qt. location = QCoreApplication::translate("QtVersion", "System"); @@ -725,20 +727,23 @@ void QtVersion::fromMap(const QVariantMap &map) d->m_isAutodetected = map.value(QTVERSIONAUTODETECTED).toBool(); d->m_detectionSource = map.value(QTVERSIONDETECTIONSOURCE).toString(); d->m_overrideFeatures = Utils::Id::fromStringList(map.value(QTVERSION_OVERRIDE_FEATURES).toStringList()); - d->m_qmakeCommand = FilePath::fromVariant(map.value(QTVERSIONQMAKEPATH)); + d->m_queryTool = FilePath::fromVariant(map.value(QTVERSIONQUERYTOOLPATH, + map.value(QTVERSIONQMAKEPATH))); + if (!d->m_queryTool.baseName().contains("qtpaths")) + d->m_qmakeCommand = d->m_queryTool; - FilePath qmake = d->m_qmakeCommand; + FilePath queryTool = d->m_queryTool; // FIXME: Check this is still needed or whether ProcessArgs::splitArg handles it. - QString string = d->m_qmakeCommand.path(); + QString string = d->m_queryTool.path(); if (string.startsWith('~')) string.remove(0, 1).prepend(QDir::homePath()); - qmake.setPath(string); - if (!d->m_qmakeCommand.needsDevice()) { - if (BuildableHelperLibrary::isQtChooser(qmake)) { + queryTool.setPath(string); + if (!d->m_queryTool.needsDevice()) { + if (BuildableHelperLibrary::isQtChooser(queryTool)) { // we don't want to treat qtchooser as a normal qmake // see e.g. QTCREATORBUG-9841, also this lead to users changing what // qtchooser forwards too behind our backs, which will inadvertly lead to bugs - d->m_qmakeCommand = BuildableHelperLibrary::qtChooserToQmakePath(qmake); + d->m_queryTool = BuildableHelperLibrary::qtChooserToQueryToolPath(queryTool); } } @@ -769,6 +774,7 @@ QVariantMap QtVersion::toMap() const result.insert(QTVERSION_OVERRIDE_FEATURES, Utils::Id::toStringList(d->m_overrideFeatures)); result.insert(QTVERSIONQMAKEPATH, qmakeFilePath().toVariant()); + result.insert(QTVERSIONQUERYTOOLPATH, queryToolFilePath().toVariant()); return result; } @@ -779,8 +785,8 @@ bool QtVersion::isValid() const d->updateVersionInfo(); d->updateMkspec(); - return !qmakeFilePath().isEmpty() && d->m_data.installed && !binPath().isEmpty() - && !d->m_mkspecFullPath.isEmpty() && d->m_qmakeIsExecutable; + return !queryToolFilePath().isEmpty() && d->m_data.installed && !binPath().isEmpty() + && !d->m_mkspecFullPath.isEmpty() && d->m_queryToolIsExecutable; } QtVersion::Predicate QtVersion::isValidPredicate(const QtVersion::Predicate &predicate) @@ -794,15 +800,18 @@ QString QtVersion::invalidReason() const { if (displayName().isEmpty()) return QCoreApplication::translate("QtVersion", "Qt version has no name"); - if (qmakeFilePath().isEmpty()) - return QCoreApplication::translate("QtVersion", "No qmake path set"); - if (!d->m_qmakeIsExecutable) - return QCoreApplication::translate("QtVersion", "qmake does not exist or is not executable"); + if (queryToolFilePath().isEmpty()) + return QCoreApplication::translate("QtVersion", "No Qt query tool path set"); + if (!d->m_queryToolIsExecutable) + return QCoreApplication::translate("QtVersion", "%1 does not exist or is not executable") + .arg(queryToolFilePath().baseName()); if (!d->m_data.installed) return QCoreApplication::translate("QtVersion", "Qt version is not properly installed, please run make install"); if (binPath().isEmpty()) return QCoreApplication::translate("QtVersion", - "Could not determine the path to the binaries of the Qt installation, maybe the qmake path is wrong?"); + "Could not determine the path to the binaries of the " + "Qt installation, maybe the %1 path is wrong?") + .arg(queryToolFilePath().baseName()); if (d->m_mkspecUpToDate && d->m_mkspecFullPath.isEmpty()) return QCoreApplication::translate("QtVersion", "The default mkspec symlink is broken."); return QString(); @@ -820,8 +829,20 @@ QStringList QtVersion::warningReason() const return ret; } +FilePath QtVersion::queryToolFilePath() const +{ + return d->m_queryTool; +} + FilePath QtVersion::qmakeFilePath() const { + if (d->m_qmakeCommand.isEmpty() && d->m_queryTool.baseName().contains("qtpaths")) { + // TODO: might need a less lazy implementation + const FilePath qmake = + FilePath::fromString(d->m_queryTool.toString().replace("qtpaths", "qmake")); + if (qmake.exists()) + d->m_qmakeCommand = qmake; + } return d->m_qmakeCommand; } @@ -855,7 +876,7 @@ bool QtVersion::hasAbi(ProjectExplorer::Abi::OS os, ProjectExplorer::Abi::OSFlav bool QtVersion::equals(QtVersion *other) { - if (d->m_qmakeCommand != other->d->m_qmakeCommand) + if (d->m_queryTool != other->d->m_queryTool) return false; if (type() != other->type()) return false; @@ -933,13 +954,15 @@ QString QtVersion::toHtml(bool verbose) const str << "" << abis.at(i).toString() << ""; } } - const OsType osType = d->m_qmakeCommand.osType(); + const OsType osType = d->m_queryTool.osType(); str << "" << QCoreApplication::translate("QtVersion", "Source:") << "" << sourcePath().toUserOutput() << ""; str << "" << QCoreApplication::translate("QtVersion", "mkspec:") << "" << QDir::toNativeSeparators(mkspec()) << ""; str << "" << QCoreApplication::translate("QtVersion", "qmake:") - << "" << d->m_qmakeCommand.toUserOutput() << ""; + << "" << qmakeFilePath().toUserOutput() << ""; + str << "" << QCoreApplication::translate("QtVersion", "Query tool:") + << "" << d->m_queryTool.toUserOutput() << ""; ensureMkSpecParsed(); if (!mkspecPath().isEmpty()) { if (d->m_defaultConfigIsDebug || d->m_defaultConfigIsDebugAndRelease) { @@ -1164,13 +1187,13 @@ void QtVersionPrivate::updateMkspec() return; m_mkspecUpToDate = true; - m_mkspecFullPath = mkspecFromVersionInfo(versionInfo(), m_qmakeCommand); + m_mkspecFullPath = mkspecFromVersionInfo(versionInfo(), m_queryTool); m_mkspec = m_mkspecFullPath; if (m_mkspecFullPath.isEmpty()) return; - FilePath baseMkspecDir = mkspecDirectoryFromVersionInfo(versionInfo(), m_qmakeCommand); + FilePath baseMkspecDir = mkspecDirectoryFromVersionInfo(versionInfo(), m_queryTool); if (m_mkspec.isChildOf(baseMkspecDir)) { m_mkspec = m_mkspec.relativeChildPath(baseMkspecDir); @@ -1197,7 +1220,7 @@ void QtVersion::ensureMkSpecParsed() const QMakeVfs vfs; QMakeGlobals option; applyProperties(&option); - Environment env = d->m_qmakeCommand.deviceEnvironment(); + Environment env = d->m_queryTool.deviceEnvironment(); setupQmakeRunEnvironment(env); option.environment = env.toProcessEnvironment(); ProMessageHandler msgHandler(true); @@ -1310,7 +1333,7 @@ QtVersionNumber QtVersion::qtVersion() const void QtVersionPrivate::updateVersionInfo() { - if (m_versionInfoUpToDate || !m_qmakeIsExecutable || m_isUpdating) + if (m_versionInfoUpToDate || !m_queryToolIsExecutable || m_isUpdating) return; m_isUpdating = true; @@ -1321,16 +1344,16 @@ void QtVersionPrivate::updateVersionInfo() m_data.hasExamples = false; m_data.hasDocumentation = false; - if (!queryQMakeVariables(m_qmakeCommand, q->qmakeRunEnvironment(), &m_versionInfo)) { - m_qmakeIsExecutable = false; + if (!queryQtPaths(m_queryTool, q->qmakeRunEnvironment(), &m_versionInfo)) { + m_queryToolIsExecutable = false; qWarning("Cannot update Qt version information: %s cannot be run.", - qPrintable(m_qmakeCommand.toString())); + qPrintable(m_queryTool.toString())); return; } - m_qmakeIsExecutable = true; + m_queryToolIsExecutable = true; auto fileProperty = [this](const QByteArray &name) { - return FilePath::fromUserInput(qmakeProperty(name)).onDevice(m_qmakeCommand); + return FilePath::fromUserInput(qmakeProperty(name)).onDevice(m_queryTool); }; m_data.prefix = fileProperty("QT_INSTALL_PREFIX"); @@ -1385,8 +1408,8 @@ QHash QtVersionPrivate::versionInfo() } QString QtVersionPrivate::qmakeProperty(const QHash &versionInfo, - const QByteArray &name, - PropertyVariant variant) + const QByteArray &name, + PropertyVariant variant) { QString val = versionInfo .value(ProKey(QString::fromLatin1( @@ -1728,7 +1751,7 @@ void QtVersion::addToEnvironment(const Kit *k, Environment &env) const Environment QtVersion::qmakeRunEnvironment() const { - Environment env = d->m_qmakeCommand.deviceEnvironment(); + Environment env = d->m_queryTool.deviceEnvironment(); setupQmakeRunEnvironment(env); return env; } @@ -1756,7 +1779,7 @@ Tasks QtVersion::reportIssuesImpl(const QString &proFile, const QString &buildDi results.append(BuildSystemTask(Task::Error, msg)); } - FilePath qmake = qmakeFilePath(); + FilePath qmake = queryToolFilePath(); if (!qmake.isExecutableFile()) { //: %1: Path to qmake executable const QString msg = QCoreApplication::translate("QmakeProjectManager::QtVersion", @@ -1816,20 +1839,21 @@ static QByteArray runQmakeQuery(const FilePath &binary, const Environment &env, return process.readAllStandardOutput(); } -bool QtVersionPrivate::queryQMakeVariables(const FilePath &binary, const Environment &env, - QHash *versionInfo, QString *error) +bool QtVersionPrivate::queryQtPaths(const FilePath &queryTool, const Environment &env, + QHash *versionInfo, QString *error) { QString tmp; if (!error) error = &tmp; - if (!binary.isExecutableFile()) { - *error = QCoreApplication::translate("QtVersion", "qmake \"%1\" is not an executable.").arg(binary.toUserOutput()); + if (!queryTool.isExecutableFile()) { + *error = QCoreApplication::translate("QtVersion", "\"%1\" is not an executable.") + .arg(queryTool.toUserOutput()); return false; } QByteArray output; - output = runQmakeQuery(binary, env, error); + output = runQmakeQuery(queryTool, env, error); if (!output.contains("QMAKE_VERSION:")) { // Some setups pass error messages via stdout, fooling the logic below. @@ -1847,14 +1871,14 @@ bool QtVersionPrivate::queryQMakeVariables(const FilePath &binary, const Environ // Try running qmake with all kinds of tool chains set up in the environment. // This is required to make non-static qmakes work on windows where every tool chain // tries to be incompatible with any other. - const Abis abiList = Abi::abisOfBinary(binary); + const Abis abiList = Abi::abisOfBinary(queryTool); const Toolchains tcList = ToolChainManager::toolchains([&abiList](const ToolChain *t) { return abiList.contains(t->targetAbi()); }); for (ToolChain *tc : tcList) { Environment realEnv = env; tc->addToEnvironment(realEnv); - output = runQmakeQuery(binary, realEnv, error); + output = runQmakeQuery(queryTool, realEnv, error); if (error->isEmpty()) break; } @@ -1876,18 +1900,18 @@ QString QtVersionPrivate::qmakeProperty(const QByteArray &name, } FilePath QtVersionPrivate::mkspecDirectoryFromVersionInfo(const QHash &versionInfo, - const FilePath &qmakeCommand) + const FilePath &queryTool) { QString dataDir = qmakeProperty(versionInfo, "QT_HOST_DATA", PropertyVariantSrc); if (dataDir.isEmpty()) return FilePath(); - return FilePath::fromUserInput(dataDir + "/mkspecs").onDevice(qmakeCommand); + return FilePath::fromUserInput(dataDir + "/mkspecs").onDevice(queryTool); } FilePath QtVersionPrivate::mkspecFromVersionInfo(const QHash &versionInfo, - const FilePath &qmakeCommand) + const FilePath &queryTool) { - FilePath baseMkspecDir = mkspecDirectoryFromVersionInfo(versionInfo, qmakeCommand); + FilePath baseMkspecDir = mkspecDirectoryFromVersionInfo(versionInfo, queryTool); if (baseMkspecDir.isEmpty()) return FilePath(); @@ -2319,14 +2343,16 @@ void QtVersion::resetCache() const static QList g_qtVersionFactories; -QtVersion *QtVersionFactory::createQtVersionFromQMakePath - (const FilePath &qmakePath, bool isAutoDetected, const QString &detectionSource, QString *error) +QtVersion *QtVersionFactory::createQtVersionFromQueryToolPath(const FilePath &queryTool, + bool isAutoDetected, + const QString &detectionSource, + QString *error) { QHash versionInfo; - const Environment env = qmakePath.deviceEnvironment(); - if (!QtVersionPrivate::queryQMakeVariables(qmakePath, env, &versionInfo, error)) + const Environment env = queryTool.deviceEnvironment(); + if (!QtVersionPrivate::queryQtPaths(queryTool, env, &versionInfo, error)) return nullptr; - FilePath mkspec = QtVersionPrivate::mkspecFromVersionInfo(versionInfo, qmakePath); + FilePath mkspec = QtVersionPrivate::mkspecFromVersionInfo(versionInfo, queryTool); QMakeVfs vfs; QMakeGlobals globals; @@ -2342,7 +2368,7 @@ QtVersion *QtVersionFactory::createQtVersionFromQMakePath return l->m_priority > r->m_priority; }); - if (!qmakePath.isExecutableFile()) + if (!queryTool.isExecutableFile()) return nullptr; QtVersionFactory::SetupData setup; @@ -2355,8 +2381,8 @@ QtVersion *QtVersionFactory::createQtVersionFromQMakePath QtVersion *ver = factory->create(); QTC_ASSERT(ver, continue); ver->d->m_id = QtVersionManager::getUniqueId(); - QTC_CHECK(ver->d->m_qmakeCommand.isEmpty()); // Should only be used once. - ver->d->m_qmakeCommand = qmakePath; + QTC_CHECK(ver->d->m_queryTool.isEmpty()); // Should only be used once. + ver->d->m_queryTool = queryTool; ver->d->m_detectionSource = detectionSource; ver->d->m_isAutodetected = isAutoDetected; ver->updateDefaultDisplayName(); @@ -2367,7 +2393,7 @@ QtVersion *QtVersionFactory::createQtVersionFromQMakePath ProFileCacheManager::instance()->decRefCount(); if (error) { *error = QCoreApplication::translate("QtSupport::QtVersionFactory", - "No factory found for qmake: \"%1\"").arg(qmakePath.toUserOutput()); + "No factory found for query tool \"%1\"").arg(queryTool.toUserOutput()); } return nullptr; } diff --git a/src/plugins/qtsupport/baseqtversion.h b/src/plugins/qtsupport/baseqtversion.h index 269a6507168..f0400bc99b5 100644 --- a/src/plugins/qtsupport/baseqtversion.h +++ b/src/plugins/qtsupport/baseqtversion.h @@ -150,6 +150,8 @@ public: bool hasDocs() const; bool hasDemos() const; + Utils::FilePath queryToolFilePath() const; + // former local functions Utils::FilePath qmakeFilePath() const; diff --git a/src/plugins/qtsupport/qtkitinformation.cpp b/src/plugins/qtsupport/qtkitinformation.cpp index 43bbc07c1c3..672ad493df4 100644 --- a/src/plugins/qtsupport/qtkitinformation.cpp +++ b/src/plugins/qtsupport/qtkitinformation.cpp @@ -324,6 +324,11 @@ void QtKitAspect::addToMacroExpander(Kit *kit, MacroExpander *expander) const QtVersion *version = qtVersion(kit); return version ? version->qmakeFilePath().path() : QString(); }); + expander->registerVariable("Qt:queryToolExecutable", tr("Path to the query tool executable"), + [kit]() -> QString { + QtVersion *version = qtVersion(kit); + return version ? version->queryToolFilePath().path() : QString(); + }); } Id QtKitAspect::id() diff --git a/src/plugins/qtsupport/qtoptionspage.cpp b/src/plugins/qtsupport/qtoptionspage.cpp index c0049058abd..06a8a6bbd52 100644 --- a/src/plugins/qtsupport/qtoptionspage.cpp +++ b/src/plugins/qtsupport/qtoptionspage.cpp @@ -51,6 +51,7 @@ #include #include #include +#include #include #include #include @@ -111,7 +112,7 @@ public: if (column == 0) return m_version->displayName(); if (column == 1) - return m_version->qmakeFilePath().toUserOutput(); + return m_version->queryToolFilePath().toUserOutput(); } if (role == Qt::FontRole && m_changed) { @@ -128,7 +129,8 @@ public: "
%2
"; return QString("
" + row.arg(tr("Qt Version"), m_version->qtVersionString()) - + row.arg(tr("Location of qmake"), m_version->qmakeFilePath().toUserOutput()) + + row.arg(tr("Location of the query tool"), + m_version->queryToolFilePath().toUserOutput()) + "
"); } @@ -600,27 +602,42 @@ QtOptionsPageWidget::~QtOptionsPageWidget() delete m_configurationWidget; } +static bool isIncompatibleQtPathsTool(const FilePath &tool) +{ + if (!tool.baseName().startsWith("qtpaths")) + return false; + QtcProcess process; + process.setTimeoutS(1); + process.setCommand({tool, {"-query"}}); + process.runBlocking(); + return process.result() != ProcessResult::FinishedWithSuccess; +} + void QtOptionsPageWidget::addQtDir() { - FilePath qtVersion = FileUtils::getOpenFilePath(this, - tr("Select a qmake Executable"), - {}, - BuildableHelperLibrary::filterForQmakeFileDialog(), - 0, - QFileDialog::DontResolveSymlinks); - if (qtVersion.isEmpty()) + FilePath qtQueryTool = + FileUtils::getOpenFilePath(this, + tr("Select a qmake or qtpaths Executable"), + {}, + BuildableHelperLibrary::filterForQtQueryToolsFileDialog(), + 0, + QFileDialog::DontResolveSymlinks); + if (qtQueryTool.isEmpty()) return; - // should add all qt versions here ? - if (BuildableHelperLibrary::isQtChooser(qtVersion)) - qtVersion = BuildableHelperLibrary::qtChooserToQmakePath(qtVersion.symLinkTarget()); + if (isIncompatibleQtPathsTool(qtQueryTool)) + qtQueryTool = qtQueryTool.parentDir() / HostOsInfo::withExecutableSuffix("qmake"); - auto checkAlreadyExists = [qtVersion](TreeItem *parent) { + // should add all qt versions here ? + if (BuildableHelperLibrary::isQtChooser(qtQueryTool)) + qtQueryTool = BuildableHelperLibrary::qtChooserToQueryToolPath(qtQueryTool.symLinkTarget()); + + auto checkAlreadyExists = [qtQueryTool](TreeItem *parent) { for (int i = 0; i < parent->childCount(); ++i) { auto item = static_cast(parent->childAt(i)); - if (item->version()->qmakeFilePath() == qtVersion) { + // Compare parent dirs, since it could be either qmake or qtpaths + if (item->version()->queryToolFilePath().parentDir() == qtQueryTool.parentDir()) return std::make_pair(true, item->version()->displayName()); - } } return std::make_pair(false, QString()); }; @@ -640,7 +657,8 @@ void QtOptionsPageWidget::addQtDir() } QString error; - QtVersion *version = QtVersionFactory::createQtVersionFromQMakePath(qtVersion, false, QString(), &error); + QtVersion *version = QtVersionFactory::createQtVersionFromQueryToolPath(qtQueryTool, false, + QString(), &error); if (version) { auto item = new QtVersionItem(version); item->setIcon(version->isValid()? m_validVersionIcon : m_invalidVersionIcon); @@ -650,8 +668,9 @@ void QtOptionsPageWidget::addQtDir() m_versionUi.nameEdit->setFocus(); m_versionUi.nameEdit->selectAll(); } else { - QMessageBox::warning(this, tr("Qmake Not Executable"), - tr("The qmake executable %1 could not be added: %2").arg(qtVersion.toUserOutput()).arg(error)); + QMessageBox::warning(this, tr("Not Executable"), + tr("The executable %1 could not be added: %2").arg( + qtQueryTool.toUserOutput()).arg(error)); return; } updateCleanUpButton(); @@ -671,16 +690,16 @@ void QtOptionsPageWidget::removeQtDir() void QtOptionsPageWidget::editPath() { QtVersion *current = currentVersion(); - FilePath qtVersion = + const FilePath queryTool = FileUtils::getOpenFilePath(this, - tr("Select a qmake Executable"), - current->qmakeFilePath().absolutePath(), - BuildableHelperLibrary::filterForQmakeFileDialog(), + tr("Select a qmake or qtpaths Executable"), + current->queryToolFilePath().absolutePath(), + BuildableHelperLibrary::filterForQtQueryToolsFileDialog(), nullptr, QFileDialog::DontResolveSymlinks); - if (qtVersion.isEmpty()) + if (queryTool.isEmpty()) return; - QtVersion *version = QtVersionFactory::createQtVersionFromQMakePath(qtVersion); + QtVersion *version = QtVersionFactory::createQtVersionFromQueryToolPath(queryTool); if (!version) return; // Same type? then replace! @@ -768,7 +787,7 @@ void QtOptionsPageWidget::updateWidgets() QtVersion *version = currentVersion(); if (version) { m_versionUi.nameEdit->setText(version->unexpandedDisplayName()); - m_versionUi.qmakePath->setText(version->qmakeFilePath().toUserOutput()); + m_versionUi.queryToolPath->setText(version->queryToolFilePath().toUserOutput()); m_configurationWidget = version->createConfigurationWidget(); if (m_configurationWidget) { m_versionUi.formLayout->addRow(m_configurationWidget); @@ -778,7 +797,7 @@ void QtOptionsPageWidget::updateWidgets() } } else { m_versionUi.nameEdit->clear(); - m_versionUi.qmakePath->clear(); + m_versionUi.queryToolPath->clear(); } const bool enabled = version != nullptr; diff --git a/src/plugins/qtsupport/qtprojectimporter.cpp b/src/plugins/qtsupport/qtprojectimporter.cpp index 9014aa71f08..fc44f3b7d37 100644 --- a/src/plugins/qtsupport/qtprojectimporter.cpp +++ b/src/plugins/qtsupport/qtprojectimporter.cpp @@ -57,7 +57,7 @@ QtProjectImporter::QtVersionData QtProjectImporter::findOrCreateQtVersion(const Utils::FilePath &qmakePath) const { QtVersionData result; - result.qt = QtVersionManager::version(Utils::equal(&QtVersion::qmakeFilePath, qmakePath)); + result.qt = QtVersionManager::version(Utils::equal(&QtVersion::queryToolFilePath, qmakePath)); if (result.qt) { // Check if version is a temporary qt const int qtId = result.qt->uniqueId(); @@ -67,7 +67,7 @@ QtProjectImporter::findOrCreateQtVersion(const Utils::FilePath &qmakePath) const // Create a new version if not found: // Do not use the canonical path here... - result.qt = QtVersionFactory::createQtVersionFromQMakePath(qmakePath); + result.qt = QtVersionFactory::createQtVersionFromQueryToolPath(qmakePath); result.isTemporary = true; if (result.qt) { UpdateGuard guard(*this); @@ -281,7 +281,7 @@ static QStringList additionalFilesToCopy(const QtVersion *qt) } 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(); + const FilePath base = qt->queryToolFilePath().parentDir().parentDir(); if (base.pathAppended(release).exists()) return {release}; if (base.pathAppended(debug).exists()) @@ -289,7 +289,7 @@ static QStringList additionalFilesToCopy(const QtVersion *qt) 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 QDir base(qt->queryToolFilePath().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; } @@ -300,7 +300,7 @@ static QStringList additionalFilesToCopy(const QtVersion *qt) static Utils::FilePath setupQmake(const QtVersion *qt, const QString &path) { // This is a hack and only works with local, "standard" installations of Qt - const FilePath qmake = qt->qmakeFilePath().canonicalPath(); + const FilePath qmake = qt->queryToolFilePath().canonicalPath(); const QString qmakeFile = "bin/" + qmake.fileName(); const FilePath source = qmake.parentDir().parentDir(); const FilePath target = FilePath::fromString(path); diff --git a/src/plugins/qtsupport/qtversionfactory.h b/src/plugins/qtsupport/qtversionfactory.h index bc01ad7601a..96bf8e2088a 100644 --- a/src/plugins/qtsupport/qtversionfactory.h +++ b/src/plugins/qtsupport/qtversionfactory.h @@ -51,7 +51,7 @@ public: /// the desktop factory claims to handle all paths int priority() const { return m_priority; } - static QtVersion *createQtVersionFromQMakePath(const Utils::FilePath &qmakePath, + static QtVersion *createQtVersionFromQueryToolPath(const Utils::FilePath &qmakePath, bool isAutoDetected = false, const QString &detectionSource = {}, QString *error = nullptr); diff --git a/src/plugins/qtsupport/qtversioninfo.ui b/src/plugins/qtsupport/qtversioninfo.ui index 467e898a20e..815be818177 100644 --- a/src/plugins/qtsupport/qtversioninfo.ui +++ b/src/plugins/qtsupport/qtversioninfo.ui @@ -39,14 +39,14 @@ - qmake path: + Query tool path: - + 0 diff --git a/src/plugins/qtsupport/qtversionmanager.cpp b/src/plugins/qtsupport/qtversionmanager.cpp index 2ca6c3a1237..c5f00e96189 100644 --- a/src/plugins/qtsupport/qtversionmanager.cpp +++ b/src/plugins/qtsupport/qtversionmanager.cpp @@ -265,7 +265,8 @@ void QtVersionManager::updateFromInstaller(bool emitSignal) if (log().isDebugEnabled()) { qCDebug(log) << "======= Existing Qt versions ======="; for (QtVersion *version : qAsConst(m_versions)) { - qCDebug(log) << version->qmakeFilePath().toUserOutput() << "id:"<uniqueId(); + qCDebug(log) << version->queryToolFilePath().toUserOutput() + << "id:" <uniqueId(); qCDebug(log) << " autodetection source:" << version->detectionSource(); qCDebug(log) << ""; } @@ -341,7 +342,8 @@ void QtVersionManager::updateFromInstaller(bool emitSignal) if (log().isDebugEnabled()) { qCDebug(log) << "======= Before removing outdated sdk versions ======="; for (QtVersion *version : qAsConst(m_versions)) { - qCDebug(log) << version->qmakeFilePath().toUserOutput() << "id:" << version->uniqueId(); + qCDebug(log) << version->queryToolFilePath().toUserOutput() + << "id:" << version->uniqueId(); qCDebug(log) << " autodetection source:" << version->detectionSource(); qCDebug(log) << ""; } @@ -360,7 +362,8 @@ void QtVersionManager::updateFromInstaller(bool emitSignal) if (log().isDebugEnabled()) { qCDebug(log)<< "======= End result ======="; for (QtVersion *version : qAsConst(m_versions)) { - qCDebug(log) << version->qmakeFilePath().toUserOutput() << "id:" << version->uniqueId(); + qCDebug(log) << version->queryToolFilePath().toUserOutput() + << "id:" << version->uniqueId(); qCDebug(log) << " autodetection source:" << version->detectionSource(); qCDebug(log) << ""; } @@ -401,14 +404,20 @@ static QList runQtChooser(const QString &qtchooser, const QStringLis } // Asks qtchooser for the qmake path of a given version +// TODO: Extend to qtpaths if qtchooser is also used for Qt 6 static QString qmakePath(const QString &qtchooser, const QString &version) { const QList outputs = runQtChooser(qtchooser, {QStringLiteral("-qt=%1").arg(version), QStringLiteral("-print-env")}); + // Exemplary output of "qtchooser -qt=qt5-x86_64-linux-gnu -print-env": + // QT_SELECT="qt5-x86_64-linux-gnu" + // QTTOOLDIR="/usr/lib/qt5/bin" + // QTLIBDIR="/usr/lib/x86_64-linux-gnu" + const QByteArray qtToolDirPrefix("QTTOOLDIR=\""); for (const QByteArray &output : outputs) { - if (output.startsWith("QTTOOLDIR=\"")) { - QByteArray withoutVarName = output.mid(11); // remove QTTOOLDIR=" + if (output.startsWith(qtToolDirPrefix)) { + QByteArray withoutVarName = output.mid(qtToolDirPrefix.size()); // remove QTTOOLDIR=" withoutVarName.chop(1); // remove trailing quote return QStandardPaths::findExecutable(QStringLiteral("qmake"), QStringList() << QString::fromLocal8Bit(withoutVarName)); @@ -424,6 +433,15 @@ static FilePaths gatherQmakePathsFromQtChooser() return FilePaths(); const QList versions = runQtChooser(qtchooser, QStringList("-l")); + // Exemplary output of "qtchooser -l": + // 4 + // 5 + // default + // qt4-x86_64-linux-gnu + // qt4 + // qt5-x86_64-linux-gnu + // qt5 + // "" QSet foundQMakes; for (const QByteArray &version : versions) { FilePath possibleQMake = FilePath::fromString( @@ -436,19 +454,20 @@ static FilePaths gatherQmakePathsFromQtChooser() static void findSystemQt() { - FilePaths systemQMakes + FilePaths systemQueryTools = BuildableHelperLibrary::findQtsInEnvironment(Environment::systemEnvironment()); - systemQMakes.append(gatherQmakePathsFromQtChooser()); - for (const FilePath &qmakePath : qAsConst(systemQMakes)) { - if (BuildableHelperLibrary::isQtChooser(qmakePath)) + systemQueryTools.append(gatherQmakePathsFromQtChooser()); + for (const FilePath &queryToolPath : qAsConst(systemQueryTools)) { + if (BuildableHelperLibrary::isQtChooser(queryToolPath)) continue; - const auto isSameQmake = [qmakePath](const QtVersion *version) { + const auto isSameQueryTool = [queryToolPath](const QtVersion *version) { return Environment::systemEnvironment(). - isSameExecutable(qmakePath.toString(), version->qmakeFilePath().toString()); + isSameExecutable(queryToolPath.toString(), + version->queryToolFilePath().toString()); }; - if (contains(m_versions, isSameQmake)) + if (contains(m_versions, isSameQueryTool)) continue; - QtVersion *version = QtVersionFactory::createQtVersionFromQMakePath(qmakePath, + QtVersion *version = QtVersionFactory::createQtVersionFromQueryToolPath(queryToolPath, false, "PATH"); if (version)