diff --git a/src/libs/utils/qtcprocess.cpp b/src/libs/utils/qtcprocess.cpp index b9507d8d91c..53bae9da539 100644 --- a/src/libs/utils/qtcprocess.cpp +++ b/src/libs/utils/qtcprocess.cpp @@ -1698,4 +1698,89 @@ QString QtcProcess::Arguments::toString() const return QtcProcess::joinArgs(m_unixArgs, OsTypeLinux); } +// Path utilities + +// Locate a binary in a directory, applying all kinds of +// extensions the operating system supports. +static QString checkBinary(const QDir &dir, const QString &binary) +{ + // naive UNIX approach + const QFileInfo info(dir.filePath(binary)); + if (info.isFile() && info.isExecutable()) + return info.absoluteFilePath(); + + // Does the OS have some weird extension concept or does the + // binary have a 3 letter extension? + if (HostOsInfo::isAnyUnixHost() && !HostOsInfo::isMacHost()) + return QString(); + const int dotIndex = binary.lastIndexOf(QLatin1Char('.')); + if (dotIndex != -1 && dotIndex == binary.size() - 4) + return QString(); + + switch (HostOsInfo::hostOs()) { + case OsTypeLinux: + case OsTypeOtherUnix: + case OsTypeOther: + break; + case OsTypeWindows: { + static const char *windowsExtensions[] = {".cmd", ".bat", ".exe", ".com"}; + // Check the Windows extensions using the order + const int windowsExtensionCount = sizeof(windowsExtensions)/sizeof(const char*); + for (int e = 0; e < windowsExtensionCount; e ++) { + const QFileInfo windowsBinary(dir.filePath(binary + QLatin1String(windowsExtensions[e]))); + if (windowsBinary.isFile() && windowsBinary.isExecutable()) + return windowsBinary.absoluteFilePath(); + } + } + break; + case OsTypeMac: { + // Check for Mac app folders + const QFileInfo appFolder(dir.filePath(binary + QLatin1String(".app"))); + if (appFolder.isDir()) { + QString macBinaryPath = appFolder.absoluteFilePath(); + macBinaryPath += QLatin1String("/Contents/MacOS/"); + macBinaryPath += binary; + const QFileInfo macBinary(macBinaryPath); + if (macBinary.isFile() && macBinary.isExecutable()) + return macBinary.absoluteFilePath(); + } + } + break; + } + return QString(); +} + +QString QtcProcess::locateBinary(const QString &path, const QString &binary) +{ + // Absolute file? + const QFileInfo absInfo(binary); + if (absInfo.isAbsolute()) + return checkBinary(absInfo.dir(), absInfo.fileName()); + + // Windows finds binaries in the current directory + if (HostOsInfo::isWindowsHost()) { + const QString currentDirBinary = checkBinary(QDir::current(), binary); + if (!currentDirBinary.isEmpty()) + return currentDirBinary; + } + + const QStringList paths = path.split(HostOsInfo::pathListSeparator()); + if (paths.empty()) + return QString(); + const QStringList::const_iterator cend = paths.constEnd(); + for (QStringList::const_iterator it = paths.constBegin(); it != cend; ++it) { + const QDir dir(*it); + const QString rc = checkBinary(dir, binary); + if (!rc.isEmpty()) + return rc; + } + return QString(); +} + +QString QtcProcess::locateBinary(const QString &binary) +{ + const QByteArray path = qgetenv("PATH"); + return locateBinary(QString::fromLocal8Bit(path), binary); +} + } // namespace Utils diff --git a/src/libs/utils/qtcprocess.h b/src/libs/utils/qtcprocess.h index 47ddfc409a6..cb5f8b8812f 100644 --- a/src/libs/utils/qtcprocess.h +++ b/src/libs/utils/qtcprocess.h @@ -157,6 +157,11 @@ public: static QString normalizeNewlines(const QString &text); + // Helpers to find binaries. Do not use it for other path variables + // and file types. + static QString locateBinary(const QString &binary); + static QString locateBinary(const QString &path, const QString &binary); + private: #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) void setupChildProcess() override; diff --git a/src/libs/utils/synchronousprocess.cpp b/src/libs/utils/synchronousprocess.cpp index faa608f3457..a4e62ee351f 100644 --- a/src/libs/utils/synchronousprocess.cpp +++ b/src/libs/utils/synchronousprocess.cpp @@ -638,91 +638,6 @@ void SynchronousProcess::processStdErr(bool emitSignals) d->m_stdErr.append(d->m_process.readAllStandardError(), emitSignals); } -// Path utilities - -// Locate a binary in a directory, applying all kinds of -// extensions the operating system supports. -static QString checkBinary(const QDir &dir, const QString &binary) -{ - // naive UNIX approach - const QFileInfo info(dir.filePath(binary)); - if (info.isFile() && info.isExecutable()) - return info.absoluteFilePath(); - - // Does the OS have some weird extension concept or does the - // binary have a 3 letter extension? - if (HostOsInfo::isAnyUnixHost() && !HostOsInfo::isMacHost()) - return QString(); - const int dotIndex = binary.lastIndexOf(QLatin1Char('.')); - if (dotIndex != -1 && dotIndex == binary.size() - 4) - return QString(); - - switch (HostOsInfo::hostOs()) { - case OsTypeLinux: - case OsTypeOtherUnix: - case OsTypeOther: - break; - case OsTypeWindows: { - static const char *windowsExtensions[] = {".cmd", ".bat", ".exe", ".com"}; - // Check the Windows extensions using the order - const int windowsExtensionCount = sizeof(windowsExtensions)/sizeof(const char*); - for (int e = 0; e < windowsExtensionCount; e ++) { - const QFileInfo windowsBinary(dir.filePath(binary + QLatin1String(windowsExtensions[e]))); - if (windowsBinary.isFile() && windowsBinary.isExecutable()) - return windowsBinary.absoluteFilePath(); - } - } - break; - case OsTypeMac: { - // Check for Mac app folders - const QFileInfo appFolder(dir.filePath(binary + QLatin1String(".app"))); - if (appFolder.isDir()) { - QString macBinaryPath = appFolder.absoluteFilePath(); - macBinaryPath += QLatin1String("/Contents/MacOS/"); - macBinaryPath += binary; - const QFileInfo macBinary(macBinaryPath); - if (macBinary.isFile() && macBinary.isExecutable()) - return macBinary.absoluteFilePath(); - } - } - break; - } - return QString(); -} - -QString SynchronousProcess::locateBinary(const QString &path, const QString &binary) -{ - // Absolute file? - const QFileInfo absInfo(binary); - if (absInfo.isAbsolute()) - return checkBinary(absInfo.dir(), absInfo.fileName()); - - // Windows finds binaries in the current directory - if (HostOsInfo::isWindowsHost()) { - const QString currentDirBinary = checkBinary(QDir::current(), binary); - if (!currentDirBinary.isEmpty()) - return currentDirBinary; - } - - const QStringList paths = path.split(HostOsInfo::pathListSeparator()); - if (paths.empty()) - return QString(); - const QStringList::const_iterator cend = paths.constEnd(); - for (QStringList::const_iterator it = paths.constBegin(); it != cend; ++it) { - const QDir dir(*it); - const QString rc = checkBinary(dir, binary); - if (!rc.isEmpty()) - return rc; - } - return QString(); -} - -QString SynchronousProcess::locateBinary(const QString &binary) -{ - const QByteArray path = qgetenv("PATH"); - return locateBinary(QString::fromLocal8Bit(path), binary); -} - } // namespace Utils #include "synchronousprocess.moc" diff --git a/src/libs/utils/synchronousprocess.h b/src/libs/utils/synchronousprocess.h index fc9e4f84202..8d0ac27732b 100644 --- a/src/libs/utils/synchronousprocess.h +++ b/src/libs/utils/synchronousprocess.h @@ -129,11 +129,6 @@ public: // Starts the command blocking the UI fully SynchronousProcessResponse runBlocking(const CommandLine &cmd); - // Helpers to find binaries. Do not use it for other path variables - // and file types. - static QString locateBinary(const QString &binary); - static QString locateBinary(const QString &path, const QString &binary); - signals: void stdOutBuffered(const QString &lines, bool firstTime); void stdErrBuffered(const QString &lines, bool firstTime); diff --git a/src/plugins/qmakeprojectmanager/externaleditors.cpp b/src/plugins/qmakeprojectmanager/externaleditors.cpp index 7db24b732e9..1a7c79d5527 100644 --- a/src/plugins/qmakeprojectmanager/externaleditors.cpp +++ b/src/plugins/qmakeprojectmanager/externaleditors.cpp @@ -27,7 +27,7 @@ #include #include -#include +#include #include #include #include @@ -187,7 +187,7 @@ bool ExternalQtEditor::getEditorLaunchData(const QString &fileName, data->binary = findFirstCommand(qtVersionsToCheck, m_commandForQtVersion); // fallback if (data->binary.isEmpty()) - data->binary = Utils::SynchronousProcess::locateBinary(m_commandForQtVersion(nullptr)); + data->binary = Utils::QtcProcess::locateBinary(m_commandForQtVersion(nullptr)); if (data->binary.isEmpty()) { *errorMessage = msgAppNotFound(id().toString()); return false;