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:
Ivan Donchevskii
2018-04-30 15:26:36 +02:00
parent 80ae992c91
commit 52ac74b61c
21 changed files with 87 additions and 340 deletions

View File

@@ -74,6 +74,11 @@ function libDir(llvmConfig)
return FileInfo.fromNativeSeparators(readOutput(llvmConfig, ["--libdir"])); return FileInfo.fromNativeSeparators(readOutput(llvmConfig, ["--libdir"]));
} }
function binDir(llvmConfig)
{
return FileInfo.fromNativeSeparators(readOutput(llvmConfig, ["--bindir"]));
}
function version(llvmConfig) function version(llvmConfig)
{ {
return readOutput(llvmConfig, ["--version"]).replace(/(\d+\.\d+\.\d+).*/, "$1") return readOutput(llvmConfig, ["--version"]).replace(/(\d+\.\d+\.\d+).*/, "$1")

View File

@@ -16,6 +16,7 @@ Module {
property string llvmVersion property string llvmVersion
property string llvmIncludeDir property string llvmIncludeDir
property string llvmLibDir property string llvmLibDir
property string llvmBinDir
property stringList llvmLibs property stringList llvmLibs
property stringList llvmToolingLibs property stringList llvmToolingLibs
property stringList llvmToolingDefines property stringList llvmToolingDefines
@@ -28,6 +29,7 @@ Module {
llvmVersion = ClangFunctions.version(llvmConfig); llvmVersion = ClangFunctions.version(llvmConfig);
llvmIncludeDir = ClangFunctions.includeDir(llvmConfig); llvmIncludeDir = ClangFunctions.includeDir(llvmConfig);
llvmLibDir = ClangFunctions.libDir(llvmConfig); llvmLibDir = ClangFunctions.libDir(llvmConfig);
llvmBinDir = ClangFunctions.binDir(llvmConfig);
llvmLibs = ClangFunctions.libraries(targetOS); llvmLibs = ClangFunctions.libraries(targetOS);
llvmToolingLibs = ClangFunctions.toolingLibs(llvmConfig, targetOS); llvmToolingLibs = ClangFunctions.toolingLibs(llvmConfig, targetOS);
llvmBuildMode = ClangFunctions.buildMode(llvmConfig); llvmBuildMode = ClangFunctions.buildMode(llvmConfig);
@@ -43,6 +45,7 @@ Module {
property string llvmVersion: clangProbe.llvmVersion property string llvmVersion: clangProbe.llvmVersion
property string llvmIncludeDir: clangProbe.llvmIncludeDir property string llvmIncludeDir: clangProbe.llvmIncludeDir
property string llvmLibDir: clangProbe.llvmLibDir property string llvmLibDir: clangProbe.llvmLibDir
property string llvmBinDir: clangProbe.llvmBinDir
property stringList llvmLibs: clangProbe.llvmLibs property stringList llvmLibs: clangProbe.llvmLibs
property stringList llvmToolingLibs: clangProbe.llvmToolingLibs property stringList llvmToolingLibs: clangProbe.llvmToolingLibs
property string llvmBuildMode: clangProbe.llvmBuildMode property string llvmBuildMode: clangProbe.llvmBuildMode

View File

@@ -27,6 +27,7 @@ QtcPlugin {
var resourceDir = FileInfo.joinPaths(libclang.llvmLibDir, "clang", libclang.llvmVersion, var resourceDir = FileInfo.joinPaths(libclang.llvmLibDir, "clang", libclang.llvmVersion,
"include"); "include");
defines.push('CLANG_RESOURCE_DIR="' + resourceDir + '"'); defines.push('CLANG_RESOURCE_DIR="' + resourceDir + '"');
defines.push('CLANG_BINDIR="' + libclang.llvmBinDir + '"');
return defines; return defines;
} }

View File

@@ -23,6 +23,7 @@ QtcPlugin {
var resourceDir = FileInfo.joinPaths(libclang.llvmLibDir, "clang", libclang.llvmVersion, var resourceDir = FileInfo.joinPaths(libclang.llvmLibDir, "clang", libclang.llvmVersion,
"include"); "include");
defines.push('CLANG_RESOURCE_DIR="' + resourceDir + '"'); defines.push('CLANG_RESOURCE_DIR="' + resourceDir + '"');
defines.push('CLANG_BINDIR="' + libclang.llvmBinDir + '"');
return defines; return defines;
} }

View File

@@ -25,6 +25,7 @@ QtcPlugin {
var resourceDir = FileInfo.joinPaths(libclang.llvmLibDir, "clang", libclang.llvmVersion, var resourceDir = FileInfo.joinPaths(libclang.llvmLibDir, "clang", libclang.llvmVersion,
"include"); "include");
defines.push('CLANG_RESOURCE_DIR="' + resourceDir + '"'); defines.push('CLANG_RESOURCE_DIR="' + resourceDir + '"');
defines.push('CLANG_BINDIR="' + libclang.llvmBinDir + '"');
return defines; return defines;
} }

View File

@@ -43,50 +43,7 @@ ClangStaticAnalyzerConfigWidget::ClangStaticAnalyzerConfigWidget(
{ {
m_ui->setupUi(this); m_ui->setupUi(this);
Utils::PathChooser * const chooser = m_ui->clangExecutableChooser; m_ui->simultaneousProccessesSpinBox->setValue(settings->savedSimultaneousProcesses());
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->setMinimum(1); m_ui->simultaneousProccessesSpinBox->setMinimum(1);
m_ui->simultaneousProccessesSpinBox->setMaximum(QThread::idealThreadCount()); m_ui->simultaneousProccessesSpinBox->setMaximum(QThread::idealThreadCount());
connect(m_ui->simultaneousProccessesSpinBox, connect(m_ui->simultaneousProccessesSpinBox,
@@ -99,29 +56,5 @@ ClangStaticAnalyzerConfigWidget::~ClangStaticAnalyzerConfigWidget()
delete m_ui; 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 Internal
} // namespace ClangTools } // namespace ClangTools

View File

@@ -45,9 +45,6 @@ public:
QWidget *parent = 0); QWidget *parent = 0);
~ClangStaticAnalyzerConfigWidget(); ~ClangStaticAnalyzerConfigWidget();
void updateDetectedVersionLabel(bool executableIsValid,
const ClangExecutableVersion &providedVersion);
private: private:
Ui::ClangStaticAnalyzerConfigWidget *m_ui; Ui::ClangStaticAnalyzerConfigWidget *m_ui;
ClangToolsSettings *m_settings; ClangToolsSettings *m_settings;

View File

@@ -21,34 +21,13 @@
</property> </property>
<layout class="QFormLayout" name="formLayout"> <layout class="QFormLayout" name="formLayout">
<item row="0" column="0"> <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"> <widget class="QLabel" name="label_2">
<property name="text"> <property name="text">
<string>Simultaneous processes:</string> <string>Simultaneous processes:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="1"> <item row="0" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_2"> <layout class="QHBoxLayout" name="horizontalLayout_2">
<item> <item>
<widget class="QSpinBox" name="simultaneousProccessesSpinBox"> <widget class="QSpinBox" name="simultaneousProccessesSpinBox">
@@ -93,14 +72,6 @@
</item> </item>
</layout> </layout>
</widget> </widget>
<customwidgets>
<customwidget>
<class>Utils::PathChooser</class>
<extends>QWidget</extends>
<header location="global">utils/pathchooser.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/> <resources/>
<connections/> <connections/>
</ui> </ui>

View File

@@ -29,6 +29,7 @@
#include "clangstaticanalyzertool.h" #include "clangstaticanalyzertool.h"
#include "clangtoolsutils.h" #include "clangtoolsutils.h"
#include <cpptools/compileroptionsbuilder.h>
#include <cpptools/projectinfo.h> #include <cpptools/projectinfo.h>
#include <projectexplorer/kitinformation.h> #include <projectexplorer/kitinformation.h>
#include <projectexplorer/kitmanager.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); const ToolChain * const toolchain = ToolChainKitInformation::toolChain(kit, ProjectExplorer::Constants::CXX_LANGUAGE_ID);
QTC_ASSERT(toolchain, return false); QTC_ASSERT(toolchain, return false);
bool hasClangExecutable;
clangExecutableFromSettings(&hasClangExecutable); if (CppTools::clangExecutable(CLANG_BINDIR).isEmpty()) {
if (!hasClangExecutable) {
qWarning("Project \"%s\": Skipping target \"%s\" since no suitable clang was found for the toolchain.", qWarning("Project \"%s\": Skipping target \"%s\" since no suitable clang was found for the toolchain.",
qPrintable(projectFileName), qPrintable(projectFileName),
qPrintable(target->displayName())); qPrintable(target->displayName()));

View File

@@ -147,7 +147,6 @@ ClangStaticAnalyzerRunControl::ClangStaticAnalyzerRunControl(RunControl *runCont
ClangToolRunner *ClangStaticAnalyzerRunControl::createRunner() ClangToolRunner *ClangStaticAnalyzerRunControl::createRunner()
{ {
QTC_ASSERT(!m_clangExecutable.isEmpty(), return 0);
QTC_ASSERT(!m_clangLogFileDir.isEmpty(), return 0); QTC_ASSERT(!m_clangLogFileDir.isEmpty(), return 0);
auto runner = new ClangStaticAnalyzerRunner(m_clangExecutable, auto runner = new ClangStaticAnalyzerRunner(m_clangExecutable,

View File

@@ -145,18 +145,11 @@ static AnalyzeUnits unitsToAnalyzeFromProjectParts(const QVector<ProjectPart::Pt
return unitsToAnalyze; 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) AnalyzeUnits ClangToolRunControl::sortedUnitsToAnalyze(const QString &clangVersion)
{ {
QTC_ASSERT(m_projectInfo.isValid(), return AnalyzeUnits()); 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, AnalyzeUnits units = unitsToAnalyzeFromProjectParts(m_projectInfo.projectParts(), clangVersion,
clangResourceDirectory); clangResourceDirectory);
@@ -179,7 +172,9 @@ static QDebug operator<<(QDebug debug, const AnalyzeUnits &analyzeUnits)
} }
ClangToolRunControl::ClangToolRunControl(RunControl *runControl, Target *target) 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; 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()); m_projectInfo = CppTools::CppModelManager::instance()->projectInfo(m_target->project());
const QString toolName = tool()->name();
// Some projects provides CompilerCallData once a build is finished, // Some projects provides CompilerCallData once a build is finished,
if (m_projectInfo.configurationOrFilesChanged(m_projectInfoBeforeBuild)) { if (m_projectInfo.configurationOrFilesChanged(m_projectInfoBeforeBuild)) {
// If it's more than a release/debug build configuration change, e.g. // 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()), appendMessage(tr("Running %1 on %2").arg(toolName).arg(projectFile.toUserOutput()),
Utils::NormalMessageFormat); 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 // Create log dir
Utils::TemporaryDirectory temporaryDir("qtc-clangtools-XXXXXX"); Utils::TemporaryDirectory temporaryDir("qtc-clangtools-XXXXXX");
temporaryDir.setAutoRemove(false); temporaryDir.setAutoRemove(false);
@@ -276,7 +244,7 @@ void ClangToolRunControl::start()
m_clangLogFileDir = temporaryDir.path(); m_clangLogFileDir = temporaryDir.path();
// Collect files // Collect files
const AnalyzeUnits unitsToProcess = sortedUnitsToAnalyze(version.toString()); const AnalyzeUnits unitsToProcess = sortedUnitsToAnalyze(CLANG_VERSION);
qCDebug(LOG) << "Files to process:" << unitsToProcess; qCDebug(LOG) << "Files to process:" << unitsToProcess;
m_unitsToProcess = unitsToProcess; m_unitsToProcess = unitsToProcess;
m_initialFilesToProcessSize = m_unitsToProcess.count(); m_initialFilesToProcessSize = m_unitsToProcess.count();
@@ -298,7 +266,7 @@ void ClangToolRunControl::start()
// Start process(es) // Start process(es)
qCDebug(LOG) << "Environment:" << m_environment; qCDebug(LOG) << "Environment:" << m_environment;
m_runners.clear(); m_runners.clear();
const int parallelRuns = ClangToolsSettings::instance()->simultaneousProcesses(); const int parallelRuns = ClangToolsSettings::instance()->savedSimultaneousProcesses();
QTC_ASSERT(parallelRuns >= 1, reportFailure(); return); QTC_ASSERT(parallelRuns >= 1, reportFailure(); return);
m_success = true; m_success = true;

View File

@@ -1,6 +1,8 @@
include(../../qtcreatorplugin.pri) include(../../qtcreatorplugin.pri)
include(../../shared/clang/clang_installation.pri) include(../../shared/clang/clang_installation.pri)
include(../../shared/clang/clang_defines.pri)
requires(!isEmpty(LLVM_VERSION)) requires(!isEmpty(LLVM_VERSION))
LIBS += $$LIBCLANG_LIBS LIBS += $$LIBCLANG_LIBS

View File

@@ -1,4 +1,5 @@
import qbs import qbs
import qbs.FileInfo
QtcPlugin { QtcPlugin {
name: "ClangTools" name: "ClangTools"
@@ -26,6 +27,19 @@ QtcPlugin {
cpp.dynamicLibraries: base.concat(libclang.llvmLibs) cpp.dynamicLibraries: base.concat(libclang.llvmLibs)
cpp.rpaths: base.concat(libclang.llvmLibDir) 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: [ files: [
"clangstaticanalyzerconfigwidget.cpp", "clangstaticanalyzerconfigwidget.cpp",
"clangstaticanalyzerconfigwidget.h", "clangstaticanalyzerconfigwidget.h",

View File

@@ -35,14 +35,12 @@
#include <QFileInfo> #include <QFileInfo>
#include <QThread> #include <QThread>
static const char clangExecutableKey[] = "clangExecutable";
static const char simultaneousProcessesKey[] = "simultaneousProcesses"; static const char simultaneousProcessesKey[] = "simultaneousProcesses";
namespace ClangTools { namespace ClangTools {
namespace Internal { namespace Internal {
ClangToolsSettings::ClangToolsSettings() ClangToolsSettings::ClangToolsSettings()
: m_simultaneousProcesses(-1)
{ {
readSettings(); readSettings();
} }
@@ -53,36 +51,9 @@ ClangToolsSettings *ClangToolsSettings::instance()
return &instance; return &instance;
} }
static QString clangExecutableFileName() int ClangToolsSettings::savedSimultaneousProcesses() const
{ {
return QLatin1String("clang" QTC_HOST_EXE_SUFFIX); return m_savedSimultaneousProcesses;
}
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;
} }
int ClangToolsSettings::simultaneousProcesses() const int ClangToolsSettings::simultaneousProcesses() const
@@ -92,7 +63,6 @@ int ClangToolsSettings::simultaneousProcesses() const
void ClangToolsSettings::setSimultaneousProcesses(int processes) void ClangToolsSettings::setSimultaneousProcesses(int processes)
{ {
QTC_ASSERT(processes >=1, return);
m_simultaneousProcesses = processes; m_simultaneousProcesses = processes;
} }
@@ -101,21 +71,22 @@ void ClangToolsSettings::readSettings()
QSettings *settings = Core::ICore::settings(); QSettings *settings = Core::ICore::settings();
settings->beginGroup(QLatin1String(Constants::SETTINGS_ID)); settings->beginGroup(QLatin1String(Constants::SETTINGS_ID));
setClangExecutable(settings->value(QLatin1String(clangExecutableKey)).toString());
const int defaultSimultaneousProcesses = qMax(0, QThread::idealThreadCount() / 2); const int defaultSimultaneousProcesses = qMax(0, QThread::idealThreadCount() / 2);
setSimultaneousProcesses(settings->value(QLatin1String(simultaneousProcessesKey), m_savedSimultaneousProcesses = m_simultaneousProcesses
defaultSimultaneousProcesses).toInt()); = settings->value(QString(simultaneousProcessesKey),
defaultSimultaneousProcesses).toInt();
settings->endGroup(); settings->endGroup();
} }
void ClangToolsSettings::writeSettings() const void ClangToolsSettings::writeSettings()
{ {
QSettings *settings = Core::ICore::settings(); QSettings *settings = Core::ICore::settings();
settings->beginGroup(QLatin1String(Constants::SETTINGS_ID)); settings->beginGroup(QString(Constants::SETTINGS_ID));
settings->setValue(QLatin1String(clangExecutableKey), m_clangExecutable); settings->setValue(QString(simultaneousProcessesKey), m_simultaneousProcesses);
settings->setValue(QLatin1String(simultaneousProcessesKey), simultaneousProcesses());
m_savedSimultaneousProcesses = m_simultaneousProcesses;
settings->endGroup(); settings->endGroup();
} }

View File

@@ -35,11 +35,9 @@ class ClangToolsSettings
public: public:
static ClangToolsSettings *instance(); static ClangToolsSettings *instance();
void writeSettings() const; void writeSettings();
QString defaultClangExecutable() const; int savedSimultaneousProcesses() const;
QString clangExecutable(bool *isSet = nullptr) const;
void setClangExecutable(const QString &exectuable);
int simultaneousProcesses() const; int simultaneousProcesses() const;
void setSimultaneousProcesses(int processes); void setSimultaneousProcesses(int processes);
@@ -48,8 +46,8 @@ private:
ClangToolsSettings(); ClangToolsSettings();
void readSettings(); void readSettings();
QString m_clangExecutable; int m_simultaneousProcesses = -1;
int m_simultaneousProcesses; int m_savedSimultaneousProcesses = -1;
}; };
} // namespace Internal } // namespace Internal

View File

@@ -62,9 +62,8 @@ void ClangToolsUnitTests::initTestCase()
Constants::CXX_LANGUAGE_ID); Constants::CXX_LANGUAGE_ID);
if (!toolchain) if (!toolchain)
QSKIP("This test requires that there is a kit with a toolchain."); QSKIP("This test requires that there is a kit with a toolchain.");
bool hasClangExecutable;
clangExecutableFromSettings(&hasClangExecutable); if (CppTools::clangExecutable(CLANG_BINDIR).isEmpty())
if (!hasClangExecutable)
QSKIP("No clang suitable for analyzing found"); QSKIP("No clang suitable for analyzing found");
m_tmpDir = new CppTools::Tests::TemporaryCopiedDir(QLatin1String(":/unit-tests")); m_tmpDir = new CppTools::Tests::TemporaryCopiedDir(QLatin1String(":/unit-tests"));

View File

@@ -28,6 +28,8 @@
#include "clangtoolsdiagnostic.h" #include "clangtoolsdiagnostic.h"
#include "clangtoolssettings.h" #include "clangtoolssettings.h"
#include <coreplugin/icore.h>
#include <projectexplorer/projectexplorerconstants.h> #include <projectexplorer/projectexplorerconstants.h>
#include <utils/hostosinfo.h> #include <utils/hostosinfo.h>
@@ -38,118 +40,14 @@
#include <QFileInfo> #include <QFileInfo>
#include <QRegularExpression> #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 ClangTools {
namespace Internal { 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) QString createFullLocationString(const Debugger::DiagnosticLocation &location)
{ {
return location.filePath + QLatin1Char(':') + QString::number(location.line) return location.filePath + QLatin1Char(':') + QString::number(location.line)
+ QLatin1Char(':') + QString::number(location.column); + 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 Internal
} // namespace ClangTools } // namespace ClangTools

View File

@@ -39,36 +39,7 @@ namespace Debugger { class DiagnosticLocation; }
namespace ClangTools { namespace ClangTools {
namespace Internal { namespace Internal {
bool isClangExecutableUsable(const QString &filePath, QString *errorMessage = 0);
QString clangExecutableFromSettings(bool *isValid);
QString createFullLocationString(const Debugger::DiagnosticLocation &location); 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 Internal
} // namespace ClangTools } // namespace ClangTools

View File

@@ -528,7 +528,7 @@ void CompilerOptionsBuilder::addClangIncludeFolder()
{ {
QTC_CHECK(!m_clangVersion.isEmpty()); QTC_CHECK(!m_clangVersion.isEmpty());
add(SYSTEM_INCLUDE_PREFIX); add(SYSTEM_INCLUDE_PREFIX);
add(clangIncludeDirectory()); add(clangIncludeDirectory(m_clangVersion, m_clangResourceDirectory));
} }
void CompilerOptionsBuilder::addProjectConfigFileInclude() void CompilerOptionsBuilder::addProjectConfigFileInclude()
@@ -548,14 +548,23 @@ static QString creatorLibexecPath()
#endif #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()) if (!dir.exists() || !QFileInfo(dir, "stdint.h").exists())
dir = QDir(m_clangResourceDirectory); dir = QDir(clangResourceDirectory);
return QDir::toNativeSeparators(dir.canonicalPath()); 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() void CompilerOptionsBuilder::undefineClangVersionMacrosForMsvc()
{ {
if (m_projectPart.toolchainType == ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID) { if (m_projectPart.toolchainType == ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID) {

View File

@@ -90,7 +90,6 @@ private:
QByteArray macroOption(const ProjectExplorer::Macro &macro) const; QByteArray macroOption(const ProjectExplorer::Macro &macro) const;
QByteArray toDefineOption(const ProjectExplorer::Macro &macro) const; QByteArray toDefineOption(const ProjectExplorer::Macro &macro) const;
QString defineDirectiveToDefineOption(const ProjectExplorer::Macro &marco) const; QString defineDirectiveToDefineOption(const ProjectExplorer::Macro &marco) const;
QString clangIncludeDirectory() const;
void addClangIncludeFolder(); void addClangIncludeFolder();
QStringList m_options; QStringList m_options;
@@ -98,6 +97,11 @@ private:
QString m_clangResourceDirectory; QString m_clangResourceDirectory;
}; };
QString CPPTOOLS_EXPORT clangExecutable(const QString &clangBinDirectory);
QString CPPTOOLS_EXPORT clangIncludeDirectory(const QString &clangVersion,
const QString &clangResourceDirectory);
template<class T> template<class T>
T clangIncludePath(const T &clangVersion) T clangIncludePath(const T &clangVersion)
{ {

View File

@@ -1,3 +1,5 @@
DEFINES += CLANG_VERSION=\\\"$${LLVM_VERSION}\\\" DEFINES += CLANG_VERSION=\\\"$${LLVM_VERSION}\\\"
CLANG_RESOURCE_DIR=$$clean_path($${LLVM_LIBDIR}/clang/$${LLVM_VERSION}/include) CLANG_RESOURCE_DIR=$$clean_path($${LLVM_LIBDIR}/clang/$${LLVM_VERSION}/include)
DEFINES += "\"CLANG_RESOURCE_DIR=\\\"$${CLANG_RESOURCE_DIR}\\\"\"" DEFINES += "\"CLANG_RESOURCE_DIR=\\\"$${CLANG_RESOURCE_DIR}\\\"\""
CLANG_BINDIR=$$clean_path($${LLVM_BINDIR})
DEFINES += "\"CLANG_BINDIR=\\\"$${CLANG_BINDIR}\\\"\""