forked from qt-creator/qt-creator
ClangTools: Remove clang executable settings
We use custom clang executable and it does not make sense anymore to give a choice of changing it. Change-Id: Icf86042ac3fcd08c320ef2bbdaabef1102b023b5 Reviewed-by: Nikolai Kosjar <nikolai.kosjar@qt.io>
This commit is contained in:
@@ -74,6 +74,11 @@ function libDir(llvmConfig)
|
||||
return FileInfo.fromNativeSeparators(readOutput(llvmConfig, ["--libdir"]));
|
||||
}
|
||||
|
||||
function binDir(llvmConfig)
|
||||
{
|
||||
return FileInfo.fromNativeSeparators(readOutput(llvmConfig, ["--bindir"]));
|
||||
}
|
||||
|
||||
function version(llvmConfig)
|
||||
{
|
||||
return readOutput(llvmConfig, ["--version"]).replace(/(\d+\.\d+\.\d+).*/, "$1")
|
||||
|
||||
@@ -16,6 +16,7 @@ Module {
|
||||
property string llvmVersion
|
||||
property string llvmIncludeDir
|
||||
property string llvmLibDir
|
||||
property string llvmBinDir
|
||||
property stringList llvmLibs
|
||||
property stringList llvmToolingLibs
|
||||
property stringList llvmToolingDefines
|
||||
@@ -28,6 +29,7 @@ Module {
|
||||
llvmVersion = ClangFunctions.version(llvmConfig);
|
||||
llvmIncludeDir = ClangFunctions.includeDir(llvmConfig);
|
||||
llvmLibDir = ClangFunctions.libDir(llvmConfig);
|
||||
llvmBinDir = ClangFunctions.binDir(llvmConfig);
|
||||
llvmLibs = ClangFunctions.libraries(targetOS);
|
||||
llvmToolingLibs = ClangFunctions.toolingLibs(llvmConfig, targetOS);
|
||||
llvmBuildMode = ClangFunctions.buildMode(llvmConfig);
|
||||
@@ -43,6 +45,7 @@ Module {
|
||||
property string llvmVersion: clangProbe.llvmVersion
|
||||
property string llvmIncludeDir: clangProbe.llvmIncludeDir
|
||||
property string llvmLibDir: clangProbe.llvmLibDir
|
||||
property string llvmBinDir: clangProbe.llvmBinDir
|
||||
property stringList llvmLibs: clangProbe.llvmLibs
|
||||
property stringList llvmToolingLibs: clangProbe.llvmToolingLibs
|
||||
property string llvmBuildMode: clangProbe.llvmBuildMode
|
||||
|
||||
@@ -27,6 +27,7 @@ QtcPlugin {
|
||||
var resourceDir = FileInfo.joinPaths(libclang.llvmLibDir, "clang", libclang.llvmVersion,
|
||||
"include");
|
||||
defines.push('CLANG_RESOURCE_DIR="' + resourceDir + '"');
|
||||
defines.push('CLANG_BINDIR="' + libclang.llvmBinDir + '"');
|
||||
return defines;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ QtcPlugin {
|
||||
var resourceDir = FileInfo.joinPaths(libclang.llvmLibDir, "clang", libclang.llvmVersion,
|
||||
"include");
|
||||
defines.push('CLANG_RESOURCE_DIR="' + resourceDir + '"');
|
||||
defines.push('CLANG_BINDIR="' + libclang.llvmBinDir + '"');
|
||||
return defines;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ QtcPlugin {
|
||||
var resourceDir = FileInfo.joinPaths(libclang.llvmLibDir, "clang", libclang.llvmVersion,
|
||||
"include");
|
||||
defines.push('CLANG_RESOURCE_DIR="' + resourceDir + '"');
|
||||
defines.push('CLANG_BINDIR="' + libclang.llvmBinDir + '"');
|
||||
return defines;
|
||||
}
|
||||
|
||||
|
||||
@@ -43,50 +43,7 @@ ClangStaticAnalyzerConfigWidget::ClangStaticAnalyzerConfigWidget(
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
|
||||
Utils::PathChooser * const chooser = m_ui->clangExecutableChooser;
|
||||
chooser->setExpectedKind(Utils::PathChooser::ExistingCommand);
|
||||
chooser->setHistoryCompleter(QLatin1String("ClangStaticAnalyzer.ClangCommand.History"));
|
||||
chooser->setPromptDialogTitle(tr("Clang Command"));
|
||||
const auto validator = [chooser, this](Utils::FancyLineEdit *edit, QString *errorMessage) {
|
||||
const QString currentFilePath = chooser->fileName().toString();
|
||||
Utils::PathChooser pc;
|
||||
Utils::PathChooser *helperPathChooser;
|
||||
if (currentFilePath.isEmpty()) {
|
||||
pc.setExpectedKind(chooser->expectedKind());
|
||||
pc.setPath(edit->placeholderText());
|
||||
helperPathChooser = &pc;
|
||||
} else {
|
||||
helperPathChooser = chooser;
|
||||
}
|
||||
|
||||
const bool isExecutableValid =
|
||||
chooser->defaultValidationFunction()(helperPathChooser->lineEdit(), errorMessage)
|
||||
&& isClangExecutableUsable(helperPathChooser->fileName().toString(), errorMessage);
|
||||
|
||||
const ClangExecutableVersion detectedVersion = isExecutableValid
|
||||
? clangExecutableVersion(helperPathChooser->fileName().toString())
|
||||
: ClangExecutableVersion();
|
||||
updateDetectedVersionLabel(isExecutableValid, detectedVersion);
|
||||
|
||||
return isExecutableValid;
|
||||
};
|
||||
chooser->setValidationFunction(validator);
|
||||
bool clangExeIsSet;
|
||||
const QString clangExe = settings->clangExecutable(&clangExeIsSet);
|
||||
chooser->lineEdit()->setPlaceholderText(QDir::toNativeSeparators(
|
||||
settings->defaultClangExecutable()));
|
||||
if (clangExeIsSet) {
|
||||
chooser->setPath(clangExe);
|
||||
} else {
|
||||
// Setting an empty string does not trigger the validator, as that is the initial value
|
||||
// in the line edit.
|
||||
chooser->setPath(QLatin1String(" "));
|
||||
chooser->lineEdit()->clear();
|
||||
}
|
||||
connect(m_ui->clangExecutableChooser, &Utils::PathChooser::rawPathChanged,
|
||||
[settings](const QString &path) { settings->setClangExecutable(path); });
|
||||
|
||||
m_ui->simultaneousProccessesSpinBox->setValue(settings->simultaneousProcesses());
|
||||
m_ui->simultaneousProccessesSpinBox->setValue(settings->savedSimultaneousProcesses());
|
||||
m_ui->simultaneousProccessesSpinBox->setMinimum(1);
|
||||
m_ui->simultaneousProccessesSpinBox->setMaximum(QThread::idealThreadCount());
|
||||
connect(m_ui->simultaneousProccessesSpinBox,
|
||||
@@ -99,29 +56,5 @@ ClangStaticAnalyzerConfigWidget::~ClangStaticAnalyzerConfigWidget()
|
||||
delete m_ui;
|
||||
}
|
||||
|
||||
void ClangStaticAnalyzerConfigWidget::updateDetectedVersionLabel(
|
||||
bool isExecutableValid,
|
||||
const ClangExecutableVersion &providedVersion)
|
||||
{
|
||||
QLabel &label = *m_ui->detectedVersionLabel;
|
||||
|
||||
if (isExecutableValid) {
|
||||
if (providedVersion.isValid()) {
|
||||
if (providedVersion.isSupportedVersion()) {
|
||||
label.setText(tr("Version: %1, supported.")
|
||||
.arg(providedVersion.toString()));
|
||||
} else {
|
||||
label.setText(tr("Version: %1, unsupported (supported version is %2).")
|
||||
.arg(providedVersion.toString())
|
||||
.arg(ClangExecutableVersion::supportedVersionAsString()));
|
||||
}
|
||||
} else {
|
||||
label.setText(tr("Version: Could not determine version."));
|
||||
}
|
||||
} else {
|
||||
label.setText(tr("Version: Set valid executable first."));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace ClangTools
|
||||
|
||||
@@ -45,9 +45,6 @@ public:
|
||||
QWidget *parent = 0);
|
||||
~ClangStaticAnalyzerConfigWidget();
|
||||
|
||||
void updateDetectedVersionLabel(bool executableIsValid,
|
||||
const ClangExecutableVersion &providedVersion);
|
||||
|
||||
private:
|
||||
Ui::ClangStaticAnalyzerConfigWidget *m_ui;
|
||||
ClangToolsSettings *m_settings;
|
||||
|
||||
@@ -21,34 +21,13 @@
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Clang executable:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="Utils::PathChooser" name="clangExecutableChooser" native="true"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="detectedVersionLabel">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Simultaneous processes:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<item row="0" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QSpinBox" name="simultaneousProccessesSpinBox">
|
||||
@@ -93,14 +72,6 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>Utils::PathChooser</class>
|
||||
<extends>QWidget</extends>
|
||||
<header location="global">utils/pathchooser.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "clangstaticanalyzertool.h"
|
||||
#include "clangtoolsutils.h"
|
||||
|
||||
#include <cpptools/compileroptionsbuilder.h>
|
||||
#include <cpptools/projectinfo.h>
|
||||
#include <projectexplorer/kitinformation.h>
|
||||
#include <projectexplorer/kitmanager.h>
|
||||
@@ -166,9 +167,8 @@ static QList<Target *> validTargets(Project *project)
|
||||
|
||||
const ToolChain * const toolchain = ToolChainKitInformation::toolChain(kit, ProjectExplorer::Constants::CXX_LANGUAGE_ID);
|
||||
QTC_ASSERT(toolchain, return false);
|
||||
bool hasClangExecutable;
|
||||
clangExecutableFromSettings(&hasClangExecutable);
|
||||
if (!hasClangExecutable) {
|
||||
|
||||
if (CppTools::clangExecutable(CLANG_BINDIR).isEmpty()) {
|
||||
qWarning("Project \"%s\": Skipping target \"%s\" since no suitable clang was found for the toolchain.",
|
||||
qPrintable(projectFileName),
|
||||
qPrintable(target->displayName()));
|
||||
|
||||
@@ -147,7 +147,6 @@ ClangStaticAnalyzerRunControl::ClangStaticAnalyzerRunControl(RunControl *runCont
|
||||
|
||||
ClangToolRunner *ClangStaticAnalyzerRunControl::createRunner()
|
||||
{
|
||||
QTC_ASSERT(!m_clangExecutable.isEmpty(), return 0);
|
||||
QTC_ASSERT(!m_clangLogFileDir.isEmpty(), return 0);
|
||||
|
||||
auto runner = new ClangStaticAnalyzerRunner(m_clangExecutable,
|
||||
|
||||
@@ -145,18 +145,11 @@ static AnalyzeUnits unitsToAnalyzeFromProjectParts(const QVector<ProjectPart::Pt
|
||||
return unitsToAnalyze;
|
||||
}
|
||||
|
||||
static QString clangResourceDir(const QString &clangExecutable, const QString &clangVersion)
|
||||
{
|
||||
QDir llvmDir = QFileInfo(clangExecutable).dir();
|
||||
llvmDir.cdUp();
|
||||
return llvmDir.absolutePath() + clangIncludePath(clangVersion);
|
||||
}
|
||||
|
||||
AnalyzeUnits ClangToolRunControl::sortedUnitsToAnalyze(const QString &clangVersion)
|
||||
{
|
||||
QTC_ASSERT(m_projectInfo.isValid(), return AnalyzeUnits());
|
||||
|
||||
const QString clangResourceDirectory = clangResourceDir(m_clangExecutable, clangVersion);
|
||||
const QString clangResourceDirectory = clangIncludeDirectory(m_clangExecutable, clangVersion);
|
||||
AnalyzeUnits units = unitsToAnalyzeFromProjectParts(m_projectInfo.projectParts(), clangVersion,
|
||||
clangResourceDirectory);
|
||||
|
||||
@@ -179,7 +172,9 @@ static QDebug operator<<(QDebug debug, const AnalyzeUnits &analyzeUnits)
|
||||
}
|
||||
|
||||
ClangToolRunControl::ClangToolRunControl(RunControl *runControl, Target *target)
|
||||
: RunWorker(runControl), m_target(target)
|
||||
: RunWorker(runControl)
|
||||
, m_clangExecutable(CppTools::clangExecutable(CLANG_BINDIR))
|
||||
, m_target(target)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -208,9 +203,18 @@ void ClangToolRunControl::start()
|
||||
return;
|
||||
}
|
||||
|
||||
const QString &toolName = tool()->name();
|
||||
if (m_clangExecutable.isEmpty()) {
|
||||
const QString errorMessage = tr("%1 : Can't find clang executable, stop.").arg(toolName);
|
||||
appendMessage(errorMessage, Utils::ErrorMessageFormat);
|
||||
TaskHub::addTask(Task::Error, errorMessage, Debugger::Constants::ANALYZERTASK_ID);
|
||||
TaskHub::requestPopup();
|
||||
reportFailure();
|
||||
return;
|
||||
}
|
||||
|
||||
m_projectInfo = CppTools::CppModelManager::instance()->projectInfo(m_target->project());
|
||||
|
||||
const QString toolName = tool()->name();
|
||||
// Some projects provides CompilerCallData once a build is finished,
|
||||
if (m_projectInfo.configurationOrFilesChanged(m_projectInfoBeforeBuild)) {
|
||||
// If it's more than a release/debug build configuration change, e.g.
|
||||
@@ -225,42 +229,6 @@ void ClangToolRunControl::start()
|
||||
appendMessage(tr("Running %1 on %2").arg(toolName).arg(projectFile.toUserOutput()),
|
||||
Utils::NormalMessageFormat);
|
||||
|
||||
// Check clang executable
|
||||
bool isValidClangExecutable;
|
||||
const QString executable = clangExecutableFromSettings(&isValidClangExecutable);
|
||||
if (!isValidClangExecutable) {
|
||||
const QString errorMessage = toolName
|
||||
+ tr(": Invalid executable \"%1\", stop.").arg(executable);
|
||||
appendMessage(errorMessage, Utils::ErrorMessageFormat);
|
||||
TaskHub::addTask(Task::Error, errorMessage, Debugger::Constants::ANALYZERTASK_ID);
|
||||
TaskHub::requestPopup();
|
||||
reportFailure();
|
||||
return;
|
||||
}
|
||||
|
||||
// Check clang version
|
||||
const ClangExecutableVersion version = clangExecutableVersion(executable);
|
||||
if (!version.isValid()) {
|
||||
const QString warningMessage
|
||||
= toolName + tr(": Running with possibly unsupported version, "
|
||||
"could not determine version from executable \"%1\".")
|
||||
.arg(executable);
|
||||
appendMessage(warningMessage, Utils::StdErrFormat);
|
||||
TaskHub::addTask(Task::Warning, warningMessage, Debugger::Constants::ANALYZERTASK_ID);
|
||||
TaskHub::requestPopup();
|
||||
} else if (!version.isSupportedVersion()) {
|
||||
const QString warningMessage
|
||||
= toolName + tr(": Running with unsupported version %1, "
|
||||
"supported version is %2.")
|
||||
.arg(version.toString())
|
||||
.arg(ClangExecutableVersion::supportedVersionAsString());
|
||||
appendMessage(warningMessage, Utils::StdErrFormat);
|
||||
TaskHub::addTask(Task::Warning, warningMessage, Debugger::Constants::ANALYZERTASK_ID);
|
||||
TaskHub::requestPopup();
|
||||
}
|
||||
|
||||
m_clangExecutable = executable;
|
||||
|
||||
// Create log dir
|
||||
Utils::TemporaryDirectory temporaryDir("qtc-clangtools-XXXXXX");
|
||||
temporaryDir.setAutoRemove(false);
|
||||
@@ -276,7 +244,7 @@ void ClangToolRunControl::start()
|
||||
m_clangLogFileDir = temporaryDir.path();
|
||||
|
||||
// Collect files
|
||||
const AnalyzeUnits unitsToProcess = sortedUnitsToAnalyze(version.toString());
|
||||
const AnalyzeUnits unitsToProcess = sortedUnitsToAnalyze(CLANG_VERSION);
|
||||
qCDebug(LOG) << "Files to process:" << unitsToProcess;
|
||||
m_unitsToProcess = unitsToProcess;
|
||||
m_initialFilesToProcessSize = m_unitsToProcess.count();
|
||||
@@ -298,7 +266,7 @@ void ClangToolRunControl::start()
|
||||
// Start process(es)
|
||||
qCDebug(LOG) << "Environment:" << m_environment;
|
||||
m_runners.clear();
|
||||
const int parallelRuns = ClangToolsSettings::instance()->simultaneousProcesses();
|
||||
const int parallelRuns = ClangToolsSettings::instance()->savedSimultaneousProcesses();
|
||||
QTC_ASSERT(parallelRuns >= 1, reportFailure(); return);
|
||||
m_success = true;
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
include(../../qtcreatorplugin.pri)
|
||||
include(../../shared/clang/clang_installation.pri)
|
||||
|
||||
include(../../shared/clang/clang_defines.pri)
|
||||
|
||||
requires(!isEmpty(LLVM_VERSION))
|
||||
|
||||
LIBS += $$LIBCLANG_LIBS
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import qbs
|
||||
import qbs.FileInfo
|
||||
|
||||
QtcPlugin {
|
||||
name: "ClangTools"
|
||||
@@ -26,6 +27,19 @@ QtcPlugin {
|
||||
cpp.dynamicLibraries: base.concat(libclang.llvmLibs)
|
||||
cpp.rpaths: base.concat(libclang.llvmLibDir)
|
||||
|
||||
cpp.defines: {
|
||||
var defines = base;
|
||||
defines.push("CLANGPCHMANAGER_LIB");
|
||||
|
||||
// The following defines are used to determine the clang include path for intrinsics.
|
||||
defines.push('CLANG_VERSION="' + libclang.llvmVersion + '"');
|
||||
var resourceDir = FileInfo.joinPaths(libclang.llvmLibDir, "clang", libclang.llvmVersion,
|
||||
"include");
|
||||
defines.push('CLANG_RESOURCE_DIR="' + resourceDir + '"');
|
||||
defines.push('CLANG_BINDIR="' + libclang.llvmBinDir + '"');
|
||||
return defines;
|
||||
}
|
||||
|
||||
files: [
|
||||
"clangstaticanalyzerconfigwidget.cpp",
|
||||
"clangstaticanalyzerconfigwidget.h",
|
||||
|
||||
@@ -35,14 +35,12 @@
|
||||
#include <QFileInfo>
|
||||
#include <QThread>
|
||||
|
||||
static const char clangExecutableKey[] = "clangExecutable";
|
||||
static const char simultaneousProcessesKey[] = "simultaneousProcesses";
|
||||
|
||||
namespace ClangTools {
|
||||
namespace Internal {
|
||||
|
||||
ClangToolsSettings::ClangToolsSettings()
|
||||
: m_simultaneousProcesses(-1)
|
||||
{
|
||||
readSettings();
|
||||
}
|
||||
@@ -53,36 +51,9 @@ ClangToolsSettings *ClangToolsSettings::instance()
|
||||
return &instance;
|
||||
}
|
||||
|
||||
static QString clangExecutableFileName()
|
||||
int ClangToolsSettings::savedSimultaneousProcesses() const
|
||||
{
|
||||
return QLatin1String("clang" QTC_HOST_EXE_SUFFIX);
|
||||
}
|
||||
|
||||
QString ClangToolsSettings::defaultClangExecutable() const
|
||||
{
|
||||
const QString shippedBinary = Core::ICore::libexecPath()
|
||||
+ QLatin1String("/clang/bin/")
|
||||
+ clangExecutableFileName();
|
||||
if (QFileInfo(shippedBinary).isExecutable())
|
||||
return shippedBinary;
|
||||
return clangExecutableFileName();
|
||||
}
|
||||
|
||||
QString ClangToolsSettings::clangExecutable(bool *isSet) const
|
||||
{
|
||||
if (m_clangExecutable.isEmpty()) {
|
||||
if (isSet)
|
||||
*isSet = false;
|
||||
return defaultClangExecutable();
|
||||
}
|
||||
if (isSet)
|
||||
*isSet = true;
|
||||
return m_clangExecutable;
|
||||
}
|
||||
|
||||
void ClangToolsSettings::setClangExecutable(const QString &exectuable)
|
||||
{
|
||||
m_clangExecutable = exectuable;
|
||||
return m_savedSimultaneousProcesses;
|
||||
}
|
||||
|
||||
int ClangToolsSettings::simultaneousProcesses() const
|
||||
@@ -92,7 +63,6 @@ int ClangToolsSettings::simultaneousProcesses() const
|
||||
|
||||
void ClangToolsSettings::setSimultaneousProcesses(int processes)
|
||||
{
|
||||
QTC_ASSERT(processes >=1, return);
|
||||
m_simultaneousProcesses = processes;
|
||||
}
|
||||
|
||||
@@ -101,21 +71,22 @@ void ClangToolsSettings::readSettings()
|
||||
QSettings *settings = Core::ICore::settings();
|
||||
settings->beginGroup(QLatin1String(Constants::SETTINGS_ID));
|
||||
|
||||
setClangExecutable(settings->value(QLatin1String(clangExecutableKey)).toString());
|
||||
|
||||
const int defaultSimultaneousProcesses = qMax(0, QThread::idealThreadCount() / 2);
|
||||
setSimultaneousProcesses(settings->value(QLatin1String(simultaneousProcessesKey),
|
||||
defaultSimultaneousProcesses).toInt());
|
||||
m_savedSimultaneousProcesses = m_simultaneousProcesses
|
||||
= settings->value(QString(simultaneousProcessesKey),
|
||||
defaultSimultaneousProcesses).toInt();
|
||||
|
||||
settings->endGroup();
|
||||
}
|
||||
|
||||
void ClangToolsSettings::writeSettings() const
|
||||
void ClangToolsSettings::writeSettings()
|
||||
{
|
||||
QSettings *settings = Core::ICore::settings();
|
||||
settings->beginGroup(QLatin1String(Constants::SETTINGS_ID));
|
||||
settings->setValue(QLatin1String(clangExecutableKey), m_clangExecutable);
|
||||
settings->setValue(QLatin1String(simultaneousProcessesKey), simultaneousProcesses());
|
||||
settings->beginGroup(QString(Constants::SETTINGS_ID));
|
||||
settings->setValue(QString(simultaneousProcessesKey), m_simultaneousProcesses);
|
||||
|
||||
m_savedSimultaneousProcesses = m_simultaneousProcesses;
|
||||
|
||||
settings->endGroup();
|
||||
}
|
||||
|
||||
|
||||
@@ -35,11 +35,9 @@ class ClangToolsSettings
|
||||
public:
|
||||
static ClangToolsSettings *instance();
|
||||
|
||||
void writeSettings() const;
|
||||
void writeSettings();
|
||||
|
||||
QString defaultClangExecutable() const;
|
||||
QString clangExecutable(bool *isSet = nullptr) const;
|
||||
void setClangExecutable(const QString &exectuable);
|
||||
int savedSimultaneousProcesses() const;
|
||||
|
||||
int simultaneousProcesses() const;
|
||||
void setSimultaneousProcesses(int processes);
|
||||
@@ -48,8 +46,8 @@ private:
|
||||
ClangToolsSettings();
|
||||
void readSettings();
|
||||
|
||||
QString m_clangExecutable;
|
||||
int m_simultaneousProcesses;
|
||||
int m_simultaneousProcesses = -1;
|
||||
int m_savedSimultaneousProcesses = -1;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -62,9 +62,8 @@ void ClangToolsUnitTests::initTestCase()
|
||||
Constants::CXX_LANGUAGE_ID);
|
||||
if (!toolchain)
|
||||
QSKIP("This test requires that there is a kit with a toolchain.");
|
||||
bool hasClangExecutable;
|
||||
clangExecutableFromSettings(&hasClangExecutable);
|
||||
if (!hasClangExecutable)
|
||||
|
||||
if (CppTools::clangExecutable(CLANG_BINDIR).isEmpty())
|
||||
QSKIP("No clang suitable for analyzing found");
|
||||
|
||||
m_tmpDir = new CppTools::Tests::TemporaryCopiedDir(QLatin1String(":/unit-tests"));
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
#include "clangtoolsdiagnostic.h"
|
||||
#include "clangtoolssettings.h"
|
||||
|
||||
#include <coreplugin/icore.h>
|
||||
|
||||
#include <projectexplorer/projectexplorerconstants.h>
|
||||
|
||||
#include <utils/hostosinfo.h>
|
||||
@@ -38,118 +40,14 @@
|
||||
#include <QFileInfo>
|
||||
#include <QRegularExpression>
|
||||
|
||||
static bool isFileExecutable(const QString &executablePath)
|
||||
{
|
||||
if (executablePath.isEmpty())
|
||||
return false;
|
||||
|
||||
const QFileInfo fileInfo(executablePath);
|
||||
return fileInfo.isFile() && fileInfo.isExecutable();
|
||||
}
|
||||
|
||||
namespace ClangTools {
|
||||
namespace Internal {
|
||||
|
||||
QString clangExecutableFromSettings(bool *isValid)
|
||||
{
|
||||
QString executable = ClangToolsSettings::instance()->clangExecutable();
|
||||
if (executable.isEmpty()) {
|
||||
*isValid = false;
|
||||
return executable;
|
||||
}
|
||||
|
||||
const QString hostExeSuffix = QLatin1String(QTC_HOST_EXE_SUFFIX);
|
||||
const Qt::CaseSensitivity caseSensitivity = Utils::HostOsInfo::fileNameCaseSensitivity();
|
||||
const bool hasSuffix = executable.endsWith(hostExeSuffix, caseSensitivity);
|
||||
|
||||
const QFileInfo fileInfo = QFileInfo(executable);
|
||||
if (fileInfo.isAbsolute()) {
|
||||
if (!hasSuffix)
|
||||
executable.append(hostExeSuffix);
|
||||
} else {
|
||||
const Utils::Environment &environment = Utils::Environment::systemEnvironment();
|
||||
const QString executableFromPath = environment.searchInPath(executable).toString();
|
||||
if (executableFromPath.isEmpty()) {
|
||||
*isValid = false;
|
||||
return executable;
|
||||
}
|
||||
executable = executableFromPath;
|
||||
}
|
||||
|
||||
*isValid = isFileExecutable(executable) && isClangExecutableUsable(executable);
|
||||
return executable;
|
||||
}
|
||||
|
||||
QString createFullLocationString(const Debugger::DiagnosticLocation &location)
|
||||
{
|
||||
return location.filePath + QLatin1Char(':') + QString::number(location.line)
|
||||
+ QLatin1Char(':') + QString::number(location.column);
|
||||
}
|
||||
|
||||
bool isClangExecutableUsable(const QString &filePath, QString *errorMessage)
|
||||
{
|
||||
const QFileInfo fi(filePath);
|
||||
if (fi.isSymLink() && fi.symLinkTarget().contains(QLatin1String("icecc"))) {
|
||||
if (errorMessage) {
|
||||
*errorMessage = QCoreApplication::translate("ClangTools",
|
||||
"The chosen file \"%1\" seems to point to an icecc binary not suitable "
|
||||
"for analyzing.\nPlease set a real Clang executable.")
|
||||
.arg(filePath);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
ClangExecutableVersion clangExecutableVersion(const QString &executable)
|
||||
{
|
||||
const ClangExecutableVersion invalidVersion;
|
||||
|
||||
// Sanity checks
|
||||
const QFileInfo fileInfo(executable);
|
||||
const bool isExecutableFile = fileInfo.isFile() && fileInfo.isExecutable();
|
||||
if (!isExecutableFile)
|
||||
return invalidVersion;
|
||||
|
||||
// Get version output
|
||||
Utils::Environment environment = Utils::Environment::systemEnvironment();
|
||||
Utils::Environment::setupEnglishOutput(&environment);
|
||||
Utils::SynchronousProcess runner;
|
||||
runner.setEnvironment(environment.toStringList());
|
||||
runner.setTimeoutS(10);
|
||||
// We would prefer "-dumpversion", but that one is only there for GCC compatibility
|
||||
// and returns some static/old version.
|
||||
// See also https://bugs.llvm.org/show_bug.cgi?id=28597
|
||||
const QStringList arguments(QLatin1String(("--version")));
|
||||
const Utils::SynchronousProcessResponse response = runner.runBlocking(executable, arguments);
|
||||
if (response.result != Utils::SynchronousProcessResponse::Finished)
|
||||
return invalidVersion;
|
||||
const QString output = response.stdOut();
|
||||
|
||||
// Parse version output
|
||||
const QRegularExpression re(QLatin1String("clang version (\\d+)\\.(\\d+)\\.(\\d+)"));
|
||||
const QRegularExpressionMatch reMatch = re.match(output);
|
||||
if (re.captureCount() != 3)
|
||||
return invalidVersion;
|
||||
|
||||
const QString majorString = reMatch.captured(1);
|
||||
bool convertedSuccessfully = false;
|
||||
const int major = majorString.toInt(&convertedSuccessfully);
|
||||
if (!convertedSuccessfully)
|
||||
return invalidVersion;
|
||||
|
||||
const QString minorString = reMatch.captured(2);
|
||||
const int minor = minorString.toInt(&convertedSuccessfully);
|
||||
if (!convertedSuccessfully)
|
||||
return invalidVersion;
|
||||
|
||||
const QString patchString = reMatch.captured(3);
|
||||
const int patch = patchString.toInt(&convertedSuccessfully);
|
||||
if (!convertedSuccessfully)
|
||||
return invalidVersion;
|
||||
|
||||
return ClangExecutableVersion(major, minor, patch);
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace ClangTools
|
||||
|
||||
@@ -39,36 +39,7 @@ namespace Debugger { class DiagnosticLocation; }
|
||||
namespace ClangTools {
|
||||
namespace Internal {
|
||||
|
||||
bool isClangExecutableUsable(const QString &filePath, QString *errorMessage = 0);
|
||||
|
||||
QString clangExecutableFromSettings(bool *isValid);
|
||||
|
||||
QString createFullLocationString(const Debugger::DiagnosticLocation &location);
|
||||
|
||||
// CLANG-UPGRADE-CHECK: Adapt minimum version numbers.
|
||||
class ClangExecutableVersion : public QVersionNumber {
|
||||
public:
|
||||
ClangExecutableVersion() : QVersionNumber(-1, -1, -1) {}
|
||||
ClangExecutableVersion(int major, int minor, int micro)
|
||||
: QVersionNumber(major, minor, micro) {}
|
||||
|
||||
bool isValid() const
|
||||
{
|
||||
return majorVersion() >= 0 && minorVersion() >= 0 && microVersion() >= 0;
|
||||
}
|
||||
|
||||
bool isSupportedVersion() const
|
||||
{
|
||||
return majorVersion() == 5 && minorVersion() == 0;
|
||||
}
|
||||
|
||||
static QString supportedVersionAsString()
|
||||
{
|
||||
return QLatin1String("5.0");
|
||||
}
|
||||
};
|
||||
|
||||
ClangExecutableVersion clangExecutableVersion(const QString &absolutePath);
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace ClangTools
|
||||
|
||||
@@ -528,7 +528,7 @@ void CompilerOptionsBuilder::addClangIncludeFolder()
|
||||
{
|
||||
QTC_CHECK(!m_clangVersion.isEmpty());
|
||||
add(SYSTEM_INCLUDE_PREFIX);
|
||||
add(clangIncludeDirectory());
|
||||
add(clangIncludeDirectory(m_clangVersion, m_clangResourceDirectory));
|
||||
}
|
||||
|
||||
void CompilerOptionsBuilder::addProjectConfigFileInclude()
|
||||
@@ -548,14 +548,23 @@ static QString creatorLibexecPath()
|
||||
#endif
|
||||
}
|
||||
|
||||
QString CompilerOptionsBuilder::clangIncludeDirectory() const
|
||||
QString clangIncludeDirectory(const QString &clangVersion, const QString &clangResourceDirectory)
|
||||
{
|
||||
QDir dir(creatorLibexecPath() + "/clang" + clangIncludePath(m_clangVersion));
|
||||
QDir dir(creatorLibexecPath() + "/clang" + clangIncludePath(clangVersion));
|
||||
if (!dir.exists() || !QFileInfo(dir, "stdint.h").exists())
|
||||
dir = QDir(m_clangResourceDirectory);
|
||||
dir = QDir(clangResourceDirectory);
|
||||
return QDir::toNativeSeparators(dir.canonicalPath());
|
||||
}
|
||||
|
||||
QString clangExecutable(const QString &clangBinDirectory)
|
||||
{
|
||||
const QString hostExeSuffix(QTC_HOST_EXE_SUFFIX);
|
||||
QDir executable(creatorLibexecPath() + "/clang/bin/clang" + hostExeSuffix);
|
||||
if (!executable.exists())
|
||||
executable = QDir(clangBinDirectory + "/clang" + hostExeSuffix);
|
||||
return QDir::toNativeSeparators(executable.canonicalPath());
|
||||
}
|
||||
|
||||
void CompilerOptionsBuilder::undefineClangVersionMacrosForMsvc()
|
||||
{
|
||||
if (m_projectPart.toolchainType == ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID) {
|
||||
|
||||
@@ -90,7 +90,6 @@ private:
|
||||
QByteArray macroOption(const ProjectExplorer::Macro ¯o) const;
|
||||
QByteArray toDefineOption(const ProjectExplorer::Macro ¯o) const;
|
||||
QString defineDirectiveToDefineOption(const ProjectExplorer::Macro &marco) const;
|
||||
QString clangIncludeDirectory() const;
|
||||
void addClangIncludeFolder();
|
||||
|
||||
QStringList m_options;
|
||||
@@ -98,6 +97,11 @@ private:
|
||||
QString m_clangResourceDirectory;
|
||||
};
|
||||
|
||||
QString CPPTOOLS_EXPORT clangExecutable(const QString &clangBinDirectory);
|
||||
|
||||
QString CPPTOOLS_EXPORT clangIncludeDirectory(const QString &clangVersion,
|
||||
const QString &clangResourceDirectory);
|
||||
|
||||
template<class T>
|
||||
T clangIncludePath(const T &clangVersion)
|
||||
{
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
DEFINES += CLANG_VERSION=\\\"$${LLVM_VERSION}\\\"
|
||||
CLANG_RESOURCE_DIR=$$clean_path($${LLVM_LIBDIR}/clang/$${LLVM_VERSION}/include)
|
||||
DEFINES += "\"CLANG_RESOURCE_DIR=\\\"$${CLANG_RESOURCE_DIR}\\\"\""
|
||||
CLANG_BINDIR=$$clean_path($${LLVM_BINDIR})
|
||||
DEFINES += "\"CLANG_BINDIR=\\\"$${CLANG_BINDIR}\\\"\""
|
||||
|
||||
Reference in New Issue
Block a user