QtSupport: Add support to register Qt versions via qtpaths

qmake is a "build tool", and it is also a "query tool" when called with
parameter "-query". Qt Creator, so far, assumes that building and
querying with a Qt installation are done with one and the same tool:
qmake. This change adds the ability to register a Qt version vie either
qmake or qtpaths and still build with qmake, if that is installed (which
is not anymore mandatory from Qt 6 on).

1) Distinguish between Qt query tool and qmake build tool:
Add QtVersion::queryToolFilePath() to the existing
QtVersion::qmakeFilePath(), and use queryToolFilePath in most "query"
related code, and qmakeFilePath when building with qmake (e.g. in
QmakeProjectManager).
Also, a couple of functions and variables were renamed from *qmake* to
*queryTool* in order to express that the affected code is about
querying/managing Qt versions rather than about building with qmake.

2) Support manual Qt Version adding by qtpaths via file dialog
This change adds qtpaths to the "Add" Qt Version file picker filter.
After selection, "qtpaths -query" is executed for testing purposes. If
that fails, (e.g. because it is an older Qt version), qmake is instead
chosen, silently.

Task-number: QTCREATORBUG-22175
Task-number: QTCREATORBUG-25546
Change-Id: I4d9c1e7eec7d5ae7c5a8d2e1a1ed95addff69966
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: hjk <hjk@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
This commit is contained in:
Alessandro Portale
2022-05-11 13:26:57 +02:00
parent 79236605fd
commit 72aa77ced7
28 changed files with 338 additions and 267 deletions

View File

@@ -32121,16 +32121,16 @@ Spustil jste Qemu?</translation>
<translation>Qt %1 (%2)</translation>
</message>
<message>
<source>qmake does not exist or is not executable</source>
<translation>Soubor qmake neexistuje nebo není spustitelný</translation>
<source>%1 does not exist or is not executable</source>
<translation>Soubor %1 neexistuje nebo není spustitelný</translation>
</message>
<message>
<source>Qt version is not properly installed, please run make install</source>
<translation>Verze Qt není správně nainstalována. Proveďte, prosím, příkaz &quot;make install&quot;</translation>
</message>
<message>
<source>Could not determine the path to the binaries of the Qt installation, maybe the qmake path is wrong?</source>
<translation>Cestu ke spustitelným souborům instalace Qt se nepodařilo určit. Možná je cesta k qmake chybná?</translation>
<source>Could not determine the path to the binaries of the Qt installation, maybe the %1 path is wrong?</source>
<translation>Cestu ke spustitelným souborům instalace Qt se nepodařilo určit. Možná je cesta k %1 chybná?</translation>
</message>
<message>
<source>The default mkspec symlink is broken.</source>

View File

@@ -35382,16 +35382,16 @@ For flere detaljer, se /etc/sysctl.d/10-ptrace.conf
<translation>Ingen qmake-sti sat</translation>
</message>
<message>
<source>qmake does not exist or is not executable</source>
<translation>qmake findes ikke eller er ikke eksekverbar</translation>
<source>%1 does not exist or is not executable</source>
<translation>%1 findes ikke eller er ikke eksekverbar</translation>
</message>
<message>
<source>Qt version is not properly installed, please run make install</source>
<translation>Qt version er ikke ordentligt installeret, kør venligst make install</translation>
</message>
<message>
<source>Could not determine the path to the binaries of the Qt installation, maybe the qmake path is wrong?</source>
<translation>Kunne ikke beslutte stien til binærene af Qt installationen, måske er qmake-stien forkert?</translation>
<source>Could not determine the path to the binaries of the Qt installation, maybe the %1 path is wrong?</source>
<translation>Kunne ikke beslutte stien til binærene af Qt installationen, måske er %1-stien forkert?</translation>
</message>
<message>
<source>The default mkspec symlink is broken.</source>

View File

@@ -10113,8 +10113,8 @@ Dies ist unabhängig vom Wert der Eigenschaft &quot;visible&quot; in QML.</trans
<translation>Es ist keine qmake-Pfad gesetzt</translation>
</message>
<message>
<source>qmake does not exist or is not executable</source>
<translation>Die qmake-Datei existiert nicht oder ist nicht ausführbar</translation>
<source>%1 does not exist or is not executable</source>
<translation>Die %1-Datei existiert nicht oder ist nicht ausführbar</translation>
</message>
<message>
<source>Qt version has no name</source>
@@ -10141,8 +10141,8 @@ Dies ist unabhängig vom Wert der Eigenschaft &quot;visible&quot; in QML.</trans
<translation>Die Qt-Version ist nicht richtig installiert, führen Sie bitte make install aus</translation>
</message>
<message>
<source>Could not determine the path to the binaries of the Qt installation, maybe the qmake path is wrong?</source>
<translation>Der Pfad zu den ausführbaren Dateien der Qt-Installation konnte nicht bestimmt werden, möglicherweise ist der Pfad zu qmake falsch?</translation>
<source>Could not determine the path to the binaries of the Qt installation, maybe the %1 path is wrong?</source>
<translation>Der Pfad zu den ausführbaren Dateien der Qt-Installation konnte nicht bestimmt werden, möglicherweise ist der Pfad zu %1 falsch?</translation>
</message>
<message>
<source>The default mkspec symlink is broken.</source>

View File

@@ -33604,8 +33604,8 @@ Nous allons essayer de travailler avec cela mais vous pourrez rencontrer des pro
<translation>Chemin de qmake non spécifié</translation>
</message>
<message>
<source>qmake does not exist or is not executable</source>
<translation>qmake n&apos;existe pas ou n&apos;est pas exécutable</translation>
<source>%1 does not exist or is not executable</source>
<translation>%1 n&apos;existe pas ou n&apos;est pas exécutable</translation>
</message>
<message>
<source>Qt version has no name</source>
@@ -33633,8 +33633,8 @@ Nous allons essayer de travailler avec cela mais vous pourrez rencontrer des pro
<translation>La version de Qt n&apos;est pas correctement installée, veuillez exécuter make install</translation>
</message>
<message>
<source>Could not determine the path to the binaries of the Qt installation, maybe the qmake path is wrong?</source>
<translation>Impossible de déterminer le chemin vers les programmes de Qt, peut-être que le chemin vers qmake est faux ?</translation>
<source>Could not determine the path to the binaries of the Qt installation, maybe the %1 path is wrong?</source>
<translation>Impossible de déterminer le chemin vers les programmes de Qt, peut-être que le chemin vers %1 est faux ?</translation>
</message>
<message>
<source>The default mkspec symlink is broken.</source>

View File

@@ -41628,7 +41628,7 @@ Saving failed.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>qmake does not exist or is not executable</source>
<source>%1 does not exist or is not executable</source>
<translation type="unfinished"></translation>
</message>
<message>
@@ -41636,7 +41636,7 @@ Saving failed.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Could not determine the path to the binaries of the Qt installation, maybe the qmake path is wrong?</source>
<source>Could not determine the path to the binaries of the Qt installation, maybe the %1 path is wrong?</source>
<translation type="unfinished"></translation>
</message>
<message>

View File

@@ -26108,16 +26108,16 @@ Do you want to save the data first?</source>
<translation>qmake </translation>
</message>
<message>
<source>qmake does not exist or is not executable</source>
<translation>qmake </translation>
<source>%1 does not exist or is not executable</source>
<translation>%1 </translation>
</message>
<message>
<source>Qt version is not properly installed, please run make install</source>
<translation>Qt make install </translation>
</message>
<message>
<source>Could not determine the path to the binaries of the Qt installation, maybe the qmake path is wrong?</source>
<translation>Qt qmake </translation>
<source>Could not determine the path to the binaries of the Qt installation, maybe the %1 path is wrong?</source>
<translation>Qt %1 </translation>
</message>
<message>
<source>The default mkspec symlink is broken.</source>

View File

@@ -12382,8 +12382,8 @@ Dla projektów CMake, upewnij się, że zmienna QML_IMPORT_PATH jest obecna w CM
<translation>Nie ustawiono ścieżki do qmake</translation>
</message>
<message>
<source>qmake does not exist or is not executable</source>
<translation>Brak qmake lub nie jest on plikiem wykonywalnym</translation>
<source>%1 does not exist or is not executable</source>
<translation>Brak %1 lub nie jest on plikiem wykonywalnym</translation>
</message>
<message>
<source>Qt version has no name</source>
@@ -12410,8 +12410,8 @@ Dla projektów CMake, upewnij się, że zmienna QML_IMPORT_PATH jest obecna w CM
<translation>Wersja Qt zainstalowana niepoprawnie, uruchom komendę: make install</translation>
</message>
<message>
<source>Could not determine the path to the binaries of the Qt installation, maybe the qmake path is wrong?</source>
<translation>Nie można określić ścieżki do plików binarnych instalacji Qt. Sprawdź ścieżkę do qmake.</translation>
<source>Could not determine the path to the binaries of the Qt installation, maybe the %1 path is wrong?</source>
<translation>Nie można określić ścieżki do plików binarnych instalacji Qt. Sprawdź ścieżkę do %1.</translation>
</message>
<message>
<source>The default mkspec symlink is broken.</source>

View File

@@ -45319,8 +45319,8 @@ For more details, see /etc/sysctl.d/10-ptrace.conf
<translation>Путь к qmake не указан</translation>
</message>
<message>
<source>qmake does not exist or is not executable</source>
<translation>qmake отсутствует или не запускается</translation>
<source>%1 does not exist or is not executable</source>
<translation>%1 отсутствует или не запускается</translation>
</message>
<message>
<source>Qt version has no name</source>
@@ -45347,8 +45347,8 @@ For more details, see /etc/sysctl.d/10-ptrace.conf
<translation>Профиль Qt не установлен, пожалуйста выполните make install</translation>
</message>
<message>
<source>Could not determine the path to the binaries of the Qt installation, maybe the qmake path is wrong?</source>
<translation>Не удалось определить путь к утилитам Qt. Может путь к qmake неверен?</translation>
<source>Could not determine the path to the binaries of the Qt installation, maybe the %1 path is wrong?</source>
<translation>Не удалось определить путь к утилитам Qt. Может путь к %1 неверен?</translation>
</message>
<message>
<source>The default mkspec symlink is broken.</source>

View File

@@ -21803,8 +21803,8 @@ Projekte programov QML izvede pregledovalnik QML in jih ni potrebno zgraditi.</t
</message>
<message>
<location line="+58"/>
<source>qmake does not exist or is not executable</source>
<translation>Datoteka »qmake« ne obstaja ali pa ni izvršljiva</translation>
<source>%1 does not exist or is not executable</source>
<translation>Datoteka »%1« ne obstaja ali pa ni izvršljiva</translation>
</message>
<message>
<location line="+2"/>
@@ -21813,8 +21813,8 @@ Projekte programov QML izvede pregledovalnik QML in jih ni potrebno zgraditi.</t
</message>
<message>
<location line="+2"/>
<source>Could not determine the path to the binaries of the Qt installation, maybe the qmake path is wrong?</source>
<translation>Ni bilo moč ugotoviti poti do programov namestitve Qt. Morda je pot do qmake napačna?</translation>
<source>Could not determine the path to the binaries of the Qt installation, maybe the %1 path is wrong?</source>
<translation>Ni bilo moč ugotoviti poti do programov namestitve Qt. Morda je pot do %1 napačna?</translation>
</message>
<message>
<location line="+3"/>

View File

@@ -22711,8 +22711,8 @@ For more details, see /etc/sysctl.d/10-ptrace.conf
<translation>Шлях до qmake не задано</translation>
</message>
<message>
<source>qmake does not exist or is not executable</source>
<translation>qmake не існує або не є виконуваним модулем</translation>
<source>%1 does not exist or is not executable</source>
<translation>%1 не існує або не є виконуваним модулем</translation>
</message>
<message>
<source>ABI detection failed: Make sure to use a matching compiler when building.</source>
@@ -22763,8 +22763,8 @@ For more details, see /etc/sysctl.d/10-ptrace.conf
<translation>Версія Qt не встановлена як слід, будь ласка, запустіть make install</translation>
</message>
<message>
<source>Could not determine the path to the binaries of the Qt installation, maybe the qmake path is wrong?</source>
<translation>Не вдалось визначити шлях до виконуваних модулів встановлення Qt, можливо, шлях до qmake помилковий?</translation>
<source>Could not determine the path to the binaries of the Qt installation, maybe the %1 path is wrong?</source>
<translation>Не вдалось визначити шлях до виконуваних модулів встановлення Qt, можливо, шлях до %1 помилковий?</translation>
</message>
<message>
<source>The default mkspec symlink is broken.</source>

View File

@@ -27948,8 +27948,8 @@ Did you start Qemu?</source>
<translation>qmake路径</translation>
</message>
<message>
<source>qmake does not exist or is not executable</source>
<translation>qmake不存在或者不可执</translation>
<source>%1 does not exist or is not executable</source>
<translation>%1</translation>
</message>
<message>
<source>Qt version has no name</source>
@@ -27976,8 +27976,8 @@ Did you start Qemu?</source>
<translation>Qt没有被正确安装make install</translation>
</message>
<message>
<source>Could not determine the path to the binaries of the Qt installation, maybe the qmake path is wrong?</source>
<translation>Qt安装的二进制所在的路径qmake的路径设置出现了错?</translation>
<source>Could not determine the path to the binaries of the Qt installation, maybe the %1 path is wrong?</source>
<translation>Qt安装的二进制所在的路径%1?</translation>
</message>
<message>
<source>The default mkspec symlink is broken.</source>

View File

@@ -15636,8 +15636,8 @@ Requires &lt;b&gt;Qt 4.7.4&lt;/b&gt; or newer.</source>
<translation> qmake </translation>
</message>
<message>
<source>qmake does not exist or is not executable</source>
<translation>qmake </translation>
<source>%1 does not exist or is not executable</source>
<translation>%1 </translation>
</message>
<message>
<source>Qt version has no name</source>
@@ -15664,8 +15664,8 @@ Requires &lt;b&gt;Qt 4.7.4&lt;/b&gt; or newer.</source>
<translation>Qt make install</translation>
</message>
<message>
<source>Could not determine the path to the binaries of the Qt installation, maybe the qmake path is wrong?</source>
<translation> Qt qmake </translation>
<source>Could not determine the path to the binaries of the Qt installation, maybe the %1 path is wrong?</source>
<translation> Qt %1 </translation>
</message>
<message>
<source>The default mkspec symlink is broken.</source>

View File

@@ -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<QString> 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 "<queryTool>.exe" or "<queryTool>.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 <tool>, 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

View File

@@ -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

View File

@@ -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."));

View File

@@ -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()));
}
}
}

View File

@@ -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 + ".";

View File

@@ -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.

View File

@@ -103,7 +103,8 @@ QMakeStep::QMakeStep(BuildStepList *bsl, Id id)
auto updateSummary = [this] {
QtVersion *qtVersion = QtKitAspect::qtVersion(target()->kit());
if (!qtVersion)
return tr("<b>qmake:</b> No Qt version set. Cannot run qmake.");
return tr("<b>Query tool:</b> No Qt version set. "
"Cannot run neither qmake nor qtpaths.");
const QString program = qtVersion->qmakeFilePath().fileName();
return tr("<b>qmake:</b> %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

View File

@@ -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();
}

View File

@@ -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<ProKey, ProString> versionInfo();
static bool queryQMakeVariables(const FilePath &binary,
const Environment &env,
QHash<ProKey, ProString> *versionInfo,
QString *error = nullptr);
static bool queryQtPaths(const FilePath &queryTool,
const Environment &env,
QHash<ProKey, ProString> *versionInfo,
QString *error = nullptr);
enum PropertyVariant { PropertyVariantDev, PropertyVariantGet, PropertyVariantSrc };
QString qmakeProperty(const QByteArray &name, PropertyVariant variant = PropertyVariantGet);
static QString qmakeProperty(const QHash<ProKey, ProString> &versionInfo,
const QByteArray &name,
PropertyVariant variant = PropertyVariantGet);
static FilePath mkspecDirectoryFromVersionInfo(const QHash<ProKey, ProString> &versionInfo,
const FilePath &qmakeCommand);
const FilePath &queryTool);
static FilePath mkspecFromVersionInfo(const QHash<ProKey,ProString> &versionInfo,
const FilePath &qmakeCommand);
const FilePath &queryTool);
static FilePath sourcePath(const QHash<ProKey,ProString> &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<Utils::Id> m_overrideFeatures;
@@ -233,6 +234,7 @@ public:
QHash<ProKey, ProString> 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", "<unknown>");
} 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 << "<td>" << abis.at(i).toString() << "</td></tr>";
}
}
const OsType osType = d->m_qmakeCommand.osType();
const OsType osType = d->m_queryTool.osType();
str << "<tr><td><b>" << QCoreApplication::translate("QtVersion", "Source:")
<< "</b></td><td>" << sourcePath().toUserOutput() << "</td></tr>";
str << "<tr><td><b>" << QCoreApplication::translate("QtVersion", "mkspec:")
<< "</b></td><td>" << QDir::toNativeSeparators(mkspec()) << "</td></tr>";
str << "<tr><td><b>" << QCoreApplication::translate("QtVersion", "qmake:")
<< "</b></td><td>" << d->m_qmakeCommand.toUserOutput() << "</td></tr>";
<< "</b></td><td>" << qmakeFilePath().toUserOutput() << "</td></tr>";
str << "<tr><td><b>" << QCoreApplication::translate("QtVersion", "Query tool:")
<< "</b></td><td>" << d->m_queryTool.toUserOutput() << "</td></tr>";
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<ProKey,ProString> QtVersionPrivate::versionInfo()
}
QString QtVersionPrivate::qmakeProperty(const QHash<ProKey, ProString> &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<ProKey, ProString> *versionInfo, QString *error)
bool QtVersionPrivate::queryQtPaths(const FilePath &queryTool, const Environment &env,
QHash<ProKey, ProString> *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<ProKey, ProString> &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<ProKey, ProString> &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<QtVersionFactory *> 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<ProKey, ProString> 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;
}

View File

@@ -150,6 +150,8 @@ public:
bool hasDocs() const;
bool hasDemos() const;
Utils::FilePath queryToolFilePath() const;
// former local functions
Utils::FilePath qmakeFilePath() const;

View File

@@ -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()

View File

@@ -51,6 +51,7 @@
#include <utils/hostosinfo.h>
#include <utils/pathchooser.h>
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
#include <utils/runextensions.h>
#include <utils/treemodel.h>
#include <utils/utilsicons.h>
@@ -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:
"<dd>%2</dd>";
return QString("<dl style=\"white-space:pre\">"
+ 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())
+ "</dl>");
}
@@ -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<QtVersionItem *>(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;

View File

@@ -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);

View File

@@ -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);

View File

@@ -39,14 +39,14 @@
<item row="1" column="0">
<widget class="QLabel" name="pathLabel">
<property name="text">
<string>qmake path:</string>
<string>Query tool path:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="qmakePath">
<widget class="QLabel" name="queryToolPath">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>

View File

@@ -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:"<<version->uniqueId();
qCDebug(log) << version->queryToolFilePath().toUserOutput()
<< "id:" <<version->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<QByteArray> 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<QByteArray> 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<QByteArray> 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<FilePath> 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)