forked from qt-creator/qt-creator
Merge remote-tracking branch 'origin/4.3'
Change-Id: Ib5405ed2c3356f65b49fe2f454f8ac2e0de44ef6
This commit is contained in:
@@ -277,10 +277,6 @@ void BuildDirManager::generateProjectTree(CMakeProjectNode *root, const QList<co
|
||||
const Utils::FileName projectFile = m_buildConfiguration->target()->project()->projectFilePath();
|
||||
|
||||
m_reader->generateProjectTree(root, allFiles);
|
||||
|
||||
// Make sure the top level CMakeLists.txt is always visible:
|
||||
if (root->isEmpty())
|
||||
root->addNode(new FileNode(projectFile, FileType::Project, false));
|
||||
}
|
||||
|
||||
void BuildDirManager::updateCodeModel(CppTools::RawProjectParts &rpps)
|
||||
@@ -336,7 +332,12 @@ QList<CMakeBuildTarget> BuildDirManager::buildTargets() const
|
||||
m_buildTargets.append(utilityTarget(CMakeBuildStep::installTarget(), this));
|
||||
m_buildTargets.append(utilityTarget(CMakeBuildStep::testTarget(), this));
|
||||
|
||||
m_buildTargets.append(m_reader->buildTargets());
|
||||
m_buildTargets.append(Utils::filtered(m_reader->buildTargets(), [](const CMakeBuildTarget &bt) {
|
||||
return bt.title != CMakeBuildStep::allTarget()
|
||||
&& bt.title != CMakeBuildStep::cleanTarget()
|
||||
&& bt.title != CMakeBuildStep::installTarget()
|
||||
&& bt.title != CMakeBuildStep::testTarget();
|
||||
}));
|
||||
}
|
||||
return m_buildTargets;
|
||||
}
|
||||
|
||||
@@ -221,6 +221,10 @@ CMakeBuildConfiguration::generateProjectTree(const QList<const FileNode*> &allFi
|
||||
|
||||
auto root = new CMakeProjectNode(target()->project()->projectDirectory());
|
||||
m_buildDirManager->generateProjectTree(root, allFiles);
|
||||
if (root->isEmpty()) {
|
||||
delete root;
|
||||
return nullptr;
|
||||
}
|
||||
return root;
|
||||
}
|
||||
|
||||
@@ -280,7 +284,9 @@ QList<ConfigModel::DataItem> CMakeBuildConfiguration::completeCMakeConfiguration
|
||||
j.values = i.values;
|
||||
j.inCMakeCache = i.inCMakeCache;
|
||||
|
||||
j.isAdvanced = i.isAdvanced || i.type == CMakeConfigItem::INTERNAL;
|
||||
j.isAdvanced = i.isAdvanced;
|
||||
j.isHidden = i.type == CMakeConfigItem::INTERNAL || i.type == CMakeConfigItem::STATIC;
|
||||
|
||||
switch (i.type) {
|
||||
case CMakeConfigItem::FILEPATH:
|
||||
j.type = ConfigModel::DataItem::FILE;
|
||||
|
||||
@@ -267,7 +267,7 @@ void CMakeBuildStep::run(QFutureInterface<bool> &fi)
|
||||
m_runTrigger = connect(bc, &CMakeBuildConfiguration::dataAvailable,
|
||||
this, [this, &fi]() { runImpl(fi); });
|
||||
m_errorTrigger = connect(bc, &CMakeBuildConfiguration::errorOccured,
|
||||
this, [this, &fi]() { reportRunResult(fi, false); });
|
||||
this, [this, &fi](const QString& em) { handleCMakeError(fi, em); });
|
||||
} else {
|
||||
runImpl(fi);
|
||||
}
|
||||
@@ -276,10 +276,21 @@ void CMakeBuildStep::run(QFutureInterface<bool> &fi)
|
||||
void CMakeBuildStep::runImpl(QFutureInterface<bool> &fi)
|
||||
{
|
||||
// Do the actual build:
|
||||
disconnectTriggers();
|
||||
AbstractProcessStep::run(fi);
|
||||
}
|
||||
|
||||
void CMakeBuildStep::handleCMakeError(QFutureInterface<bool> &fi, const QString& errorMessage)
|
||||
{
|
||||
disconnectTriggers();
|
||||
AbstractProcessStep::stdError(tr("Error parsing CMake: %1\n").arg(errorMessage));
|
||||
reportRunResult(fi, false);
|
||||
}
|
||||
|
||||
void CMakeBuildStep::disconnectTriggers()
|
||||
{
|
||||
disconnect(m_runTrigger);
|
||||
disconnect(m_errorTrigger);
|
||||
|
||||
AbstractProcessStep::run(fi);
|
||||
}
|
||||
|
||||
BuildStepConfigWidget *CMakeBuildStep::createConfigWidget()
|
||||
|
||||
@@ -104,6 +104,8 @@ private:
|
||||
void ctor(ProjectExplorer::BuildStepList *bsl);
|
||||
|
||||
void runImpl(QFutureInterface<bool> &fi);
|
||||
void handleCMakeError(QFutureInterface<bool> &fi, const QString& errorMessage);
|
||||
void disconnectTriggers();
|
||||
|
||||
void handleBuildTargetChanges();
|
||||
CMakeRunConfiguration *targetsActiveRunConfiguration() const;
|
||||
|
||||
@@ -170,15 +170,20 @@ std::function<bool (const CMakeConfigItem &a, const CMakeConfigItem &b)> CMakeCo
|
||||
|
||||
CMakeConfigItem CMakeConfigItem::fromString(const QString &s)
|
||||
{
|
||||
// Strip comments:
|
||||
// Strip comments (only at start of line!):
|
||||
int commentStart = s.count();
|
||||
int pos = s.indexOf(QLatin1Char('#'));
|
||||
if (pos >= 0)
|
||||
commentStart = pos;
|
||||
pos = s.indexOf(QLatin1String("//"));
|
||||
if (pos >= 0 && pos < commentStart)
|
||||
commentStart = pos;
|
||||
|
||||
for (int i = 0; i < s.count(); ++i) {
|
||||
const QChar c = s.at(i);
|
||||
if (c == ' ' || c == '\t')
|
||||
continue;
|
||||
else if ((c == '#')
|
||||
|| (c == '/' && i < s.count() - 1 && s.at(i + 1) == '/')) {
|
||||
commentStart = i;
|
||||
break;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
const QString line = s.mid(0, commentStart);
|
||||
|
||||
// Split up line:
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
using namespace CMakeProjectManager;
|
||||
using namespace ProjectExplorer;
|
||||
|
||||
const char COMMON_ERROR_PATTERN[] = "^CMake Error at (.*):([0-9]*) \\((.*)\\):";
|
||||
const char COMMON_ERROR_PATTERN[] = "^CMake Error at (.*):([0-9]*)( \\((.*)\\))?:";
|
||||
const char NEXT_SUBERROR_PATTERN[] = "^CMake Error in (.*):";
|
||||
const char LOCATION_LINE_PATTERN[] = ":(\\d+):(?:(\\d+))?$";
|
||||
|
||||
@@ -250,6 +250,20 @@ void Internal::CMakeProjectPlugin::testCMakeParser_data()
|
||||
Utils::FileName(), -1, categoryBuild))
|
||||
<< QString();
|
||||
|
||||
QTest::newRow("cmake error at")
|
||||
<< QString::fromLatin1("CMake Error at CMakeLists.txt:4:\n"
|
||||
" Parse error. Expected \"(\", got newline with text \"\n"
|
||||
"\n"
|
||||
" \".\n")
|
||||
<< OutputParserTester::STDERR
|
||||
<< QString() << QString()
|
||||
<< (QList<ProjectExplorer::Task>()
|
||||
<< Task(Task::Error,
|
||||
QLatin1String("Parse error. Expected \"(\", got newline with text \" \"."),
|
||||
Utils::FileName::fromUserInput(QLatin1String("CMakeLists.txt")), 4,
|
||||
categoryBuild))
|
||||
<< QString();
|
||||
|
||||
QTest::newRow("cmake warning")
|
||||
<< QString::fromLatin1("Syntax Warning in cmake code at\n"
|
||||
"/test/path/CMakeLists.txt:9:15\n"
|
||||
|
||||
@@ -147,8 +147,8 @@ void CMakeProject::updateProjectData(CMakeBuildConfiguration *bc)
|
||||
|
||||
auto newRoot = bc->generateProjectTree(m_allFiles);
|
||||
if (newRoot) {
|
||||
setRootProjectNode(newRoot);
|
||||
setDisplayName(newRoot->displayName());
|
||||
setRootProjectNode(newRoot);
|
||||
}
|
||||
|
||||
updateApplicationAndDeploymentTargets();
|
||||
@@ -495,8 +495,13 @@ void CMakeProject::updateApplicationAndDeploymentTargets()
|
||||
if (ct.targetType == UtilityType)
|
||||
continue;
|
||||
|
||||
if (ct.targetType == ExecutableType || ct.targetType == DynamicLibraryType)
|
||||
deploymentData.addFile(ct.executable.toString(), deploymentPrefix + buildDir.relativeFilePath(ct.executable.toFileInfo().dir().path()), DeployableFile::TypeExecutable);
|
||||
if (ct.targetType == ExecutableType || ct.targetType == DynamicLibraryType) {
|
||||
if (!ct.executable.isEmpty()) {
|
||||
deploymentData.addFile(ct.executable.toString(),
|
||||
deploymentPrefix + buildDir.relativeFilePath(ct.executable.toFileInfo().dir().path()),
|
||||
DeployableFile::TypeExecutable);
|
||||
}
|
||||
}
|
||||
if (ct.targetType == ExecutableType) {
|
||||
FileName srcWithTrailingSlash = FileName::fromString(ct.sourceDirectory.toString());
|
||||
srcWithTrailingSlash.appendString('/');
|
||||
|
||||
@@ -257,7 +257,9 @@ void ConfigModel::setConfiguration(const QList<ConfigModel::DataItem> &config)
|
||||
|
||||
QList<InternalDataItem> result;
|
||||
while (newIt != newEndIt && oldIt != oldEndIt) {
|
||||
if (newIt->key < oldIt->key) {
|
||||
if (newIt->isHidden) {
|
||||
++newIt;
|
||||
} else if (newIt->key < oldIt->key) {
|
||||
// Add new entry:
|
||||
result << InternalDataItem(*newIt);
|
||||
++newIt;
|
||||
@@ -279,8 +281,11 @@ void ConfigModel::setConfiguration(const QList<ConfigModel::DataItem> &config)
|
||||
}
|
||||
|
||||
// Add remaining new entries:
|
||||
for (; newIt != newEndIt; ++newIt)
|
||||
for (; newIt != newEndIt; ++newIt) {
|
||||
if (newIt->isHidden)
|
||||
continue;
|
||||
result << InternalDataItem(*newIt);
|
||||
}
|
||||
|
||||
beginResetModel();
|
||||
m_configuration = result;
|
||||
|
||||
@@ -45,6 +45,7 @@ public:
|
||||
|
||||
QString key;
|
||||
Type type = STRING;
|
||||
bool isHidden = false;
|
||||
bool isAdvanced = false;
|
||||
bool inCMakeCache = false;
|
||||
QString value;
|
||||
|
||||
@@ -73,6 +73,17 @@ ServerModeReader::ServerModeReader()
|
||||
if (m_cmakeFiles.contains(document->filePath()))
|
||||
emit dirty();
|
||||
});
|
||||
|
||||
connect(&m_parser, &CMakeParser::addOutput,
|
||||
this, [](const QString &m) { Core::MessageManager::write(m); });
|
||||
connect(&m_parser, &CMakeParser::addTask, this, [this](const Task &t) {
|
||||
Task editable(t);
|
||||
if (!editable.file.isEmpty()) {
|
||||
QDir srcDir(m_parameters.sourceDirectory.toString());
|
||||
editable.file = FileName::fromString(srcDir.absoluteFilePath(editable.file.toString()));
|
||||
}
|
||||
TaskHub::addTask(editable);
|
||||
});
|
||||
}
|
||||
|
||||
ServerModeReader::~ServerModeReader()
|
||||
@@ -98,8 +109,13 @@ void ServerModeReader::setParameters(const BuildDirReader::Parameters &p)
|
||||
this, &ServerModeReader::handleProgress);
|
||||
connect(m_cmakeServer.get(), &ServerMode::cmakeSignal,
|
||||
this, &ServerModeReader::handleSignal);
|
||||
connect(m_cmakeServer.get(), &ServerMode::cmakeMessage,
|
||||
this, [this](const QString &m) { Core::MessageManager::write(m); });
|
||||
connect(m_cmakeServer.get(), &ServerMode::cmakeMessage, [this](const QString &m) {
|
||||
const QStringList lines = m.split('\n');
|
||||
for (const QString &l : lines) {
|
||||
m_parser.stdError(l);
|
||||
Core::MessageManager::write(l);
|
||||
}
|
||||
});
|
||||
connect(m_cmakeServer.get(), &ServerMode::message,
|
||||
this, [](const QString &m) { Core::MessageManager::write(m); });
|
||||
connect(m_cmakeServer.get(), &ServerMode::connected,
|
||||
@@ -170,6 +186,7 @@ void ServerModeReader::stop()
|
||||
m_future->reportFinished();
|
||||
m_future.reset();
|
||||
}
|
||||
m_parser.flush();
|
||||
}
|
||||
|
||||
bool ServerModeReader::isReady() const
|
||||
@@ -732,6 +749,9 @@ void ServerModeReader::addFileGroups(ProjectNode *targetRoot,
|
||||
void ServerModeReader::addHeaderNodes(ProjectNode *root, const QList<FileNode *> knownHeaders,
|
||||
const QList<const FileNode *> &allFiles)
|
||||
{
|
||||
if (root->isEmpty())
|
||||
return;
|
||||
|
||||
auto headerNode = new VirtualFolderNode(root->filePath(), Node::DefaultPriority - 5);
|
||||
headerNode->setDisplayName(tr("<Headers>"));
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
|
||||
#include "builddirreader.h"
|
||||
#include "servermode.h"
|
||||
#include "cmakeparser.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
@@ -148,6 +149,8 @@ private:
|
||||
QList<Project *> m_projects;
|
||||
mutable QList<Target *> m_targets;
|
||||
QList<FileGroup *> m_fileGroups;
|
||||
|
||||
CMakeParser m_parser;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -243,6 +243,10 @@ CMakeConfig TeaLeafReader::takeParsedConfiguration()
|
||||
{
|
||||
FileName cacheFile = m_parameters.buildDirectory;
|
||||
cacheFile.appendPath(QLatin1String("CMakeCache.txt"));
|
||||
|
||||
if (!cacheFile.exists())
|
||||
return { };
|
||||
|
||||
QString errorMessage;
|
||||
CMakeConfig result = BuildDirManager::parseConfiguration(cacheFile, &errorMessage);
|
||||
|
||||
@@ -266,6 +270,9 @@ CMakeConfig TeaLeafReader::takeParsedConfiguration()
|
||||
|
||||
void TeaLeafReader::generateProjectTree(CMakeProjectNode *root, const QList<const FileNode *> &allFiles)
|
||||
{
|
||||
if (m_files.isEmpty())
|
||||
return;
|
||||
|
||||
root->setDisplayName(m_projectName);
|
||||
|
||||
// Delete no longer necessary file watcher based on m_cmakeFiles:
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
|
||||
#include "treescanner.h"
|
||||
|
||||
#include <coreplugin/iversioncontrol.h>
|
||||
#include <coreplugin/vcsmanager.h>
|
||||
#include <projectexplorer/projectexplorerconstants.h>
|
||||
|
||||
#include <cpptools/cpptoolsconstants.h>
|
||||
@@ -67,7 +69,10 @@ bool TreeScanner::asyncScanForFiles(const Utils::FileName &directory)
|
||||
m_scanFuture = fi->future();
|
||||
m_futureWatcher.setFuture(m_scanFuture);
|
||||
|
||||
Utils::runAsync([this, fi, directory]() { TreeScanner::scanForFiles(fi, directory, m_filter, m_factory); });
|
||||
if (m_versionControls.isEmpty())
|
||||
m_versionControls = Core::VcsManager::versionControls();
|
||||
|
||||
Utils::runAsync([this, fi, directory]() { TreeScanner::scanForFiles(fi, directory, m_filter, m_factory, m_versionControls); });
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -144,13 +149,17 @@ FileType TreeScanner::genericFileType(const Utils::MimeType &mimeType, const Uti
|
||||
return Node::fileTypeForMimeType(mimeType);
|
||||
}
|
||||
|
||||
void TreeScanner::scanForFiles(FutureInterface *fi, const Utils::FileName& directory, const FileFilter &filter, const FileTypeFactory &factory)
|
||||
void TreeScanner::scanForFiles(FutureInterface *fi, const Utils::FileName& directory,
|
||||
const FileFilter &filter, const FileTypeFactory &factory,
|
||||
QList<Core::IVersionControl *> &versionControls)
|
||||
{
|
||||
std::unique_ptr<FutureInterface> fip(fi);
|
||||
fip->reportStarted();
|
||||
|
||||
Result nodes = FileNode::scanForFiles(directory,
|
||||
[&filter, &factory](const Utils::FileName &fn) -> FileNode * {
|
||||
Result nodes
|
||||
= FileNode::scanForFilesWithVersionControls(
|
||||
directory,
|
||||
[&filter, &factory](const Utils::FileName &fn) -> FileNode * {
|
||||
const Utils::MimeType mimeType = Utils::mimeTypeForFile(fn.toString());
|
||||
|
||||
// Skip some files during scan.
|
||||
@@ -163,8 +172,7 @@ void TreeScanner::scanForFiles(FutureInterface *fi, const Utils::FileName& direc
|
||||
type = factory(mimeType, fn);
|
||||
|
||||
return new FileNode(fn, type, false);
|
||||
},
|
||||
fip.get());
|
||||
}, versionControls, fip.get());
|
||||
|
||||
Utils::sort(nodes, ProjectExplorer::Node::sortByPath);
|
||||
|
||||
|
||||
@@ -36,6 +36,8 @@
|
||||
|
||||
#include <functional>
|
||||
|
||||
namespace Core { class IVersionControl; }
|
||||
|
||||
namespace CMakeProjectManager {
|
||||
namespace Internal {
|
||||
|
||||
@@ -86,7 +88,8 @@ signals:
|
||||
|
||||
private:
|
||||
static void scanForFiles(FutureInterface *fi, const Utils::FileName &directory,
|
||||
const FileFilter &filter, const FileTypeFactory &factory);
|
||||
const FileFilter &filter, const FileTypeFactory &factory,
|
||||
QList<Core::IVersionControl *> &versionControls);
|
||||
|
||||
private:
|
||||
FileFilter m_filter;
|
||||
@@ -94,6 +97,7 @@ private:
|
||||
|
||||
FutureWatcher m_futureWatcher;
|
||||
Future m_scanFuture;
|
||||
QList<Core::IVersionControl *> m_versionControls;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
Reference in New Issue
Block a user