forked from qt-creator/qt-creator
ProjectExplorer: Rewrite GccToolchain candidate identification
Change-Id: I9555588b64e0beeafc854d13a43dd0fad32662e2 Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
This commit is contained in:
@@ -23,6 +23,7 @@
|
|||||||
#include <utils/pathchooser.h>
|
#include <utils/pathchooser.h>
|
||||||
#include <utils/process.h>
|
#include <utils/process.h>
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
|
#include <utils/scopedtimer.h>
|
||||||
|
|
||||||
#include <QBuffer>
|
#include <QBuffer>
|
||||||
#include <QCheckBox>
|
#include <QCheckBox>
|
||||||
@@ -1247,56 +1248,78 @@ GccToolChainFactory::GccToolChainFactory(GccToolChain::SubType subType)
|
|||||||
setUserCreatable(true);
|
setUserCreatable(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static FilePaths findCompilerCandidates(const ToolchainDetector &detector,
|
static FilePaths findCompilerCandidates(OsType os,
|
||||||
|
const FilePaths &executables,
|
||||||
const QString &compilerName,
|
const QString &compilerName,
|
||||||
bool detectVariants)
|
bool detectVariants)
|
||||||
{
|
{
|
||||||
QStringList nameFilters(compilerName);
|
// We expect the following patterns:
|
||||||
if (detectVariants) {
|
// compilerName "clang", "gcc"
|
||||||
nameFilters
|
// compilerName + "-[1-9]*" "clang-8", "gcc-5"
|
||||||
<< compilerName + "-[1-9]*" // "clang-8", "gcc-5"
|
// "*-" + compilerName "avr-gcc", "avr32-gcc"
|
||||||
<< ("*-" + compilerName) // "avr-gcc", "avr32-gcc", "arm-none-eabi-gcc",
|
// "arm-none-eabi-gcc"
|
||||||
// "x86_64-pc-linux-gnu-gcc"
|
// "x86_64-pc-linux-gnu-gcc"
|
||||||
<< ("*-" + compilerName + "-[1-9]*"); // "avr-gcc-4.8.1", "avr32-gcc-4.4.7",
|
// "*-" + compilerName + "-[1-9]*" "avr-gcc-4.8.1", "avr32-gcc-4.4.7"
|
||||||
// "arm-none-eabi-gcc-9.1.0"
|
// "arm-none-eabi-gcc-9.1.0"
|
||||||
// "x86_64-pc-linux-gnu-gcc-7.4.1"
|
// "x86_64-pc-linux-gnu-gcc-7.4.1"
|
||||||
}
|
|
||||||
const Utils::OsType os = detector.device->osType();
|
|
||||||
nameFilters = transform(nameFilters, [os](const QString &baseName) {
|
|
||||||
return OsSpecificAspects::withExecutableSuffix(os, baseName);
|
|
||||||
});
|
|
||||||
|
|
||||||
FilePaths compilerPaths;
|
FilePaths compilerPaths;
|
||||||
for (const FilePath &searchPath : std::as_const(detector.searchPaths)) {
|
const int cl = compilerName.size();
|
||||||
static const QRegularExpression regexp(binaryRegexp);
|
for (const FilePath &executable : executables) {
|
||||||
const auto callBack = [os, &compilerPaths, compilerName](const FilePath &candidate) {
|
QStringView fileName = executable.fileNameView();
|
||||||
if (candidate.fileName() == OsSpecificAspects::withExecutableSuffix(os, compilerName)
|
if (os == OsTypeWindows && fileName.endsWith(u".exe", Qt::CaseInsensitive))
|
||||||
|| regexp.match(candidate.path()).hasMatch()) {
|
fileName.chop(4);
|
||||||
compilerPaths << candidate;
|
|
||||||
|
if (fileName == compilerName)
|
||||||
|
compilerPaths << executable;
|
||||||
|
|
||||||
|
if (!detectVariants)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int pos = fileName.indexOf(compilerName);
|
||||||
|
if (pos == -1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// if not at the beginning, it must be preceded by a hyphen.
|
||||||
|
if (pos > 0 && fileName.at(pos - 1) != '-')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// if not at the end, it must by followed by a hyphen and a digit between 1 and 9
|
||||||
|
pos += cl;
|
||||||
|
if (pos != fileName.size()) {
|
||||||
|
if (pos + 2 >= fileName.size())
|
||||||
|
continue;
|
||||||
|
if (fileName.at(pos) != '-')
|
||||||
|
continue;
|
||||||
|
const QChar c = fileName.at(pos + 1);
|
||||||
|
if (c < '1' || c > '9')
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
return IterationPolicy::Continue;
|
|
||||||
};
|
compilerPaths << executable;
|
||||||
searchPath.iterateDirectory(callBack, {nameFilters, QDir::Files | QDir::Executable});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return compilerPaths;
|
return compilerPaths;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Toolchains GccToolChainFactory::autoDetect(const ToolchainDetector &detector_) const
|
Toolchains GccToolChainFactory::autoDetect(const ToolchainDetector &detector) const
|
||||||
{
|
{
|
||||||
QTC_ASSERT(detector_.device, return {});
|
QTC_SCOPED_TIMER("Autodetect");
|
||||||
|
|
||||||
|
QTC_ASSERT(detector.device, return {});
|
||||||
|
|
||||||
// Do all autodetection in th 'RealGcc' case, and none in the others.
|
// Do all autodetection in th 'RealGcc' case, and none in the others.
|
||||||
if (!m_autoDetecting)
|
if (!m_autoDetecting)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
FilePaths searchPaths = detector_.searchPaths;
|
const bool isLocal = detector.device->type() == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE;
|
||||||
if (detector_.device->type() != ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE) {
|
FilePaths searchPaths = detector.searchPaths;
|
||||||
|
if (!isLocal) {
|
||||||
if (searchPaths.isEmpty())
|
if (searchPaths.isEmpty())
|
||||||
searchPaths = detector_.device->systemEnvironment().path();
|
searchPaths = detector.device->systemEnvironment().path();
|
||||||
searchPaths = Utils::transform(searchPaths, [&](const FilePath &onDevice) {
|
searchPaths = Utils::transform(searchPaths, [&](const FilePath &onDevice) {
|
||||||
return detector_.device->filePath(onDevice.path());
|
return detector.device->filePath(onDevice.path());
|
||||||
});
|
});
|
||||||
} else if (searchPaths.isEmpty()) {
|
} else if (searchPaths.isEmpty()) {
|
||||||
searchPaths = Environment::systemEnvironment().path();
|
searchPaths = Environment::systemEnvironment().path();
|
||||||
@@ -1317,24 +1340,32 @@ Toolchains GccToolChainFactory::autoDetect(const ToolchainDetector &detector_) c
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FilePaths executables;
|
||||||
|
|
||||||
ToolchainDetector detector{detector_.alreadyKnown, detector_.device, searchPaths};
|
QStringList nameFilters = {"*icpc*", "*icc*", "*g++*", "*gcc*", "*clang++*", "*clang*"};
|
||||||
|
|
||||||
|
FilePath::iterateDirectories(searchPaths, [&executables](const FilePath &path) {
|
||||||
|
executables.append(path);
|
||||||
|
return IterationPolicy::Continue;
|
||||||
|
}, {nameFilters, QDir::Files | QDir::Executable});
|
||||||
|
|
||||||
|
const OsType os = detector.device->osType();
|
||||||
|
|
||||||
Toolchains result;
|
Toolchains result;
|
||||||
|
|
||||||
// Linux ICC
|
// Linux ICC
|
||||||
|
|
||||||
result += autoDetectToolchains(findCompilerCandidates(detector, "icpc", false),
|
result += autoDetectToolchains(findCompilerCandidates(os, executables, "icpc", false),
|
||||||
Constants::CXX_LANGUAGE_ID,
|
Constants::CXX_LANGUAGE_ID,
|
||||||
Constants::LINUXICC_TOOLCHAIN_TYPEID,
|
Constants::LINUXICC_TOOLCHAIN_TYPEID,
|
||||||
detector,
|
detector.alreadyKnown,
|
||||||
&constructLinuxIccToolchain);
|
&constructLinuxIccToolchain);
|
||||||
|
|
||||||
|
|
||||||
result += autoDetectToolchains(findCompilerCandidates(detector, "icc", true),
|
result += autoDetectToolchains(findCompilerCandidates(os, executables, "icc", true),
|
||||||
Constants::C_LANGUAGE_ID,
|
Constants::C_LANGUAGE_ID,
|
||||||
Constants::LINUXICC_TOOLCHAIN_TYPEID,
|
Constants::LINUXICC_TOOLCHAIN_TYPEID,
|
||||||
detector,
|
detector.alreadyKnown,
|
||||||
&constructLinuxIccToolchain);
|
&constructLinuxIccToolchain);
|
||||||
|
|
||||||
// MinGW
|
// MinGW
|
||||||
@@ -1343,16 +1374,16 @@ Toolchains GccToolChainFactory::autoDetect(const ToolchainDetector &detector_) c
|
|||||||
return tc->targetAbi().osFlavor() == Abi::WindowsMSysFlavor;
|
return tc->targetAbi().osFlavor() == Abi::WindowsMSysFlavor;
|
||||||
};
|
};
|
||||||
|
|
||||||
result += autoDetectToolchains(findCompilerCandidates(detector, "g++", true),
|
result += autoDetectToolchains(findCompilerCandidates(os, executables, "g++", true),
|
||||||
Constants::CXX_LANGUAGE_ID,
|
Constants::CXX_LANGUAGE_ID,
|
||||||
Constants::MINGW_TOOLCHAIN_TYPEID,
|
Constants::MINGW_TOOLCHAIN_TYPEID,
|
||||||
detector,
|
detector.alreadyKnown,
|
||||||
&constructMinGWToolchain,
|
&constructMinGWToolchain,
|
||||||
tcChecker);
|
tcChecker);
|
||||||
result += autoDetectToolchains(findCompilerCandidates(detector, "gcc", true),
|
result += autoDetectToolchains(findCompilerCandidates(os, executables, "gcc", true),
|
||||||
Constants::C_LANGUAGE_ID,
|
Constants::C_LANGUAGE_ID,
|
||||||
Constants::MINGW_TOOLCHAIN_TYPEID,
|
Constants::MINGW_TOOLCHAIN_TYPEID,
|
||||||
detector,
|
detector.alreadyKnown,
|
||||||
&constructMinGWToolchain,
|
&constructMinGWToolchain,
|
||||||
tcChecker);
|
tcChecker);
|
||||||
|
|
||||||
@@ -1361,15 +1392,15 @@ Toolchains GccToolChainFactory::autoDetect(const ToolchainDetector &detector_) c
|
|||||||
Toolchains tcs;
|
Toolchains tcs;
|
||||||
Toolchains known = detector.alreadyKnown;
|
Toolchains known = detector.alreadyKnown;
|
||||||
|
|
||||||
tcs.append(autoDetectToolchains(findCompilerCandidates(detector, "clang++", true),
|
tcs.append(autoDetectToolchains(findCompilerCandidates(os, executables, "clang++", true),
|
||||||
Constants::CXX_LANGUAGE_ID,
|
Constants::CXX_LANGUAGE_ID,
|
||||||
Constants::CLANG_TOOLCHAIN_TYPEID,
|
Constants::CLANG_TOOLCHAIN_TYPEID,
|
||||||
detector,
|
detector.alreadyKnown,
|
||||||
&constructClangToolchain));
|
&constructClangToolchain));
|
||||||
tcs.append(autoDetectToolchains(findCompilerCandidates(detector, "clang", true),
|
tcs.append(autoDetectToolchains(findCompilerCandidates(os, executables, "clang", true),
|
||||||
Constants::C_LANGUAGE_ID,
|
Constants::C_LANGUAGE_ID,
|
||||||
Constants::CLANG_TOOLCHAIN_TYPEID,
|
Constants::CLANG_TOOLCHAIN_TYPEID,
|
||||||
detector,
|
detector.alreadyKnown,
|
||||||
&constructClangToolchain));
|
&constructClangToolchain));
|
||||||
known.append(tcs);
|
known.append(tcs);
|
||||||
|
|
||||||
@@ -1379,7 +1410,7 @@ Toolchains GccToolChainFactory::autoDetect(const ToolchainDetector &detector_) c
|
|||||||
autoDetectToolchains({compilerPath},
|
autoDetectToolchains({compilerPath},
|
||||||
Constants::C_LANGUAGE_ID,
|
Constants::C_LANGUAGE_ID,
|
||||||
Constants::CLANG_TOOLCHAIN_TYPEID,
|
Constants::CLANG_TOOLCHAIN_TYPEID,
|
||||||
ToolchainDetector(known, detector.device, detector.searchPaths),
|
known,
|
||||||
&constructClangToolchain));
|
&constructClangToolchain));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1395,16 +1426,16 @@ Toolchains GccToolChainFactory::autoDetect(const ToolchainDetector &detector_) c
|
|||||||
&& tc->compilerCommand().fileName() != "c89-gcc"
|
&& tc->compilerCommand().fileName() != "c89-gcc"
|
||||||
&& tc->compilerCommand().fileName() != "c99-gcc";
|
&& tc->compilerCommand().fileName() != "c99-gcc";
|
||||||
};
|
};
|
||||||
result += autoDetectToolchains(findCompilerCandidates(detector, "g++", true),
|
result += autoDetectToolchains(findCompilerCandidates(os, executables, "g++", true),
|
||||||
Constants::CXX_LANGUAGE_ID,
|
Constants::CXX_LANGUAGE_ID,
|
||||||
Constants::GCC_TOOLCHAIN_TYPEID,
|
Constants::GCC_TOOLCHAIN_TYPEID,
|
||||||
detector,
|
detector.alreadyKnown,
|
||||||
&constructRealGccToolchain,
|
&constructRealGccToolchain,
|
||||||
tcChecker);
|
tcChecker);
|
||||||
result += autoDetectToolchains(findCompilerCandidates(detector, "gcc", true),
|
result += autoDetectToolchains(findCompilerCandidates(os, executables, "gcc", true),
|
||||||
Constants::C_LANGUAGE_ID,
|
Constants::C_LANGUAGE_ID,
|
||||||
Constants::GCC_TOOLCHAIN_TYPEID,
|
Constants::GCC_TOOLCHAIN_TYPEID,
|
||||||
detector,
|
detector.alreadyKnown,
|
||||||
&constructRealGccToolchain,
|
&constructRealGccToolchain,
|
||||||
tcChecker);
|
tcChecker);
|
||||||
}
|
}
|
||||||
@@ -1483,11 +1514,11 @@ Toolchains GccToolChainFactory::detectForImport(const ToolChainDescription &tcd)
|
|||||||
Toolchains GccToolChainFactory::autoDetectToolchains(const FilePaths &compilerPaths,
|
Toolchains GccToolChainFactory::autoDetectToolchains(const FilePaths &compilerPaths,
|
||||||
const Id language,
|
const Id language,
|
||||||
const Id requiredTypeId,
|
const Id requiredTypeId,
|
||||||
const ToolchainDetector &detector,
|
const Toolchains &known,
|
||||||
const ToolChainConstructor &constructor,
|
const ToolChainConstructor &constructor,
|
||||||
const ToolchainChecker &checker)
|
const ToolchainChecker &checker)
|
||||||
{
|
{
|
||||||
Toolchains existingCandidates = filtered(detector.alreadyKnown,
|
Toolchains existingCandidates = filtered(known,
|
||||||
[language](const ToolChain *tc) { return tc->language() == language; });
|
[language](const ToolChain *tc) { return tc->language() == language; });
|
||||||
Toolchains result;
|
Toolchains result;
|
||||||
for (const FilePath &compilerPath : std::as_const(compilerPaths)) {
|
for (const FilePath &compilerPath : std::as_const(compilerPaths)) {
|
||||||
|
|||||||
@@ -196,7 +196,7 @@ private:
|
|||||||
static Toolchains autoDetectToolchains(const Utils::FilePaths &compilerPaths,
|
static Toolchains autoDetectToolchains(const Utils::FilePaths &compilerPaths,
|
||||||
const Utils::Id language,
|
const Utils::Id language,
|
||||||
const Utils::Id requiredTypeId,
|
const Utils::Id requiredTypeId,
|
||||||
const ToolchainDetector &detector,
|
const Toolchains &known,
|
||||||
const ToolChainConstructor &constructor,
|
const ToolChainConstructor &constructor,
|
||||||
const ToolchainChecker &checker = {});
|
const ToolchainChecker &checker = {});
|
||||||
static Toolchains autoDetectToolChain(const ToolChainDescription &tcd,
|
static Toolchains autoDetectToolChain(const ToolChainDescription &tcd,
|
||||||
|
|||||||
Reference in New Issue
Block a user