diff --git a/src/libs/utils/buildablehelperlibrary.cpp b/src/libs/utils/buildablehelperlibrary.cpp index 2be40b6c9bf..6530113bb3e 100644 --- a/src/libs/utils/buildablehelperlibrary.cpp +++ b/src/libs/utils/buildablehelperlibrary.cpp @@ -2,6 +2,8 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "buildablehelperlibrary.h" + +#include "algorithm.h" #include "environment.h" #include "hostosinfo.h" #include "qtcprocess.h" @@ -42,7 +44,7 @@ FilePath BuildableHelperLibrary::qtChooserToQmakePath(const FilePath &qtChooser) static bool isQmake(FilePath path) { - if (path.isEmpty()) + if (!path.isExecutableFile()) return false; if (BuildableHelperLibrary::isQtChooser(path)) path = BuildableHelperLibrary::qtChooserToQmakePath(path.symLinkTarget()); @@ -51,37 +53,42 @@ static bool isQmake(FilePath path) return !BuildableHelperLibrary::qtVersionForQMake(path).isEmpty(); } -static FilePath findQmakeInDir(const FilePath &dir) +static FilePaths findQmakesInDir(const FilePath &dir) { if (dir.isEmpty()) return {}; - FilePath qmakePath = dir.pathAppended("qmake").withExecutableSuffix(); - if (qmakePath.exists()) { - if (isQmake(qmakePath)) - return qmakePath; - } - // Prefer qmake-qt5 to qmake-qt4 by sorting the filenames in reverse order. + FilePaths qmakes; + std::set canonicalQmakes; const FilePaths candidates = dir.dirEntries( {BuildableHelperLibrary::possibleQMakeCommands(), QDir::Files}, QDir::Name | QDir::Reversed); + + const auto probablyMatchesExistingQmake = [&](const FilePath &qmake) { + // This deals with symlinks. + if (!canonicalQmakes.insert(qmake).second) + return true; + + // Symlinks have high potential for false positives in file size check, so skip that one. + if (qmake.isSymLink()) + return false; + + // This deals with the case where copies are shipped instead of symlinks + // (Windows, Qt installer, ...). + return contains(qmakes, [size = qmake.fileSize()](const FilePath &existing) { + return existing.fileSize() == size; + }); + }; + for (const FilePath &candidate : candidates) { - if (candidate == qmakePath) - continue; - if (isQmake(candidate)) - return candidate; + if (isQmake(candidate) && !probablyMatchesExistingQmake(candidate)) + qmakes << candidate; } - return {}; + return qmakes; } -FilePath BuildableHelperLibrary::findSystemQt(const Environment &env) -{ - const FilePaths list = findQtsInEnvironment(env, 1); - return list.size() == 1 ? list.first() : FilePath(); -} - -FilePaths BuildableHelperLibrary::findQtsInEnvironment(const Environment &env, int maxCount) +FilePaths BuildableHelperLibrary::findQtsInEnvironment(const Environment &env) { FilePaths qmakeList; std::set canonicalEnvPaths; @@ -89,12 +96,7 @@ FilePaths BuildableHelperLibrary::findQtsInEnvironment(const Environment &env, i for (const FilePath &path : paths) { if (!canonicalEnvPaths.insert(path.canonicalPath()).second) continue; - const FilePath qmake = findQmakeInDir(path); - if (qmake.isEmpty()) - continue; - qmakeList << qmake; - if (maxCount != -1 && qmakeList.size() == maxCount) - break; + qmakeList << findQmakesInDir(path); } return qmakeList; } diff --git a/src/libs/utils/buildablehelperlibrary.h b/src/libs/utils/buildablehelperlibrary.h index e668fb81ad1..ea545fc4e27 100644 --- a/src/libs/utils/buildablehelperlibrary.h +++ b/src/libs/utils/buildablehelperlibrary.h @@ -16,10 +16,7 @@ class Environment; class QTCREATOR_UTILS_EXPORT BuildableHelperLibrary { public: - // returns the full path to the first qmake, qmake-qt4, qmake4 that has - // at least version 2.0.0 and thus is a qt4 qmake - static FilePath findSystemQt(const Environment &env); - static FilePaths findQtsInEnvironment(const Environment &env, int maxCount = -1); + static FilePaths findQtsInEnvironment(const Environment &env); 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)