forked from qt-creator/qt-creator
ProjectExplorer: Move BuildSystem owership to BuildConfiguration
... or Target. This patch moves build system from conceptually "one per project" to "one per target (i.e. per project-and-kit)" or "per BuildConfigurations" for targets where the builds differ significantly. Building requires usually items from the kit (Qt version, compiler, ...) so a target-agnostic build is practically almost always wrong. Moving the build system to the target also has the potential to solve issues caused by switching targets while parsing, that used Project::activeTarget() regularly, with potentially different results before and after the switch. This patch might create performance/size regressions when several targets are set up per project as the build system implementation's internal data are duplicated in this case. The idea is to fix that by sharing per-project pieces again in the project implementation once these problems occur. Change-Id: I87f640ce418b93175b5029124eaa55f3b8721dca Reviewed-by: Christian Stenger <christian.stenger@qt.io> Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
This commit is contained in:
@@ -45,11 +45,11 @@ AndroidExtraLibraryListModel::AndroidExtraLibraryListModel(ProjectExplorer::Targ
|
||||
{
|
||||
updateModel();
|
||||
|
||||
connect(target->project(), &ProjectExplorer::Project::parsingStarted,
|
||||
connect(target, &Target::parsingStarted,
|
||||
this, &AndroidExtraLibraryListModel::updateModel);
|
||||
connect(target->project(), &ProjectExplorer::Project::parsingFinished,
|
||||
connect(target, &Target::parsingFinished,
|
||||
this, &AndroidExtraLibraryListModel::updateModel);
|
||||
connect(target, &ProjectExplorer::Target::activeRunConfigurationChanged,
|
||||
connect(target, &Target::activeRunConfigurationChanged,
|
||||
this, &AndroidExtraLibraryListModel::updateModel);
|
||||
}
|
||||
|
||||
|
@@ -132,7 +132,7 @@ AndroidRunConfiguration::AndroidRunConfiguration(Target *target, Core::Id id)
|
||||
postStartShellCmdAspect->setSettingsKey("Android.PostStartShellCmdListKey");
|
||||
postStartShellCmdAspect->setLabel(tr("Shell commands to run on Android device after application quits."));
|
||||
|
||||
connect(target->project(), &Project::parsingFinished, this, [this] {
|
||||
connect(target, &Target::parsingFinished, this, [this] {
|
||||
updateTargetInformation();
|
||||
AndroidManager::updateGradleProperties(this->target(), buildKey());
|
||||
});
|
||||
|
@@ -42,13 +42,13 @@ using namespace ProjectExplorer;
|
||||
namespace AutotoolsProjectManager {
|
||||
namespace Internal {
|
||||
|
||||
AutotoolsBuildSystem::AutotoolsBuildSystem(Project *project)
|
||||
: BuildSystem(project)
|
||||
AutotoolsBuildSystem::AutotoolsBuildSystem(Target *target)
|
||||
: BuildSystem(target)
|
||||
, m_cppCodeModelUpdater(new CppTools::CppProjectUpdater)
|
||||
{
|
||||
connect(project, &Project::activeBuildConfigurationChanged, this, [this]() { requestParse(); });
|
||||
connect(target, &Target::activeBuildConfigurationChanged, this, [this]() { requestParse(); });
|
||||
|
||||
connect(project, &Project::projectFileIsDirty, this, [this]() { requestParse(); });
|
||||
connect(target->project(), &Project::projectFileIsDirty, this, [this]() { requestParse(); });
|
||||
}
|
||||
|
||||
AutotoolsBuildSystem::~AutotoolsBuildSystem()
|
||||
@@ -62,7 +62,7 @@ AutotoolsBuildSystem::~AutotoolsBuildSystem()
|
||||
}
|
||||
}
|
||||
|
||||
void AutotoolsBuildSystem::parseProject(BuildSystem::ParsingContext &&ctx)
|
||||
void AutotoolsBuildSystem::triggerParsing()
|
||||
{
|
||||
if (m_makefileParserThread) {
|
||||
// The thread is still busy parsing a previous configuration.
|
||||
@@ -78,8 +78,7 @@ void AutotoolsBuildSystem::parseProject(BuildSystem::ParsingContext &&ctx)
|
||||
}
|
||||
|
||||
// Parse the makefile asynchronously in a thread
|
||||
m_makefileParserThread = new MakefileParserThread(project()->projectFilePath().toString(),
|
||||
std::move(ctx.guard));
|
||||
m_makefileParserThread = new MakefileParserThread(this);
|
||||
|
||||
connect(m_makefileParserThread,
|
||||
&MakefileParserThread::finished,
|
||||
@@ -114,7 +113,7 @@ void AutotoolsBuildSystem::makefileParsingFinished()
|
||||
QVector<Utils::FilePath> filesToWatch;
|
||||
|
||||
// Apply sources to m_files, which are returned at AutotoolsBuildSystem::files()
|
||||
const QFileInfo fileInfo = project()->projectFilePath().toFileInfo();
|
||||
const QFileInfo fileInfo = projectFilePath().toFileInfo();
|
||||
const QDir dir = fileInfo.absoluteDir();
|
||||
const QStringList files = m_makefileParserThread->sources();
|
||||
foreach (const QString& file, files)
|
||||
@@ -202,7 +201,7 @@ void AutotoolsBuildSystem::updateCppCodeModel()
|
||||
rpp.setMacros(m_makefileParserThread->macros());
|
||||
rpp.setFiles(m_files);
|
||||
|
||||
m_cppCodeModelUpdater->update({project(), kitInfo, project()->activeParseEnvironment(), {rpp}});
|
||||
m_cppCodeModelUpdater->update({project(), kitInfo, activeParseEnvironment(), {rpp}});
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
|
@@ -29,12 +29,9 @@
|
||||
|
||||
#include <projectexplorer/buildsystem.h>
|
||||
|
||||
namespace Utils { class FileSystemWatcher; }
|
||||
|
||||
namespace CppTools { class CppProjectUpdater; }
|
||||
|
||||
namespace AutotoolsProjectManager {
|
||||
|
||||
namespace Internal {
|
||||
|
||||
class MakefileParserThread;
|
||||
@@ -44,13 +41,12 @@ class AutotoolsBuildSystem : public ProjectExplorer::BuildSystem
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AutotoolsBuildSystem(ProjectExplorer::Project *project);
|
||||
explicit AutotoolsBuildSystem(ProjectExplorer::Target *target);
|
||||
~AutotoolsBuildSystem() override;
|
||||
|
||||
protected:
|
||||
void parseProject(ParsingContext &&ctx) final;
|
||||
|
||||
private:
|
||||
void triggerParsing() final;
|
||||
|
||||
/**
|
||||
* Is invoked when the makefile parsing by m_makefileParserThread has
|
||||
* been finished. Adds all sources and files into the project tree and
|
||||
|
@@ -36,7 +36,9 @@
|
||||
#include "makestep.h"
|
||||
|
||||
#include <coreplugin/icontext.h>
|
||||
|
||||
#include <projectexplorer/projectmanager.h>
|
||||
#include <projectexplorer/target.h>
|
||||
|
||||
namespace AutotoolsProjectManager {
|
||||
namespace Internal {
|
||||
@@ -50,7 +52,7 @@ AutotoolsProject::AutotoolsProject(const Utils::FilePath &fileName)
|
||||
|
||||
setHasMakeInstallEquivalent(true);
|
||||
|
||||
setBuildSystemCreator([](Project *p) { return new AutotoolsBuildSystem(p); });
|
||||
setBuildSystemCreator([](ProjectExplorer::Target *t) { return new AutotoolsBuildSystem(t); });
|
||||
}
|
||||
|
||||
class AutotoolsProjectPluginPrivate
|
||||
|
@@ -31,10 +31,9 @@
|
||||
|
||||
using namespace AutotoolsProjectManager::Internal;
|
||||
|
||||
MakefileParserThread::MakefileParserThread(const QString &makefile,
|
||||
ProjectExplorer::Project::ParseGuard &&guard)
|
||||
: m_parser(makefile)
|
||||
, m_guard(std::move(guard))
|
||||
MakefileParserThread::MakefileParserThread(ProjectExplorer::BuildSystem *bs)
|
||||
: m_parser(bs->projectFilePath().toString()),
|
||||
m_guard(bs->guardParsingRun())
|
||||
{
|
||||
connect(&m_parser, &MakefileParser::status,
|
||||
this, &MakefileParserThread::status);
|
||||
|
@@ -29,7 +29,7 @@
|
||||
|
||||
#include "makefileparser.h"
|
||||
|
||||
#include <projectexplorer/project.h>
|
||||
#include <projectexplorer/buildsystem.h>
|
||||
#include <projectexplorer/projectmacro.h>
|
||||
|
||||
#include <QMutex>
|
||||
@@ -54,7 +54,7 @@ class MakefileParserThread : public QThread
|
||||
using Macros = ProjectExplorer::Macros;
|
||||
|
||||
public:
|
||||
MakefileParserThread(const QString &makefile, ProjectExplorer::Project::ParseGuard &&guard);
|
||||
explicit MakefileParserThread(ProjectExplorer::BuildSystem *bs);
|
||||
|
||||
/** @see QThread::run() */
|
||||
void run() override;
|
||||
@@ -143,7 +143,7 @@ private:
|
||||
QStringList m_cflags; ///< Return value for MakefileParserThread::cflags()
|
||||
QStringList m_cxxflags; ///< Return value for MakefileParserThread::cxxflags()
|
||||
|
||||
ProjectExplorer::Project::ParseGuard m_guard;
|
||||
ProjectExplorer::BuildSystem::ParseGuard m_guard;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
@@ -55,7 +55,7 @@ BareMetalRunConfiguration::BareMetalRunConfiguration(Target *target, Core::Id id
|
||||
this, &BareMetalRunConfiguration::updateTargetInformation);
|
||||
connect(target, &Target::kitChanged,
|
||||
this, &BareMetalRunConfiguration::updateTargetInformation); // Handles device changes, etc.
|
||||
connect(target->project(), &Project::parsingFinished,
|
||||
connect(target, &Target::parsingFinished,
|
||||
this, &BareMetalRunConfiguration::updateTargetInformation);
|
||||
}
|
||||
|
||||
|
@@ -91,7 +91,7 @@ QdbRunConfiguration::QdbRunConfiguration(Target *target, Core::Id id)
|
||||
this, &QdbRunConfiguration::updateTargetInformation);
|
||||
connect(target, &Target::kitChanged,
|
||||
this, &QdbRunConfiguration::updateTargetInformation);
|
||||
connect(target->project(), &Project::parsingFinished,
|
||||
connect(target, &Target::parsingFinished,
|
||||
this, &QdbRunConfiguration::updateTargetInformation);
|
||||
|
||||
setDefaultDisplayName(tr("Run on Boot2Qt Device"));
|
||||
|
@@ -65,24 +65,29 @@ Q_LOGGING_CATEGORY(cmakeBuildDirManagerLog, "qtc.cmake.builddirmanager", QtWarni
|
||||
// BuildDirManager:
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
BuildDirManager::BuildDirManager(CMakeProject *project) : m_project(project) { assert(project); }
|
||||
BuildDirManager::BuildDirManager(CMakeBuildSystem *buildSystem)
|
||||
: m_buildSystem(buildSystem)
|
||||
{
|
||||
assert(buildSystem);
|
||||
}
|
||||
|
||||
BuildDirManager::~BuildDirManager() = default;
|
||||
|
||||
Utils::FilePath BuildDirManager::workDirectory(const BuildDirParameters ¶meters) const
|
||||
FilePath BuildDirManager::workDirectory(const BuildDirParameters ¶meters) const
|
||||
{
|
||||
const Utils::FilePath bdir = parameters.buildDirectory;
|
||||
const CMakeTool *cmake = parameters.cmakeTool();
|
||||
if (bdir.exists()) {
|
||||
m_buildDirToTempDir.erase(bdir);
|
||||
return bdir;
|
||||
} else {
|
||||
if (cmake && cmake->autoCreateBuildDirectory()) {
|
||||
if (!QDir().mkpath(bdir.toString()))
|
||||
emitErrorOccured(tr("Failed to create build directory \"%1\".").arg(bdir.toUserOutput()));
|
||||
return bdir;
|
||||
}
|
||||
}
|
||||
|
||||
if (cmake && cmake->autoCreateBuildDirectory()) {
|
||||
if (!QDir().mkpath(bdir.toString()))
|
||||
emitErrorOccured(tr("Failed to create build directory \"%1\".").arg(bdir.toUserOutput()));
|
||||
return bdir;
|
||||
}
|
||||
|
||||
auto tmpDirIt = m_buildDirToTempDir.find(bdir);
|
||||
if (tmpDirIt == m_buildDirToTempDir.end()) {
|
||||
auto ret = m_buildDirToTempDir.emplace(std::make_pair(bdir, std::make_unique<Utils::TemporaryDirectory>("qtc-cmake-XXXXXXXX")));
|
||||
@@ -290,22 +295,20 @@ void BuildDirManager::setParametersAndRequestParse(const BuildDirParameters &par
|
||||
updateReaderType(m_parameters, [this]() { emitReparseRequest(); });
|
||||
}
|
||||
|
||||
CMakeBuildConfiguration *BuildDirManager::buildConfiguration() const
|
||||
CMakeBuildSystem *BuildDirManager::buildSystem() const
|
||||
{
|
||||
if (m_project->activeTarget() && m_project->activeTarget()->activeBuildConfiguration() == m_parameters.buildConfiguration)
|
||||
return m_parameters.buildConfiguration;
|
||||
return nullptr;
|
||||
return m_buildSystem;
|
||||
}
|
||||
|
||||
FilePath BuildDirManager::buildDirectory() const
|
||||
{
|
||||
return buildConfiguration() ? m_parameters.buildDirectory : FilePath();
|
||||
return m_parameters.buildDirectory;
|
||||
}
|
||||
|
||||
void BuildDirManager::becameDirty()
|
||||
{
|
||||
qCDebug(cmakeBuildDirManagerLog) << "BuildDirManager: becameDirty was triggered.";
|
||||
if (isParsing() || !buildConfiguration())
|
||||
if (isParsing() || !buildSystem())
|
||||
return;
|
||||
|
||||
const CMakeTool *tool = m_parameters.cmakeTool();
|
||||
@@ -444,7 +447,7 @@ static CMakeBuildTarget utilityTarget(const QString &title, const BuildDirManage
|
||||
target.title = title;
|
||||
target.targetType = UtilityType;
|
||||
target.workingDirectory = bdm->buildDirectory();
|
||||
target.sourceDirectory = bdm->project()->projectDirectory();
|
||||
target.sourceDirectory = bdm->buildSystem()->project()->projectDirectory();
|
||||
|
||||
return target;
|
||||
}
|
||||
@@ -528,13 +531,10 @@ QString BuildDirManager::flagsString(int reparseFlags)
|
||||
|
||||
bool BuildDirManager::checkConfiguration()
|
||||
{
|
||||
CMakeBuildConfiguration *bc = buildConfiguration();
|
||||
QTC_ASSERT(m_parameters.isValid() || !bc, return false);
|
||||
|
||||
if (m_parameters.workDirectory != m_parameters.buildDirectory) // always throw away changes in the tmpdir!
|
||||
return false;
|
||||
|
||||
const CMakeConfig cache = bc->configurationFromCMake();
|
||||
const CMakeConfig cache = m_buildSystem->cmakeBuildConfiguration()->configurationFromCMake();
|
||||
if (cache.isEmpty())
|
||||
return false; // No cache file yet.
|
||||
|
||||
@@ -586,8 +586,8 @@ bool BuildDirManager::checkConfiguration()
|
||||
box->exec();
|
||||
if (box->clickedButton() == applyButton) {
|
||||
m_parameters.configuration = newConfig;
|
||||
QSignalBlocker blocker(bc);
|
||||
bc->setConfigurationForCMake(newConfig);
|
||||
QSignalBlocker blocker(m_buildSystem->buildConfiguration());
|
||||
m_buildSystem->cmakeBuildConfiguration()->setConfigurationForCMake(newConfig);
|
||||
return false;
|
||||
} else if (box->clickedButton() == defaultButton)
|
||||
return true;
|
||||
|
@@ -27,7 +27,6 @@
|
||||
|
||||
#include "builddirparameters.h"
|
||||
#include "builddirreader.h"
|
||||
#include "cmakebuildsystem.h"
|
||||
#include "cmakebuildtarget.h"
|
||||
#include "cmakeconfigitem.h"
|
||||
|
||||
@@ -46,14 +45,11 @@
|
||||
namespace ProjectExplorer { class FileNode; }
|
||||
|
||||
namespace CMakeProjectManager {
|
||||
|
||||
class CMakeProject;
|
||||
class CMakeTool;
|
||||
|
||||
namespace Internal {
|
||||
|
||||
class CMakeProjectNode;
|
||||
class CMakeBuildConfiguration;
|
||||
class CMakeBuildSystem;
|
||||
class CMakeProjectNode;
|
||||
|
||||
class BuildDirManager : public QObject
|
||||
{
|
||||
@@ -71,7 +67,7 @@ public:
|
||||
|
||||
static QString flagsString(int reparseFlags);
|
||||
|
||||
BuildDirManager(CMakeProject *project);
|
||||
explicit BuildDirManager(CMakeBuildSystem *buildSystem);
|
||||
~BuildDirManager() final;
|
||||
|
||||
bool isParsing() const;
|
||||
@@ -81,8 +77,7 @@ public:
|
||||
void setParametersAndRequestParse(const BuildDirParameters ¶meters,
|
||||
const int reparseOptions);
|
||||
// nullptr if the BC is not active anymore!
|
||||
CMakeBuildConfiguration *buildConfiguration() const;
|
||||
CMakeProject *project() const {return m_project; }
|
||||
CMakeBuildSystem *buildSystem() const;
|
||||
Utils::FilePath buildDirectory() const;
|
||||
|
||||
void clearCache();
|
||||
@@ -133,7 +128,7 @@ private:
|
||||
|
||||
BuildDirParameters m_parameters;
|
||||
int m_reparseParameters;
|
||||
CMakeProject *m_project = nullptr;
|
||||
CMakeBuildSystem *m_buildSystem = nullptr;
|
||||
mutable std::unordered_map<Utils::FilePath, std::unique_ptr<Utils::TemporaryDirectory>> m_buildDirToTempDir;
|
||||
mutable std::unique_ptr<BuildDirReader> m_reader;
|
||||
mutable bool m_isHandlingError = false;
|
||||
|
@@ -45,7 +45,7 @@ BuildDirParameters::BuildDirParameters() = default;
|
||||
|
||||
BuildDirParameters::BuildDirParameters(CMakeBuildConfiguration *bc)
|
||||
{
|
||||
buildConfiguration = bc;
|
||||
initialized = bc != nullptr;
|
||||
|
||||
const Kit *k = bc->target()->kit();
|
||||
|
||||
@@ -82,7 +82,7 @@ BuildDirParameters::BuildDirParameters(CMakeBuildConfiguration *bc)
|
||||
generatorArguments = CMakeGeneratorKitAspect::generatorArguments(k);
|
||||
}
|
||||
|
||||
bool BuildDirParameters::isValid() const { return buildConfiguration && cmakeTool(); }
|
||||
bool BuildDirParameters::isValid() const { return initialized && cmakeTool(); }
|
||||
|
||||
CMakeTool *BuildDirParameters::cmakeTool() const
|
||||
{
|
||||
|
@@ -42,14 +42,14 @@ class CMakeBuildConfiguration;
|
||||
class BuildDirParameters {
|
||||
public:
|
||||
BuildDirParameters();
|
||||
BuildDirParameters(CMakeBuildConfiguration *bc);
|
||||
explicit BuildDirParameters(CMakeBuildConfiguration *bc);
|
||||
BuildDirParameters(const BuildDirParameters &other);
|
||||
BuildDirParameters &operator=(const BuildDirParameters &other);
|
||||
|
||||
bool isValid() const;
|
||||
CMakeTool *cmakeTool() const;
|
||||
|
||||
CMakeBuildConfiguration *buildConfiguration = nullptr;
|
||||
bool initialized = false;
|
||||
QString projectName;
|
||||
|
||||
Utils::FilePath sourceDirectory;
|
||||
|
@@ -84,101 +84,17 @@ const char CONFIGURATION_KEY[] = "CMake.Configuration";
|
||||
|
||||
CMakeBuildConfiguration::CMakeBuildConfiguration(Target *parent, Core::Id id)
|
||||
: BuildConfiguration(parent, id)
|
||||
, m_buildDirManager(qobject_cast<CMakeProject *>(parent->project()))
|
||||
{
|
||||
m_buildSystem = new CMakeBuildSystem(this);
|
||||
setBuildDirectory(shadowBuildDirectory(project()->projectFilePath(),
|
||||
target()->kit(),
|
||||
displayName(),
|
||||
BuildConfiguration::Unknown));
|
||||
}
|
||||
|
||||
BuildSystem *bs = qobject_cast<CMakeBuildSystem *>(project()->buildSystem());
|
||||
|
||||
// BuildDirManager:
|
||||
connect(&m_buildDirManager, &BuildDirManager::requestReparse, this, [this, bs]() {
|
||||
if (isActive())
|
||||
bs->requestParse();
|
||||
});
|
||||
connect(&m_buildDirManager, &BuildDirManager::requestDelayedReparse, this, [this, bs]() {
|
||||
if (isActive())
|
||||
bs->requestDelayedParse();
|
||||
});
|
||||
connect(&m_buildDirManager,
|
||||
&BuildDirManager::dataAvailable,
|
||||
this,
|
||||
&CMakeBuildConfiguration::handleParsingSucceeded);
|
||||
connect(&m_buildDirManager,
|
||||
&BuildDirManager::errorOccured,
|
||||
this,
|
||||
&CMakeBuildConfiguration::handleParsingFailed);
|
||||
connect(&m_buildDirManager, &BuildDirManager::parsingStarted, this, [this]() {
|
||||
clearError(CMakeBuildConfiguration::ForceEnabledChanged::True);
|
||||
});
|
||||
|
||||
// Kit changed:
|
||||
connect(KitManager::instance(), &KitManager::kitUpdated, this, [this](Kit *k) {
|
||||
if (k != target()->kit())
|
||||
return; // not for us...
|
||||
// Build configuration has not changed, but Kit settings might have:
|
||||
// reparse and check the configuration, independent of whether the reader has changed
|
||||
m_buildDirManager.setParametersAndRequestParse(BuildDirParameters(this),
|
||||
BuildDirManager::REPARSE_CHECK_CONFIGURATION);
|
||||
});
|
||||
|
||||
// Became active/inactive:
|
||||
connect(project(), &Project::activeBuildConfigurationChanged, this, [this]() {
|
||||
if (isActive()) {
|
||||
// Build configuration has switched:
|
||||
// * Check configuration if reader changes due to it not existing yet:-)
|
||||
// * run cmake without configuration arguments if the reader stays
|
||||
m_buildDirManager
|
||||
.setParametersAndRequestParse(BuildDirParameters(this),
|
||||
BuildDirManager::REPARSE_CHECK_CONFIGURATION);
|
||||
} else {
|
||||
m_buildDirManager.stopParsingAndClearState();
|
||||
}
|
||||
});
|
||||
|
||||
// BuildConfiguration changed:
|
||||
connect(this, &CMakeBuildConfiguration::environmentChanged, this, [this]() {
|
||||
if (isActive()) {
|
||||
// The environment on our BC has changed:
|
||||
// * Error out if the reader updates, cannot happen since all BCs share a target/kit.
|
||||
// * run cmake without configuration arguments if the reader stays
|
||||
m_buildDirManager
|
||||
.setParametersAndRequestParse(BuildDirParameters(this),
|
||||
BuildDirManager::REPARSE_CHECK_CONFIGURATION);
|
||||
}
|
||||
});
|
||||
connect(this, &CMakeBuildConfiguration::buildDirectoryChanged, this, [this]() {
|
||||
if (isActive()) {
|
||||
// The build directory of our BC has changed:
|
||||
// * Error out if the reader updates, cannot happen since all BCs share a target/kit.
|
||||
// * run cmake without configuration arguments if the reader stays
|
||||
// If no configuration exists, then the arguments will get added automatically by
|
||||
// the reader.
|
||||
m_buildDirManager
|
||||
.setParametersAndRequestParse(BuildDirParameters(this),
|
||||
BuildDirManager::REPARSE_CHECK_CONFIGURATION);
|
||||
}
|
||||
});
|
||||
connect(this, &CMakeBuildConfiguration::configurationForCMakeChanged, this, [this]() {
|
||||
if (isActive()) {
|
||||
// The CMake configuration has changed on our BC:
|
||||
// * Error out if the reader updates, cannot happen since all BCs share a target/kit.
|
||||
// * run cmake with configuration arguments if the reader stays
|
||||
m_buildDirManager
|
||||
.setParametersAndRequestParse(BuildDirParameters(this),
|
||||
BuildDirManager::REPARSE_FORCE_CONFIGURATION);
|
||||
}
|
||||
});
|
||||
|
||||
connect(parent->project(), &Project::projectFileIsDirty, this, [this]() {
|
||||
if (isActive()) {
|
||||
m_buildDirManager
|
||||
.setParametersAndRequestParse(BuildDirParameters(this),
|
||||
BuildDirManager::REPARSE_DEFAULT);
|
||||
}
|
||||
});
|
||||
CMakeBuildConfiguration::~CMakeBuildConfiguration()
|
||||
{
|
||||
delete m_buildSystem;
|
||||
}
|
||||
|
||||
void CMakeBuildConfiguration::initialize()
|
||||
@@ -284,82 +200,11 @@ bool CMakeBuildConfiguration::fromMap(const QVariantMap &map)
|
||||
return true;
|
||||
}
|
||||
|
||||
const QList<BuildTargetInfo> CMakeBuildConfiguration::appTargets() const
|
||||
{
|
||||
QList<BuildTargetInfo> appTargetList;
|
||||
const bool forAndroid = DeviceTypeKitAspect::deviceTypeId(target()->kit())
|
||||
== Android::Constants::ANDROID_DEVICE_TYPE;
|
||||
for (const CMakeBuildTarget &ct : m_buildTargets) {
|
||||
if (ct.targetType == UtilityType)
|
||||
continue;
|
||||
|
||||
if (ct.targetType == ExecutableType || (forAndroid && ct.targetType == DynamicLibraryType)) {
|
||||
BuildTargetInfo bti;
|
||||
bti.displayName = ct.title;
|
||||
bti.targetFilePath = ct.executable;
|
||||
bti.projectFilePath = ct.sourceDirectory.stringAppended("/");
|
||||
bti.workingDirectory = ct.workingDirectory;
|
||||
bti.buildKey = ct.title;
|
||||
|
||||
// Workaround for QTCREATORBUG-19354:
|
||||
bti.runEnvModifier = [this](Environment &env, bool) {
|
||||
if (HostOsInfo::isWindowsHost()) {
|
||||
const Kit *k = target()->kit();
|
||||
if (const QtSupport::BaseQtVersion *qt = QtSupport::QtKitAspect::qtVersion(k))
|
||||
env.prependOrSetPath(qt->binPath().toString());
|
||||
}
|
||||
};
|
||||
|
||||
appTargetList.append(bti);
|
||||
}
|
||||
}
|
||||
|
||||
return appTargetList;
|
||||
}
|
||||
|
||||
DeploymentData CMakeBuildConfiguration::deploymentData() const
|
||||
{
|
||||
DeploymentData result;
|
||||
|
||||
QDir sourceDir = target()->project()->projectDirectory().toString();
|
||||
QDir buildDir = buildDirectory().toString();
|
||||
|
||||
QString deploymentPrefix;
|
||||
QString deploymentFilePath = sourceDir.filePath("QtCreatorDeployment.txt");
|
||||
|
||||
bool hasDeploymentFile = QFileInfo::exists(deploymentFilePath);
|
||||
if (!hasDeploymentFile) {
|
||||
deploymentFilePath = buildDir.filePath("QtCreatorDeployment.txt");
|
||||
hasDeploymentFile = QFileInfo::exists(deploymentFilePath);
|
||||
}
|
||||
if (!hasDeploymentFile)
|
||||
return result;
|
||||
|
||||
deploymentPrefix = result.addFilesFromDeploymentFile(deploymentFilePath,
|
||||
sourceDir.absolutePath());
|
||||
for (const CMakeBuildTarget &ct : m_buildTargets) {
|
||||
if (ct.targetType == ExecutableType || ct.targetType == DynamicLibraryType) {
|
||||
if (!ct.executable.isEmpty()
|
||||
&& result.deployableForLocalFile(ct.executable).localFilePath() != ct.executable) {
|
||||
result.addFile(ct.executable.toString(),
|
||||
deploymentPrefix + buildDir.relativeFilePath(ct.executable.toFileInfo().dir().path()),
|
||||
DeployableFile::TypeExecutable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
QStringList CMakeBuildConfiguration::buildTargetTitles() const
|
||||
{
|
||||
return transform(m_buildTargets, &CMakeBuildTarget::title);
|
||||
}
|
||||
|
||||
const QList<CMakeBuildTarget> &CMakeBuildConfiguration::buildTargets() const
|
||||
{
|
||||
return m_buildTargets;
|
||||
}
|
||||
|
||||
FilePath CMakeBuildConfiguration::shadowBuildDirectory(const FilePath &projectFilePath,
|
||||
const Kit *k,
|
||||
@@ -408,11 +253,6 @@ void CMakeBuildConfiguration::setConfigurationFromCMake(const CMakeConfig &confi
|
||||
m_configurationFromCMake = config;
|
||||
}
|
||||
|
||||
void CMakeBuildConfiguration::setBuildTargets(const QList<CMakeBuildTarget> &targets)
|
||||
{
|
||||
m_buildTargets = targets;
|
||||
}
|
||||
|
||||
void CMakeBuildConfiguration::setConfigurationForCMake(const QList<ConfigModel::DataItem> &items)
|
||||
{
|
||||
const CMakeConfig newConfig = Utils::transform(items, [](const ConfigModel::DataItem &i) {
|
||||
@@ -548,64 +388,6 @@ void CMakeBuildConfiguration::setWarning(const QString &message)
|
||||
emit warningOccured(m_warning);
|
||||
}
|
||||
|
||||
void CMakeBuildConfiguration::handleParsingSucceeded()
|
||||
{
|
||||
if (!isActive()) {
|
||||
m_buildDirManager.stopParsingAndClearState();
|
||||
return;
|
||||
}
|
||||
|
||||
clearError();
|
||||
|
||||
QString errorMessage;
|
||||
{
|
||||
const QList<CMakeBuildTarget> buildTargets = m_buildDirManager.takeBuildTargets(
|
||||
errorMessage);
|
||||
checkAndReportError(errorMessage);
|
||||
setBuildTargets(buildTargets);
|
||||
}
|
||||
|
||||
{
|
||||
const CMakeConfig cmakeConfig = m_buildDirManager.takeCMakeConfiguration(errorMessage);
|
||||
checkAndReportError(errorMessage);
|
||||
setConfigurationFromCMake(cmakeConfig);
|
||||
}
|
||||
|
||||
{
|
||||
target()->setApplicationTargets(appTargets());
|
||||
target()->setDeploymentData(deploymentData());
|
||||
}
|
||||
|
||||
static_cast<CMakeBuildSystem *>(project()->buildSystem())->handleParsingSuccess(this);
|
||||
}
|
||||
|
||||
void CMakeBuildConfiguration::handleParsingFailed(const QString &msg)
|
||||
{
|
||||
setError(msg);
|
||||
|
||||
QString errorMessage;
|
||||
setConfigurationFromCMake(m_buildDirManager.takeCMakeConfiguration(errorMessage));
|
||||
// ignore errorMessage here, we already got one.
|
||||
|
||||
static_cast<CMakeBuildSystem *>(project()->buildSystem())->handleParsingError(this);
|
||||
}
|
||||
|
||||
std::unique_ptr<CMakeProjectNode> CMakeBuildConfiguration::generateProjectTree(
|
||||
const QList<const FileNode *> &allFiles)
|
||||
{
|
||||
QString errorMessage;
|
||||
auto root = m_buildDirManager.generateProjectTree(allFiles, errorMessage);
|
||||
checkAndReportError(errorMessage);
|
||||
return root;
|
||||
}
|
||||
|
||||
void CMakeBuildConfiguration::checkAndReportError(QString &errorMessage)
|
||||
{
|
||||
if (!errorMessage.isEmpty()) {
|
||||
setError(errorMessage);
|
||||
errorMessage.clear();
|
||||
}
|
||||
}
|
||||
|
||||
QString CMakeBuildConfiguration::error() const
|
||||
{
|
||||
@@ -775,5 +557,10 @@ CMakeProject *CMakeBuildConfiguration::project() const
|
||||
return qobject_cast<CMakeProject *>(BuildConfiguration::project());
|
||||
}
|
||||
|
||||
BuildSystem *CMakeBuildConfiguration::buildSystem() const
|
||||
{
|
||||
return m_buildSystem;
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace CMakeProjectManager
|
||||
|
@@ -34,13 +34,12 @@
|
||||
#include <projectexplorer/deploymentdata.h>
|
||||
|
||||
namespace CMakeProjectManager {
|
||||
class CMakeBuildSystem;
|
||||
class CMakeExtraBuildInfo;
|
||||
class CMakeProject;
|
||||
|
||||
namespace Internal {
|
||||
|
||||
class BuildDirManager;
|
||||
class CMakeBuildSystem;
|
||||
class CMakeBuildSettingsWidget;
|
||||
|
||||
class CMakeBuildConfiguration : public ProjectExplorer::BuildConfiguration
|
||||
@@ -49,6 +48,7 @@ class CMakeBuildConfiguration : public ProjectExplorer::BuildConfiguration
|
||||
|
||||
friend class ProjectExplorer::BuildConfigurationFactory;
|
||||
CMakeBuildConfiguration(ProjectExplorer::Target *parent, Core::Id id);
|
||||
~CMakeBuildConfiguration() final;
|
||||
|
||||
public:
|
||||
void emitBuildTypeChanged();
|
||||
@@ -61,17 +61,14 @@ public:
|
||||
|
||||
CMakeProject *project() const;
|
||||
|
||||
QStringList buildTargetTitles() const;
|
||||
const QList<CMakeBuildTarget> &buildTargets() const;
|
||||
const QList<ProjectExplorer::BuildTargetInfo> appTargets() const;
|
||||
ProjectExplorer::DeploymentData deploymentData() const;
|
||||
|
||||
static Utils::FilePath
|
||||
shadowBuildDirectory(const Utils::FilePath &projectFilePath, const ProjectExplorer::Kit *k,
|
||||
const QString &bcName, BuildConfiguration::BuildType buildType);
|
||||
|
||||
// Context menu action:
|
||||
void buildTarget(const QString &buildTarget);
|
||||
ProjectExplorer::BuildSystem *buildSystem() const final;
|
||||
|
||||
signals:
|
||||
void errorOccured(const QString &message);
|
||||
void warningOccured(const QString &message);
|
||||
@@ -92,7 +89,6 @@ private:
|
||||
enum ForceEnabledChanged { False, True };
|
||||
void clearError(ForceEnabledChanged fec = ForceEnabledChanged::False);
|
||||
|
||||
void setBuildTargets(const QList<CMakeBuildTarget> &targets);
|
||||
void setConfigurationFromCMake(const CMakeConfig &config);
|
||||
void setConfigurationForCMake(const QList<ConfigModel::DataItem> &items);
|
||||
void setConfigurationForCMake(const CMakeConfig &config);
|
||||
@@ -100,27 +96,17 @@ private:
|
||||
void setError(const QString &message);
|
||||
void setWarning(const QString &message);
|
||||
|
||||
void handleParsingSucceeded();
|
||||
void handleParsingFailed(const QString &msg);
|
||||
|
||||
std::unique_ptr<CMakeProjectNode> generateProjectTree(
|
||||
const QList<const ProjectExplorer::FileNode *> &allFiles);
|
||||
|
||||
void checkAndReportError(QString &errorMessage);
|
||||
|
||||
Internal::BuildDirManager m_buildDirManager;
|
||||
|
||||
CMakeConfig m_configurationForCMake;
|
||||
CMakeConfig m_initialConfiguration;
|
||||
QString m_error;
|
||||
QString m_warning;
|
||||
|
||||
CMakeConfig m_configurationFromCMake;
|
||||
QList<CMakeBuildTarget> m_buildTargets;
|
||||
CMakeBuildSystem *m_buildSystem = nullptr;
|
||||
|
||||
friend class CMakeBuildSettingsWidget;
|
||||
friend class CMakeProjectManager::CMakeBuildSystem;
|
||||
friend class CMakeProjectManager::CMakeProject;
|
||||
friend class CMakeBuildSystem;
|
||||
friend class CMakeProject;
|
||||
friend class BuildDirManager;
|
||||
};
|
||||
|
||||
|
@@ -59,6 +59,8 @@
|
||||
#include <QStyledItemDelegate>
|
||||
#include <QMenu>
|
||||
|
||||
using namespace ProjectExplorer;
|
||||
|
||||
namespace CMakeProjectManager {
|
||||
namespace Internal {
|
||||
|
||||
@@ -102,7 +104,7 @@ CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeBuildConfiguration *bc)
|
||||
mainLayout->setContentsMargins(0, 0, 0, 0);
|
||||
mainLayout->setColumnStretch(1, 10);
|
||||
|
||||
auto project = static_cast<CMakeProject *>(bc->project());
|
||||
auto project = bc->project();
|
||||
|
||||
auto buildDirChooser = new Utils::PathChooser;
|
||||
buildDirChooser->setBaseFileName(project->projectDirectory());
|
||||
@@ -245,21 +247,20 @@ CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeBuildConfiguration *bc)
|
||||
setError(bc->error());
|
||||
setWarning(bc->warning());
|
||||
|
||||
connect(project, &ProjectExplorer::Project::parsingStarted, this, [this]() {
|
||||
connect(bc->target(), &Target::parsingStarted, this, [this]() {
|
||||
updateButtonState();
|
||||
m_configView->setEnabled(false);
|
||||
m_showProgressTimer.start();
|
||||
});
|
||||
|
||||
if (project->isParsing())
|
||||
if (bc->buildSystem()->isParsing())
|
||||
m_showProgressTimer.start();
|
||||
else {
|
||||
m_configModel->setConfiguration(m_buildConfiguration->configurationFromCMake());
|
||||
m_configView->expandAll();
|
||||
}
|
||||
|
||||
connect(project, &ProjectExplorer::Project::parsingFinished,
|
||||
this, [this, buildDirChooser, stretcher]() {
|
||||
connect(bc->target(), &Target::parsingFinished, this, [this, buildDirChooser, stretcher] {
|
||||
m_configModel->setConfiguration(m_buildConfiguration->configurationFromCMake());
|
||||
m_configView->expandAll();
|
||||
m_configView->setEnabled(true);
|
||||
@@ -363,7 +364,7 @@ void CMakeBuildSettingsWidget::setWarning(const QString &message)
|
||||
|
||||
void CMakeBuildSettingsWidget::updateButtonState()
|
||||
{
|
||||
const bool isParsing = m_buildConfiguration->project()->isParsing();
|
||||
const bool isParsing = m_buildConfiguration->buildSystem()->isParsing();
|
||||
const bool hasChanges = m_configModel->hasChanges();
|
||||
m_resetButton->setEnabled(hasChanges && !isParsing);
|
||||
m_reconfigureButton->setEnabled((hasChanges || m_configModel->hasCMakeChanges()) && !isParsing);
|
||||
|
@@ -26,6 +26,7 @@
|
||||
#include "cmakebuildstep.h"
|
||||
|
||||
#include "cmakebuildconfiguration.h"
|
||||
#include "cmakebuildsystem.h"
|
||||
#include "cmakekitinformation.h"
|
||||
#include "cmakeparser.h"
|
||||
#include "cmakeprojectconstants.h"
|
||||
@@ -91,7 +92,7 @@ CMakeBuildStep::CMakeBuildStep(BuildStepList *bsl) :
|
||||
setLowPriority();
|
||||
|
||||
connect(target(), &Target::kitChanged, this, &CMakeBuildStep::cmakeCommandChanged);
|
||||
connect(project(), &Project::parsingFinished,
|
||||
connect(target(), &Target::parsingFinished,
|
||||
this, &CMakeBuildStep::handleBuildTargetChanges);
|
||||
}
|
||||
|
||||
@@ -221,17 +222,17 @@ void CMakeBuildStep::doRun()
|
||||
QTC_ASSERT(bc, return);
|
||||
|
||||
m_waiting = false;
|
||||
auto p = static_cast<CMakeProject *>(bc->project());
|
||||
if (p->persistCMakeState()) {
|
||||
auto bs = static_cast<CMakeBuildSystem *>(buildConfiguration()->buildSystem());
|
||||
if (bs->persistCMakeState()) {
|
||||
emit addOutput(tr("Persisting CMake state..."), BuildStep::OutputFormat::NormalMessage);
|
||||
m_waiting = true;
|
||||
} else if (p->mustUpdateCMakeStateBeforeBuild()) {
|
||||
} else if (buildConfiguration()->buildSystem()->isWaitingForParse()) {
|
||||
emit addOutput(tr("Running CMake in preparation to build..."), BuildStep::OutputFormat::NormalMessage);
|
||||
m_waiting = true;
|
||||
}
|
||||
|
||||
if (m_waiting) {
|
||||
m_runTrigger = connect(project(), &Project::parsingFinished,
|
||||
m_runTrigger = connect(target(), &Target::parsingFinished,
|
||||
this, [this](bool success) { handleProjectWasParsed(success); });
|
||||
} else {
|
||||
runImpl();
|
||||
@@ -367,7 +368,7 @@ Utils::CommandLine CMakeBuildStep::cmakeCommand(RunConfiguration *rc) const
|
||||
|
||||
QStringList CMakeBuildStep::knownBuildTargets()
|
||||
{
|
||||
auto bc = qobject_cast<CMakeBuildConfiguration *>(buildConfiguration());
|
||||
auto bc = qobject_cast<CMakeBuildSystem *>(buildConfiguration()->buildSystem());
|
||||
return bc ? bc->buildTargetTitles() : QStringList();
|
||||
}
|
||||
|
||||
|
@@ -30,13 +30,18 @@
|
||||
#include "cmakeprojectconstants.h"
|
||||
#include "cmakeprojectnodes.h"
|
||||
|
||||
#include <android/androidconstants.h>
|
||||
|
||||
#include <coreplugin/progressmanager/progressmanager.h>
|
||||
#include <cpptools/cppprojectupdater.h>
|
||||
#include <cpptools/generatedcodemodelsupport.h>
|
||||
#include <projectexplorer/kitmanager.h>
|
||||
#include <projectexplorer/project.h>
|
||||
#include <projectexplorer/target.h>
|
||||
#include <qmljs/qmljsmodelmanagerinterface.h>
|
||||
|
||||
#include <qtsupport/qtcppkitinfo.h>
|
||||
#include <qtsupport/qtkitinformation.h>
|
||||
|
||||
#include <utils/fileutils.h>
|
||||
#include <utils/mimetypes/mimetype.h>
|
||||
@@ -48,8 +53,7 @@ using namespace ProjectExplorer;
|
||||
using namespace Utils;
|
||||
|
||||
namespace CMakeProjectManager {
|
||||
|
||||
using namespace Internal;
|
||||
namespace Internal {
|
||||
|
||||
Q_LOGGING_CATEGORY(cmakeBuildSystemLog, "qtc.cmake.buildsystem", QtWarningMsg);
|
||||
|
||||
@@ -57,15 +61,15 @@ Q_LOGGING_CATEGORY(cmakeBuildSystemLog, "qtc.cmake.buildsystem", QtWarningMsg);
|
||||
// CMakeBuildSystem:
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
CMakeBuildSystem::CMakeBuildSystem(Project *project)
|
||||
: BuildSystem(project)
|
||||
CMakeBuildSystem::CMakeBuildSystem(CMakeBuildConfiguration *bc)
|
||||
: BuildSystem(bc)
|
||||
, m_buildConfiguration(bc)
|
||||
, m_buildDirManager(this)
|
||||
, m_cppCodeModelUpdater(new CppTools::CppProjectUpdater)
|
||||
{
|
||||
// TreeScanner:
|
||||
connect(&m_treeScanner,
|
||||
&TreeScanner::finished,
|
||||
this,
|
||||
&CMakeBuildSystem::handleTreeScanningFinished);
|
||||
connect(&m_treeScanner, &TreeScanner::finished,
|
||||
this, &CMakeBuildSystem::handleTreeScanningFinished);
|
||||
|
||||
m_treeScanner.setFilter([this](const MimeType &mimeType, const FilePath &fn) {
|
||||
// Mime checks requires more resources, so keep it last in check list
|
||||
@@ -98,6 +102,109 @@ CMakeBuildSystem::CMakeBuildSystem(Project *project)
|
||||
}
|
||||
return type;
|
||||
});
|
||||
|
||||
// BuildDirManager:
|
||||
connect(&m_buildDirManager, &BuildDirManager::requestReparse, this, [this] {
|
||||
if (m_buildConfiguration->isActive())
|
||||
requestParse();
|
||||
});
|
||||
connect(&m_buildDirManager, &BuildDirManager::requestDelayedReparse, this, [this] {
|
||||
if (m_buildConfiguration->isActive())
|
||||
requestDelayedParse();
|
||||
});
|
||||
|
||||
connect(&m_buildDirManager, &BuildDirManager::dataAvailable,
|
||||
this, &CMakeBuildSystem::handleParsingSucceeded);
|
||||
|
||||
connect(&m_buildDirManager, &BuildDirManager::errorOccured,
|
||||
this, &CMakeBuildSystem::handleParsingFailed);
|
||||
|
||||
connect(&m_buildDirManager, &BuildDirManager::parsingStarted, this, [this]() {
|
||||
m_buildConfiguration->clearError(CMakeBuildConfiguration::ForceEnabledChanged::True);
|
||||
});
|
||||
|
||||
// Kit changed:
|
||||
connect(KitManager::instance(), &KitManager::kitUpdated, this, [this](Kit *k) {
|
||||
if (k != target()->kit())
|
||||
return; // not for us...
|
||||
// Build configuration has not changed, but Kit settings might have:
|
||||
// reparse and check the configuration, independent of whether the reader has changed
|
||||
m_buildDirManager.setParametersAndRequestParse(BuildDirParameters(m_buildConfiguration),
|
||||
BuildDirManager::REPARSE_CHECK_CONFIGURATION);
|
||||
});
|
||||
|
||||
// Became active/inactive:
|
||||
connect(project(), &Project::activeTargetChanged, this, [this](Target *t) {
|
||||
if (t == target()) {
|
||||
// Build configuration has switched:
|
||||
// * Check configuration if reader changes due to it not existing yet:-)
|
||||
// * run cmake without configuration arguments if the reader stays
|
||||
m_buildDirManager
|
||||
.setParametersAndRequestParse(BuildDirParameters(m_buildConfiguration),
|
||||
BuildDirManager::REPARSE_CHECK_CONFIGURATION);
|
||||
} else {
|
||||
m_buildDirManager.stopParsingAndClearState();
|
||||
}
|
||||
});
|
||||
connect(target(), &Target::activeBuildConfigurationChanged, this, [this](BuildConfiguration *bc) {
|
||||
if (m_buildConfiguration->isActive()) {
|
||||
if (m_buildConfiguration == bc) {
|
||||
// Build configuration has switched:
|
||||
// * Check configuration if reader changes due to it not existing yet:-)
|
||||
// * run cmake without configuration arguments if the reader stays
|
||||
m_buildDirManager
|
||||
.setParametersAndRequestParse(BuildDirParameters(m_buildConfiguration),
|
||||
BuildDirManager::REPARSE_CHECK_CONFIGURATION);
|
||||
} else {
|
||||
m_buildDirManager.stopParsingAndClearState();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// BuildConfiguration changed:
|
||||
connect(m_buildConfiguration, &CMakeBuildConfiguration::environmentChanged, this, [this]() {
|
||||
if (m_buildConfiguration->isActive()) {
|
||||
// The environment on our BC has changed:
|
||||
// * Error out if the reader updates, cannot happen since all BCs share a target/kit.
|
||||
// * run cmake without configuration arguments if the reader stays
|
||||
m_buildDirManager
|
||||
.setParametersAndRequestParse(BuildDirParameters(m_buildConfiguration),
|
||||
BuildDirManager::REPARSE_CHECK_CONFIGURATION);
|
||||
}
|
||||
});
|
||||
connect(m_buildConfiguration, &CMakeBuildConfiguration::buildDirectoryChanged, this, [this]() {
|
||||
if (m_buildConfiguration->isActive()) {
|
||||
// The build directory of our BC has changed:
|
||||
// * Error out if the reader updates, cannot happen since all BCs share a target/kit.
|
||||
// * run cmake without configuration arguments if the reader stays
|
||||
// If no configuration exists, then the arguments will get added automatically by
|
||||
// the reader.
|
||||
m_buildDirManager
|
||||
.setParametersAndRequestParse(BuildDirParameters(m_buildConfiguration),
|
||||
BuildDirManager::REPARSE_CHECK_CONFIGURATION);
|
||||
}
|
||||
});
|
||||
connect(m_buildConfiguration, &CMakeBuildConfiguration::configurationForCMakeChanged, this, [this]() {
|
||||
if (m_buildConfiguration->isActive()) {
|
||||
// The CMake configuration has changed on our BC:
|
||||
// * Error out if the reader updates, cannot happen since all BCs share a target/kit.
|
||||
// * run cmake with configuration arguments if the reader stays
|
||||
m_buildDirManager
|
||||
.setParametersAndRequestParse(BuildDirParameters(m_buildConfiguration),
|
||||
BuildDirManager::REPARSE_FORCE_CONFIGURATION);
|
||||
}
|
||||
});
|
||||
|
||||
connect(project(), &Project::projectFileIsDirty, this, [this]() {
|
||||
if (m_buildConfiguration->isActive()) {
|
||||
m_buildDirManager
|
||||
.setParametersAndRequestParse(BuildDirParameters(m_buildConfiguration),
|
||||
BuildDirManager::REPARSE_DEFAULT);
|
||||
}
|
||||
});
|
||||
|
||||
m_buildDirManager.setParametersAndRequestParse(BuildDirParameters(m_buildConfiguration),
|
||||
BuildDirManager::REPARSE_CHECK_CONFIGURATION);
|
||||
}
|
||||
|
||||
CMakeBuildSystem::~CMakeBuildSystem()
|
||||
@@ -112,36 +219,84 @@ CMakeBuildSystem::~CMakeBuildSystem()
|
||||
qDeleteAll(m_allFiles);
|
||||
}
|
||||
|
||||
bool CMakeBuildSystem::validateParsingContext(const ParsingContext &ctx)
|
||||
void CMakeBuildSystem::triggerParsing()
|
||||
{
|
||||
QTC_ASSERT(!m_currentContext.guard.guardsProject(), return false);
|
||||
return ctx.project && qobject_cast<CMakeBuildConfiguration *>(ctx.buildConfiguration);
|
||||
}
|
||||
|
||||
void CMakeBuildSystem::parseProject(ParsingContext &&ctx)
|
||||
{
|
||||
m_currentContext = std::move(ctx);
|
||||
|
||||
auto bc = qobject_cast<CMakeBuildConfiguration *>(m_currentContext.buildConfiguration);
|
||||
QTC_ASSERT(bc, return );
|
||||
m_currentGuard = guardParsingRun();
|
||||
|
||||
if (m_allFiles.isEmpty())
|
||||
bc->m_buildDirManager.requestFilesystemScan();
|
||||
m_buildDirManager.requestFilesystemScan();
|
||||
|
||||
m_waitingForScan = bc->m_buildDirManager.isFilesystemScanRequested();
|
||||
m_waitingForScan = m_buildDirManager.isFilesystemScanRequested();
|
||||
m_waitingForParse = true;
|
||||
m_combinedScanAndParseResult = true;
|
||||
|
||||
if (m_waitingForScan) {
|
||||
QTC_CHECK(m_treeScanner.isFinished());
|
||||
m_treeScanner.asyncScanForFiles(m_currentContext.project->projectDirectory());
|
||||
m_treeScanner.asyncScanForFiles(projectDirectory());
|
||||
Core::ProgressManager::addTask(m_treeScanner.future(),
|
||||
tr("Scan \"%1\" project tree")
|
||||
.arg(m_currentContext.project->displayName()),
|
||||
.arg(project()->displayName()),
|
||||
"CMake.Scan.Tree");
|
||||
}
|
||||
|
||||
bc->m_buildDirManager.parse();
|
||||
m_buildDirManager.parse();
|
||||
}
|
||||
|
||||
QStringList CMakeBuildSystem::filesGeneratedFrom(const QString &sourceFile) const
|
||||
{
|
||||
QFileInfo fi(sourceFile);
|
||||
FilePath project = projectDirectory();
|
||||
FilePath baseDirectory = FilePath::fromString(fi.absolutePath());
|
||||
|
||||
while (baseDirectory.isChildOf(project)) {
|
||||
const FilePath cmakeListsTxt = baseDirectory.pathAppended("CMakeLists.txt");
|
||||
if (cmakeListsTxt.exists())
|
||||
break;
|
||||
baseDirectory = baseDirectory.parentDir();
|
||||
}
|
||||
|
||||
QDir srcDirRoot = QDir(project.toString());
|
||||
QString relativePath = srcDirRoot.relativeFilePath(baseDirectory.toString());
|
||||
QDir buildDir = QDir(target()->activeBuildConfiguration()->buildDirectory().toString());
|
||||
QString generatedFilePath = buildDir.absoluteFilePath(relativePath);
|
||||
|
||||
if (fi.suffix() == "ui") {
|
||||
generatedFilePath += "/ui_";
|
||||
generatedFilePath += fi.completeBaseName();
|
||||
generatedFilePath += ".h";
|
||||
return {QDir::cleanPath(generatedFilePath)};
|
||||
}
|
||||
if (fi.suffix() == "scxml") {
|
||||
generatedFilePath += "/";
|
||||
generatedFilePath += QDir::cleanPath(fi.completeBaseName());
|
||||
return {generatedFilePath + ".h", generatedFilePath + ".cpp"};
|
||||
}
|
||||
|
||||
// TODO: Other types will be added when adapters for their compilers become available.
|
||||
return {};
|
||||
}
|
||||
|
||||
void CMakeBuildSystem::runCMake()
|
||||
{
|
||||
BuildDirParameters parameters(m_buildConfiguration);
|
||||
m_buildDirManager.setParametersAndRequestParse(parameters,
|
||||
BuildDirManager::REPARSE_CHECK_CONFIGURATION
|
||||
| BuildDirManager::REPARSE_FORCE_CMAKE_RUN
|
||||
| BuildDirManager::REPARSE_URGENT);
|
||||
}
|
||||
|
||||
void CMakeBuildSystem::runCMakeAndScanProjectTree()
|
||||
{
|
||||
BuildDirParameters parameters(m_buildConfiguration);
|
||||
m_buildDirManager.setParametersAndRequestParse(parameters,
|
||||
BuildDirManager::REPARSE_CHECK_CONFIGURATION
|
||||
| BuildDirManager::REPARSE_SCAN);
|
||||
}
|
||||
|
||||
void CMakeBuildSystem::buildCMakeTarget(const QString &buildTarget)
|
||||
{
|
||||
QTC_ASSERT(!buildTarget.isEmpty(), return);
|
||||
m_buildConfiguration->buildTarget(buildTarget);
|
||||
}
|
||||
|
||||
void CMakeBuildSystem::handleTreeScanningFinished()
|
||||
@@ -156,11 +311,18 @@ void CMakeBuildSystem::handleTreeScanningFinished()
|
||||
combineScanAndParse();
|
||||
}
|
||||
|
||||
void CMakeBuildSystem::handleParsingSuccess(CMakeBuildConfiguration *bc)
|
||||
bool CMakeBuildSystem::persistCMakeState()
|
||||
{
|
||||
if (bc != m_currentContext.buildConfiguration)
|
||||
return; // Not current information, ignore.
|
||||
return m_buildDirManager.persistCMakeState();
|
||||
}
|
||||
|
||||
void CMakeBuildSystem::clearCMakeCache()
|
||||
{
|
||||
m_buildDirManager.clearCache();
|
||||
}
|
||||
|
||||
void CMakeBuildSystem::handleParsingSuccess()
|
||||
{
|
||||
QTC_ASSERT(m_waitingForParse, return );
|
||||
|
||||
m_waitingForParse = false;
|
||||
@@ -168,11 +330,8 @@ void CMakeBuildSystem::handleParsingSuccess(CMakeBuildConfiguration *bc)
|
||||
combineScanAndParse();
|
||||
}
|
||||
|
||||
void CMakeBuildSystem::handleParsingError(CMakeBuildConfiguration *bc)
|
||||
void CMakeBuildSystem::handleParsingError()
|
||||
{
|
||||
if (bc != m_currentContext.buildConfiguration)
|
||||
return; // Not current information, ignore.
|
||||
|
||||
QTC_CHECK(m_waitingForParse);
|
||||
|
||||
m_waitingForParse = false;
|
||||
@@ -181,35 +340,51 @@ void CMakeBuildSystem::handleParsingError(CMakeBuildConfiguration *bc)
|
||||
combineScanAndParse();
|
||||
}
|
||||
|
||||
std::unique_ptr<CMakeProjectNode>
|
||||
CMakeBuildSystem::generateProjectTree(const QList<const FileNode *> &allFiles)
|
||||
{
|
||||
QString errorMessage;
|
||||
auto root = m_buildDirManager.generateProjectTree(allFiles, errorMessage);
|
||||
checkAndReportError(errorMessage);
|
||||
return root;
|
||||
}
|
||||
|
||||
void CMakeBuildSystem::combineScanAndParse()
|
||||
{
|
||||
auto bc = qobject_cast<CMakeBuildConfiguration *>(m_currentContext.buildConfiguration);
|
||||
if (bc && bc->isActive()) {
|
||||
if (m_buildConfiguration->isActive()) {
|
||||
if (m_waitingForParse || m_waitingForScan)
|
||||
return;
|
||||
|
||||
if (m_combinedScanAndParseResult) {
|
||||
updateProjectData(qobject_cast<CMakeProject *>(m_currentContext.project), bc);
|
||||
m_currentContext.guard.markAsSuccess();
|
||||
updateProjectData();
|
||||
m_currentGuard.markAsSuccess();
|
||||
}
|
||||
}
|
||||
|
||||
m_currentContext = BuildSystem::ParsingContext();
|
||||
m_currentGuard = {};
|
||||
}
|
||||
|
||||
void CMakeBuildSystem::updateProjectData(CMakeProject *p, CMakeBuildConfiguration *bc)
|
||||
void CMakeBuildSystem::checkAndReportError(QString &errorMessage)
|
||||
{
|
||||
if (!errorMessage.isEmpty()) {
|
||||
m_buildConfiguration->setError(errorMessage);
|
||||
errorMessage.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void CMakeBuildSystem::updateProjectData()
|
||||
{
|
||||
qCDebug(cmakeBuildSystemLog) << "Updating CMake project data";
|
||||
|
||||
QTC_ASSERT(m_treeScanner.isFinished() && !bc->m_buildDirManager.isParsing(), return );
|
||||
QTC_ASSERT(m_treeScanner.isFinished() && !m_buildDirManager.isParsing(), return);
|
||||
|
||||
project()->setExtraProjectFiles(bc->m_buildDirManager.takeProjectFilesToWatch());
|
||||
m_buildConfiguration->project()->setExtraProjectFiles(m_buildDirManager.takeProjectFilesToWatch());
|
||||
|
||||
CMakeConfig patchedConfig = bc->configurationFromCMake();
|
||||
CMakeConfig patchedConfig = m_buildConfiguration->configurationFromCMake();
|
||||
{
|
||||
CMakeConfigItem settingFileItem;
|
||||
settingFileItem.key = "ANDROID_DEPLOYMENT_SETTINGS_FILE";
|
||||
settingFileItem.value = bc->buildDirectory()
|
||||
settingFileItem.value = m_buildConfiguration->buildDirectory()
|
||||
.pathAppended("android_deployment_settings.json")
|
||||
.toString()
|
||||
.toUtf8();
|
||||
@@ -218,7 +393,7 @@ void CMakeBuildSystem::updateProjectData(CMakeProject *p, CMakeBuildConfiguratio
|
||||
{
|
||||
QSet<QString> res;
|
||||
QStringList apps;
|
||||
for (const auto &target : bc->buildTargets()) {
|
||||
for (const auto &target : m_buildTargets) {
|
||||
if (target.targetType == CMakeProjectManager::DynamicLibraryType) {
|
||||
res.insert(target.executable.parentDir().toString());
|
||||
apps.push_back(target.executable.toUserOutput());
|
||||
@@ -241,14 +416,15 @@ void CMakeBuildSystem::updateProjectData(CMakeProject *p, CMakeBuildConfiguratio
|
||||
}
|
||||
}
|
||||
|
||||
Project *p = project();
|
||||
{
|
||||
auto newRoot = bc->generateProjectTree(m_allFiles);
|
||||
auto newRoot = generateProjectTree(m_allFiles);
|
||||
if (newRoot) {
|
||||
p->setRootProjectNode(std::move(newRoot));
|
||||
if (p->rootProjectNode())
|
||||
p->setDisplayName(p->rootProjectNode()->displayName());
|
||||
|
||||
for (const CMakeBuildTarget &bt : bc->buildTargets()) {
|
||||
for (const CMakeBuildTarget &bt : m_buildTargets) {
|
||||
const QString buildKey = bt.title;
|
||||
if (ProjectNode *node = p->findNodeForBuildKey(buildKey)) {
|
||||
if (auto targetNode = dynamic_cast<CMakeTargetNode *>(node))
|
||||
@@ -260,7 +436,7 @@ void CMakeBuildSystem::updateProjectData(CMakeProject *p, CMakeBuildConfiguratio
|
||||
|
||||
{
|
||||
qDeleteAll(m_extraCompilers);
|
||||
m_extraCompilers = findExtraCompilers(p);
|
||||
m_extraCompilers = findExtraCompilers();
|
||||
CppTools::GeneratedCodeModelSupport::update(m_extraCompilers);
|
||||
qCDebug(cmakeBuildSystemLog) << "Extra compilers updated.";
|
||||
}
|
||||
@@ -270,9 +446,9 @@ void CMakeBuildSystem::updateProjectData(CMakeProject *p, CMakeBuildConfiguratio
|
||||
|
||||
{
|
||||
QString errorMessage;
|
||||
RawProjectParts rpps = bc->m_buildDirManager.createRawProjectParts(errorMessage);
|
||||
RawProjectParts rpps = m_buildDirManager.createRawProjectParts(errorMessage);
|
||||
if (!errorMessage.isEmpty())
|
||||
bc->setError(errorMessage);
|
||||
m_buildConfiguration->setError(errorMessage);
|
||||
qCDebug(cmakeBuildSystemLog) << "Raw project parts created." << errorMessage;
|
||||
|
||||
for (RawProjectPart &rpp : rpps) {
|
||||
@@ -284,22 +460,147 @@ void CMakeBuildSystem::updateProjectData(CMakeProject *p, CMakeBuildConfiguratio
|
||||
rpp.setFlagsForC({kitInfo.cToolChain, rpp.flagsForC.commandLineFlags});
|
||||
}
|
||||
|
||||
m_cppCodeModelUpdater->update({p, kitInfo, bc->environment(), rpps});
|
||||
m_cppCodeModelUpdater->update({p, kitInfo, m_buildConfiguration->environment(), rpps});
|
||||
}
|
||||
{
|
||||
updateQmlJSCodeModel(p, bc);
|
||||
updateQmlJSCodeModel();
|
||||
}
|
||||
|
||||
emit p->fileListChanged();
|
||||
|
||||
emit bc->emitBuildTypeChanged();
|
||||
emit m_buildConfiguration->emitBuildTypeChanged();
|
||||
|
||||
bc->m_buildDirManager.resetData();
|
||||
m_buildDirManager.resetData();
|
||||
|
||||
qCDebug(cmakeBuildSystemLog) << "All CMake project data up to date.";
|
||||
}
|
||||
|
||||
QList<ProjectExplorer::ExtraCompiler *> CMakeBuildSystem::findExtraCompilers(CMakeProject *p)
|
||||
void CMakeBuildSystem::handleParsingSucceeded()
|
||||
{
|
||||
if (!m_buildConfiguration->isActive()) {
|
||||
m_buildDirManager.stopParsingAndClearState();
|
||||
return;
|
||||
}
|
||||
|
||||
m_buildConfiguration->clearError();
|
||||
|
||||
QString errorMessage;
|
||||
{
|
||||
m_buildTargets = m_buildDirManager.takeBuildTargets(errorMessage);
|
||||
checkAndReportError(errorMessage);
|
||||
}
|
||||
|
||||
{
|
||||
const CMakeConfig cmakeConfig = m_buildDirManager.takeCMakeConfiguration(errorMessage);
|
||||
checkAndReportError(errorMessage);
|
||||
m_buildConfiguration->setConfigurationFromCMake(cmakeConfig);
|
||||
}
|
||||
|
||||
setApplicationTargets(appTargets());
|
||||
setDeploymentData(deploymentData());
|
||||
|
||||
handleParsingSuccess();
|
||||
}
|
||||
|
||||
void CMakeBuildSystem::handleParsingFailed(const QString &msg)
|
||||
{
|
||||
m_buildConfiguration->setError(msg);
|
||||
|
||||
QString errorMessage;
|
||||
m_buildConfiguration->setConfigurationFromCMake(m_buildDirManager.takeCMakeConfiguration(errorMessage));
|
||||
// ignore errorMessage here, we already got one.
|
||||
|
||||
handleParsingError();
|
||||
}
|
||||
|
||||
BuildConfiguration *CMakeBuildSystem::buildConfiguration() const
|
||||
{
|
||||
return m_buildConfiguration;
|
||||
}
|
||||
|
||||
CMakeBuildConfiguration *CMakeBuildSystem::cmakeBuildConfiguration() const
|
||||
{
|
||||
return m_buildConfiguration;
|
||||
}
|
||||
|
||||
const QList<BuildTargetInfo> CMakeBuildSystem::appTargets() const
|
||||
{
|
||||
QList<BuildTargetInfo> appTargetList;
|
||||
const bool forAndroid = DeviceTypeKitAspect::deviceTypeId(target()->kit())
|
||||
== Android::Constants::ANDROID_DEVICE_TYPE;
|
||||
for (const CMakeBuildTarget &ct : m_buildTargets) {
|
||||
if (ct.targetType == UtilityType)
|
||||
continue;
|
||||
|
||||
if (ct.targetType == ExecutableType || (forAndroid && ct.targetType == DynamicLibraryType)) {
|
||||
BuildTargetInfo bti;
|
||||
bti.displayName = ct.title;
|
||||
bti.targetFilePath = ct.executable;
|
||||
bti.projectFilePath = ct.sourceDirectory.stringAppended("/");
|
||||
bti.workingDirectory = ct.workingDirectory;
|
||||
bti.buildKey = ct.title;
|
||||
|
||||
// Workaround for QTCREATORBUG-19354:
|
||||
bti.runEnvModifier = [this](Environment &env, bool) {
|
||||
if (HostOsInfo::isWindowsHost()) {
|
||||
const Kit *k = target()->kit();
|
||||
if (const QtSupport::BaseQtVersion *qt = QtSupport::QtKitAspect::qtVersion(k))
|
||||
env.prependOrSetPath(qt->binPath().toString());
|
||||
}
|
||||
};
|
||||
|
||||
appTargetList.append(bti);
|
||||
}
|
||||
}
|
||||
|
||||
return appTargetList;
|
||||
}
|
||||
|
||||
QStringList CMakeBuildSystem::buildTargetTitles() const
|
||||
{
|
||||
return transform(m_buildTargets, &CMakeBuildTarget::title);
|
||||
}
|
||||
|
||||
const QList<CMakeBuildTarget> &CMakeBuildSystem::buildTargets() const
|
||||
{
|
||||
return m_buildTargets;
|
||||
}
|
||||
|
||||
DeploymentData CMakeBuildSystem::deploymentData() const
|
||||
{
|
||||
DeploymentData result;
|
||||
|
||||
QDir sourceDir = target()->project()->projectDirectory().toString();
|
||||
QDir buildDir = buildConfiguration()->buildDirectory().toString();
|
||||
|
||||
QString deploymentPrefix;
|
||||
QString deploymentFilePath = sourceDir.filePath("QtCreatorDeployment.txt");
|
||||
|
||||
bool hasDeploymentFile = QFileInfo::exists(deploymentFilePath);
|
||||
if (!hasDeploymentFile) {
|
||||
deploymentFilePath = buildDir.filePath("QtCreatorDeployment.txt");
|
||||
hasDeploymentFile = QFileInfo::exists(deploymentFilePath);
|
||||
}
|
||||
if (!hasDeploymentFile)
|
||||
return result;
|
||||
|
||||
deploymentPrefix = result.addFilesFromDeploymentFile(deploymentFilePath,
|
||||
sourceDir.absolutePath());
|
||||
for (const CMakeBuildTarget &ct : m_buildTargets) {
|
||||
if (ct.targetType == ExecutableType || ct.targetType == DynamicLibraryType) {
|
||||
if (!ct.executable.isEmpty()
|
||||
&& result.deployableForLocalFile(ct.executable).localFilePath() != ct.executable) {
|
||||
result.addFile(ct.executable.toString(),
|
||||
deploymentPrefix + buildDir.relativeFilePath(ct.executable.toFileInfo().dir().path()),
|
||||
DeployableFile::TypeExecutable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
QList<ProjectExplorer::ExtraCompiler *> CMakeBuildSystem::findExtraCompilers()
|
||||
{
|
||||
qCDebug(cmakeBuildSystemLog) << "Finding Extra Compilers: start.";
|
||||
|
||||
@@ -315,6 +616,7 @@ QList<ProjectExplorer::ExtraCompiler *> CMakeBuildSystem::findExtraCompilers(CMa
|
||||
<< fileExtensions;
|
||||
|
||||
// Find all files generated by any of the extra compilers, in a rather crude way.
|
||||
Project *p = project();
|
||||
const FilePathList fileList = p->files([&fileExtensions, p](const Node *n) {
|
||||
if (!p->SourceFiles(n))
|
||||
return false;
|
||||
@@ -336,7 +638,7 @@ QList<ProjectExplorer::ExtraCompiler *> CMakeBuildSystem::findExtraCompilers(CMa
|
||||
});
|
||||
QTC_ASSERT(factory, continue);
|
||||
|
||||
QStringList generated = p->filesGeneratedFrom(file.toString());
|
||||
QStringList generated = filesGeneratedFrom(file.toString());
|
||||
qCDebug(cmakeBuildSystemLog)
|
||||
<< "Finding Extra Compilers: generated files:" << generated;
|
||||
if (generated.isEmpty())
|
||||
@@ -355,19 +657,20 @@ QList<ProjectExplorer::ExtraCompiler *> CMakeBuildSystem::findExtraCompilers(CMa
|
||||
return extraCompilers;
|
||||
}
|
||||
|
||||
void CMakeBuildSystem::updateQmlJSCodeModel(CMakeProject *p, CMakeBuildConfiguration *bc)
|
||||
void CMakeBuildSystem::updateQmlJSCodeModel()
|
||||
{
|
||||
QmlJS::ModelManagerInterface *modelManager = QmlJS::ModelManagerInterface::instance();
|
||||
|
||||
if (!modelManager)
|
||||
return;
|
||||
|
||||
Project *p = project();
|
||||
QmlJS::ModelManagerInterface::ProjectInfo projectInfo = modelManager
|
||||
->defaultProjectInfoForProject(p);
|
||||
|
||||
projectInfo.importPaths.clear();
|
||||
|
||||
const CMakeConfig &cm = bc->configurationFromCMake();
|
||||
const CMakeConfig &cm = m_buildConfiguration->configurationFromCMake();
|
||||
const QString cmakeImports = QString::fromUtf8(CMakeConfigItem::valueOf("QML_IMPORT_PATH", cm));
|
||||
|
||||
foreach (const QString &cmakeImport, CMakeConfigItem::cmakeSplitValue(cmakeImports))
|
||||
@@ -376,4 +679,5 @@ void CMakeBuildSystem::updateQmlJSCodeModel(CMakeProject *p, CMakeBuildConfigura
|
||||
modelManager->updateProjectInfo(projectInfo, p);
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace CMakeProjectManager
|
||||
|
@@ -25,8 +25,12 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "builddirmanager.h"
|
||||
|
||||
#include <projectexplorer/buildsystem.h>
|
||||
|
||||
namespace ProjectExplorer { class ExtraCompiler; }
|
||||
|
||||
namespace CppTools {
|
||||
class CppProjectUpdater;
|
||||
} // namespace CppTools
|
||||
@@ -37,7 +41,6 @@ class CMakeProject;
|
||||
|
||||
namespace Internal {
|
||||
class CMakeBuildConfiguration;
|
||||
} // namespace Internal
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// CMakeBuildSystem:
|
||||
@@ -48,12 +51,10 @@ class CMakeBuildSystem : public ProjectExplorer::BuildSystem
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit CMakeBuildSystem(ProjectExplorer::Project *project);
|
||||
explicit CMakeBuildSystem(CMakeBuildConfiguration *bc);
|
||||
~CMakeBuildSystem() final;
|
||||
|
||||
protected:
|
||||
bool validateParsingContext(const ParsingContext &ctx) final;
|
||||
void parseProject(ParsingContext &&ctx) final;
|
||||
void triggerParsing() final;
|
||||
|
||||
bool supportsAction(ProjectExplorer::Node *context,
|
||||
ProjectExplorer::ProjectAction action,
|
||||
@@ -62,20 +63,49 @@ protected:
|
||||
bool addFiles(ProjectExplorer::Node *context,
|
||||
const QStringList &filePaths, QStringList *) final;
|
||||
|
||||
private:
|
||||
QStringList filesGeneratedFrom(const QString &sourceFile) const final;
|
||||
|
||||
void runCMake();
|
||||
void runCMakeAndScanProjectTree();
|
||||
|
||||
// Context menu actions:
|
||||
void buildCMakeTarget(const QString &buildTarget);
|
||||
// Treescanner states:
|
||||
void handleTreeScanningFinished();
|
||||
|
||||
bool persistCMakeState();
|
||||
void clearCMakeCache();
|
||||
|
||||
// Parser states:
|
||||
void handleParsingSuccess(Internal::CMakeBuildConfiguration *bc);
|
||||
void handleParsingError(Internal::CMakeBuildConfiguration *bc);
|
||||
void handleParsingSuccess();
|
||||
void handleParsingError();
|
||||
|
||||
ProjectExplorer::BuildConfiguration *buildConfiguration() const;
|
||||
CMakeBuildConfiguration *cmakeBuildConfiguration() const;
|
||||
|
||||
const QList<ProjectExplorer::BuildTargetInfo> appTargets() const;
|
||||
QStringList buildTargetTitles() const;
|
||||
const QList<CMakeBuildTarget> &buildTargets() const;
|
||||
ProjectExplorer::DeploymentData deploymentData() const;
|
||||
|
||||
private:
|
||||
std::unique_ptr<CMakeProjectNode> generateProjectTree(
|
||||
const QList<const ProjectExplorer::FileNode *> &allFiles);
|
||||
|
||||
// Combining Treescanner and Parser states:
|
||||
void combineScanAndParse();
|
||||
|
||||
void updateProjectData(CMakeProject *p, Internal::CMakeBuildConfiguration *bc);
|
||||
QList<ProjectExplorer::ExtraCompiler *> findExtraCompilers(CMakeProject *p);
|
||||
void updateQmlJSCodeModel(CMakeProject *p, Internal::CMakeBuildConfiguration *bc);
|
||||
void checkAndReportError(QString &errorMessage);
|
||||
|
||||
void updateProjectData();
|
||||
QList<ProjectExplorer::ExtraCompiler *> findExtraCompilers();
|
||||
void updateQmlJSCodeModel();
|
||||
|
||||
void handleParsingSucceeded();
|
||||
void handleParsingFailed(const QString &msg);
|
||||
|
||||
CMakeBuildConfiguration *m_buildConfiguration = nullptr;
|
||||
BuildDirManager m_buildDirManager;
|
||||
|
||||
ProjectExplorer::TreeScanner m_treeScanner;
|
||||
QHash<QString, bool> m_mimeBinaryCache;
|
||||
@@ -85,12 +115,12 @@ private:
|
||||
bool m_waitingForParse = false;
|
||||
bool m_combinedScanAndParseResult = false;
|
||||
|
||||
ParsingContext m_currentContext;
|
||||
ParseGuard m_currentGuard;
|
||||
|
||||
CppTools::CppProjectUpdater *m_cppCodeModelUpdater = nullptr;
|
||||
QList<ProjectExplorer::ExtraCompiler *> m_extraCompilers;
|
||||
|
||||
friend class Internal::CMakeBuildConfiguration; // For handleParsing* callbacks
|
||||
QList<CMakeBuildTarget> m_buildTargets;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace CMakeProjectManager
|
||||
|
@@ -66,12 +66,11 @@ void CMakeTargetLocatorFilter::prepareSearch(const QString &entry)
|
||||
auto cmakeProject = qobject_cast<const CMakeProject *>(p);
|
||||
if (!cmakeProject || !cmakeProject->activeTarget())
|
||||
continue;
|
||||
auto bc = qobject_cast<CMakeBuildConfiguration *>(
|
||||
cmakeProject->activeTarget()->activeBuildConfiguration());
|
||||
if (!bc)
|
||||
auto bs = qobject_cast<CMakeBuildSystem *>(cmakeProject->activeTarget()->buildSystem());
|
||||
if (!bs)
|
||||
continue;
|
||||
|
||||
const QList<CMakeBuildTarget> buildTargets = bc->buildTargets();
|
||||
const QList<CMakeBuildTarget> buildTargets = bs->buildTargets();
|
||||
for (const CMakeBuildTarget &target : buildTargets) {
|
||||
const int index = target.title.indexOf(entry);
|
||||
if (index >= 0) {
|
||||
|
@@ -68,11 +68,6 @@ namespace CMakeProjectManager {
|
||||
|
||||
using namespace Internal;
|
||||
|
||||
static CMakeBuildConfiguration *activeBc(const CMakeProject *p)
|
||||
{
|
||||
return qobject_cast<CMakeBuildConfiguration *>(p->activeTarget() ? p->activeTarget()->activeBuildConfiguration() : nullptr);
|
||||
}
|
||||
|
||||
// QtCreator CMake Generator wishlist:
|
||||
// Which make targets we need to build to get all executables
|
||||
// What is the actual compiler executable
|
||||
@@ -90,8 +85,6 @@ CMakeProject::CMakeProject(const FilePath &fileName)
|
||||
setCanBuildProducts();
|
||||
setKnowsAllBuildExecutables(false);
|
||||
setHasMakeInstallEquivalent(true);
|
||||
|
||||
setBuildSystemCreator([](Project *p) { return new CMakeBuildSystem(p); });
|
||||
}
|
||||
|
||||
CMakeProject::~CMakeProject() = default;
|
||||
@@ -108,38 +101,6 @@ Tasks CMakeProject::projectIssues(const Kit *k) const
|
||||
return result;
|
||||
}
|
||||
|
||||
void CMakeProject::runCMake()
|
||||
{
|
||||
CMakeBuildConfiguration *bc = activeBc(this);
|
||||
if (isParsing() || !bc)
|
||||
return;
|
||||
|
||||
BuildDirParameters parameters(bc);
|
||||
bc->m_buildDirManager.setParametersAndRequestParse(parameters,
|
||||
BuildDirManager::REPARSE_CHECK_CONFIGURATION
|
||||
| BuildDirManager::REPARSE_FORCE_CMAKE_RUN
|
||||
| BuildDirManager::REPARSE_URGENT);
|
||||
}
|
||||
|
||||
void CMakeProject::runCMakeAndScanProjectTree()
|
||||
{
|
||||
CMakeBuildConfiguration *bc = activeBc(this);
|
||||
if (isParsing() || !bc)
|
||||
return;
|
||||
|
||||
BuildDirParameters parameters(bc);
|
||||
bc->m_buildDirManager.setParametersAndRequestParse(parameters,
|
||||
BuildDirManager::REPARSE_CHECK_CONFIGURATION
|
||||
| BuildDirManager::REPARSE_SCAN);
|
||||
}
|
||||
|
||||
void CMakeProject::buildCMakeTarget(const QString &buildTarget)
|
||||
{
|
||||
QTC_ASSERT(!buildTarget.isEmpty(), return);
|
||||
CMakeBuildConfiguration *bc = activeBc(this);
|
||||
if (bc)
|
||||
bc->buildTarget(buildTarget);
|
||||
}
|
||||
|
||||
ProjectImporter *CMakeProject::projectImporter() const
|
||||
{
|
||||
@@ -148,19 +109,6 @@ ProjectImporter *CMakeProject::projectImporter() const
|
||||
return m_projectImporter.get();
|
||||
}
|
||||
|
||||
bool CMakeProject::persistCMakeState()
|
||||
{
|
||||
CMakeBuildConfiguration *bc = activeBc(this);
|
||||
return bc ? bc->m_buildDirManager.persistCMakeState() : false;
|
||||
}
|
||||
|
||||
void CMakeProject::clearCMakeCache()
|
||||
{
|
||||
CMakeBuildConfiguration *bc = activeBc(this);
|
||||
if (bc)
|
||||
bc->m_buildDirManager.clearCache();
|
||||
}
|
||||
|
||||
bool CMakeProject::setupTarget(Target *t)
|
||||
{
|
||||
t->updateDefaultBuildConfigurations();
|
||||
@@ -170,42 +118,6 @@ bool CMakeProject::setupTarget(Target *t)
|
||||
return true;
|
||||
}
|
||||
|
||||
QStringList CMakeProject::filesGeneratedFrom(const QString &sourceFile) const
|
||||
{
|
||||
if (!activeTarget())
|
||||
return QStringList();
|
||||
QFileInfo fi(sourceFile);
|
||||
FilePath project = projectDirectory();
|
||||
FilePath baseDirectory = FilePath::fromString(fi.absolutePath());
|
||||
|
||||
while (baseDirectory.isChildOf(project)) {
|
||||
const FilePath cmakeListsTxt = baseDirectory.pathAppended("CMakeLists.txt");
|
||||
if (cmakeListsTxt.exists())
|
||||
break;
|
||||
baseDirectory = baseDirectory.parentDir();
|
||||
}
|
||||
|
||||
QDir srcDirRoot = QDir(project.toString());
|
||||
QString relativePath = srcDirRoot.relativeFilePath(baseDirectory.toString());
|
||||
QDir buildDir = QDir(activeTarget()->activeBuildConfiguration()->buildDirectory().toString());
|
||||
QString generatedFilePath = buildDir.absoluteFilePath(relativePath);
|
||||
|
||||
if (fi.suffix() == "ui") {
|
||||
generatedFilePath += "/ui_";
|
||||
generatedFilePath += fi.completeBaseName();
|
||||
generatedFilePath += ".h";
|
||||
return QStringList(QDir::cleanPath(generatedFilePath));
|
||||
} else if (fi.suffix() == "scxml") {
|
||||
generatedFilePath += "/";
|
||||
generatedFilePath += QDir::cleanPath(fi.completeBaseName());
|
||||
return QStringList({generatedFilePath + ".h",
|
||||
generatedFilePath + ".cpp"});
|
||||
} else {
|
||||
// TODO: Other types will be added when adapters for their compilers become available.
|
||||
return QStringList();
|
||||
}
|
||||
}
|
||||
|
||||
ProjectExplorer::DeploymentKnowledge CMakeProject::deploymentKnowledge() const
|
||||
{
|
||||
return !files([](const ProjectExplorer::Node *n) {
|
||||
@@ -232,9 +144,4 @@ MakeInstallCommand CMakeProject::makeInstallCommand(const Target *target,
|
||||
return cmd;
|
||||
}
|
||||
|
||||
bool CMakeProject::mustUpdateCMakeStateBeforeBuild() const
|
||||
{
|
||||
return buildSystem()->isWaitingForParse();
|
||||
}
|
||||
|
||||
} // namespace CMakeProjectManager
|
||||
|
@@ -49,24 +49,12 @@ public:
|
||||
|
||||
ProjectExplorer::Tasks projectIssues(const ProjectExplorer::Kit *k) const final;
|
||||
|
||||
void runCMake();
|
||||
void runCMakeAndScanProjectTree();
|
||||
|
||||
// Context menu actions:
|
||||
void buildCMakeTarget(const QString &buildTarget);
|
||||
|
||||
ProjectExplorer::ProjectImporter *projectImporter() const final;
|
||||
|
||||
bool persistCMakeState();
|
||||
void clearCMakeCache();
|
||||
bool mustUpdateCMakeStateBeforeBuild() const;
|
||||
|
||||
protected:
|
||||
bool setupTarget(ProjectExplorer::Target *t) final;
|
||||
|
||||
private:
|
||||
QStringList filesGeneratedFrom(const QString &sourceFile) const final;
|
||||
|
||||
ProjectExplorer::DeploymentKnowledge deploymentKnowledge() const override;
|
||||
ProjectExplorer::MakeInstallCommand makeInstallCommand(const ProjectExplorer::Target *target,
|
||||
const QString &installRoot) override;
|
||||
|
@@ -78,7 +78,7 @@ CMakeManager::CMakeManager() :
|
||||
command->setAttribute(Core::Command::CA_Hide);
|
||||
mbuild->addAction(command, ProjectExplorer::Constants::G_BUILD_DEPLOY);
|
||||
connect(m_runCMakeAction, &QAction::triggered, [this]() {
|
||||
runCMake(SessionManager::startupProject());
|
||||
runCMake(SessionManager::startupBuildSystem());
|
||||
});
|
||||
|
||||
command = Core::ActionManager::registerAction(m_clearCMakeCacheAction,
|
||||
@@ -86,7 +86,7 @@ CMakeManager::CMakeManager() :
|
||||
command->setAttribute(Core::Command::CA_Hide);
|
||||
mbuild->addAction(command, ProjectExplorer::Constants::G_BUILD_DEPLOY);
|
||||
connect(m_clearCMakeCacheAction, &QAction::triggered, [this]() {
|
||||
clearCMakeCache(SessionManager::startupProject());
|
||||
clearCMakeCache(SessionManager::startupBuildSystem());
|
||||
});
|
||||
|
||||
command = Core::ActionManager::registerAction(m_runCMakeActionContextMenu,
|
||||
@@ -95,7 +95,7 @@ CMakeManager::CMakeManager() :
|
||||
mproject->addAction(command, ProjectExplorer::Constants::G_PROJECT_BUILD);
|
||||
msubproject->addAction(command, ProjectExplorer::Constants::G_PROJECT_BUILD);
|
||||
connect(m_runCMakeActionContextMenu, &QAction::triggered, [this]() {
|
||||
runCMake(ProjectTree::currentProject());
|
||||
runCMake(ProjectTree::currentBuildSystem());
|
||||
});
|
||||
|
||||
m_buildFileContextMenu = new QAction(tr("Build"), this);
|
||||
@@ -111,7 +111,7 @@ CMakeManager::CMakeManager() :
|
||||
command->setAttribute(Core::Command::CA_Hide);
|
||||
mbuild->addAction(command, ProjectExplorer::Constants::G_BUILD_DEPLOY);
|
||||
connect(m_rescanProjectAction, &QAction::triggered, [this]() {
|
||||
rescanProject(ProjectTree::currentProject());
|
||||
rescanProject(ProjectTree::currentBuildSystem());
|
||||
});
|
||||
|
||||
m_buildFileAction = new Utils::ParameterAction(tr("Build File"), tr("Build File \"%1\""),
|
||||
@@ -146,34 +146,29 @@ void CMakeManager::updateCmakeActions()
|
||||
enableBuildFileMenus(ProjectTree::currentNode());
|
||||
}
|
||||
|
||||
void CMakeManager::clearCMakeCache(Project *project)
|
||||
void CMakeManager::clearCMakeCache(BuildSystem *buildSystem)
|
||||
{
|
||||
auto cmakeProject = qobject_cast<CMakeProject *>(project);
|
||||
if (!cmakeProject || !cmakeProject->activeTarget() || !cmakeProject->activeTarget()->activeBuildConfiguration())
|
||||
return;
|
||||
auto cmakeBuildSystem = dynamic_cast<CMakeBuildSystem *>(buildSystem);
|
||||
QTC_ASSERT(cmakeBuildSystem, return);
|
||||
|
||||
cmakeProject->clearCMakeCache();
|
||||
cmakeBuildSystem->clearCMakeCache();
|
||||
}
|
||||
|
||||
void CMakeManager::runCMake(Project *project)
|
||||
void CMakeManager::runCMake(BuildSystem *buildSystem)
|
||||
{
|
||||
auto cmakeProject = qobject_cast<CMakeProject *>(project);
|
||||
if (!cmakeProject || !cmakeProject->activeTarget() || !cmakeProject->activeTarget()->activeBuildConfiguration())
|
||||
return;
|
||||
auto cmakeBuildSystem = dynamic_cast<CMakeBuildSystem *>(buildSystem);
|
||||
QTC_ASSERT(cmakeBuildSystem, return);
|
||||
|
||||
if (!ProjectExplorerPlugin::saveModifiedFiles())
|
||||
return;
|
||||
|
||||
cmakeProject->runCMake();
|
||||
if (ProjectExplorerPlugin::saveModifiedFiles())
|
||||
cmakeBuildSystem->runCMake();
|
||||
}
|
||||
|
||||
void CMakeManager::rescanProject(Project *project)
|
||||
void CMakeManager::rescanProject(BuildSystem *buildSystem)
|
||||
{
|
||||
auto cmakeProject = qobject_cast<CMakeProject *>(project);
|
||||
if (!cmakeProject || !cmakeProject->activeTarget() || !cmakeProject->activeTarget()->activeBuildConfiguration())
|
||||
return;
|
||||
auto cmakeBuildSystem = dynamic_cast<CMakeBuildSystem *>(buildSystem);
|
||||
QTC_ASSERT(cmakeBuildSystem, return);
|
||||
|
||||
cmakeProject->runCMakeAndScanProjectTree();// by my experience: every rescan run requires cmake run too
|
||||
cmakeBuildSystem->runCMakeAndScanProjectTree();// by my experience: every rescan run requires cmake run too
|
||||
}
|
||||
|
||||
void CMakeManager::updateBuildFileAction()
|
||||
@@ -235,14 +230,15 @@ void CMakeManager::buildFile(Node *node)
|
||||
CMakeTargetNode *targetNode = dynamic_cast<CMakeTargetNode *>(fileNode->parentProjectNode());
|
||||
if (!targetNode)
|
||||
return;
|
||||
auto cmakeProject = static_cast<CMakeProject *>(project);
|
||||
Target *target = cmakeProject->activeTarget();
|
||||
Target *target = project->activeTarget();
|
||||
QTC_ASSERT(target, return);
|
||||
const QString generator = CMakeGeneratorKitAspect::generator(target->kit());
|
||||
const QString relativeSource = fileNode->filePath().relativeChildPath(targetNode->filePath()).toString();
|
||||
const QString objExtension = Utils::HostOsInfo::isWindowsHost() ? QString(".obj") : QString(".o");
|
||||
Utils::FilePath targetBase;
|
||||
BuildConfiguration *bc = target->activeBuildConfiguration();
|
||||
QTC_ASSERT(bc, return);
|
||||
if (generator == "Ninja") {
|
||||
BuildConfiguration *bc = target->activeBuildConfiguration();
|
||||
const Utils::FilePath relativeBuildDir = targetNode->buildDirectory().relativeChildPath(
|
||||
bc->buildDirectory());
|
||||
targetBase = relativeBuildDir
|
||||
@@ -253,7 +249,9 @@ void CMakeManager::buildFile(Node *node)
|
||||
.arg(generator));
|
||||
return;
|
||||
}
|
||||
cmakeProject->buildCMakeTarget(targetBase.pathAppended(relativeSource).toString() + objExtension);
|
||||
|
||||
static_cast<CMakeBuildSystem *>(bc->buildSystem())
|
||||
->buildCMakeTarget(targetBase.pathAppended(relativeSource).toString() + objExtension);
|
||||
}
|
||||
|
||||
void CMakeManager::buildFileContextMenu()
|
||||
|
@@ -45,9 +45,9 @@ public:
|
||||
|
||||
private:
|
||||
void updateCmakeActions();
|
||||
void clearCMakeCache(ProjectExplorer::Project *project);
|
||||
void runCMake(ProjectExplorer::Project *project);
|
||||
void rescanProject(ProjectExplorer::Project *project);
|
||||
void clearCMakeCache(ProjectExplorer::BuildSystem *buildSystem);
|
||||
void runCMake(ProjectExplorer::BuildSystem *buildSystem);
|
||||
void rescanProject(ProjectExplorer::BuildSystem *buildSystem);
|
||||
void buildFileContextMenu();
|
||||
void buildFile(ProjectExplorer::Node *node = nullptr);
|
||||
void updateBuildFileAction();
|
||||
|
@@ -265,7 +265,10 @@ Utils::optional<Utils::FilePath> CMakeTargetNode::visibleAfterAddFileAction() co
|
||||
|
||||
void CMakeTargetNode::build()
|
||||
{
|
||||
static_cast<CMakeProject *>(getProject())->buildCMakeTarget(displayName());
|
||||
Project *p = getProject();
|
||||
Target *t = p ? p->activeTarget() : nullptr;
|
||||
if (t)
|
||||
static_cast<CMakeBuildSystem *>(t->buildSystem())->buildCMakeTarget(displayName());
|
||||
}
|
||||
|
||||
void CMakeTargetNode::setTargetInformation(const QList<Utils::FilePath> &artifacts,
|
||||
|
@@ -47,6 +47,7 @@
|
||||
#include <projectexplorer/projectmanager.h>
|
||||
#include <projectexplorer/projecttree.h>
|
||||
#include <projectexplorer/runcontrol.h>
|
||||
#include <projectexplorer/target.h>
|
||||
|
||||
#include <texteditor/snippets/snippetprovider.h>
|
||||
|
||||
@@ -70,8 +71,6 @@ public:
|
||||
ParameterAction::AlwaysEnabled/*handled manually*/
|
||||
};
|
||||
|
||||
QMetaObject::Connection m_actionConnect;
|
||||
|
||||
CMakeSettingsPage settingsPage;
|
||||
CMakeSpecificSettingsPage specificSettings{CMakeProjectPlugin::projectTypeSpecificSettings()};
|
||||
|
||||
@@ -129,6 +128,13 @@ bool CMakeProjectPlugin::initialize(const QStringList & /*arguments*/, QString *
|
||||
connect(ProjectTree::instance(), &ProjectTree::currentNodeChanged,
|
||||
this, &CMakeProjectPlugin::updateContextActions);
|
||||
|
||||
connect(&d->buildTargetContextAction, &ParameterAction::triggered, this, [] {
|
||||
if (auto bs = qobject_cast<CMakeBuildSystem *>(ProjectTree::currentBuildSystem())) {
|
||||
auto targetNode = dynamic_cast<const CMakeTargetNode *>(ProjectTree::currentNode());
|
||||
bs->buildCMakeTarget(targetNode ? targetNode->displayName() : QString());
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -140,24 +146,13 @@ void CMakeProjectPlugin::extensionsInitialized()
|
||||
|
||||
void CMakeProjectPlugin::updateContextActions()
|
||||
{
|
||||
Project *project = ProjectTree::currentProject();
|
||||
const Node *node = ProjectTree::currentNode();
|
||||
auto targetNode = dynamic_cast<const CMakeTargetNode *>(node);
|
||||
// as targetNode can be deleted while the menu is open, we keep only the
|
||||
auto targetNode = dynamic_cast<const CMakeTargetNode *>(ProjectTree::currentNode());
|
||||
const QString targetDisplayName = targetNode ? targetNode->displayName() : QString();
|
||||
auto cmProject = dynamic_cast<CMakeProject *>(project);
|
||||
|
||||
// Build Target:
|
||||
disconnect(d->m_actionConnect);
|
||||
d->buildTargetContextAction.setParameter(targetDisplayName);
|
||||
d->buildTargetContextAction.setEnabled(targetNode);
|
||||
d->buildTargetContextAction.setVisible(targetNode);
|
||||
if (cmProject && targetNode) {
|
||||
d->m_actionConnect = connect(&d->buildTargetContextAction, &ParameterAction::triggered,
|
||||
cmProject, [cmProject, targetDisplayName]() {
|
||||
cmProject->buildCMakeTarget(targetDisplayName);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
} // Internal
|
||||
|
@@ -337,9 +337,46 @@ void createTree(std::unique_ptr<ProjectNode> &root,
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
void CompilationDatabaseProject::buildTreeAndProjectParts()
|
||||
CompilationDatabaseBuildSystem::CompilationDatabaseBuildSystem(Target *target)
|
||||
: BuildSystem(target)
|
||||
, m_cppCodeModelUpdater(std::make_unique<CppTools::CppProjectUpdater>())
|
||||
, m_parseDelay(new QTimer(this))
|
||||
, m_deployFileWatcher(new FileSystemWatcher(this))
|
||||
{
|
||||
ProjectExplorer::KitInfo kitInfo(this);
|
||||
connect(target->project(), &CompilationDatabaseProject::rootProjectDirectoryChanged,
|
||||
this, [this] {
|
||||
m_projectFileHash.clear();
|
||||
m_parseDelay->start();
|
||||
});
|
||||
|
||||
connect(m_parseDelay, &QTimer::timeout, this, &CompilationDatabaseBuildSystem::reparseProject);
|
||||
|
||||
m_parseDelay->setSingleShot(true);
|
||||
m_parseDelay->setInterval(1000);
|
||||
m_parseDelay->start();
|
||||
|
||||
connect(project(), &Project::projectFileIsDirty, this, &CompilationDatabaseBuildSystem::reparseProject);
|
||||
|
||||
connect(m_deployFileWatcher, &FileSystemWatcher::fileChanged,
|
||||
this, &CompilationDatabaseBuildSystem::updateDeploymentData);
|
||||
connect(target->project(), &Project::activeTargetChanged,
|
||||
this, &CompilationDatabaseBuildSystem::updateDeploymentData);
|
||||
}
|
||||
|
||||
CompilationDatabaseBuildSystem::~CompilationDatabaseBuildSystem()
|
||||
{
|
||||
m_parserWatcher.cancel();
|
||||
m_parserWatcher.waitForFinished();
|
||||
}
|
||||
|
||||
void CompilationDatabaseBuildSystem::triggerParsing()
|
||||
{
|
||||
reparseProject();
|
||||
}
|
||||
|
||||
void CompilationDatabaseBuildSystem::buildTreeAndProjectParts()
|
||||
{
|
||||
ProjectExplorer::KitInfo kitInfo(project());
|
||||
QTC_ASSERT(kitInfo.isValid(), return);
|
||||
// Reset toolchains to pick them based on the database entries.
|
||||
kitInfo.cToolChain = nullptr;
|
||||
@@ -349,6 +386,7 @@ void CompilationDatabaseProject::buildTreeAndProjectParts()
|
||||
QTC_ASSERT(m_parser, return);
|
||||
const DbContents dbContents = m_parser->dbContents();
|
||||
const DbEntry *prevEntry = nullptr;
|
||||
Kit *kit = static_cast<CompilationDatabaseProject *>(project())->kit();
|
||||
for (const DbEntry &entry : dbContents.entries) {
|
||||
if (prevEntry && prevEntry->flags == entry.flags) {
|
||||
rpps.back().files.append(entry.fileName.toString());
|
||||
@@ -358,7 +396,7 @@ void CompilationDatabaseProject::buildTreeAndProjectParts()
|
||||
prevEntry = &entry;
|
||||
|
||||
RawProjectPart rpp = makeRawProjectPart(projectFilePath(),
|
||||
m_kit.get(),
|
||||
kit,
|
||||
kitInfo,
|
||||
entry.workingDir,
|
||||
entry.fileName,
|
||||
@@ -381,7 +419,7 @@ void CompilationDatabaseProject::buildTreeAndProjectParts()
|
||||
|
||||
|
||||
auto root = std::make_unique<ProjectNode>(projectDirectory());
|
||||
createTree(root, rootProjectDirectory(), rpps, m_parser->scannedFiles());
|
||||
createTree(root, project()->rootProjectDirectory(), rpps, m_parser->scannedFiles());
|
||||
|
||||
root->addNode(std::make_unique<FileNode>(projectFilePath(), FileType::Project));
|
||||
|
||||
@@ -389,43 +427,26 @@ void CompilationDatabaseProject::buildTreeAndProjectParts()
|
||||
root->addNode(std::make_unique<FileNode>(Utils::FilePath::fromString(dbContents.extraFileName),
|
||||
FileType::Project));
|
||||
|
||||
setRootProjectNode(std::move(root));
|
||||
project()->setRootProjectNode(std::move(root));
|
||||
|
||||
m_cppCodeModelUpdater->update({this, kitInfo, activeParseEnvironment(), rpps});
|
||||
m_cppCodeModelUpdater->update({project(), kitInfo, activeParseEnvironment(), rpps});
|
||||
updateDeploymentData();
|
||||
}
|
||||
|
||||
CompilationDatabaseProject::CompilationDatabaseProject(const Utils::FilePath &projectFile)
|
||||
: Project(Constants::COMPILATIONDATABASEMIMETYPE, projectFile)
|
||||
, m_cppCodeModelUpdater(std::make_unique<CppTools::CppProjectUpdater>())
|
||||
, m_parseDelay(new QTimer(this))
|
||||
, m_deployFileWatcher(new FileSystemWatcher(this))
|
||||
{
|
||||
setId(Constants::COMPILATIONDATABASEPROJECT_ID);
|
||||
setProjectLanguages(Core::Context(ProjectExplorer::Constants::CXX_LANGUAGE_ID));
|
||||
setDisplayName(projectDirectory().fileName());
|
||||
|
||||
setBuildSystemCreator([](Target *t) { return new CompilationDatabaseBuildSystem(t); });
|
||||
|
||||
m_kit.reset(KitManager::defaultKit()->clone());
|
||||
addTargetForKit(m_kit.get());
|
||||
|
||||
connect(this, &CompilationDatabaseProject::rootProjectDirectoryChanged,
|
||||
this, [this] {
|
||||
m_projectFileHash.clear();
|
||||
m_parseDelay->start();
|
||||
});
|
||||
|
||||
setExtraProjectFiles(
|
||||
{projectFile.stringAppended(Constants::COMPILATIONDATABASEPROJECT_FILES_SUFFIX)});
|
||||
connect(m_parseDelay, &QTimer::timeout, this, &CompilationDatabaseProject::reparseProject);
|
||||
|
||||
m_parseDelay->setSingleShot(true);
|
||||
m_parseDelay->setInterval(1000);
|
||||
|
||||
connect(this, &Project::projectFileIsDirty, this, &CompilationDatabaseProject::reparseProject);
|
||||
connect(m_deployFileWatcher, &FileSystemWatcher::fileChanged,
|
||||
this, &CompilationDatabaseProject::updateDeploymentData);
|
||||
connect(this, &Project::activeTargetChanged,
|
||||
this, &CompilationDatabaseProject::updateDeploymentData);
|
||||
}
|
||||
|
||||
Utils::FilePath CompilationDatabaseProject::rootPathFromSettings() const
|
||||
@@ -442,26 +463,19 @@ Project::RestoreResult CompilationDatabaseProject::fromMap(const QVariantMap &ma
|
||||
QString *errorMessage)
|
||||
{
|
||||
Project::RestoreResult result = Project::fromMap(map, errorMessage);
|
||||
if (result == Project::RestoreResult::Ok) {
|
||||
const Utils::FilePath rootPath = rootPathFromSettings();
|
||||
if (rootPath.isEmpty())
|
||||
changeRootProjectDirectory(); // This triggers reparse itself.
|
||||
else
|
||||
reparseProject();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void CompilationDatabaseProject::reparseProject()
|
||||
void CompilationDatabaseBuildSystem::reparseProject()
|
||||
{
|
||||
if (m_parser) {
|
||||
QTC_CHECK(isParsing());
|
||||
m_parser->stop();
|
||||
}
|
||||
m_parser = new CompilationDbParser(displayName(),
|
||||
const FilePath rootPath = static_cast<CompilationDatabaseProject *>(project())->rootPathFromSettings();
|
||||
m_parser = new CompilationDbParser(project()->displayName(),
|
||||
projectFilePath(),
|
||||
rootPathFromSettings(),
|
||||
rootPath,
|
||||
m_mimeBinaryCache,
|
||||
guardParsingRun(),
|
||||
this);
|
||||
@@ -475,17 +489,14 @@ void CompilationDatabaseProject::reparseProject()
|
||||
m_parser->start();
|
||||
}
|
||||
|
||||
void CompilationDatabaseProject::updateDeploymentData()
|
||||
void CompilationDatabaseBuildSystem::updateDeploymentData()
|
||||
{
|
||||
Target * const target = activeTarget();
|
||||
if (!target)
|
||||
return;
|
||||
const Utils::FilePath deploymentFilePath = projectDirectory()
|
||||
.pathAppended("QtCreatorDeployment.txt");
|
||||
DeploymentData deploymentData;
|
||||
deploymentData.addFilesFromDeploymentFile(deploymentFilePath.toString(),
|
||||
projectDirectory().toString());
|
||||
target->setDeploymentData(deploymentData);
|
||||
setDeploymentData(deploymentData);
|
||||
if (m_deployFileWatcher->files() != QStringList(deploymentFilePath.toString())) {
|
||||
m_deployFileWatcher->removeFiles(m_deployFileWatcher->files());
|
||||
m_deployFileWatcher->addFile(deploymentFilePath.toString(),
|
||||
@@ -493,12 +504,6 @@ void CompilationDatabaseProject::updateDeploymentData()
|
||||
}
|
||||
}
|
||||
|
||||
CompilationDatabaseProject::~CompilationDatabaseProject()
|
||||
{
|
||||
m_parserWatcher.cancel();
|
||||
m_parserWatcher.waitForFinished();
|
||||
}
|
||||
|
||||
static TextEditor::TextDocument *createCompilationDatabaseDocument()
|
||||
{
|
||||
auto doc = new TextEditor::TextDocument;
|
||||
|
@@ -28,8 +28,11 @@
|
||||
#include "compilationdatabaseutils.h"
|
||||
|
||||
#include <projectexplorer/buildconfiguration.h>
|
||||
#include <projectexplorer/buildsystem.h>
|
||||
#include <projectexplorer/project.h>
|
||||
|
||||
#include <texteditor/texteditor.h>
|
||||
|
||||
#include <utils/filesystemwatcher.h>
|
||||
|
||||
#include <QFutureWatcher>
|
||||
@@ -52,20 +55,31 @@ class CompilationDatabaseProject : public ProjectExplorer::Project
|
||||
|
||||
public:
|
||||
explicit CompilationDatabaseProject(const Utils::FilePath &filename);
|
||||
~CompilationDatabaseProject() override;
|
||||
|
||||
bool needsConfiguration() const override { return false; }
|
||||
|
||||
Utils::FilePath rootPathFromSettings() const;
|
||||
ProjectExplorer::Kit *kit() const { return m_kit.get(); }
|
||||
|
||||
private:
|
||||
RestoreResult fromMap(const QVariantMap &map, QString *errorMessage) override;
|
||||
std::unique_ptr<ProjectExplorer::Kit> m_kit;
|
||||
};
|
||||
|
||||
class CompilationDatabaseBuildSystem : public ProjectExplorer::BuildSystem
|
||||
{
|
||||
public:
|
||||
explicit CompilationDatabaseBuildSystem(ProjectExplorer::Target *target);
|
||||
~CompilationDatabaseBuildSystem();
|
||||
|
||||
void triggerParsing() final;
|
||||
|
||||
void reparseProject();
|
||||
void updateDeploymentData();
|
||||
void buildTreeAndProjectParts();
|
||||
Utils::FilePath rootPathFromSettings() const;
|
||||
|
||||
QFutureWatcher<void> m_parserWatcher;
|
||||
std::unique_ptr<CppTools::CppProjectUpdater> m_cppCodeModelUpdater;
|
||||
std::unique_ptr<ProjectExplorer::Kit> m_kit;
|
||||
MimeBinaryCache m_mimeBinaryCache;
|
||||
QByteArray m_projectFileHash;
|
||||
QTimer * const m_parseDelay;
|
||||
|
@@ -48,7 +48,7 @@ CompilationDbParser::CompilationDbParser(const QString &projectName,
|
||||
const FilePath &projectPath,
|
||||
const FilePath &rootPath,
|
||||
MimeBinaryCache &mimeBinaryCache,
|
||||
ProjectExplorer::Project::ParseGuard &&guard,
|
||||
BuildSystem::ParseGuard &&guard,
|
||||
QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_projectName(projectName)
|
||||
|
@@ -27,7 +27,7 @@
|
||||
|
||||
#include "compilationdatabaseutils.h"
|
||||
|
||||
#include <projectexplorer/project.h>
|
||||
#include <projectexplorer/buildsystem.h>
|
||||
|
||||
#include <utils/fileutils.h>
|
||||
|
||||
@@ -56,7 +56,7 @@ public:
|
||||
const Utils::FilePath &projectPath,
|
||||
const Utils::FilePath &rootPath,
|
||||
MimeBinaryCache &mimeBinaryCache,
|
||||
ProjectExplorer::Project::ParseGuard &&guard,
|
||||
ProjectExplorer::BuildSystem::ParseGuard &&guard,
|
||||
QObject *parent = nullptr);
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ private:
|
||||
QByteArray m_projectFileContents;
|
||||
QByteArray m_projectFileHash;
|
||||
|
||||
ProjectExplorer::Project::ParseGuard m_guard;
|
||||
ProjectExplorer::BuildSystem::ParseGuard m_guard;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
@@ -27,15 +27,19 @@
|
||||
|
||||
#include <cpptools/cppmodelmanager.h>
|
||||
|
||||
#include <projectexplorer/buildsystem.h>
|
||||
#include <projectexplorer/project.h>
|
||||
#include <projectexplorer/projectexplorer.h>
|
||||
#include <projectexplorer/session.h>
|
||||
#include <projectexplorer/target.h>
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QDebug>
|
||||
|
||||
// Debug helpers for code model. @todo: Move to some CppTools library?
|
||||
|
||||
using namespace ProjectExplorer;
|
||||
|
||||
typedef QMap<QString, QStringList> DependencyMap;
|
||||
typedef CPlusPlus::Document::Ptr DocumentPtr;
|
||||
typedef QList<CPlusPlus::Symbol *> SymbolList;
|
||||
@@ -46,11 +50,15 @@ static const char setupUiC[] = "setupUi";
|
||||
// Find the generated "ui_form.h" header of the form via project.
|
||||
static QString generatedHeaderOf(const QString &uiFileName)
|
||||
{
|
||||
if (const ProjectExplorer::Project *uiProject =
|
||||
ProjectExplorer::SessionManager::projectForFile(Utils::FilePath::fromString(uiFileName))) {
|
||||
QStringList files = uiProject->filesGeneratedFrom(uiFileName);
|
||||
if (!files.isEmpty()) // There should be at most one header generated from a .ui
|
||||
return files.front();
|
||||
if (const Project *uiProject =
|
||||
SessionManager::projectForFile(Utils::FilePath::fromString(uiFileName))) {
|
||||
if (Target *t = uiProject->activeTarget()) {
|
||||
if (BuildSystem *bs = t->buildSystem()) {
|
||||
QStringList files = bs->filesGeneratedFrom(uiFileName);
|
||||
if (!files.isEmpty()) // There should be at most one header generated from a .ui
|
||||
return files.front();
|
||||
}
|
||||
}
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
@@ -120,9 +120,11 @@ private:
|
||||
class GenericBuildSystem : public BuildSystem
|
||||
{
|
||||
public:
|
||||
explicit GenericBuildSystem(Project *project);
|
||||
explicit GenericBuildSystem(Target *target);
|
||||
~GenericBuildSystem();
|
||||
|
||||
void triggerParsing() final;
|
||||
|
||||
bool supportsAction(Node *, ProjectAction action, const Node *) const final
|
||||
{
|
||||
return action == AddNewFile
|
||||
@@ -136,8 +138,6 @@ public:
|
||||
bool renameFile(Node *, const QString &filePath, const QString &newFilePath) final;
|
||||
bool addFiles(Node *, const QStringList &filePaths, QStringList *) final;
|
||||
|
||||
GenericProject *project() const { return static_cast<GenericProject *>(BuildSystem::project()); }
|
||||
|
||||
FilePath filesFilePath() const { return ::FilePath::fromString(m_filesFileName); }
|
||||
|
||||
void refresh(RefreshOptions options);
|
||||
@@ -172,7 +172,9 @@ private:
|
||||
|
||||
CppTools::CppProjectUpdaterInterface *m_cppCodeModelUpdater = nullptr;
|
||||
|
||||
Utils::FileSystemWatcher * const m_deployFileWatcher = nullptr;
|
||||
Utils::FileSystemWatcher m_deployFileWatcher;
|
||||
|
||||
ParseGuard m_guard;
|
||||
};
|
||||
|
||||
|
||||
@@ -194,11 +196,11 @@ GenericProject::GenericProject(const Utils::FilePath &fileName)
|
||||
setId(Constants::GENERICPROJECT_ID);
|
||||
setProjectLanguages(Context(ProjectExplorer::Constants::CXX_LANGUAGE_ID));
|
||||
setDisplayName(fileName.toFileInfo().completeBaseName());
|
||||
setBuildSystemCreator([](Project *p) { return new GenericBuildSystem(p); });
|
||||
setBuildSystemCreator([](Target *t) { return new GenericBuildSystem(t); });
|
||||
}
|
||||
|
||||
GenericBuildSystem::GenericBuildSystem(Project *project)
|
||||
: BuildSystem(project)
|
||||
GenericBuildSystem::GenericBuildSystem(Target *target)
|
||||
: BuildSystem(target)
|
||||
{
|
||||
QObject *projectUpdaterFactory = ExtensionSystem::PluginManager::getObjectByName(
|
||||
"CppProjectUpdaterFactory");
|
||||
@@ -211,7 +213,7 @@ GenericBuildSystem::GenericBuildSystem(Project *project)
|
||||
QTC_CHECK(successFullyCreatedProjectUpdater);
|
||||
}
|
||||
|
||||
connect(project, &Project::projectFileIsDirty, this, [this](const FilePath &p) {
|
||||
connect(target->project(), &Project::projectFileIsDirty, this, [this](const FilePath &p) {
|
||||
if (p.endsWith(".files"))
|
||||
refresh(Files);
|
||||
else if (p.endsWith(".includes") || p.endsWith(".config") || p.endsWith(".cxxflags")
|
||||
@@ -242,18 +244,16 @@ GenericBuildSystem::GenericBuildSystem(Project *project)
|
||||
QTC_CHECK(writeFile(m_cflagsFileName, Constants::GENERICPROJECT_CFLAGS_FILE_TEMPLATE));
|
||||
}
|
||||
|
||||
project->setExtraProjectFiles({FilePath::fromString(m_filesFileName),
|
||||
FilePath::fromString(m_includesFileName),
|
||||
FilePath::fromString(m_configFileName),
|
||||
FilePath::fromString(m_cxxflagsFileName),
|
||||
FilePath::fromString(m_cflagsFileName)});
|
||||
project()->setExtraProjectFiles({FilePath::fromString(m_filesFileName),
|
||||
FilePath::fromString(m_includesFileName),
|
||||
FilePath::fromString(m_configFileName),
|
||||
FilePath::fromString(m_cxxflagsFileName),
|
||||
FilePath::fromString(m_cflagsFileName)});
|
||||
|
||||
connect(m_deployFileWatcher, &FileSystemWatcher::fileChanged,
|
||||
connect(&m_deployFileWatcher, &FileSystemWatcher::fileChanged,
|
||||
this, &GenericBuildSystem::updateDeploymentData);
|
||||
|
||||
connect(project, &Project::activeTargetChanged, this, [this] { refresh(Everything); });
|
||||
|
||||
connect(project, &Project::activeBuildConfigurationChanged, this, [this] { refresh(Everything); });
|
||||
connect(target, &Target::activeBuildConfigurationChanged, this, [this] { refresh(Everything); });
|
||||
}
|
||||
|
||||
GenericBuildSystem::~GenericBuildSystem()
|
||||
@@ -261,6 +261,12 @@ GenericBuildSystem::~GenericBuildSystem()
|
||||
delete m_cppCodeModelUpdater;
|
||||
}
|
||||
|
||||
void GenericBuildSystem::triggerParsing()
|
||||
{
|
||||
m_guard = guardParsingRun();
|
||||
refresh(Everything);
|
||||
}
|
||||
|
||||
static QStringList readLines(const QString &absoluteFileName)
|
||||
{
|
||||
QStringList lines;
|
||||
@@ -455,7 +461,7 @@ FilePath GenericBuildSystem::findCommonSourceRoot()
|
||||
|
||||
void GenericBuildSystem::refresh(RefreshOptions options)
|
||||
{
|
||||
Project::ParseGuard guard = project()->guardParsingRun();
|
||||
ParseGuard guard = guardParsingRun();
|
||||
parse(options);
|
||||
|
||||
if (options & Files) {
|
||||
@@ -504,9 +510,7 @@ void GenericBuildSystem::refresh(RefreshOptions options)
|
||||
QStringList GenericBuildSystem::processEntries(const QStringList &paths,
|
||||
QHash<QString, QString> *map) const
|
||||
{
|
||||
Target *target = project()->activeTarget();
|
||||
const BuildConfiguration *const buildConfig = target ? target->activeBuildConfiguration()
|
||||
: nullptr;
|
||||
const BuildConfiguration *const buildConfig = target()->activeBuildConfiguration();
|
||||
|
||||
const Utils::Environment buildEnv = buildConfig ? buildConfig->environment()
|
||||
: Utils::Environment::systemEnvironment();
|
||||
@@ -514,8 +518,8 @@ QStringList GenericBuildSystem::processEntries(const QStringList &paths,
|
||||
const Utils::MacroExpander *expander = project()->macroExpander();
|
||||
if (buildConfig)
|
||||
expander = buildConfig->macroExpander();
|
||||
else if (target)
|
||||
expander = target->macroExpander();
|
||||
else
|
||||
expander = target()->macroExpander();
|
||||
|
||||
const QDir projectDir(projectDirectory().toString());
|
||||
|
||||
@@ -560,7 +564,7 @@ void GenericBuildSystem::refreshCppCodeModel()
|
||||
rpp.setFlagsForC({nullptr, m_cflags});
|
||||
rpp.setFiles(m_files);
|
||||
|
||||
m_cppCodeModelUpdater->update({project(), kitInfo, project()->activeParseEnvironment(), {rpp}});
|
||||
m_cppCodeModelUpdater->update({project(), kitInfo, activeParseEnvironment(), {rpp}});
|
||||
}
|
||||
|
||||
void GenericBuildSystem::updateDeploymentData()
|
||||
@@ -581,11 +585,11 @@ void GenericBuildSystem::updateDeploymentData()
|
||||
DeploymentData deploymentData;
|
||||
deploymentData.addFilesFromDeploymentFile(deploymentFilePath.toString(),
|
||||
projectDirectory().toString());
|
||||
project()->activeTarget()->setDeploymentData(deploymentData);
|
||||
if (m_deployFileWatcher->files() != QStringList(deploymentFilePath.toString())) {
|
||||
m_deployFileWatcher->removeFiles(m_deployFileWatcher->files());
|
||||
m_deployFileWatcher->addFile(deploymentFilePath.toString(),
|
||||
FileSystemWatcher::WatchModifiedDate);
|
||||
setDeploymentData(deploymentData);
|
||||
if (m_deployFileWatcher.files() != QStringList(deploymentFilePath.toString())) {
|
||||
m_deployFileWatcher.removeFiles(m_deployFileWatcher.files());
|
||||
m_deployFileWatcher.addFile(deploymentFilePath.toString(),
|
||||
FileSystemWatcher::WatchModifiedDate);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -622,7 +626,9 @@ Project::RestoreResult GenericProject::fromMap(const QVariantMap &map, QString *
|
||||
t->addRunConfiguration(new CustomExecutableRunConfiguration(t));
|
||||
}
|
||||
|
||||
static_cast<GenericBuildSystem *>(buildSystem())->refresh(Everything);
|
||||
if (Target *t = activeTarget())
|
||||
static_cast<GenericBuildSystem *>(t->buildSystem())->refresh(Everything);
|
||||
|
||||
return RestoreResult::Ok;
|
||||
}
|
||||
|
||||
@@ -637,7 +643,10 @@ bool GenericProjectFile::reload(QString *errorString, IDocument::ReloadFlag flag
|
||||
Q_UNUSED(flag)
|
||||
if (type == TypePermissions)
|
||||
return true;
|
||||
static_cast<GenericBuildSystem *>(m_project->buildSystem())->refresh(m_options);
|
||||
|
||||
if (Target *t = m_project->activeTarget())
|
||||
static_cast<GenericBuildSystem *>(t->buildSystem())->refresh(m_options);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -646,14 +655,18 @@ void GenericProject::editFilesTriggered()
|
||||
SelectableFilesDialogEditFiles sfd(projectDirectory(),
|
||||
files(Project::AllFiles),
|
||||
ICore::mainWindow());
|
||||
if (sfd.exec() == QDialog::Accepted)
|
||||
static_cast<GenericBuildSystem *>(buildSystem())
|
||||
->setFiles(transform(sfd.selectedFiles(), &FilePath::toString));
|
||||
if (sfd.exec() == QDialog::Accepted) {
|
||||
if (Target *t = activeTarget()) {
|
||||
auto bs = static_cast<GenericBuildSystem *>(t->buildSystem());
|
||||
bs->setFiles(transform(sfd.selectedFiles(), &FilePath::toString));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GenericProject::removeFilesTriggered(const QStringList &filesToRemove)
|
||||
{
|
||||
static_cast<GenericBuildSystem *>(buildSystem())->removeFiles(filesToRemove);
|
||||
if (Target *t = activeTarget())
|
||||
static_cast<GenericBuildSystem *>(t->buildSystem())->removeFiles(filesToRemove);
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
|
@@ -139,19 +139,17 @@ void IosRunConfiguration::updateDisplayNames()
|
||||
aspect<ExecutableAspect>()->setExecutable(localExecutable());
|
||||
}
|
||||
|
||||
void IosRunConfiguration::updateEnabledState()
|
||||
bool IosRunConfiguration::isEnabled() const
|
||||
{
|
||||
Core::Id devType = DeviceTypeKitAspect::deviceTypeId(target()->kit());
|
||||
if (devType != Constants::IOS_DEVICE_TYPE && devType != Constants::IOS_SIMULATOR_TYPE) {
|
||||
setEnabled(false);
|
||||
return;
|
||||
}
|
||||
if (devType != Constants::IOS_DEVICE_TYPE && devType != Constants::IOS_SIMULATOR_TYPE)
|
||||
return false;
|
||||
|
||||
IDevice::ConstPtr dev = DeviceKitAspect::device(target()->kit());
|
||||
if (dev.isNull() || dev->deviceState() != IDevice::DeviceReadyToUse) {
|
||||
setEnabled(false);
|
||||
return;
|
||||
}
|
||||
return RunConfiguration::updateEnabledState();
|
||||
if (dev.isNull() || dev->deviceState() != IDevice::DeviceReadyToUse)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QString IosRunConfiguration::applicationName() const
|
||||
|
@@ -55,7 +55,7 @@ public:
|
||||
private:
|
||||
friend class IosDeviceTypeAspect;
|
||||
void updateDisplayNames();
|
||||
void updateEnabledState() final;
|
||||
bool isEnabled() const final;
|
||||
|
||||
IosDeviceTypeAspect *m_deviceTypeAspect = nullptr;
|
||||
};
|
||||
|
@@ -40,10 +40,6 @@ const char C_EDITOR_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("OpenWith::Editors", "Nim
|
||||
const char C_NIMTOOLCHAIN_TYPEID[] = "Nim.NimToolChain";
|
||||
const char C_NIMTOOLCHAIN_COMPILER_COMMAND_KEY[] = "Nim.NimToolChain.CompilerCommand";
|
||||
|
||||
// NimbleProject
|
||||
const char C_NIMBLEPROJECT_TASKS[] = "Nim.NimbleProject.Tasks";
|
||||
const char C_NIMBLEPROJECT_METADATA[] = "Nim.NimbleProject.Metadata";
|
||||
|
||||
// NimProject
|
||||
const char C_NIMPROJECT_EXCLUDEDFILES[] = "Nim.NimProjectExcludedFiles";
|
||||
|
||||
|
@@ -24,9 +24,11 @@
|
||||
****************************************************************************/
|
||||
|
||||
#include "nimblebuildconfiguration.h"
|
||||
|
||||
#include "nimconstants.h"
|
||||
#include "nimblebuildstep.h"
|
||||
#include "nimbleproject.h"
|
||||
#include "nimblebuildsystem.h"
|
||||
|
||||
#include <projectexplorer/buildinfo.h>
|
||||
#include <projectexplorer/buildstep.h>
|
||||
@@ -52,10 +54,8 @@ NimbleBuildConfiguration::NimbleBuildConfiguration(Target *target, Core::Id id)
|
||||
setConfigWidgetHasFrame(true);
|
||||
setBuildDirectorySettingsKey("Nim.NimbleBuildConfiguration.BuildDirectory");
|
||||
|
||||
m_nimbleProject = dynamic_cast<NimbleProject*>(project());
|
||||
QTC_ASSERT(m_nimbleProject, return);
|
||||
QObject::connect(m_nimbleProject, &NimbleProject::metadataChanged, this, &NimbleBuildConfiguration::updateApplicationTargets);
|
||||
updateApplicationTargets();
|
||||
m_nimbleBuildSystem = dynamic_cast<NimbleBuildSystem *>(buildSystem());
|
||||
QTC_ASSERT(m_nimbleBuildSystem, return);
|
||||
}
|
||||
|
||||
BuildConfiguration::BuildType NimbleBuildConfiguration::buildType() const
|
||||
@@ -72,35 +72,13 @@ void NimbleBuildConfiguration::initialize()
|
||||
setBuildDirectory(project()->projectDirectory());
|
||||
|
||||
// Don't add a nimble build step when the package has no binaries (i.e a library package)
|
||||
if (!m_nimbleProject->metadata().bin.empty())
|
||||
if (!m_nimbleBuildSystem->metadata().bin.empty())
|
||||
{
|
||||
BuildStepList *buildSteps = stepList(ProjectExplorer::Constants::BUILDSTEPS_BUILD);
|
||||
buildSteps->appendStep(new NimbleBuildStep(buildSteps));
|
||||
}
|
||||
}
|
||||
|
||||
void NimbleBuildConfiguration::updateApplicationTargets()
|
||||
{
|
||||
QTC_ASSERT(m_nimbleProject, return);
|
||||
|
||||
const NimbleMetadata &metaData = m_nimbleProject->metadata();
|
||||
const FilePath &projectDir = project()->projectDirectory();
|
||||
const FilePath binDir = projectDir.pathAppended(metaData.binDir);
|
||||
const FilePath srcDir = projectDir.pathAppended("src");
|
||||
|
||||
QList<BuildTargetInfo> targets = Utils::transform(metaData.bin, [&](const QString &bin){
|
||||
BuildTargetInfo info = {};
|
||||
info.displayName = bin;
|
||||
info.targetFilePath = binDir.pathAppended(HostOsInfo::withExecutableSuffix(bin));
|
||||
info.projectFilePath = srcDir.pathAppended(bin).stringAppended(".nim");
|
||||
info.workingDirectory = binDir;
|
||||
info.buildKey = bin;
|
||||
return info;
|
||||
});
|
||||
|
||||
target()->setApplicationTargets(std::move(targets));
|
||||
}
|
||||
|
||||
bool NimbleBuildConfiguration::fromMap(const QVariantMap &map)
|
||||
{
|
||||
m_buildType = static_cast<BuildType>(map[Constants::C_NIMBLEBUILDCONFIGURATION_BUILDTYPE].toInt());
|
||||
|
@@ -30,7 +30,7 @@
|
||||
|
||||
namespace Nim {
|
||||
|
||||
class NimbleProject;
|
||||
class NimbleBuildSystem;
|
||||
|
||||
class NimbleBuildConfiguration : public ProjectExplorer::BuildConfiguration
|
||||
{
|
||||
@@ -49,10 +49,8 @@ class NimbleBuildConfiguration : public ProjectExplorer::BuildConfiguration
|
||||
protected:
|
||||
void initialize() override;
|
||||
|
||||
void updateApplicationTargets();
|
||||
|
||||
private:
|
||||
NimbleProject *m_nimbleProject = nullptr;
|
||||
NimbleBuildSystem *m_nimbleBuildSystem = nullptr;
|
||||
BuildType m_buildType;
|
||||
};
|
||||
|
||||
|
@@ -26,6 +26,8 @@
|
||||
#include "nimblebuildsystem.h"
|
||||
#include "nimbleproject.h"
|
||||
|
||||
#include <projectexplorer/target.h>
|
||||
|
||||
#include <utils/algorithm.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
@@ -38,6 +40,9 @@ using namespace Utils;
|
||||
|
||||
namespace {
|
||||
|
||||
const char C_NIMBLEPROJECT_TASKS[] = "Nim.NimbleProject.Tasks";
|
||||
const char C_NIMBLEPROJECT_METADATA[] = "Nim.NimbleProject.Metadata";
|
||||
|
||||
std::vector<NimbleTask> parseTasks(const QString &nimblePath, const QString &workingDirectory)
|
||||
{
|
||||
QProcess process;
|
||||
@@ -102,28 +107,25 @@ NimbleMetadata parseMetadata(const QString &nimblePath, const QString &workingDi
|
||||
|
||||
}
|
||||
|
||||
NimbleBuildSystem::NimbleBuildSystem(Project *project)
|
||||
: NimBuildSystem(project)
|
||||
NimbleBuildSystem::NimbleBuildSystem(Target *target)
|
||||
: NimBuildSystem(target)
|
||||
{
|
||||
// Not called in parseProject due to nimble behavior to create temporary
|
||||
// files in project directory. This creation in turn stimulate the fs watcher
|
||||
// that in turn causes project parsing (thus a loop if invoke in parseProject).
|
||||
// For this reason we call this function manually during project creation
|
||||
// See https://github.com/nim-lang/nimble/issues/720
|
||||
m_directoryWatcher.addFile(this->project()->projectFilePath().toString(),
|
||||
FileSystemWatcher::WatchModifiedDate);
|
||||
m_directoryWatcher.addFile(projectFilePath().toString(), FileSystemWatcher::WatchModifiedDate);
|
||||
|
||||
connect(&m_directoryWatcher, &FileSystemWatcher::fileChanged, this, [this](const QString &path) {
|
||||
if (path == this->project()->projectFilePath().toString()) {
|
||||
if (path == project()->projectFilePath().toString()) {
|
||||
updateProject();
|
||||
}
|
||||
});
|
||||
|
||||
updateProject();
|
||||
}
|
||||
|
||||
void NimbleBuildSystem::parseProject(BuildSystem::ParsingContext &&ctx)
|
||||
{
|
||||
NimBuildSystem::parseProject(std::move(ctx));
|
||||
}
|
||||
|
||||
void NimbleBuildSystem::updateProject()
|
||||
{
|
||||
@@ -133,14 +135,82 @@ void NimbleBuildSystem::updateProject()
|
||||
|
||||
void NimbleBuildSystem::updateProjectTasks()
|
||||
{
|
||||
auto prj = dynamic_cast<NimbleProject*>(project());
|
||||
QTC_ASSERT(prj, return);
|
||||
prj->setTasks(parseTasks(QStandardPaths::findExecutable("nimble"), project()->projectDirectory().toString()));
|
||||
setTasks(parseTasks(QStandardPaths::findExecutable("nimble"), projectDirectory().toString()));
|
||||
}
|
||||
|
||||
void NimbleBuildSystem::updateProjectMetaData()
|
||||
{
|
||||
auto prj = dynamic_cast<NimbleProject*>(project());
|
||||
QTC_ASSERT(prj, return);
|
||||
prj->setMetadata(parseMetadata(QStandardPaths::findExecutable("nimble"), project()->projectDirectory().toString()));
|
||||
setMetadata(parseMetadata(QStandardPaths::findExecutable("nimble"), projectDirectory().toString()));
|
||||
}
|
||||
|
||||
void NimbleBuildSystem::updateApplicationTargets()
|
||||
{
|
||||
const NimbleMetadata &metaData = metadata();
|
||||
const FilePath &projectDir = project()->projectDirectory();
|
||||
const FilePath binDir = projectDir.pathAppended(metaData.binDir);
|
||||
const FilePath srcDir = projectDir.pathAppended("src");
|
||||
|
||||
QList<BuildTargetInfo> targets = Utils::transform(metaData.bin, [&](const QString &bin){
|
||||
BuildTargetInfo info = {};
|
||||
info.displayName = bin;
|
||||
info.targetFilePath = binDir.pathAppended(HostOsInfo::withExecutableSuffix(bin));
|
||||
info.projectFilePath = srcDir.pathAppended(bin).stringAppended(".nim");
|
||||
info.workingDirectory = binDir;
|
||||
info.buildKey = bin;
|
||||
return info;
|
||||
});
|
||||
|
||||
setApplicationTargets(std::move(targets));
|
||||
}
|
||||
|
||||
std::vector<NimbleTask> NimbleBuildSystem::tasks() const
|
||||
{
|
||||
return m_tasks;
|
||||
}
|
||||
|
||||
NimbleMetadata NimbleBuildSystem::metadata() const
|
||||
{
|
||||
return m_metadata;
|
||||
}
|
||||
|
||||
void NimbleBuildSystem::setTasks(std::vector<NimbleTask> tasks)
|
||||
{
|
||||
if (tasks == m_tasks)
|
||||
return;
|
||||
m_tasks = std::move(tasks);
|
||||
emit tasksChanged();
|
||||
emit target()->targetPropertiesChanged();
|
||||
}
|
||||
|
||||
void NimbleBuildSystem::setMetadata(NimbleMetadata metadata)
|
||||
{
|
||||
if (m_metadata == metadata)
|
||||
return;
|
||||
m_metadata = std::move(metadata);
|
||||
|
||||
updateApplicationTargets();
|
||||
}
|
||||
|
||||
void NimbleBuildSystem::saveSettings()
|
||||
{
|
||||
QStringList result;
|
||||
for (const NimbleTask &task : m_tasks) {
|
||||
result.push_back(task.name);
|
||||
result.push_back(task.description);
|
||||
}
|
||||
|
||||
project()->setNamedSettings(C_NIMBLEPROJECT_TASKS, result);
|
||||
}
|
||||
|
||||
void NimbleBuildSystem::loadSettings()
|
||||
{
|
||||
QStringList list = project()->namedSettings(C_NIMBLEPROJECT_TASKS).toStringList();
|
||||
|
||||
m_tasks.clear();
|
||||
if (list.size() % 2 != 0)
|
||||
return;
|
||||
|
||||
std::vector<NimbleTask> result;
|
||||
for (int i = 0; i < list.size(); i += 2)
|
||||
result.push_back({list[i], list[i + 1]});
|
||||
}
|
||||
|
@@ -29,19 +29,55 @@
|
||||
|
||||
namespace Nim {
|
||||
|
||||
struct NimbleTask
|
||||
{
|
||||
QString name;
|
||||
QString description;
|
||||
|
||||
bool operator==(const NimbleTask &o) const {
|
||||
return name == o.name && description == o.description;
|
||||
}
|
||||
};
|
||||
|
||||
struct NimbleMetadata
|
||||
{
|
||||
QStringList bin;
|
||||
QString binDir;
|
||||
QString srcDir;
|
||||
|
||||
bool operator==(const NimbleMetadata &o) const {
|
||||
return bin == o.bin && binDir == o.binDir && srcDir == o.srcDir;
|
||||
}
|
||||
};
|
||||
|
||||
class NimbleBuildSystem : public NimBuildSystem
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
NimbleBuildSystem(ProjectExplorer::Project *project);
|
||||
NimbleBuildSystem(ProjectExplorer::Target *target);
|
||||
|
||||
protected:
|
||||
void parseProject(ParsingContext &&ctx) override;
|
||||
std::vector<NimbleTask> tasks() const;
|
||||
|
||||
NimbleMetadata metadata() const;
|
||||
|
||||
void setTasks(std::vector<NimbleTask> tasks);
|
||||
void setMetadata(NimbleMetadata metadata);
|
||||
|
||||
signals:
|
||||
void tasksChanged();
|
||||
|
||||
private:
|
||||
void loadSettings() override;
|
||||
void saveSettings() override;
|
||||
|
||||
void updateProject();
|
||||
void updateProjectTasks();
|
||||
void updateProjectMetaData();
|
||||
void updateApplicationTargets();
|
||||
|
||||
NimbleMetadata m_metadata;
|
||||
std::vector<NimbleTask> m_tasks;
|
||||
};
|
||||
|
||||
}
|
||||
|
@@ -41,70 +41,7 @@ NimbleProject::NimbleProject(const Utils::FilePath &fileName)
|
||||
setDisplayName(fileName.toFileInfo().completeBaseName());
|
||||
// ensure debugging is enabled (Nim plugin translates nim code to C code)
|
||||
setProjectLanguages(Core::Context(ProjectExplorer::Constants::CXX_LANGUAGE_ID));
|
||||
setBuildSystemCreator([] (Project *p) { return new NimbleBuildSystem(p); });
|
||||
setBuildSystemCreator([] (Target *t) { return new NimbleBuildSystem(t); });
|
||||
}
|
||||
|
||||
std::vector<NimbleTask> NimbleProject::tasks() const
|
||||
{
|
||||
return m_tasks;
|
||||
}
|
||||
|
||||
NimbleMetadata NimbleProject::metadata() const
|
||||
{
|
||||
return m_metadata;
|
||||
}
|
||||
|
||||
void NimbleProject::setTasks(std::vector<NimbleTask> tasks)
|
||||
{
|
||||
if (tasks == m_tasks)
|
||||
return;
|
||||
m_tasks = std::move(tasks);
|
||||
emit tasksChanged(m_tasks);
|
||||
}
|
||||
|
||||
void NimbleProject::setMetadata(NimbleMetadata metadata)
|
||||
{
|
||||
if (m_metadata == metadata)
|
||||
return;
|
||||
m_metadata = std::move(metadata);
|
||||
emit metadataChanged(m_metadata);
|
||||
}
|
||||
|
||||
QVariantMap NimbleProject::toMap() const
|
||||
{
|
||||
QVariantMap result = Project::toMap();
|
||||
result[Constants::C_NIMPROJECT_EXCLUDEDFILES] = static_cast<NimBuildSystem *>(buildSystem())
|
||||
->excludedFiles();
|
||||
result[Constants::C_NIMBLEPROJECT_TASKS] = toStringList(m_tasks);
|
||||
return result;
|
||||
}
|
||||
|
||||
Project::RestoreResult NimbleProject::fromMap(const QVariantMap &map, QString *errorMessage)
|
||||
{
|
||||
static_cast<NimBuildSystem *>(buildSystem())
|
||||
->setExcludedFiles(map.value(Constants::C_NIMPROJECT_EXCLUDEDFILES).toStringList());
|
||||
Project::RestoreResult result = Project::RestoreResult::Error;
|
||||
std::tie(result, m_tasks) = fromStringList(map.value(Constants::C_NIMBLEPROJECT_TASKS).toStringList());
|
||||
return result == Project::RestoreResult::Ok ? Project::fromMap(map, errorMessage) : result;
|
||||
}
|
||||
|
||||
QStringList NimbleProject::toStringList(const std::vector<NimbleTask> &tasks)
|
||||
{
|
||||
QStringList result;
|
||||
for (const NimbleTask &task : tasks) {
|
||||
result.push_back(task.name);
|
||||
result.push_back(task.description);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::tuple<Project::RestoreResult, std::vector<NimbleTask>> NimbleProject::fromStringList(const QStringList &list)
|
||||
{
|
||||
if (list.size() % 2 != 0)
|
||||
return std::make_tuple(Project::RestoreResult::Error, std::vector<NimbleTask>());
|
||||
|
||||
std::vector<NimbleTask> result;
|
||||
for (int i = 0; i < list.size(); i += 2)
|
||||
result.push_back({list[i], list[i + 1]});
|
||||
return std::make_tuple(Project::RestoreResult::Ok, result);
|
||||
}
|
||||
|
@@ -25,64 +25,17 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <projectexplorer/buildsystem.h>
|
||||
#include <projectexplorer/project.h>
|
||||
|
||||
namespace Nim {
|
||||
|
||||
struct NimbleTask
|
||||
{
|
||||
QString name;
|
||||
QString description;
|
||||
|
||||
bool operator==(const NimbleTask &o) const {
|
||||
return name == o.name && description == o.description;
|
||||
}
|
||||
};
|
||||
|
||||
struct NimbleMetadata
|
||||
{
|
||||
QStringList bin;
|
||||
QString binDir;
|
||||
QString srcDir;
|
||||
|
||||
bool operator==(const NimbleMetadata &o) const {
|
||||
return bin == o.bin && binDir == o.binDir && srcDir == o.srcDir;
|
||||
}
|
||||
};
|
||||
|
||||
class NimbleProject : public ProjectExplorer::Project
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
NimbleProject(const Utils::FilePath &filename);
|
||||
|
||||
std::vector<NimbleTask> tasks() const;
|
||||
|
||||
NimbleMetadata metadata() const;
|
||||
|
||||
void setTasks(std::vector<NimbleTask> tasks);
|
||||
|
||||
void setMetadata(NimbleMetadata metadata);
|
||||
|
||||
// Keep for compatibility with Qt Creator 4.10
|
||||
QVariantMap toMap() const final;
|
||||
|
||||
signals:
|
||||
void tasksChanged(std::vector<NimbleTask>);
|
||||
void metadataChanged(NimbleMetadata);
|
||||
|
||||
protected:
|
||||
// Keep for compatibility with Qt Creator 4.10
|
||||
RestoreResult fromMap(const QVariantMap &map, QString *errorMessage) final;
|
||||
|
||||
private:
|
||||
static QStringList toStringList(const std::vector<NimbleTask> &tasks);
|
||||
|
||||
static std::tuple<RestoreResult, std::vector<NimbleTask>> fromStringList(const QStringList &list);
|
||||
|
||||
NimbleMetadata m_metadata;
|
||||
std::vector<NimbleTask> m_tasks;
|
||||
};
|
||||
|
||||
}
|
||||
|
@@ -43,20 +43,15 @@ using namespace ProjectExplorer;
|
||||
NimbleRunConfiguration::NimbleRunConfiguration(ProjectExplorer::Target *target, Core::Id id)
|
||||
: RunConfiguration(target, id)
|
||||
{
|
||||
auto project = dynamic_cast<NimbleProject*>(target->project());
|
||||
QTC_ASSERT(project, return);
|
||||
|
||||
addAspect<LocalEnvironmentAspect>(target);
|
||||
addAspect<ExecutableAspect>();
|
||||
addAspect<ArgumentsAspect>();
|
||||
addAspect<WorkingDirectoryAspect>();
|
||||
addAspect<TerminalAspect>();
|
||||
|
||||
connect(project, &Project::parsingFinished,
|
||||
connect(target, &Target::parsingFinished,
|
||||
this, &NimbleRunConfiguration::updateTargetInformation);
|
||||
connect(project, &NimbleProject::metadataChanged,
|
||||
this, &NimbleRunConfiguration::updateTargetInformation);
|
||||
connect(project, &NimbleProject::tasksChanged,
|
||||
connect(target, &Target::targetPropertiesChanged,
|
||||
this, &NimbleRunConfiguration::updateTargetInformation);
|
||||
|
||||
updateTargetInformation();
|
||||
@@ -85,14 +80,6 @@ QString NimbleRunConfiguration::disabledReason() const
|
||||
return RunConfiguration::disabledReason();
|
||||
}
|
||||
|
||||
void NimbleRunConfiguration::updateEnabledState()
|
||||
{
|
||||
if (!isBuildTargetValid())
|
||||
setEnabled(false);
|
||||
else
|
||||
RunConfiguration::updateEnabledState();
|
||||
}
|
||||
|
||||
NimbleRunConfigurationFactory::NimbleRunConfigurationFactory()
|
||||
: RunConfigurationFactory()
|
||||
{
|
||||
|
@@ -38,9 +38,6 @@ public:
|
||||
|
||||
QString disabledReason() const override;
|
||||
|
||||
protected:
|
||||
void updateEnabledState() override;
|
||||
|
||||
private:
|
||||
void updateTargetInformation();
|
||||
|
||||
|
@@ -104,10 +104,10 @@ bool NimbleTaskStep::validate()
|
||||
if (m_taskName.isEmpty())
|
||||
return true;
|
||||
|
||||
auto nimbleProject = dynamic_cast<NimbleProject*>(project());
|
||||
QTC_ASSERT(nimbleProject, return false);
|
||||
auto nimbleBuildSystem = dynamic_cast<NimbleBuildSystem*>(buildSystem());
|
||||
QTC_ASSERT(nimbleBuildSystem, return false);
|
||||
|
||||
if (!Utils::contains(nimbleProject->tasks(), [this](const NimbleTask &task){ return task.name == m_taskName; })) {
|
||||
if (!Utils::contains(nimbleBuildSystem->tasks(), [this](const NimbleTask &task){ return task.name == m_taskName; })) {
|
||||
emit addTask(Task(Task::Error,
|
||||
tr("Nimble task %1 not found").arg(m_taskName),
|
||||
Utils::FilePath(), -1,
|
||||
|
@@ -40,14 +40,14 @@ NimbleTaskStepWidget::NimbleTaskStepWidget(NimbleTaskStep *bs)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
auto project = dynamic_cast<NimbleProject*>(bs->project());
|
||||
QTC_ASSERT(project, return);
|
||||
auto buildSystem = dynamic_cast<NimbleBuildSystem *>(bs->buildSystem());
|
||||
QTC_ASSERT(buildSystem, return);
|
||||
|
||||
ui->taskList->setModel(&m_tasks);
|
||||
QObject::connect(&m_tasks, &QAbstractItemModel::dataChanged, this, &NimbleTaskStepWidget::onDataChanged);
|
||||
|
||||
updateTaskList(project->tasks());
|
||||
QObject::connect(project, &NimbleProject::tasksChanged, this, &NimbleTaskStepWidget::updateTaskList);
|
||||
updateTaskList();
|
||||
QObject::connect(buildSystem, &NimbleBuildSystem::tasksChanged, this, &NimbleTaskStepWidget::updateTaskList);
|
||||
|
||||
selectTask(bs->taskName());
|
||||
QObject::connect(bs, &NimbleTaskStep::taskNameChanged, this, &NimbleTaskStepWidget::selectTask);
|
||||
@@ -73,8 +73,12 @@ NimbleTaskStepWidget::~NimbleTaskStepWidget()
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void NimbleTaskStepWidget::updateTaskList(const std::vector<NimbleTask> &tasks)
|
||||
void NimbleTaskStepWidget::updateTaskList()
|
||||
{
|
||||
auto buildSystem = dynamic_cast<NimbleBuildSystem *>(step()->buildSystem());
|
||||
QTC_ASSERT(buildSystem, return);
|
||||
const std::vector<NimbleTask> &tasks = buildSystem->tasks();
|
||||
|
||||
QSet<QString> newTasks;
|
||||
for (const NimbleTask &t : tasks)
|
||||
newTasks.insert(t.name);
|
||||
|
@@ -28,6 +28,7 @@
|
||||
#include <projectexplorer/buildstep.h>
|
||||
|
||||
#include <nim/project/nimbleproject.h>
|
||||
#include <nim/project/nimblebuildsystem.h>
|
||||
|
||||
#include <QStandardItemModel>
|
||||
|
||||
@@ -50,7 +51,7 @@ signals:
|
||||
void selectedTaskChanged(const QString &name);
|
||||
|
||||
private:
|
||||
void updateTaskList(const std::vector<NimbleTask> &tasks);
|
||||
void updateTaskList();
|
||||
|
||||
void selectTask(const QString &name);
|
||||
|
||||
|
@@ -78,7 +78,7 @@ void NimBuildConfiguration::initialize()
|
||||
{
|
||||
BuildConfiguration::initialize();
|
||||
|
||||
auto bs = qobject_cast<NimBuildSystem *>(project()->buildSystem());
|
||||
auto bs = qobject_cast<NimBuildSystem *>(buildSystem());
|
||||
QTC_ASSERT(bs, return );
|
||||
|
||||
// Create the build configuration and initialize it from build info
|
||||
|
@@ -25,9 +25,12 @@
|
||||
|
||||
#include "nimbuildsystem.h"
|
||||
|
||||
#include "nimproject.h"
|
||||
#include "nimbleproject.h"
|
||||
#include "nimprojectnode.h"
|
||||
|
||||
#include <projectexplorer/target.h>
|
||||
|
||||
#include <utils/algorithm.h>
|
||||
#include <utils/fileutils.h>
|
||||
#include <utils/qtcassert.h>
|
||||
@@ -42,11 +45,11 @@ namespace Nim {
|
||||
const char SETTINGS_KEY[] = "Nim.BuildSystem";
|
||||
const char EXCLUDED_FILES_KEY[] = "ExcludedFiles";
|
||||
|
||||
NimBuildSystem::NimBuildSystem(Project *project)
|
||||
: BuildSystem(project)
|
||||
NimBuildSystem::NimBuildSystem(Target *target)
|
||||
: BuildSystem(target)
|
||||
{
|
||||
connect(project, &Project::settingsLoaded, this, &NimBuildSystem::loadSettings);
|
||||
connect(project, &Project::aboutToSaveSettings, this, &NimBuildSystem::saveSettings);
|
||||
connect(target->project(), &Project::settingsLoaded, this, &NimBuildSystem::loadSettings);
|
||||
connect(target->project(), &Project::aboutToSaveSettings, this, &NimBuildSystem::saveSettings);
|
||||
|
||||
connect(&m_scanner, &TreeScanner::finished, this, &NimBuildSystem::updateProject);
|
||||
m_scanner.setFilter([this](const Utils::MimeType &, const Utils::FilePath &fp) {
|
||||
@@ -64,17 +67,16 @@ NimBuildSystem::NimBuildSystem(Project *project)
|
||||
|
||||
bool NimBuildSystem::addFiles(const QStringList &filePaths)
|
||||
{
|
||||
m_excludedFiles = Utils::filtered(m_excludedFiles, [&](const QString & f) {
|
||||
setExcludedFiles(Utils::filtered(excludedFiles(), [&](const QString & f) {
|
||||
return !filePaths.contains(f);
|
||||
});
|
||||
}));
|
||||
requestParse();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NimBuildSystem::removeFiles(const QStringList &filePaths)
|
||||
{
|
||||
m_excludedFiles.append(filePaths);
|
||||
m_excludedFiles = Utils::filteredUnique(m_excludedFiles);
|
||||
setExcludedFiles(Utils::filteredUnique(excludedFiles() + filePaths));
|
||||
requestParse();
|
||||
return true;
|
||||
}
|
||||
@@ -82,27 +84,27 @@ bool NimBuildSystem::removeFiles(const QStringList &filePaths)
|
||||
bool NimBuildSystem::renameFile(const QString &filePath, const QString &newFilePath)
|
||||
{
|
||||
Q_UNUSED(filePath)
|
||||
m_excludedFiles.removeOne(newFilePath);
|
||||
QStringList files = excludedFiles();
|
||||
files.removeOne(newFilePath);
|
||||
setExcludedFiles(files);
|
||||
requestParse();
|
||||
return true;
|
||||
}
|
||||
|
||||
void NimBuildSystem::setExcludedFiles(const QStringList &list)
|
||||
{
|
||||
m_excludedFiles = list;
|
||||
static_cast<NimProject *>(project())->setExcludedFiles(list);
|
||||
}
|
||||
|
||||
QStringList NimBuildSystem::excludedFiles()
|
||||
{
|
||||
return m_excludedFiles;
|
||||
return static_cast<NimProject *>(project())->excludedFiles();
|
||||
}
|
||||
|
||||
void NimBuildSystem::parseProject(BuildSystem::ParsingContext &&ctx)
|
||||
void NimBuildSystem::triggerParsing()
|
||||
{
|
||||
QTC_ASSERT(!m_currentContext.project, return );
|
||||
m_currentContext = std::move(ctx);
|
||||
QTC_CHECK(m_currentContext.project);
|
||||
m_scanner.asyncScanForFiles(m_currentContext.project->projectDirectory());
|
||||
m_guard = guardParsingRun();
|
||||
m_scanner.asyncScanForFiles(projectDirectory());
|
||||
}
|
||||
|
||||
const FilePathList NimBuildSystem::nimFiles() const
|
||||
@@ -116,7 +118,7 @@ void NimBuildSystem::loadSettings()
|
||||
{
|
||||
QVariantMap settings = project()->namedSettings(SETTINGS_KEY).toMap();
|
||||
if (settings.contains(EXCLUDED_FILES_KEY))
|
||||
m_excludedFiles = settings.value(EXCLUDED_FILES_KEY, m_excludedFiles).toStringList();
|
||||
setExcludedFiles(settings.value(EXCLUDED_FILES_KEY, excludedFiles()).toStringList());
|
||||
|
||||
requestParse();
|
||||
}
|
||||
@@ -124,7 +126,7 @@ void NimBuildSystem::loadSettings()
|
||||
void NimBuildSystem::saveSettings()
|
||||
{
|
||||
QVariantMap settings;
|
||||
settings.insert(EXCLUDED_FILES_KEY, m_excludedFiles);
|
||||
settings.insert(EXCLUDED_FILES_KEY, excludedFiles());
|
||||
project()->setNamedSettings(SETTINGS_KEY, settings);
|
||||
}
|
||||
|
||||
@@ -156,8 +158,8 @@ void NimBuildSystem::updateProject()
|
||||
}
|
||||
|
||||
// Complete scan
|
||||
m_currentContext.guard.markAsSuccess();
|
||||
m_currentContext = {};
|
||||
m_guard.markAsSuccess();
|
||||
m_guard = {}; // Trigger destructor of previous object, emitting parsingFinished()
|
||||
}
|
||||
|
||||
bool NimBuildSystem::supportsAction(Node *context, ProjectAction action, const Node *node) const
|
||||
|
@@ -37,7 +37,7 @@ class NimBuildSystem : public ProjectExplorer::BuildSystem
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit NimBuildSystem(ProjectExplorer::Project *project);
|
||||
explicit NimBuildSystem(ProjectExplorer::Target *target);
|
||||
|
||||
bool addFiles(const QStringList &filePaths);
|
||||
bool removeFiles(const QStringList &filePaths);
|
||||
@@ -58,22 +58,20 @@ public:
|
||||
void setExcludedFiles(const QStringList &list); // Keep for compatibility with Qt Creator 4.10
|
||||
QStringList excludedFiles(); // Make private when no longer supporting Qt Creator 4.10
|
||||
|
||||
void parseProject(ParsingContext &&ctx) override;
|
||||
void triggerParsing();
|
||||
|
||||
const Utils::FilePathList nimFiles() const;
|
||||
|
||||
protected:
|
||||
void loadSettings();
|
||||
void saveSettings();
|
||||
virtual void loadSettings();
|
||||
virtual void saveSettings();
|
||||
|
||||
void collectProjectFiles();
|
||||
void updateProject();
|
||||
|
||||
QStringList m_excludedFiles;
|
||||
|
||||
ProjectExplorer::TreeScanner m_scanner;
|
||||
|
||||
ParsingContext m_currentContext;
|
||||
ParseGuard m_guard;
|
||||
|
||||
Utils::FileSystemWatcher m_directoryWatcher;
|
||||
};
|
||||
|
@@ -271,8 +271,8 @@ void NimCompilerBuildStep::updateTargetNimFile()
|
||||
{
|
||||
if (!m_targetNimFile.isEmpty())
|
||||
return;
|
||||
const Utils::FilePathList nimFiles = static_cast<NimBuildSystem *>(project()->buildSystem())
|
||||
->nimFiles();
|
||||
const Utils::FilePathList nimFiles =
|
||||
static_cast<NimBuildSystem *>(buildConfiguration()->buildSystem())->nimFiles();
|
||||
if (!nimFiles.isEmpty())
|
||||
setTargetNimFile(nimFiles.at(0));
|
||||
}
|
||||
|
@@ -116,7 +116,7 @@ void NimCompilerBuildStepConfigWidget::updateTargetComboBox()
|
||||
{
|
||||
QTC_ASSERT(m_buildStep, return );
|
||||
|
||||
const auto bs = qobject_cast<NimBuildSystem *>(m_buildStep->project()->buildSystem());
|
||||
const auto bs = qobject_cast<NimBuildSystem *>(m_buildStep->buildConfiguration()->buildSystem());
|
||||
QTC_ASSERT(bs, return );
|
||||
|
||||
// Re enter the files
|
||||
|
@@ -45,7 +45,7 @@ NimProject::NimProject(const FilePath &fileName) : Project(Constants::C_NIM_MIME
|
||||
// ensure debugging is enabled (Nim plugin translates nim code to C code)
|
||||
setProjectLanguages(Core::Context(ProjectExplorer::Constants::CXX_LANGUAGE_ID));
|
||||
|
||||
setBuildSystemCreator([](Project *p) { return new NimBuildSystem(p); });
|
||||
setBuildSystemCreator([](Target *t) { return new NimBuildSystem(t); });
|
||||
}
|
||||
|
||||
Tasks NimProject::projectIssues(const Kit *k) const
|
||||
@@ -65,17 +65,25 @@ Tasks NimProject::projectIssues(const Kit *k) const
|
||||
QVariantMap NimProject::toMap() const
|
||||
{
|
||||
QVariantMap result = Project::toMap();
|
||||
result[Constants::C_NIMPROJECT_EXCLUDEDFILES] = static_cast<NimBuildSystem *>(buildSystem())
|
||||
->excludedFiles();
|
||||
result[Constants::C_NIMPROJECT_EXCLUDEDFILES] = m_excludedFiles;
|
||||
return result;
|
||||
}
|
||||
|
||||
Project::RestoreResult NimProject::fromMap(const QVariantMap &map, QString *errorMessage)
|
||||
{
|
||||
auto result = Project::fromMap(map, errorMessage);
|
||||
static_cast<NimBuildSystem *>(buildSystem())
|
||||
->setExcludedFiles(map.value(Constants::C_NIMPROJECT_EXCLUDEDFILES).toStringList());
|
||||
m_excludedFiles = map.value(Constants::C_NIMPROJECT_EXCLUDEDFILES).toStringList();
|
||||
return result;
|
||||
}
|
||||
|
||||
QStringList NimProject::excludedFiles() const
|
||||
{
|
||||
return m_excludedFiles;
|
||||
}
|
||||
|
||||
void NimProject::setExcludedFiles(const QStringList &excludedFiles)
|
||||
{
|
||||
m_excludedFiles = excludedFiles;
|
||||
}
|
||||
|
||||
} // namespace Nim
|
||||
|
@@ -48,9 +48,14 @@ public:
|
||||
// Keep for compatibility with Qt Creator 4.10
|
||||
QVariantMap toMap() const final;
|
||||
|
||||
QStringList excludedFiles() const;
|
||||
void setExcludedFiles(const QStringList &excludedFiles);
|
||||
|
||||
protected:
|
||||
// Keep for compatibility with Qt Creator 4.10
|
||||
RestoreResult fromMap(const QVariantMap &map, QString *errorMessage) final;
|
||||
|
||||
QStringList m_excludedFiles;
|
||||
};
|
||||
|
||||
} // namespace Nim
|
||||
|
@@ -28,6 +28,8 @@
|
||||
#include "buildenvironmentwidget.h"
|
||||
#include "buildinfo.h"
|
||||
#include "buildsteplist.h"
|
||||
#include "buildstepspage.h"
|
||||
#include "buildsystem.h"
|
||||
#include "namedwidget.h"
|
||||
#include "kit.h"
|
||||
#include "kitinformation.h"
|
||||
@@ -89,6 +91,7 @@ BuildConfiguration::BuildConfiguration(Target *target, Core::Id id)
|
||||
: ProjectConfiguration(target, id), d(new Internal::BuildConfigurationPrivate)
|
||||
{
|
||||
QTC_CHECK(target && target == this->target());
|
||||
|
||||
Utils::MacroExpander *expander = macroExpander();
|
||||
expander->setDisplayName(tr("Build Settings"));
|
||||
expander->setAccumulating(true);
|
||||
@@ -128,8 +131,8 @@ BuildConfiguration::BuildConfiguration(Target *target, Core::Id id)
|
||||
this->target()->buildEnvironmentChanged(this);
|
||||
});
|
||||
|
||||
connect(project(), &Project::parsingStarted, this, &BuildConfiguration::enabledChanged);
|
||||
connect(project(), &Project::parsingFinished, this, &BuildConfiguration::enabledChanged);
|
||||
connect(target, &Target::parsingStarted, this, &BuildConfiguration::enabledChanged);
|
||||
connect(target, &Target::parsingFinished, this, &BuildConfiguration::enabledChanged);
|
||||
|
||||
connect(this, &BuildConfiguration::enabledChanged, this, [this] {
|
||||
if (isActive() && project() == SessionManager::startupProject()) {
|
||||
@@ -164,6 +167,19 @@ void BuildConfiguration::setBuildDirectory(const Utils::FilePath &dir)
|
||||
emitBuildDirectoryChanged();
|
||||
}
|
||||
|
||||
void BuildConfiguration::addConfigWidgets(const std::function<void(NamedWidget *)> &adder)
|
||||
{
|
||||
if (NamedWidget *generalConfigWidget = createConfigWidget())
|
||||
adder(generalConfigWidget);
|
||||
|
||||
adder(new Internal::BuildStepListWidget(stepList(Constants::BUILDSTEPS_BUILD)));
|
||||
adder(new Internal::BuildStepListWidget(stepList(Constants::BUILDSTEPS_CLEAN)));
|
||||
|
||||
QList<NamedWidget *> subConfigWidgets = createSubConfigWidgets();
|
||||
foreach (NamedWidget *subConfigWidget, subConfigWidgets)
|
||||
adder(subConfigWidget);
|
||||
}
|
||||
|
||||
NamedWidget *BuildConfiguration::createConfigWidget()
|
||||
{
|
||||
NamedWidget *named = new NamedWidget(d->m_configWidgetDisplayName);
|
||||
@@ -203,6 +219,12 @@ QList<NamedWidget *> BuildConfiguration::createSubConfigWidgets()
|
||||
return {new BuildEnvironmentWidget(this)};
|
||||
}
|
||||
|
||||
BuildSystem *BuildConfiguration::buildSystem() const
|
||||
{
|
||||
QTC_CHECK(target()->fallbackBuildSystem());
|
||||
return target()->fallbackBuildSystem();
|
||||
}
|
||||
|
||||
QList<Core::Id> BuildConfiguration::knownStepLists() const
|
||||
{
|
||||
return Utils::transform(d->m_stepLists, &BuildStepList::id);
|
||||
@@ -368,14 +390,14 @@ void BuildConfiguration::setUserEnvironmentChanges(const Utils::EnvironmentItems
|
||||
|
||||
bool BuildConfiguration::isEnabled() const
|
||||
{
|
||||
return !project()->isParsing() && project()->hasParsingData();
|
||||
return !buildSystem()->isParsing() && buildSystem()->hasParsingData();
|
||||
}
|
||||
|
||||
QString BuildConfiguration::disabledReason() const
|
||||
{
|
||||
if (project()->isParsing())
|
||||
if (buildSystem()->isParsing())
|
||||
return (tr("The project is currently being parsed."));
|
||||
if (!project()->hasParsingData())
|
||||
if (!buildSystem()->hasParsingData())
|
||||
return (tr("The project was not parsed successfully."));
|
||||
return QString();
|
||||
}
|
||||
|
@@ -38,6 +38,7 @@ namespace Internal { class BuildConfigurationPrivate; }
|
||||
|
||||
class BaseStringAspect;
|
||||
class BuildInfo;
|
||||
class BuildSystem;
|
||||
class BuildStepList;
|
||||
class Kit;
|
||||
class NamedWidget;
|
||||
@@ -59,6 +60,8 @@ public:
|
||||
Utils::FilePath rawBuildDirectory() const;
|
||||
void setBuildDirectory(const Utils::FilePath &dir);
|
||||
|
||||
virtual BuildSystem *buildSystem() const;
|
||||
|
||||
virtual NamedWidget *createConfigWidget();
|
||||
virtual QList<NamedWidget *> createSubConfigWidgets();
|
||||
|
||||
@@ -110,6 +113,8 @@ public:
|
||||
void setConfigWidgetHasFrame(bool configWidgetHasFrame);
|
||||
void setBuildDirectorySettingsKey(const QString &key);
|
||||
|
||||
void addConfigWidgets(const std::function<void (NamedWidget *)> &adder);
|
||||
|
||||
signals:
|
||||
void environmentChanged();
|
||||
void buildDirectoryChanged();
|
||||
|
@@ -139,6 +139,7 @@ BuildSettingsWidget::BuildSettingsWidget(Target *target) :
|
||||
|
||||
void BuildSettingsWidget::addSubWidget(NamedWidget *widget)
|
||||
{
|
||||
widget->setParent(this);
|
||||
widget->setContentsMargins(0, 10, 0, 0);
|
||||
|
||||
auto label = new QLabel(this);
|
||||
@@ -192,23 +193,8 @@ void BuildSettingsWidget::updateBuildSettings()
|
||||
m_renameButton->setEnabled(!bcs.isEmpty());
|
||||
m_cloneButton->setEnabled(!bcs.isEmpty());
|
||||
|
||||
if (!m_buildConfiguration)
|
||||
return;
|
||||
|
||||
// Add pages
|
||||
NamedWidget *generalConfigWidget = m_buildConfiguration->createConfigWidget();
|
||||
if (generalConfigWidget)
|
||||
addSubWidget(generalConfigWidget);
|
||||
|
||||
BuildStepList *buildSteps = m_buildConfiguration->stepList(Constants::BUILDSTEPS_BUILD);
|
||||
addSubWidget(new BuildStepListWidget(buildSteps, this));
|
||||
|
||||
BuildStepList *cleanSteps = m_buildConfiguration->stepList(Constants::BUILDSTEPS_CLEAN);
|
||||
addSubWidget(new BuildStepListWidget(cleanSteps, this));
|
||||
|
||||
QList<NamedWidget *> subConfigWidgets = m_buildConfiguration->createSubConfigWidgets();
|
||||
foreach (NamedWidget *subConfigWidget, subConfigWidgets)
|
||||
addSubWidget(subConfigWidget);
|
||||
if (m_buildConfiguration)
|
||||
m_buildConfiguration->addConfigWidgets([this](NamedWidget *w) { addSubWidget(w); });
|
||||
}
|
||||
|
||||
void BuildSettingsWidget::currentIndexChanged(int index)
|
||||
|
@@ -204,6 +204,13 @@ ProjectConfiguration *BuildStep::projectConfiguration() const
|
||||
return static_cast<ProjectConfiguration *>(parent()->parent());
|
||||
}
|
||||
|
||||
BuildSystem *BuildStep::buildSystem() const
|
||||
{
|
||||
if (auto bc = buildConfiguration())
|
||||
return bc->buildSystem();
|
||||
return target()->buildSystem();
|
||||
}
|
||||
|
||||
void BuildStep::reportRunResult(QFutureInterface<bool> &fi, bool success)
|
||||
{
|
||||
fi.reportResult(success);
|
||||
|
@@ -44,6 +44,7 @@ class BuildConfiguration;
|
||||
class BuildStepConfigWidget;
|
||||
class BuildStepFactory;
|
||||
class BuildStepList;
|
||||
class BuildSystem;
|
||||
class DeployConfiguration;
|
||||
class Target;
|
||||
class Task;
|
||||
@@ -75,6 +76,8 @@ public:
|
||||
DeployConfiguration *deployConfiguration() const;
|
||||
ProjectConfiguration *projectConfiguration() const;
|
||||
|
||||
BuildSystem *buildSystem() const;
|
||||
|
||||
enum class OutputFormat {
|
||||
Stdout, Stderr, // These are for forwarded output from external tools
|
||||
NormalMessage, ErrorMessage // These are for messages from Creator itself
|
||||
|
@@ -191,9 +191,9 @@ BuildStepsWidgetData::~BuildStepsWidgetData()
|
||||
// We do not own the step
|
||||
}
|
||||
|
||||
BuildStepListWidget::BuildStepListWidget(BuildStepList *bsl, QWidget *parent)
|
||||
BuildStepListWidget::BuildStepListWidget(BuildStepList *bsl)
|
||||
//: %1 is the name returned by BuildStepList::displayName
|
||||
: NamedWidget(tr("%1 Steps").arg(bsl->displayName()), parent), m_buildStepList(bsl)
|
||||
: NamedWidget(tr("%1 Steps").arg(bsl->displayName())), m_buildStepList(bsl)
|
||||
{
|
||||
setupUi();
|
||||
|
||||
|
@@ -97,7 +97,7 @@ class BuildStepListWidget : public NamedWidget
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
BuildStepListWidget(BuildStepList *bsl, QWidget *parent = nullptr);
|
||||
explicit BuildStepListWidget(BuildStepList *bsl);
|
||||
~BuildStepListWidget() override;
|
||||
|
||||
private:
|
||||
|
@@ -26,10 +26,14 @@
|
||||
#include "buildsystem.h"
|
||||
|
||||
#include "buildconfiguration.h"
|
||||
#include "runconfiguration.h"
|
||||
#include "runcontrol.h"
|
||||
#include "target.h"
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QTimer>
|
||||
|
||||
using namespace Utils;
|
||||
|
||||
namespace ProjectExplorer {
|
||||
@@ -38,77 +42,129 @@ namespace ProjectExplorer {
|
||||
// BuildSystem:
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
BuildSystem::BuildSystem(Project *project)
|
||||
: m_project(project)
|
||||
class BuildSystemPrivate
|
||||
{
|
||||
QTC_CHECK(project);
|
||||
public:
|
||||
Target *m_target = nullptr;
|
||||
BuildConfiguration *m_buildConfiguration = nullptr;
|
||||
|
||||
QTimer m_delayedParsingTimer;
|
||||
|
||||
bool m_isParsing = false;
|
||||
bool m_hasParsingData = false;
|
||||
|
||||
DeploymentData m_deploymentData;
|
||||
QList<BuildTargetInfo> m_appTargets;
|
||||
};
|
||||
|
||||
BuildSystem::BuildSystem(BuildConfiguration *bc)
|
||||
: BuildSystem(bc->target())
|
||||
{
|
||||
d->m_buildConfiguration = bc;
|
||||
}
|
||||
|
||||
BuildSystem::BuildSystem(Target *target)
|
||||
: d(new BuildSystemPrivate)
|
||||
{
|
||||
QTC_CHECK(target);
|
||||
d->m_target = target;
|
||||
|
||||
// Timer:
|
||||
m_delayedParsingTimer.setSingleShot(true);
|
||||
d->m_delayedParsingTimer.setSingleShot(true);
|
||||
|
||||
connect(&m_delayedParsingTimer, &QTimer::timeout, this, &BuildSystem::triggerParsing);
|
||||
connect(&d->m_delayedParsingTimer, &QTimer::timeout, this, &BuildSystem::triggerParsing);
|
||||
}
|
||||
|
||||
BuildSystem::~BuildSystem()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
Project *BuildSystem::project() const
|
||||
{
|
||||
return m_project;
|
||||
return d->m_target->project();
|
||||
}
|
||||
|
||||
Target *BuildSystem::target() const
|
||||
{
|
||||
return d->m_target;
|
||||
}
|
||||
|
||||
void BuildSystem::emitParsingStarted()
|
||||
{
|
||||
QTC_ASSERT(!d->m_isParsing, return);
|
||||
|
||||
d->m_isParsing = true;
|
||||
d->m_hasParsingData = false;
|
||||
emit d->m_target->parsingStarted();
|
||||
}
|
||||
|
||||
void BuildSystem::emitParsingFinished(bool success)
|
||||
{
|
||||
// Intentionally no return, as we currently get start - start - end - end
|
||||
// sequences when switching qmake targets quickly.
|
||||
QTC_CHECK(d->m_isParsing);
|
||||
|
||||
d->m_isParsing = false;
|
||||
d->m_hasParsingData = success;
|
||||
emit d->m_target->parsingFinished(success);
|
||||
}
|
||||
|
||||
FilePath BuildSystem::projectFilePath() const
|
||||
{
|
||||
return m_project->projectFilePath();
|
||||
return d->m_target->project()->projectFilePath();
|
||||
}
|
||||
|
||||
FilePath BuildSystem::projectDirectory() const
|
||||
{
|
||||
return m_project->projectDirectory();
|
||||
return d->m_target->project()->projectDirectory();
|
||||
}
|
||||
|
||||
bool BuildSystem::isWaitingForParse() const
|
||||
{
|
||||
return m_delayedParsingTimer.isActive();
|
||||
return d->m_delayedParsingTimer.isActive();
|
||||
}
|
||||
|
||||
void BuildSystem::requestParse()
|
||||
{
|
||||
requestParse(0);
|
||||
requestParseHelper(0);
|
||||
}
|
||||
|
||||
void BuildSystem::requestDelayedParse()
|
||||
{
|
||||
requestParse(1000);
|
||||
requestParseHelper(1000);
|
||||
}
|
||||
|
||||
void BuildSystem::requestParse(int delay)
|
||||
bool BuildSystem::isParsing() const
|
||||
{
|
||||
m_delayedParsingTimer.setInterval(delay);
|
||||
m_delayedParsingTimer.start();
|
||||
return d->m_isParsing;
|
||||
}
|
||||
|
||||
void BuildSystem::triggerParsing()
|
||||
bool BuildSystem::hasParsingData() const
|
||||
{
|
||||
QTC_ASSERT(!project()->isParsing(), return );
|
||||
return d->m_hasParsingData;
|
||||
}
|
||||
|
||||
Project *p = project();
|
||||
Target *t = p->activeTarget();
|
||||
BuildConfiguration *bc = t ? t->activeBuildConfiguration() : nullptr;
|
||||
|
||||
MacroExpander *e = nullptr;
|
||||
Environment BuildSystem::activeParseEnvironment() const
|
||||
{
|
||||
const BuildConfiguration *const bc = d->m_target->activeBuildConfiguration();
|
||||
if (bc)
|
||||
e = bc->macroExpander();
|
||||
else if (t)
|
||||
e = t->macroExpander();
|
||||
else
|
||||
e = p->macroExpander();
|
||||
return bc->environment();
|
||||
|
||||
Utils::Environment env = p->activeParseEnvironment();
|
||||
const RunConfiguration *const rc = d->m_target->activeRunConfiguration();
|
||||
if (rc)
|
||||
return rc->runnable().environment;
|
||||
|
||||
ParsingContext ctx(p->guardParsingRun(), p, bc, e, env);
|
||||
Environment result = Utils::Environment::systemEnvironment();
|
||||
d->m_target->kit()->addToEnvironment(result);
|
||||
|
||||
QTC_ASSERT(ctx.guard.guardsProject(), return );
|
||||
return result;
|
||||
}
|
||||
|
||||
if (validateParsingContext(ctx))
|
||||
parseProject(std::move(ctx));
|
||||
void BuildSystem::requestParseHelper(int delay)
|
||||
{
|
||||
d->m_delayedParsingTimer.setInterval(delay);
|
||||
d->m_delayedParsingTimer.start();
|
||||
}
|
||||
|
||||
bool BuildSystem::addFiles(Node *, const QStringList &filePaths, QStringList *notAdded)
|
||||
@@ -157,4 +213,103 @@ bool BuildSystem::supportsAction(Node *, ProjectAction, const Node *) const
|
||||
return false;
|
||||
}
|
||||
|
||||
QStringList BuildSystem::filesGeneratedFrom(const QString &sourceFile) const
|
||||
{
|
||||
Q_UNUSED(sourceFile)
|
||||
return {};
|
||||
}
|
||||
|
||||
QVariant BuildSystem::additionalData(Core::Id id) const
|
||||
{
|
||||
Q_UNUSED(id)
|
||||
return {};
|
||||
}
|
||||
|
||||
// ParseGuard
|
||||
|
||||
BuildSystem::ParseGuard::ParseGuard(BuildSystem::ParseGuard &&other)
|
||||
: m_buildSystem{std::move(other.m_buildSystem)}
|
||||
, m_success{std::move(other.m_success)}
|
||||
{
|
||||
// No need to release this as this is invalid anyway:-)
|
||||
other.m_buildSystem = nullptr;
|
||||
}
|
||||
|
||||
BuildSystem::ParseGuard::ParseGuard(BuildSystem *p)
|
||||
: m_buildSystem(p)
|
||||
{
|
||||
if (m_buildSystem && !m_buildSystem->isParsing())
|
||||
m_buildSystem->emitParsingStarted();
|
||||
else
|
||||
m_buildSystem = nullptr;
|
||||
}
|
||||
|
||||
void BuildSystem::ParseGuard::release()
|
||||
{
|
||||
if (m_buildSystem)
|
||||
m_buildSystem->emitParsingFinished(m_success);
|
||||
m_buildSystem = nullptr;
|
||||
}
|
||||
|
||||
BuildSystem::ParseGuard &BuildSystem::ParseGuard::operator=(BuildSystem::ParseGuard &&other)
|
||||
{
|
||||
release();
|
||||
|
||||
m_buildSystem = std::move(other.m_buildSystem);
|
||||
m_success = std::move(other.m_success);
|
||||
|
||||
other.m_buildSystem = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void BuildSystem::setDeploymentData(const DeploymentData &deploymentData)
|
||||
{
|
||||
if (d->m_deploymentData != deploymentData) {
|
||||
d->m_deploymentData = deploymentData;
|
||||
emit deploymentDataChanged();
|
||||
emit applicationTargetsChanged();
|
||||
emit target()->deploymentDataChanged();
|
||||
emit target()->applicationTargetsChanged();
|
||||
}
|
||||
}
|
||||
|
||||
DeploymentData BuildSystem::deploymentData() const
|
||||
{
|
||||
return d->m_deploymentData;
|
||||
}
|
||||
|
||||
void BuildSystem::setApplicationTargets(const QList<BuildTargetInfo> &appTargets)
|
||||
{
|
||||
if (Utils::toSet(appTargets) != Utils::toSet(d->m_appTargets)) {
|
||||
d->m_appTargets = appTargets;
|
||||
emit applicationTargetsChanged();
|
||||
emit target()->applicationTargetsChanged();
|
||||
}
|
||||
}
|
||||
|
||||
const QList<BuildTargetInfo> BuildSystem::applicationTargets() const
|
||||
{
|
||||
return d->m_appTargets;
|
||||
}
|
||||
|
||||
BuildTargetInfo BuildSystem::buildTarget(const QString &buildKey) const
|
||||
{
|
||||
return Utils::findOrDefault(d->m_appTargets, [&buildKey](const BuildTargetInfo &ti) {
|
||||
return ti.buildKey == buildKey;
|
||||
});
|
||||
}
|
||||
|
||||
QString BuildSystem::disabledReason(const QString &buildKey) const
|
||||
{
|
||||
if (hasParsingData()) {
|
||||
QString msg = isParsing() ? tr("The project is currently being parsed.")
|
||||
: tr("The project could not be fully parsed.");
|
||||
const FilePath projectFilePath = buildTarget(buildKey).projectFilePath;
|
||||
if (!projectFilePath.isEmpty() && !projectFilePath.exists())
|
||||
msg += '\n' + tr("The project file \"%1\" does not exist.").arg(projectFilePath.toString());
|
||||
return msg;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
} // namespace ProjectExplorer
|
||||
|
@@ -27,15 +27,15 @@
|
||||
|
||||
#include "projectexplorer_export.h"
|
||||
|
||||
#include "buildtargetinfo.h"
|
||||
#include "project.h"
|
||||
#include "treescanner.h"
|
||||
|
||||
#include <QTimer>
|
||||
#include <QObject>
|
||||
|
||||
namespace ProjectExplorer {
|
||||
|
||||
class BuildConfiguration;
|
||||
class ExtraCompiler;
|
||||
class Node;
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
@@ -47,11 +47,13 @@ class PROJECTEXPLORER_EXPORT BuildSystem : public QObject
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit BuildSystem(Project *project);
|
||||
|
||||
BuildSystem(const BuildSystem &other) = delete;
|
||||
explicit BuildSystem(Target *target);
|
||||
explicit BuildSystem(BuildConfiguration *bc);
|
||||
~BuildSystem() override;
|
||||
|
||||
Project *project() const;
|
||||
Target *target() const;
|
||||
|
||||
Utils::FilePath projectFilePath() const;
|
||||
Utils::FilePath projectDirectory() const;
|
||||
|
||||
@@ -60,6 +62,11 @@ public:
|
||||
void requestParse();
|
||||
void requestDelayedParse();
|
||||
|
||||
bool isParsing() const;
|
||||
bool hasParsingData() const;
|
||||
|
||||
Utils::Environment activeParseEnvironment() const;
|
||||
|
||||
virtual bool addFiles(Node *context, const QStringList &filePaths, QStringList *notAdded = nullptr);
|
||||
virtual RemovedFilesFromProject removeFiles(Node *context, const QStringList &filePaths,
|
||||
QStringList *notRemoved = nullptr);
|
||||
@@ -69,69 +76,64 @@ public:
|
||||
virtual bool addDependencies(Node *context, const QStringList &dependencies);
|
||||
virtual bool supportsAction(Node *context, ProjectAction action, const Node *node) const;
|
||||
|
||||
protected:
|
||||
class ParsingContext
|
||||
virtual QStringList filesGeneratedFrom(const QString &sourceFile) const;
|
||||
virtual QVariant additionalData(Core::Id id) const;
|
||||
|
||||
void setDeploymentData(const DeploymentData &deploymentData);
|
||||
DeploymentData deploymentData() const;
|
||||
|
||||
void setApplicationTargets(const QList<BuildTargetInfo> &appTargets);
|
||||
const QList<BuildTargetInfo> applicationTargets() const;
|
||||
BuildTargetInfo buildTarget(const QString &buildKey) const;
|
||||
|
||||
class ParseGuard
|
||||
{
|
||||
friend class BuildSystem;
|
||||
explicit ParseGuard(BuildSystem *p);
|
||||
|
||||
void release();
|
||||
|
||||
public:
|
||||
ParsingContext() = default;
|
||||
ParseGuard() = default;
|
||||
~ParseGuard() { release(); }
|
||||
|
||||
ParsingContext(const ParsingContext &other) = delete;
|
||||
ParsingContext &operator=(const ParsingContext &other) = delete;
|
||||
ParsingContext(ParsingContext &&other)
|
||||
: guard{std::move(other.guard)}
|
||||
, project{std::move(other.project)}
|
||||
, buildConfiguration{std::move(other.buildConfiguration)}
|
||||
, expander{std::move(other.expander)}
|
||||
, environment{std::move(other.environment)}
|
||||
{}
|
||||
ParsingContext &operator=(ParsingContext &&other)
|
||||
{
|
||||
guard = std::move(other.guard);
|
||||
project = std::move(other.project);
|
||||
buildConfiguration = std::move(other.buildConfiguration);
|
||||
expander = std::move(other.expander);
|
||||
environment = std::move(other.environment);
|
||||
return *this;
|
||||
}
|
||||
void markAsSuccess() const { m_success = true; }
|
||||
bool isSuccess() const { return m_success; }
|
||||
bool guardsProject() const { return m_buildSystem; }
|
||||
|
||||
Project::ParseGuard guard;
|
||||
|
||||
Project *project = nullptr;
|
||||
BuildConfiguration *buildConfiguration = nullptr;
|
||||
Utils::MacroExpander *expander = nullptr;
|
||||
Utils::Environment environment;
|
||||
ParseGuard(const ParseGuard &other) = delete;
|
||||
ParseGuard &operator=(const ParseGuard &other) = delete;
|
||||
ParseGuard(ParseGuard &&other);
|
||||
ParseGuard &operator=(ParseGuard &&other);
|
||||
|
||||
private:
|
||||
ParsingContext(Project::ParseGuard &&g,
|
||||
Project *p,
|
||||
BuildConfiguration *bc,
|
||||
Utils::MacroExpander *e,
|
||||
Utils::Environment &env)
|
||||
: guard(std::move(g))
|
||||
, project(p)
|
||||
, buildConfiguration(bc)
|
||||
, expander(e)
|
||||
, environment(env)
|
||||
{}
|
||||
|
||||
friend class BuildSystem;
|
||||
BuildSystem *m_buildSystem = nullptr;
|
||||
mutable bool m_success = false;
|
||||
};
|
||||
|
||||
virtual bool validateParsingContext(const ParsingContext &ctx)
|
||||
{
|
||||
Q_UNUSED(ctx)
|
||||
return true;
|
||||
}
|
||||
public:
|
||||
// FIXME: Make this private and the BuildSystem a friend
|
||||
ParseGuard guardParsingRun() { return ParseGuard(this); }
|
||||
|
||||
virtual void parseProject(ParsingContext &&) {} // actual code to parse project
|
||||
QString disabledReason(const QString &buildKey) const;
|
||||
|
||||
virtual void triggerParsing() = 0;
|
||||
|
||||
signals:
|
||||
void deploymentDataChanged();
|
||||
void applicationTargetsChanged();
|
||||
|
||||
protected:
|
||||
// Helper methods to manage parsing state and signalling
|
||||
// Call in GUI thread before the actual parsing starts
|
||||
void emitParsingStarted();
|
||||
// Call in GUI thread right after the actual parsing is done
|
||||
void emitParsingFinished(bool success);
|
||||
|
||||
private:
|
||||
void requestParse(int delay); // request a (delayed!) parser run.
|
||||
void triggerParsing();
|
||||
void requestParseHelper(int delay); // request a (delayed!) parser run.
|
||||
|
||||
QTimer m_delayedParsingTimer;
|
||||
|
||||
Project *m_project;
|
||||
class BuildSystemPrivate *d = nullptr;
|
||||
};
|
||||
|
||||
} // namespace ProjectExplorer
|
||||
|
@@ -246,6 +246,11 @@ bool CustomExecutableRunConfiguration::isConfigured() const
|
||||
return !rawExecutable().isEmpty();
|
||||
}
|
||||
|
||||
bool CustomExecutableRunConfiguration::isEnabled() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
Runnable CustomExecutableRunConfiguration::runnable() const
|
||||
{
|
||||
FilePath workingDirectory =
|
||||
|
@@ -45,6 +45,7 @@ public:
|
||||
/** Returns whether this runconfiguration ever was configured with an executable
|
||||
*/
|
||||
bool isConfigured() const override;
|
||||
bool isEnabled() const override;
|
||||
ConfigurationState ensureConfigured(QString *errorMessage) override;
|
||||
|
||||
QString defaultDisplayName() const;
|
||||
|
@@ -25,9 +25,11 @@
|
||||
|
||||
#include "deploymentdataview.h"
|
||||
|
||||
#include "buildsystem.h"
|
||||
#include "deploymentdata.h"
|
||||
#include "target.h"
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
#include <utils/treemodel.h>
|
||||
|
||||
#include <QAbstractTableModel>
|
||||
@@ -78,7 +80,8 @@ DeploymentDataView::DeploymentDataView(Target *target)
|
||||
|
||||
auto updatModel = [this, target, model, view] {
|
||||
model->clear();
|
||||
for (const DeployableFile &file : target->deploymentData().allFiles())
|
||||
QTC_ASSERT(target->buildSystem(), return);
|
||||
for (const DeployableFile &file : target->buildSystem()->deploymentData().allFiles())
|
||||
model->rootItem()->appendChild(new DeploymentDataItem(file));
|
||||
|
||||
QHeaderView *header = view->header();
|
||||
|
@@ -78,7 +78,7 @@ DesktopRunConfiguration::DesktopRunConfiguration(Target *target, Core::Id id, Ki
|
||||
|
||||
if (kind == Qbs) {
|
||||
|
||||
connect(project(), &Project::parsingFinished,
|
||||
connect(target, &Target::parsingFinished,
|
||||
envAspect, &EnvironmentAspect::environmentChanged);
|
||||
|
||||
connect(target, &Target::deploymentDataChanged,
|
||||
@@ -95,12 +95,15 @@ DesktopRunConfiguration::DesktopRunConfiguration(Target *target, Core::Id id, Ki
|
||||
|
||||
}
|
||||
|
||||
connect(target->project(), &Project::parsingFinished,
|
||||
connect(target, &Target::parsingFinished,
|
||||
this, &DesktopRunConfiguration::updateTargetInformation);
|
||||
}
|
||||
|
||||
void DesktopRunConfiguration::updateTargetInformation()
|
||||
{
|
||||
if (!activeBuildSystem())
|
||||
return;
|
||||
|
||||
BuildTargetInfo bti = buildTargetInfo();
|
||||
|
||||
auto terminalAspect = aspect<TerminalAspect>();
|
||||
@@ -184,28 +187,6 @@ Utils::FilePath DesktopRunConfiguration::executableToRun(const BuildTargetInfo &
|
||||
return appInLocalInstallDir.exists() ? appInLocalInstallDir : appInBuildDir;
|
||||
}
|
||||
|
||||
bool DesktopRunConfiguration::isBuildTargetValid() const
|
||||
{
|
||||
return Utils::anyOf(target()->applicationTargets(), [this](const BuildTargetInfo &bti) {
|
||||
return bti.buildKey == buildKey();
|
||||
});
|
||||
}
|
||||
|
||||
void DesktopRunConfiguration::updateEnabledState()
|
||||
{
|
||||
if (m_kind == CMake && !isBuildTargetValid())
|
||||
setEnabled(false);
|
||||
else
|
||||
RunConfiguration::updateEnabledState();
|
||||
}
|
||||
|
||||
QString DesktopRunConfiguration::disabledReason() const
|
||||
{
|
||||
if (m_kind == CMake && !isBuildTargetValid())
|
||||
return tr("The project no longer builds the target associated with this run configuration.");
|
||||
return RunConfiguration::disabledReason();
|
||||
}
|
||||
|
||||
// Factory
|
||||
|
||||
class DesktopQmakeRunConfiguration : public DesktopRunConfiguration
|
||||
|
@@ -43,14 +43,10 @@ protected:
|
||||
private:
|
||||
void doAdditionalSetup(const RunConfigurationCreationInfo &info) final;
|
||||
bool fromMap(const QVariantMap &map) final;
|
||||
void updateEnabledState() final;
|
||||
|
||||
void updateTargetInformation();
|
||||
|
||||
Utils::FilePath executableToRun(const BuildTargetInfo &targetInfo) const;
|
||||
QString disabledReason() const override;
|
||||
|
||||
bool isBuildTargetValid() const;
|
||||
|
||||
const Kind m_kind;
|
||||
};
|
||||
|
@@ -443,7 +443,7 @@ MakeStepConfigWidget::MakeStepConfigWidget(MakeStep *makeStep)
|
||||
this, &MakeStepConfigWidget::updateDetails);
|
||||
connect(m_makeStep->buildConfiguration(), &BuildConfiguration::buildDirectoryChanged,
|
||||
this, &MakeStepConfigWidget::updateDetails);
|
||||
connect(m_makeStep->project(), &Project::parsingFinished,
|
||||
connect(m_makeStep->target(), &Target::parsingFinished,
|
||||
this, &MakeStepConfigWidget::updateDetails);
|
||||
|
||||
Core::VariableChooser::addSupportForChildWidgets(this, m_makeStep->macroExpander());
|
||||
|
@@ -176,14 +176,15 @@ public:
|
||||
~ProjectPrivate();
|
||||
|
||||
Core::Id m_id;
|
||||
bool m_isParsing = false;
|
||||
bool m_hasParsingData = false;
|
||||
bool m_needsInitialExpansion = false;
|
||||
bool m_canBuildProducts = false;
|
||||
bool m_knowsAllBuildExecutables = true;
|
||||
bool m_hasMakeInstallEquivalent = false;
|
||||
bool m_needsBuildConfigurations = true;
|
||||
std::unique_ptr<BuildSystem> m_buildSystem;
|
||||
bool m_needsDeployConfigurations = true;
|
||||
|
||||
std::function<BuildSystem *(Target *)> m_buildSystemCreator;
|
||||
|
||||
std::unique_ptr<Core::IDocument> m_document;
|
||||
std::vector<std::unique_ptr<Core::IDocument>> m_extraProjectDocuments;
|
||||
std::unique_ptr<ProjectNode> m_rootProjectNode;
|
||||
@@ -255,9 +256,9 @@ bool Project::canBuildProducts() const
|
||||
return d->m_canBuildProducts;
|
||||
}
|
||||
|
||||
BuildSystem *Project::buildSystem() const
|
||||
BuildSystem *Project::createBuildSystem(Target *target) const
|
||||
{
|
||||
return d->m_buildSystem.get();
|
||||
return d->m_buildSystemCreator ? d->m_buildSystemCreator(target) : nullptr;
|
||||
}
|
||||
|
||||
Utils::FilePath Project::projectFilePath() const
|
||||
@@ -341,8 +342,6 @@ void Project::setActiveTarget(Target *target)
|
||||
(target && Utils::contains(d->m_targets, target))) {
|
||||
d->m_activeTarget = target;
|
||||
emit activeTargetChanged(d->m_activeTarget);
|
||||
emit activeBuildConfigurationChanged(
|
||||
d->m_activeTarget ? d->m_activeTarget->activeBuildConfiguration() : nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -506,33 +505,14 @@ bool Project::copySteps(Target *sourceTarget, Target *newTarget)
|
||||
|
||||
bool Project::setupTarget(Target *t)
|
||||
{
|
||||
if (needsBuildConfigurations())
|
||||
if (d->m_needsBuildConfigurations)
|
||||
t->updateDefaultBuildConfigurations();
|
||||
t->updateDefaultDeployConfigurations();
|
||||
if (d->m_needsDeployConfigurations)
|
||||
t->updateDefaultDeployConfigurations();
|
||||
t->updateDefaultRunConfigurations();
|
||||
return true;
|
||||
}
|
||||
|
||||
void Project::emitParsingStarted()
|
||||
{
|
||||
QTC_ASSERT(!d->m_isParsing, return);
|
||||
|
||||
d->m_isParsing = true;
|
||||
d->m_hasParsingData = false;
|
||||
emit parsingStarted();
|
||||
}
|
||||
|
||||
void Project::emitParsingFinished(bool success)
|
||||
{
|
||||
// Intentionally no return, as we currently get start - start - end - end
|
||||
// sequences when switching qmake targets quickly.
|
||||
QTC_CHECK(d->m_isParsing);
|
||||
|
||||
d->m_isParsing = false;
|
||||
d->m_hasParsingData = success;
|
||||
emit parsingFinished(success);
|
||||
}
|
||||
|
||||
void Project::setDisplayName(const QString &name)
|
||||
{
|
||||
if (name == d->m_displayName)
|
||||
@@ -596,9 +576,6 @@ void Project::saveSettings()
|
||||
|
||||
Project::RestoreResult Project::restoreSettings(QString *errorMessage)
|
||||
{
|
||||
BuildConfiguration *oldBc = activeTarget() ? activeTarget()->activeBuildConfiguration()
|
||||
: nullptr;
|
||||
|
||||
if (!d->m_accessor)
|
||||
d->m_accessor = std::make_unique<Internal::UserFileAccessor>(this);
|
||||
QVariantMap map(d->m_accessor->restoreSettings(Core::ICore::mainWindow()));
|
||||
@@ -606,10 +583,6 @@ Project::RestoreResult Project::restoreSettings(QString *errorMessage)
|
||||
if (result == RestoreResult::Ok)
|
||||
emit settingsLoaded();
|
||||
|
||||
BuildConfiguration *bc = activeTarget() ? activeTarget()->activeBuildConfiguration() : nullptr;
|
||||
if (bc != oldBc)
|
||||
emit activeBuildConfigurationChanged(bc);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -798,12 +771,6 @@ EditorConfiguration *Project::editorConfiguration() const
|
||||
return &d->m_editorConfiguration;
|
||||
}
|
||||
|
||||
QStringList Project::filesGeneratedFrom(const QString &file) const
|
||||
{
|
||||
Q_UNUSED(file)
|
||||
return QStringList();
|
||||
}
|
||||
|
||||
bool Project::isKnownFile(const Utils::FilePath &filename) const
|
||||
{
|
||||
if (d->m_sortedNodeList.empty())
|
||||
@@ -852,10 +819,6 @@ void Project::setHasMakeInstallEquivalent(bool enabled)
|
||||
d->m_hasMakeInstallEquivalent = enabled;
|
||||
}
|
||||
|
||||
void Project::projectLoaded()
|
||||
{
|
||||
}
|
||||
|
||||
void Project::setKnowsAllBuildExecutables(bool value)
|
||||
{
|
||||
d->m_knowsAllBuildExecutables = value;
|
||||
@@ -866,31 +829,19 @@ void Project::setNeedsBuildConfigurations(bool value)
|
||||
d->m_needsBuildConfigurations = value;
|
||||
}
|
||||
|
||||
void Project::setNeedsDeployConfigurations(bool value)
|
||||
{
|
||||
d->m_needsDeployConfigurations = value;
|
||||
}
|
||||
|
||||
Task Project::createProjectTask(Task::TaskType type, const QString &description)
|
||||
{
|
||||
return Task(type, description, Utils::FilePath(), -1, Core::Id());
|
||||
}
|
||||
|
||||
Utils::Environment Project::activeParseEnvironment() const
|
||||
void Project::setBuildSystemCreator(const std::function<BuildSystem *(Target *)> &creator)
|
||||
{
|
||||
const Target *const t = activeTarget();
|
||||
const BuildConfiguration *const bc = t ? t->activeBuildConfiguration() : nullptr;
|
||||
if (bc)
|
||||
return bc->environment();
|
||||
|
||||
const RunConfiguration *const rc = t ? t->activeRunConfiguration() : nullptr;
|
||||
if (rc)
|
||||
return rc->runnable().environment;
|
||||
|
||||
Utils::Environment result = Utils::Environment::systemEnvironment();
|
||||
if (t)
|
||||
t->kit()->addToEnvironment(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void Project::setBuildSystemCreator(const std::function<BuildSystem *(Project *)> &creator)
|
||||
{
|
||||
d->m_buildSystem.reset(creator(this));
|
||||
d->m_buildSystemCreator = creator;
|
||||
}
|
||||
|
||||
Core::Context Project::projectContext() const
|
||||
@@ -988,23 +939,6 @@ Utils::MacroExpander *Project::macroExpander() const
|
||||
return &d->m_macroExpander;
|
||||
}
|
||||
|
||||
QVariant Project::additionalData(Core::Id id, const Target *target) const
|
||||
{
|
||||
Q_UNUSED(id)
|
||||
Q_UNUSED(target)
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
bool Project::isParsing() const
|
||||
{
|
||||
return d->m_isParsing;
|
||||
}
|
||||
|
||||
bool Project::hasParsingData() const
|
||||
{
|
||||
return d->m_hasParsingData;
|
||||
}
|
||||
|
||||
ProjectNode *Project::findNodeForBuildKey(const QString &buildKey) const
|
||||
{
|
||||
if (!d->m_rootProjectNode)
|
||||
@@ -1072,6 +1006,14 @@ const QString TEST_PROJECT_MIMETYPE = "application/vnd.test.qmakeprofile";
|
||||
const QString TEST_PROJECT_DISPLAYNAME = "testProjectFoo";
|
||||
const char TEST_PROJECT_ID[] = "Test.Project.Id";
|
||||
|
||||
class TestBuildSystem : public BuildSystem
|
||||
{
|
||||
public:
|
||||
using BuildSystem::BuildSystem;
|
||||
|
||||
void triggerParsing() {}
|
||||
};
|
||||
|
||||
class TestProject : public Project
|
||||
{
|
||||
public:
|
||||
@@ -1079,9 +1021,17 @@ public:
|
||||
{
|
||||
setId(TEST_PROJECT_ID);
|
||||
setDisplayName(TEST_PROJECT_DISPLAYNAME);
|
||||
setBuildSystemCreator([](Target *t) { return new TestBuildSystem(t); });
|
||||
setNeedsBuildConfigurations(false);
|
||||
setNeedsDeployConfigurations(false);
|
||||
|
||||
target = addTargetForKit(&testKit);
|
||||
}
|
||||
|
||||
bool needsConfiguration() const final { return false; }
|
||||
|
||||
Kit testKit;
|
||||
Target *target = nullptr;
|
||||
};
|
||||
|
||||
void ProjectExplorerPlugin::testProject_setup()
|
||||
@@ -1108,8 +1058,8 @@ void ProjectExplorerPlugin::testProject_setup()
|
||||
|
||||
QCOMPARE(project.id(), Core::Id(TEST_PROJECT_ID));
|
||||
|
||||
QVERIFY(!project.isParsing());
|
||||
QVERIFY(!project.hasParsingData());
|
||||
QVERIFY(!project.target->buildSystem()->isParsing());
|
||||
QVERIFY(!project.target->buildSystem()->hasParsingData());
|
||||
}
|
||||
|
||||
void ProjectExplorerPlugin::testProject_changeDisplayName()
|
||||
@@ -1132,16 +1082,16 @@ void ProjectExplorerPlugin::testProject_parsingSuccess()
|
||||
{
|
||||
TestProject project;
|
||||
|
||||
QSignalSpy startSpy(&project, &Project::parsingStarted);
|
||||
QSignalSpy stopSpy(&project, &Project::parsingFinished);
|
||||
QSignalSpy startSpy(project.target, &Target::parsingStarted);
|
||||
QSignalSpy stopSpy(project.target, &Target::parsingFinished);
|
||||
|
||||
{
|
||||
Project::ParseGuard guard = project.guardParsingRun();
|
||||
BuildSystem::ParseGuard guard = project.target->buildSystem()->guardParsingRun();
|
||||
QCOMPARE(startSpy.count(), 1);
|
||||
QCOMPARE(stopSpy.count(), 0);
|
||||
|
||||
QVERIFY(project.isParsing());
|
||||
QVERIFY(!project.hasParsingData());
|
||||
QVERIFY(project.target->buildSystem()->isParsing());
|
||||
QVERIFY(!project.target->buildSystem()->hasParsingData());
|
||||
|
||||
guard.markAsSuccess();
|
||||
}
|
||||
@@ -1150,32 +1100,32 @@ void ProjectExplorerPlugin::testProject_parsingSuccess()
|
||||
QCOMPARE(stopSpy.count(), 1);
|
||||
QCOMPARE(stopSpy.at(0), {QVariant(true)});
|
||||
|
||||
QVERIFY(!project.isParsing());
|
||||
QVERIFY(project.hasParsingData());
|
||||
QVERIFY(!project.target->buildSystem()->isParsing());
|
||||
QVERIFY(project.target->buildSystem()->hasParsingData());
|
||||
}
|
||||
|
||||
void ProjectExplorerPlugin::testProject_parsingFail()
|
||||
{
|
||||
TestProject project;
|
||||
|
||||
QSignalSpy startSpy(&project, &Project::parsingStarted);
|
||||
QSignalSpy stopSpy(&project, &Project::parsingFinished);
|
||||
QSignalSpy startSpy(project.target, &Target::parsingStarted);
|
||||
QSignalSpy stopSpy(project.target, &Target::parsingFinished);
|
||||
|
||||
{
|
||||
Project::ParseGuard guard = project.guardParsingRun();
|
||||
BuildSystem::ParseGuard guard = project.target->buildSystem()->guardParsingRun();
|
||||
QCOMPARE(startSpy.count(), 1);
|
||||
QCOMPARE(stopSpy.count(), 0);
|
||||
|
||||
QVERIFY(project.isParsing());
|
||||
QVERIFY(!project.hasParsingData());
|
||||
QVERIFY(project.target->buildSystem()->isParsing());
|
||||
QVERIFY(!project.target->buildSystem()->hasParsingData());
|
||||
}
|
||||
|
||||
QCOMPARE(startSpy.count(), 1);
|
||||
QCOMPARE(stopSpy.count(), 1);
|
||||
QCOMPARE(stopSpy.at(0), {QVariant(false)});
|
||||
|
||||
QVERIFY(!project.isParsing());
|
||||
QVERIFY(!project.hasParsingData());
|
||||
QVERIFY(!project.target->buildSystem()->isParsing());
|
||||
QVERIFY(!project.target->buildSystem()->hasParsingData());
|
||||
}
|
||||
|
||||
std::unique_ptr<ProjectNode> createFileTree(Project *project)
|
||||
|
@@ -50,6 +50,7 @@ namespace ProjectExplorer {
|
||||
|
||||
class BuildInfo;
|
||||
class BuildSystem;
|
||||
class BuildConfiguration;
|
||||
class ContainerNode;
|
||||
class EditorConfiguration;
|
||||
class FolderNode;
|
||||
@@ -64,7 +65,6 @@ class Target;
|
||||
class PROJECTEXPLORER_EXPORT Project : public QObject
|
||||
{
|
||||
friend class SessionManager; // for setActiveTarget
|
||||
friend class ProjectExplorerPlugin; // for projectLoaded
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
@@ -84,7 +84,7 @@ public:
|
||||
QString mimeType() const;
|
||||
bool canBuildProducts() const;
|
||||
|
||||
BuildSystem *buildSystem() const;
|
||||
BuildSystem *createBuildSystem(Target *target) const;
|
||||
|
||||
Utils::FilePath projectFilePath() const;
|
||||
Utils::FilePath projectDirectory() const;
|
||||
@@ -124,7 +124,6 @@ public:
|
||||
static const NodeMatcher GeneratedFiles;
|
||||
|
||||
Utils::FilePathList files(const NodeMatcher &matcher) const;
|
||||
virtual QStringList filesGeneratedFrom(const QString &sourceFile) const;
|
||||
bool isKnownFile(const Utils::FilePath &filename) const;
|
||||
|
||||
virtual QVariantMap toMap() const;
|
||||
@@ -155,81 +154,20 @@ public:
|
||||
void setup(const QList<BuildInfo> &infoList);
|
||||
Utils::MacroExpander *macroExpander() const;
|
||||
|
||||
virtual QVariant additionalData(Core::Id id, const Target *target) const;
|
||||
|
||||
bool isParsing() const;
|
||||
bool hasParsingData() const;
|
||||
|
||||
ProjectNode *findNodeForBuildKey(const QString &buildKey) const;
|
||||
|
||||
bool needsInitialExpansion() const;
|
||||
void setNeedsInitialExpansion(bool needsInitialExpansion);
|
||||
|
||||
class ParseGuard
|
||||
{
|
||||
public:
|
||||
ParseGuard()
|
||||
: ParseGuard(nullptr)
|
||||
{}
|
||||
|
||||
~ParseGuard() { release(); }
|
||||
|
||||
void markAsSuccess() const { m_success = true; }
|
||||
bool isSuccess() const { return m_success; }
|
||||
bool guardsProject() const { return m_project; }
|
||||
|
||||
ParseGuard(const ParseGuard &other) = delete;
|
||||
ParseGuard &operator=(const ParseGuard &other) = delete;
|
||||
ParseGuard(ParseGuard &&other)
|
||||
: m_project{std::move(other.m_project)}
|
||||
, m_success{std::move(other.m_success)}
|
||||
{
|
||||
// No need to release this as this is invalid anyway:-)
|
||||
other.m_project = nullptr;
|
||||
}
|
||||
ParseGuard &operator=(ParseGuard &&other)
|
||||
{
|
||||
release();
|
||||
|
||||
m_project = std::move(other.m_project);
|
||||
m_success = std::move(other.m_success);
|
||||
|
||||
other.m_project = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
ParseGuard(Project *p)
|
||||
: m_project(p)
|
||||
{
|
||||
if (m_project && !m_project->isParsing())
|
||||
m_project->emitParsingStarted();
|
||||
else
|
||||
m_project = nullptr;
|
||||
}
|
||||
|
||||
void release()
|
||||
{
|
||||
if (m_project)
|
||||
m_project->emitParsingFinished(m_success);
|
||||
m_project = nullptr;
|
||||
}
|
||||
|
||||
Project *m_project = nullptr;
|
||||
mutable bool m_success = false;
|
||||
|
||||
friend class Project;
|
||||
};
|
||||
|
||||
// FIXME: Make this private and the BuildSystem a friend
|
||||
ParseGuard guardParsingRun() { return ParseGuard(this); }
|
||||
void setRootProjectNode(std::unique_ptr<ProjectNode> &&root);
|
||||
|
||||
// Set project files that will be watched and trigger the same callback
|
||||
// as the main project file.
|
||||
void setExtraProjectFiles(const QVector<Utils::FilePath> &projectDocumentPaths);
|
||||
|
||||
Utils::Environment activeParseEnvironment() const;
|
||||
void setDisplayName(const QString &name);
|
||||
void setProjectLanguage(Core::Id id, bool enabled);
|
||||
void addProjectLanguage(Core::Id id);
|
||||
|
||||
signals:
|
||||
void projectFileIsDirty(const Utils::FilePath &path);
|
||||
@@ -243,11 +181,6 @@ signals:
|
||||
void removedProjectConfiguration(ProjectExplorer::ProjectConfiguration *pc);
|
||||
void addedProjectConfiguration(ProjectExplorer::ProjectConfiguration *pc);
|
||||
|
||||
// *ANY* active build configuration changed somewhere in the tree. This might not be
|
||||
// the one that would get started right now, since some part of the tree in between might
|
||||
// not be active.
|
||||
void activeBuildConfigurationChanged(ProjectExplorer::ProjectConfiguration *bc);
|
||||
|
||||
void aboutToRemoveTarget(ProjectExplorer::Target *target);
|
||||
void removedTarget(ProjectExplorer::Target *target);
|
||||
void addedTarget(ProjectExplorer::Target *target);
|
||||
@@ -257,8 +190,8 @@ signals:
|
||||
|
||||
void projectLanguagesUpdated();
|
||||
|
||||
void parsingStarted();
|
||||
void parsingFinished(bool success);
|
||||
void anyParsingStarted(Target *target);
|
||||
void anyParsingFinished(Target *target, bool success);
|
||||
|
||||
void rootProjectDirectoryChanged();
|
||||
|
||||
@@ -267,7 +200,6 @@ protected:
|
||||
void createTargetFromMap(const QVariantMap &map, int index);
|
||||
virtual bool setupTarget(Target *t);
|
||||
|
||||
void setDisplayName(const QString &name);
|
||||
// Used to pre-check kits in the TargetSetupPage. RequiredKitPredicate
|
||||
// is used to select kits available in the TargetSetupPage
|
||||
void setPreferredKitPredicate(const Kit::Predicate &predicate);
|
||||
@@ -278,35 +210,26 @@ protected:
|
||||
|
||||
void setId(Core::Id id);
|
||||
void setProjectLanguages(Core::Context language);
|
||||
void addProjectLanguage(Core::Id id);
|
||||
void removeProjectLanguage(Core::Id id);
|
||||
void setProjectLanguage(Core::Id id, bool enabled);
|
||||
void setHasMakeInstallEquivalent(bool enabled);
|
||||
virtual void projectLoaded(); // Called when the project is fully loaded.
|
||||
|
||||
void setKnowsAllBuildExecutables(bool value);
|
||||
void setNeedsBuildConfigurations(bool value);
|
||||
void setNeedsDeployConfigurations(bool value);
|
||||
|
||||
static ProjectExplorer::Task createProjectTask(ProjectExplorer::Task::TaskType type,
|
||||
const QString &description);
|
||||
|
||||
void setBuildSystemCreator(const std::function<BuildSystem *(Project *)> &creator);
|
||||
void setBuildSystemCreator(const std::function<BuildSystem *(Target *)> &creator);
|
||||
|
||||
private:
|
||||
// Helper methods to manage parsing state and signalling
|
||||
// Call in GUI thread before the actual parsing starts
|
||||
void emitParsingStarted();
|
||||
// Call in GUI thread right after the actual parsing is done
|
||||
void emitParsingFinished(bool success);
|
||||
|
||||
void addTarget(std::unique_ptr<Target> &&target);
|
||||
|
||||
void handleSubTreeChanged(FolderNode *node);
|
||||
void setActiveTarget(Target *target);
|
||||
|
||||
ProjectPrivate *d;
|
||||
|
||||
friend class ContainerNode;
|
||||
ProjectPrivate *d;
|
||||
};
|
||||
|
||||
} // namespace ProjectExplorer
|
||||
|
@@ -2046,7 +2046,6 @@ ProjectExplorerPlugin::OpenProjectResult ProjectExplorerPlugin::openProject(cons
|
||||
return result;
|
||||
dd->addToRecentProjects(fileName, project->displayName());
|
||||
SessionManager::setStartupProject(project);
|
||||
project->projectLoaded();
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -2113,9 +2112,6 @@ ProjectExplorerPlugin::OpenProjectResult ProjectExplorerPlugin::openProjects(con
|
||||
appendError(errorString,
|
||||
tr("Failed opening project \"%1\": Project is not a file.").arg(fileName));
|
||||
} else if (Project *pro = ProjectManager::openProject(mt, filePath)) {
|
||||
QObject::connect(pro, &Project::parsingFinished, [pro]() {
|
||||
emit SessionManager::instance()->projectFinishedParsing(pro);
|
||||
});
|
||||
QString restoreError;
|
||||
Project::RestoreResult restoreResult = pro->restoreSettings(&restoreError);
|
||||
if (restoreResult == Project::RestoreResult::Ok) {
|
||||
|
@@ -25,6 +25,7 @@
|
||||
|
||||
#include "projectmodels.h"
|
||||
|
||||
#include "buildsystem.h"
|
||||
#include "project.h"
|
||||
#include "projectnodes.h"
|
||||
#include "projectexplorer.h"
|
||||
@@ -119,6 +120,8 @@ QVariant FlatModel::data(const QModelIndex &index, int role) const
|
||||
const FolderNode * const folderNode = node->asFolderNode();
|
||||
const ContainerNode * const containerNode = node->asContainerNode();
|
||||
const Project * const project = containerNode ? containerNode->project() : nullptr;
|
||||
const Target * const target = project ? project->activeTarget() : nullptr;
|
||||
const BuildSystem * const bs = target ? target->buildSystem() : nullptr;
|
||||
|
||||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
@@ -128,7 +131,7 @@ QVariant FlatModel::data(const QModelIndex &index, int role) const
|
||||
case Qt::ToolTipRole: {
|
||||
QString tooltip = node->tooltip();
|
||||
if (project) {
|
||||
if (project->activeTarget()) {
|
||||
if (target) {
|
||||
QString projectIssues = toHtml(project->projectIssues(project->activeTarget()->kit()));
|
||||
if (!projectIssues.isEmpty())
|
||||
tooltip += "<p>" + projectIssues;
|
||||
@@ -148,10 +151,9 @@ QVariant FlatModel::data(const QModelIndex &index, int role) const
|
||||
static QIcon emptyIcon = Utils::Icons::EMPTY16.icon();
|
||||
if (project->needsConfiguration())
|
||||
return warnIcon;
|
||||
if (project->isParsing())
|
||||
if (bs && bs->isParsing())
|
||||
return emptyIcon;
|
||||
if (!project->activeTarget()
|
||||
|| !project->projectIssues(project->activeTarget()->kit()).isEmpty())
|
||||
if (!target || !project->projectIssues(target->kit()).isEmpty())
|
||||
return warnIcon;
|
||||
return containerNode->rootProjectNode() ? containerNode->rootProjectNode()->icon()
|
||||
: folderNode->icon();
|
||||
@@ -167,7 +169,7 @@ QVariant FlatModel::data(const QModelIndex &index, int role) const
|
||||
case Project::FilePathRole:
|
||||
return node->filePath().toString();
|
||||
case Project::isParsingRole:
|
||||
return project ? project->isParsing() && !project->needsConfiguration() : false;
|
||||
return project && bs ? bs->isParsing() && !project->needsConfiguration() : false;
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
@@ -359,12 +361,12 @@ void FlatModel::handleProjectAdded(Project *project)
|
||||
{
|
||||
QTC_ASSERT(project, return);
|
||||
|
||||
connect(project, &Project::parsingStarted,
|
||||
connect(project, &Project::anyParsingStarted,
|
||||
this, [this, project]() {
|
||||
if (nodeForProject(project))
|
||||
parsingStateChanged(project);
|
||||
});
|
||||
connect(project, &Project::parsingFinished,
|
||||
connect(project, &Project::anyParsingFinished,
|
||||
this, [this, project]() {
|
||||
if (nodeForProject(project))
|
||||
parsingStateChanged(project);
|
||||
|
@@ -25,10 +25,12 @@
|
||||
|
||||
#include "projectnodes.h"
|
||||
|
||||
#include "buildconfiguration.h"
|
||||
#include "buildsystem.h"
|
||||
#include "project.h"
|
||||
#include "projectexplorerconstants.h"
|
||||
#include "projecttree.h"
|
||||
#include "target.h"
|
||||
|
||||
#include <coreplugin/fileiconprovider.h>
|
||||
#include <coreplugin/icore.h>
|
||||
@@ -988,7 +990,8 @@ void ProjectNode::setFallbackData(Core::Id key, const QVariant &value)
|
||||
BuildSystem *ProjectNode::buildSystem() const
|
||||
{
|
||||
Project *p = getProject();
|
||||
return p ? p->buildSystem() : nullptr;
|
||||
Target *t = p ? p->activeTarget() : nullptr;
|
||||
return t ? t->buildSystem() : nullptr;
|
||||
}
|
||||
|
||||
bool FolderNode::isEmpty() const
|
||||
|
@@ -30,6 +30,7 @@
|
||||
#include "projectnodes.h"
|
||||
#include "projecttreewidget.h"
|
||||
#include "session.h"
|
||||
#include "target.h"
|
||||
|
||||
#include <coreplugin/actionmanager/actioncontainer.h>
|
||||
#include <coreplugin/actionmanager/actionmanager.h>
|
||||
@@ -104,6 +105,18 @@ Project *ProjectTree::currentProject()
|
||||
return s_instance->m_currentProject;
|
||||
}
|
||||
|
||||
Target *ProjectTree::currentTarget()
|
||||
{
|
||||
Project *p = currentProject();
|
||||
return p ? p->activeTarget() : nullptr;
|
||||
}
|
||||
|
||||
BuildSystem *ProjectTree::currentBuildSystem()
|
||||
{
|
||||
Target *t = currentTarget();
|
||||
return t ? t->buildSystem() : nullptr;
|
||||
}
|
||||
|
||||
Node *ProjectTree::currentNode()
|
||||
{
|
||||
s_instance->update();
|
||||
|
@@ -34,12 +34,14 @@
|
||||
namespace Utils { class FilePath; }
|
||||
|
||||
namespace ProjectExplorer {
|
||||
class BuildSystem;
|
||||
class FileNode;
|
||||
class FolderNode;
|
||||
class Node;
|
||||
class Project;
|
||||
class ProjectNode;
|
||||
class SessionNode;
|
||||
class Target;
|
||||
|
||||
namespace Internal { class ProjectTreeWidget; }
|
||||
|
||||
@@ -53,6 +55,8 @@ public:
|
||||
static ProjectTree *instance();
|
||||
|
||||
static Project *currentProject();
|
||||
static Target *currentTarget();
|
||||
static BuildSystem *currentBuildSystem();
|
||||
static Node *currentNode();
|
||||
static Utils::FilePath currentFilePath();
|
||||
|
||||
|
@@ -27,6 +27,7 @@
|
||||
|
||||
#include "abi.h"
|
||||
#include "buildconfiguration.h"
|
||||
#include "buildsystem.h"
|
||||
#include "environmentaspect.h"
|
||||
#include "kitinformation.h"
|
||||
#include "kitinformation.h"
|
||||
@@ -168,8 +169,7 @@ RunConfiguration::RunConfiguration(Target *target, Core::Id id)
|
||||
: ProjectConfiguration(target, id)
|
||||
{
|
||||
QTC_CHECK(target && target == this->target());
|
||||
connect(target->project(), &Project::parsingFinished,
|
||||
this, [this]() { updateEnabledState(); });
|
||||
connect(target, &Target::parsingFinished, this, [this] { updateEnabledState(); });
|
||||
|
||||
connect(target, &Target::addedRunConfiguration,
|
||||
this, [this](const RunConfiguration *rc) {
|
||||
@@ -224,25 +224,16 @@ bool RunConfiguration::isActive() const
|
||||
return target()->isActive() && target()->activeRunConfiguration() == this;
|
||||
}
|
||||
|
||||
void RunConfiguration::setEnabled(bool enabled)
|
||||
{
|
||||
if (enabled == m_isEnabled)
|
||||
return;
|
||||
m_isEnabled = enabled;
|
||||
emit enabledChanged();
|
||||
}
|
||||
|
||||
QString RunConfiguration::disabledReason() const
|
||||
{
|
||||
if (!project()->hasParsingData()) {
|
||||
QString msg = project()->isParsing() ? tr("The project is currently being parsed.")
|
||||
: tr("The project could not be fully parsed.");
|
||||
const FilePath projectFilePath = buildTargetInfo().projectFilePath;
|
||||
if (!projectFilePath.isEmpty() && !projectFilePath.exists())
|
||||
msg += '\n' + tr("The project file \"%1\" does not exist.").arg(projectFilePath.toString());
|
||||
return msg;
|
||||
}
|
||||
return QString();
|
||||
BuildSystem *bs = activeBuildSystem();
|
||||
return bs ? bs->disabledReason(m_buildKey) : tr("No build system active");
|
||||
}
|
||||
|
||||
bool RunConfiguration::isEnabled() const
|
||||
{
|
||||
BuildSystem *bs = activeBuildSystem();
|
||||
return bs && bs->hasParsingData();
|
||||
}
|
||||
|
||||
QWidget *RunConfiguration::createConfigurationWidget()
|
||||
@@ -266,7 +257,7 @@ QWidget *RunConfiguration::createConfigurationWidget()
|
||||
|
||||
void RunConfiguration::updateEnabledState()
|
||||
{
|
||||
setEnabled(project()->hasParsingData());
|
||||
emit enabledChanged();
|
||||
}
|
||||
|
||||
void RunConfiguration::addAspectFactory(const AspectFactory &aspectFactory)
|
||||
@@ -312,11 +303,14 @@ RunConfiguration::ConfigurationState RunConfiguration::ensureConfigured(QString
|
||||
|
||||
BuildConfiguration *RunConfiguration::activeBuildConfiguration() const
|
||||
{
|
||||
if (!target())
|
||||
return nullptr;
|
||||
return target()->activeBuildConfiguration();
|
||||
}
|
||||
|
||||
BuildSystem *RunConfiguration::activeBuildSystem() const
|
||||
{
|
||||
return target()->buildSystem();
|
||||
}
|
||||
|
||||
QVariantMap RunConfiguration::toMap() const
|
||||
{
|
||||
QVariantMap map = ProjectConfiguration::toMap();
|
||||
@@ -344,7 +338,9 @@ CommandLine RunConfiguration::commandLine() const
|
||||
|
||||
BuildTargetInfo RunConfiguration::buildTargetInfo() const
|
||||
{
|
||||
return target()->buildTarget(m_buildKey);
|
||||
BuildSystem *bs = target()->buildSystem();
|
||||
QTC_ASSERT(bs, return {});
|
||||
return bs->buildTarget(m_buildKey);
|
||||
}
|
||||
|
||||
bool RunConfiguration::fromMap(const QVariantMap &map)
|
||||
|
@@ -43,6 +43,7 @@ namespace Utils { class OutputFormatter; }
|
||||
|
||||
namespace ProjectExplorer {
|
||||
class BuildConfiguration;
|
||||
class BuildSystem;
|
||||
class GlobalOrProjectAspect;
|
||||
class Runnable;
|
||||
class RunConfigurationFactory;
|
||||
@@ -126,10 +127,8 @@ public:
|
||||
|
||||
bool isActive() const override;
|
||||
|
||||
bool isEnabled() const { return m_isEnabled; }
|
||||
void setEnabled(bool enabled);
|
||||
|
||||
virtual QString disabledReason() const;
|
||||
virtual bool isEnabled() const;
|
||||
|
||||
virtual QWidget *createConfigurationWidget();
|
||||
|
||||
@@ -182,6 +181,7 @@ protected:
|
||||
|
||||
/// convenience function to get current build configuration.
|
||||
BuildConfiguration *activeBuildConfiguration() const;
|
||||
BuildSystem *activeBuildSystem() const;
|
||||
|
||||
virtual void updateEnabledState();
|
||||
virtual void doAdditionalSetup(const RunConfigurationCreationInfo &) {}
|
||||
@@ -193,7 +193,6 @@ private:
|
||||
friend class RunConfigurationFactory;
|
||||
|
||||
QString m_buildKey;
|
||||
bool m_isEnabled = false;
|
||||
CommandLineGetter m_commandLineGetter;
|
||||
};
|
||||
|
||||
|
@@ -376,7 +376,7 @@ void RunControl::setTarget(Target *target)
|
||||
QTC_CHECK(!d->target);
|
||||
d->target = target;
|
||||
|
||||
if (!d->buildKey.isEmpty())
|
||||
if (!d->buildKey.isEmpty() && target->buildSystem())
|
||||
d->buildTargetInfo = target->buildTarget(d->buildKey);
|
||||
|
||||
if (auto bc = target->activeBuildConfiguration()) {
|
||||
|
@@ -381,6 +381,17 @@ Project *SessionManager::startupProject()
|
||||
return d->m_startupProject;
|
||||
}
|
||||
|
||||
Target *SessionManager::startupTarget()
|
||||
{
|
||||
return d->m_startupProject ? d->m_startupProject->activeTarget() : nullptr;
|
||||
}
|
||||
|
||||
BuildSystem *SessionManager::startupBuildSystem()
|
||||
{
|
||||
Target *t = startupTarget();
|
||||
return t ? t->buildSystem() : nullptr;
|
||||
}
|
||||
|
||||
void SessionManager::addProject(Project *pro)
|
||||
{
|
||||
QTC_ASSERT(pro, return);
|
||||
|
@@ -42,7 +42,9 @@ namespace ProjectExplorer {
|
||||
class Project;
|
||||
class Target;
|
||||
class BuildConfiguration;
|
||||
class BuildSystem;
|
||||
class DeployConfiguration;
|
||||
|
||||
enum class SetActive { Cascade, NoCascade };
|
||||
|
||||
class PROJECTEXPLORER_EXPORT SessionManager : public QObject
|
||||
@@ -96,6 +98,8 @@ public:
|
||||
|
||||
static Utils::FilePath sessionNameToFileName(const QString &session);
|
||||
static Project *startupProject();
|
||||
static Target *startupTarget();
|
||||
static BuildSystem *startupBuildSystem();
|
||||
|
||||
static const QList<Project *> projects();
|
||||
static bool hasProjects();
|
||||
@@ -119,6 +123,8 @@ public:
|
||||
static bool loadingSession();
|
||||
|
||||
signals:
|
||||
void targetAdded(ProjectExplorer::Target *target);
|
||||
void targetRemoved(ProjectExplorer::Target *target);
|
||||
void projectAdded(ProjectExplorer::Project *project);
|
||||
void aboutToRemoveProject(ProjectExplorer::Project *project);
|
||||
void projectDisplayNameChanged(ProjectExplorer::Project *project);
|
||||
|
@@ -29,6 +29,7 @@
|
||||
#include "buildconfiguration.h"
|
||||
#include "buildinfo.h"
|
||||
#include "buildmanager.h"
|
||||
#include "buildsystem.h"
|
||||
#include "buildtargetinfo.h"
|
||||
#include "deployconfiguration.h"
|
||||
#include "deploymentdata.h"
|
||||
@@ -98,20 +99,24 @@ public:
|
||||
m_runConfigurationModel(t)
|
||||
{ }
|
||||
|
||||
~TargetPrivate()
|
||||
{
|
||||
delete m_buildSystem;
|
||||
}
|
||||
|
||||
QIcon m_overlayIcon;
|
||||
|
||||
QList<BuildConfiguration *> m_buildConfigurations;
|
||||
BuildConfiguration *m_activeBuildConfiguration = nullptr;
|
||||
QPointer<BuildConfiguration> m_activeBuildConfiguration;
|
||||
QList<DeployConfiguration *> m_deployConfigurations;
|
||||
DeployConfiguration *m_activeDeployConfiguration = nullptr;
|
||||
QList<RunConfiguration *> m_runConfigurations;
|
||||
RunConfiguration* m_activeRunConfiguration = nullptr;
|
||||
DeploymentData m_deploymentData;
|
||||
QList<BuildTargetInfo> m_appTargets;
|
||||
QVariantMap m_pluginSettings;
|
||||
|
||||
Kit *const m_kit;
|
||||
MacroExpander m_macroExpander;
|
||||
BuildSystem *m_buildSystem = nullptr;
|
||||
|
||||
ProjectConfigurationModel m_buildConfigurationModel;
|
||||
ProjectConfigurationModel m_deployConfigurationModel;
|
||||
@@ -123,13 +128,24 @@ Target::Target(Project *project, Kit *k, _constructor_tag) :
|
||||
QObject(project),
|
||||
d(std::make_unique<TargetPrivate>(this, k))
|
||||
{
|
||||
// Note: nullptr is a valid state for the per-buildConfig systems.
|
||||
d->m_buildSystem = project->createBuildSystem(this);
|
||||
|
||||
QTC_CHECK(d->m_kit);
|
||||
connect(DeviceManager::instance(), &DeviceManager::updated, this, &Target::updateDeviceState);
|
||||
connect(project, &Project::parsingFinished, this, [this](bool success) {
|
||||
if (success && this->project() == SessionManager::startupProject()
|
||||
&& this == this->project()->activeTarget()) {
|
||||
|
||||
connect(this, &Target::parsingStarted, this, [this, project] {
|
||||
project->anyParsingStarted(this);
|
||||
});
|
||||
|
||||
connect(this, &Target::parsingFinished, this, [this, project](bool success) {
|
||||
if (success && project == SessionManager::startupProject()
|
||||
&& this == project->activeTarget()) {
|
||||
updateDefaultRunConfigurations();
|
||||
}
|
||||
// For testing.
|
||||
emit SessionManager::instance()->projectFinishedParsing(project);
|
||||
project->anyParsingFinished(this, success);
|
||||
}, Qt::QueuedConnection); // Must wait for run configs to change their enabled state.
|
||||
|
||||
KitManager *km = KitManager::instance();
|
||||
@@ -193,6 +209,37 @@ Kit *Target::kit() const
|
||||
return d->m_kit;
|
||||
}
|
||||
|
||||
BuildSystem *Target::buildSystem() const
|
||||
{
|
||||
if (d->m_activeBuildConfiguration)
|
||||
return d->m_activeBuildConfiguration->buildSystem();
|
||||
|
||||
return d->m_buildSystem;
|
||||
}
|
||||
|
||||
BuildSystem *Target::fallbackBuildSystem() const
|
||||
{
|
||||
return d->m_buildSystem;
|
||||
}
|
||||
|
||||
DeploymentData Target::deploymentData() const
|
||||
{
|
||||
QTC_ASSERT(buildSystem(), return {});
|
||||
return buildSystem()->deploymentData();
|
||||
}
|
||||
|
||||
const QList<BuildTargetInfo> Target::applicationTargets() const
|
||||
{
|
||||
QTC_ASSERT(buildSystem(), return {});
|
||||
return buildSystem()->applicationTargets();
|
||||
}
|
||||
|
||||
BuildTargetInfo Target::buildTarget(const QString &buildKey) const
|
||||
{
|
||||
QTC_ASSERT(buildSystem(), return {});
|
||||
return buildSystem()->buildTarget(buildKey);
|
||||
}
|
||||
|
||||
Core::Id Target::id() const
|
||||
{
|
||||
return d->m_kit->id();
|
||||
@@ -277,7 +324,6 @@ void Target::setActiveBuildConfiguration(BuildConfiguration *bc)
|
||||
(bc && d->m_buildConfigurations.contains(bc) &&
|
||||
bc != d->m_activeBuildConfiguration)) {
|
||||
d->m_activeBuildConfiguration = bc;
|
||||
project()->activeBuildConfigurationChanged(d->m_activeBuildConfiguration);
|
||||
emit activeBuildConfigurationChanged(d->m_activeBuildConfiguration);
|
||||
}
|
||||
}
|
||||
@@ -353,49 +399,6 @@ void Target::setActiveDeployConfiguration(DeployConfiguration *dc)
|
||||
updateDeviceState();
|
||||
}
|
||||
|
||||
void Target::setDeploymentData(const DeploymentData &deploymentData)
|
||||
{
|
||||
if (d->m_deploymentData != deploymentData) {
|
||||
d->m_deploymentData = deploymentData;
|
||||
emit deploymentDataChanged();
|
||||
emit applicationTargetsChanged();
|
||||
}
|
||||
}
|
||||
|
||||
DeploymentData Target::deploymentData() const
|
||||
{
|
||||
return d->m_deploymentData;
|
||||
}
|
||||
|
||||
void Target::setApplicationTargets(const QList<BuildTargetInfo> &appTargets)
|
||||
{
|
||||
if (Utils::toSet(appTargets) != Utils::toSet(d->m_appTargets)) {
|
||||
d->m_appTargets = appTargets;
|
||||
emit applicationTargetsChanged();
|
||||
}
|
||||
}
|
||||
|
||||
const QList<BuildTargetInfo> Target::applicationTargets() const
|
||||
{
|
||||
return d->m_appTargets;
|
||||
}
|
||||
|
||||
BuildTargetInfo Target::buildTarget(const QString &buildKey) const
|
||||
{
|
||||
return Utils::findOrDefault(d->m_appTargets, [&buildKey](const BuildTargetInfo &ti) {
|
||||
return ti.buildKey == buildKey;
|
||||
});
|
||||
}
|
||||
|
||||
QList<ProjectConfiguration *> Target::projectConfigurations() const
|
||||
{
|
||||
QList<ProjectConfiguration *> result;
|
||||
result.append(Utils::static_container_cast<ProjectConfiguration *>(buildConfigurations()));
|
||||
result.append(Utils::static_container_cast<ProjectConfiguration *>(deployConfigurations()));
|
||||
result.append(Utils::static_container_cast<ProjectConfiguration *>(runConfigurations()));
|
||||
return result;
|
||||
}
|
||||
|
||||
QList<RunConfiguration *> Target::runConfigurations() const
|
||||
{
|
||||
return d->m_runConfigurations;
|
||||
@@ -716,7 +719,7 @@ void Target::setNamedSettings(const QString &name, const QVariant &value)
|
||||
|
||||
QVariant Target::additionalData(Core::Id id) const
|
||||
{
|
||||
return project()->additionalData(id, this);
|
||||
return buildSystem()->additionalData(id);
|
||||
}
|
||||
|
||||
MakeInstallCommand Target::makeInstallCommand(const QString &installRoot) const
|
||||
|
@@ -35,6 +35,7 @@ QT_FORWARD_DECLARE_CLASS(QIcon)
|
||||
namespace ProjectExplorer {
|
||||
class BuildConfiguration;
|
||||
class BuildTargetInfo;
|
||||
class BuildSystem;
|
||||
class DeployConfiguration;
|
||||
class DeploymentData;
|
||||
class Kit;
|
||||
@@ -60,6 +61,7 @@ public:
|
||||
|
||||
Project *project() const;
|
||||
Kit *kit() const;
|
||||
BuildSystem *buildSystem() const;
|
||||
|
||||
Core::Id id() const;
|
||||
QString displayName() const;
|
||||
@@ -79,15 +81,6 @@ public:
|
||||
QList<DeployConfiguration *> deployConfigurations() const;
|
||||
DeployConfiguration *activeDeployConfiguration() const;
|
||||
|
||||
void setDeploymentData(const DeploymentData &deploymentData);
|
||||
DeploymentData deploymentData() const;
|
||||
|
||||
void setApplicationTargets(const QList<BuildTargetInfo> &appTargets);
|
||||
const QList<BuildTargetInfo> applicationTargets() const;
|
||||
BuildTargetInfo buildTarget(const QString &buildKey) const;
|
||||
|
||||
QList<ProjectConfiguration *> projectConfigurations() const;
|
||||
|
||||
// Running
|
||||
QList<RunConfiguration *> runConfigurations() const;
|
||||
void addRunConfiguration(RunConfiguration *rc);
|
||||
@@ -119,12 +112,20 @@ public:
|
||||
ProjectConfigurationModel *deployConfigurationModel() const;
|
||||
ProjectConfigurationModel *runConfigurationModel() const;
|
||||
|
||||
BuildSystem *fallbackBuildSystem() const;
|
||||
|
||||
DeploymentData deploymentData() const;
|
||||
const QList<BuildTargetInfo> applicationTargets() const;
|
||||
BuildTargetInfo buildTarget(const QString &buildKey) const;
|
||||
|
||||
signals:
|
||||
void targetEnabled(bool);
|
||||
void iconChanged();
|
||||
void overlayIconChanged();
|
||||
|
||||
void kitChanged();
|
||||
void parsingStarted();
|
||||
void parsingFinished(bool);
|
||||
|
||||
// TODO clean up signal names
|
||||
// might be better to also have aboutToRemove signals
|
||||
@@ -143,6 +144,7 @@ signals:
|
||||
|
||||
void deploymentDataChanged();
|
||||
void applicationTargetsChanged();
|
||||
void targetPropertiesChanged();
|
||||
|
||||
private:
|
||||
bool fromMap(const QVariantMap &map);
|
||||
|
@@ -39,6 +39,7 @@
|
||||
#include <QJsonObject>
|
||||
#include <QProcessEnvironment>
|
||||
#include <QRegularExpression>
|
||||
#include <QTimer>
|
||||
|
||||
#include <coreplugin/documentmanager.h>
|
||||
#include <coreplugin/icontext.h>
|
||||
@@ -57,7 +58,7 @@ namespace Internal {
|
||||
class PythonBuildSystem : public BuildSystem
|
||||
{
|
||||
public:
|
||||
explicit PythonBuildSystem(Project *project);
|
||||
explicit PythonBuildSystem(Target *target);
|
||||
|
||||
bool supportsAction(Node *context, ProjectAction action, const Node *node) const override;
|
||||
bool addFiles(Node *, const QStringList &filePaths, QStringList *) override;
|
||||
@@ -74,11 +75,9 @@ public:
|
||||
bool writePyProjectFile(const QString &fileName, QString &content,
|
||||
const QStringList &rawList, QString *errorMessage);
|
||||
|
||||
void refresh();
|
||||
void triggerParsing() final;
|
||||
|
||||
private:
|
||||
PythonProject *project() const;
|
||||
|
||||
QStringList m_rawFileList;
|
||||
QStringList m_files;
|
||||
QHash<QString, QString> m_rawListEntries;
|
||||
@@ -191,12 +190,12 @@ PythonProject::PythonProject(const FilePath &fileName)
|
||||
setDisplayName(fileName.toFileInfo().completeBaseName());
|
||||
|
||||
setNeedsBuildConfigurations(false);
|
||||
setBuildSystemCreator([](Project *p) { return new PythonBuildSystem(p); });
|
||||
setBuildSystemCreator([](Target *t) { return new PythonBuildSystem(t); });
|
||||
}
|
||||
|
||||
void PythonBuildSystem::refresh()
|
||||
void PythonBuildSystem::triggerParsing()
|
||||
{
|
||||
Project::ParseGuard guard = project()->guardParsingRun();
|
||||
ParseGuard guard = guardParsingRun();
|
||||
parse();
|
||||
|
||||
const QDir baseDir(projectDirectory().toString());
|
||||
@@ -225,8 +224,7 @@ void PythonBuildSystem::refresh()
|
||||
}
|
||||
project()->setRootProjectNode(std::move(newRoot));
|
||||
|
||||
if (Target *target = project()->activeTarget())
|
||||
target->setApplicationTargets(appTargets);
|
||||
setApplicationTargets(appTargets);
|
||||
|
||||
guard.markAsSuccess();
|
||||
}
|
||||
@@ -423,27 +421,16 @@ Project::RestoreResult PythonProject::fromMap(const QVariantMap &map, QString *e
|
||||
if (res == RestoreResult::Ok) {
|
||||
if (!activeTarget())
|
||||
addTargetForDefaultKit();
|
||||
|
||||
if (auto bs = dynamic_cast<PythonBuildSystem *>(buildSystem()))
|
||||
bs->refresh();
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
bool PythonProject::setupTarget(Target *t)
|
||||
PythonBuildSystem::PythonBuildSystem(Target *target)
|
||||
: BuildSystem(target)
|
||||
{
|
||||
bool res = Project::setupTarget(t);
|
||||
if (auto bs = dynamic_cast<PythonBuildSystem *>(buildSystem()))
|
||||
QTimer::singleShot(0, bs, &PythonBuildSystem::refresh);
|
||||
return res;
|
||||
}
|
||||
|
||||
PythonBuildSystem::PythonBuildSystem(Project *project)
|
||||
: BuildSystem(project)
|
||||
{
|
||||
connect(project, &Project::projectFileIsDirty, this, [this]() { refresh(); });
|
||||
QTimer::singleShot(0, this, &PythonBuildSystem::refresh);
|
||||
connect(target->project(), &Project::projectFileIsDirty, this, [this]() { triggerParsing(); });
|
||||
QTimer::singleShot(0, this, &PythonBuildSystem::triggerParsing);
|
||||
}
|
||||
|
||||
bool PythonBuildSystem::supportsAction(Node *context, ProjectAction action, const Node *node) const
|
||||
@@ -460,10 +447,5 @@ bool PythonBuildSystem::supportsAction(Node *context, ProjectAction action, cons
|
||||
return BuildSystem::supportsAction(context, action, node);
|
||||
}
|
||||
|
||||
PythonProject *PythonBuildSystem::project() const
|
||||
{
|
||||
return static_cast<PythonProject *>(BuildSystem::project());
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Python
|
||||
|
@@ -43,7 +43,6 @@ public:
|
||||
bool needsConfiguration() const final { return false; }
|
||||
private:
|
||||
RestoreResult fromMap(const QVariantMap &map, QString *errorMessage) override;
|
||||
bool setupTarget(ProjectExplorer::Target *t) override;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
@@ -279,7 +279,7 @@ PythonRunConfiguration::PythonRunConfiguration(Target *target, Core::Id id)
|
||||
|
||||
connect(target, &Target::applicationTargetsChanged,
|
||||
this, &PythonRunConfiguration::updateTargetInformation);
|
||||
connect(target->project(), &Project::parsingFinished,
|
||||
connect(target, &Target::parsingFinished,
|
||||
this, &PythonRunConfiguration::updateTargetInformation);
|
||||
}
|
||||
|
||||
|
@@ -52,6 +52,7 @@
|
||||
#include <utils/qtcprocess.h>
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QCryptographicHash>
|
||||
|
||||
using namespace ProjectExplorer;
|
||||
using namespace Utils;
|
||||
@@ -92,6 +93,18 @@ QbsBuildConfiguration::QbsBuildConfiguration(Target *target, Core::Id id)
|
||||
this, &QbsBuildConfiguration::triggerReparseIfActive);
|
||||
connect(this, &QbsBuildConfiguration::qbsConfigurationChanged,
|
||||
this, &QbsBuildConfiguration::triggerReparseIfActive);
|
||||
|
||||
m_buildSystem = new QbsBuildSystem(this);
|
||||
}
|
||||
|
||||
QbsBuildConfiguration::~QbsBuildConfiguration()
|
||||
{
|
||||
delete m_buildSystem;
|
||||
}
|
||||
|
||||
BuildSystem *QbsBuildConfiguration::buildSystem() const
|
||||
{
|
||||
return m_buildSystem;
|
||||
}
|
||||
|
||||
void QbsBuildConfiguration::initialize()
|
||||
@@ -119,7 +132,15 @@ void QbsBuildConfiguration::initialize()
|
||||
+ Utils::FileUtils::fileSystemFriendlyName(initialDisplayName());
|
||||
}
|
||||
|
||||
m_configurationName->setValue(configName);
|
||||
const Kit *kit = target()->kit();
|
||||
const QString kitName = kit->displayName();
|
||||
const QByteArray kitHash = QCryptographicHash::hash(kitName.toUtf8(), QCryptographicHash::Sha1);
|
||||
|
||||
const QString uniqueConfigName = configName
|
||||
+ '_' + kit->fileSystemFriendlyName().left(8)
|
||||
+ '_' + kitHash.toHex().left(16);
|
||||
|
||||
m_configurationName->setValue(uniqueConfigName);
|
||||
|
||||
BuildStepList *buildSteps = stepList(ProjectExplorer::Constants::BUILDSTEPS_BUILD);
|
||||
auto bs = new QbsBuildStep(buildSteps);
|
||||
@@ -137,7 +158,7 @@ void QbsBuildConfiguration::initialize()
|
||||
void QbsBuildConfiguration::triggerReparseIfActive()
|
||||
{
|
||||
if (isActive())
|
||||
qbsProject()->delayParsing();
|
||||
m_buildSystem->delayParsing();
|
||||
}
|
||||
|
||||
bool QbsBuildConfiguration::fromMap(const QVariantMap &map)
|
||||
@@ -169,11 +190,6 @@ QVariantMap QbsBuildConfiguration::qbsConfiguration() const
|
||||
return config;
|
||||
}
|
||||
|
||||
Internal::QbsProject *QbsBuildConfiguration::qbsProject() const
|
||||
{
|
||||
return qobject_cast<Internal::QbsProject *>(project());
|
||||
}
|
||||
|
||||
BuildConfiguration::BuildType QbsBuildConfiguration::buildType() const
|
||||
{
|
||||
QString variant;
|
||||
|
@@ -46,15 +46,15 @@ class QbsBuildConfiguration : public ProjectExplorer::BuildConfiguration
|
||||
|
||||
friend class ProjectExplorer::BuildConfigurationFactory;
|
||||
QbsBuildConfiguration(ProjectExplorer::Target *target, Core::Id id);
|
||||
~QbsBuildConfiguration() final;
|
||||
|
||||
public:
|
||||
void initialize() override;
|
||||
ProjectExplorer::BuildSystem *buildSystem() const final;
|
||||
void initialize() final;
|
||||
|
||||
QbsBuildStep *qbsStep() const;
|
||||
QVariantMap qbsConfiguration() const;
|
||||
|
||||
Internal::QbsProject *qbsProject() const;
|
||||
|
||||
BuildType buildType() const override;
|
||||
|
||||
void setChangedFiles(const QStringList &files);
|
||||
@@ -67,7 +67,6 @@ public:
|
||||
QStringList products() const;
|
||||
|
||||
QString configurationName() const;
|
||||
|
||||
QString equivalentCommandLine(const ProjectExplorer::BuildStep *buildStep) const;
|
||||
|
||||
signals:
|
||||
@@ -80,7 +79,8 @@ private:
|
||||
QStringList m_changedFiles;
|
||||
QStringList m_activeFileTags;
|
||||
QStringList m_products;
|
||||
ProjectExplorer::BaseStringAspect *m_configurationName;
|
||||
ProjectExplorer::BaseStringAspect *m_configurationName = nullptr;
|
||||
QbsBuildSystem *m_buildSystem = nullptr;
|
||||
};
|
||||
|
||||
class QbsBuildConfigurationFactory : public ProjectExplorer::BuildConfigurationFactory
|
||||
|
@@ -170,7 +170,7 @@ QbsBuildStep::~QbsBuildStep()
|
||||
|
||||
bool QbsBuildStep::init()
|
||||
{
|
||||
if (project()->isParsing() || m_job)
|
||||
if (qbsBuildSystem()->isParsing() || m_job)
|
||||
return false;
|
||||
|
||||
auto bc = static_cast<QbsBuildConfiguration *>(buildConfiguration());
|
||||
@@ -212,7 +212,7 @@ ProjectExplorer::BuildStepConfigWidget *QbsBuildStep::createConfigWidget()
|
||||
void QbsBuildStep::doCancel()
|
||||
{
|
||||
if (m_parsingProject)
|
||||
qbsProject()->cancelParsing();
|
||||
qbsBuildSystem()->cancelParsing();
|
||||
else if (m_job)
|
||||
m_job->cancel();
|
||||
}
|
||||
@@ -238,10 +238,8 @@ QVariantMap QbsBuildStep::qbsConfiguration(VariableHandling variableHandling) co
|
||||
|
||||
void QbsBuildStep::setQbsConfiguration(const QVariantMap &config)
|
||||
{
|
||||
auto pro = static_cast<QbsProject *>(project());
|
||||
|
||||
QVariantMap tmp = config;
|
||||
tmp.insert(Constants::QBS_CONFIG_PROFILE_KEY, pro->profileForTarget(target()));
|
||||
tmp.insert(Constants::QBS_CONFIG_PROFILE_KEY, qbsBuildSystem()->profile());
|
||||
if (!tmp.contains(Constants::QBS_CONFIG_VARIANT_KEY))
|
||||
tmp.insert(Constants::QBS_CONFIG_VARIANT_KEY,
|
||||
QString::fromLatin1(Constants::QBS_VARIANT_DEBUG));
|
||||
@@ -347,14 +345,12 @@ void QbsBuildStep::buildingDone(bool success)
|
||||
createTaskAndOutput(ProjectExplorer::Task::Error, item.description(),
|
||||
item.codeLocation().filePath(), item.codeLocation().line());
|
||||
|
||||
auto pro = static_cast<QbsProject *>(project());
|
||||
|
||||
// Building can uncover additional target artifacts.
|
||||
pro->updateAfterBuild();
|
||||
qbsBuildSystem()->updateAfterBuild();
|
||||
|
||||
// The reparsing, if it is necessary, has to be done before finished() is emitted, as
|
||||
// otherwise a potential additional build step could conflict with the parsing step.
|
||||
if (pro->parsingScheduled())
|
||||
if (qbsBuildSystem()->parsingScheduled())
|
||||
parseProject();
|
||||
else
|
||||
finish();
|
||||
@@ -362,7 +358,7 @@ void QbsBuildStep::buildingDone(bool success)
|
||||
|
||||
void QbsBuildStep::reparsingDone(bool success)
|
||||
{
|
||||
disconnect(project(), &Project::parsingFinished, this, &QbsBuildStep::reparsingDone);
|
||||
disconnect(target(), &Target::parsingFinished, this, &QbsBuildStep::reparsingDone);
|
||||
m_parsingProject = false;
|
||||
if (m_job) { // This was a scheduled reparsing after building.
|
||||
finish();
|
||||
@@ -431,6 +427,11 @@ QString QbsBuildStep::buildVariant() const
|
||||
return qbsConfiguration(PreserveVariables).value(Constants::QBS_CONFIG_VARIANT_KEY).toString();
|
||||
}
|
||||
|
||||
QbsBuildSystem *QbsBuildStep::qbsBuildSystem() const
|
||||
{
|
||||
return static_cast<QbsBuildSystem *>(buildConfiguration()->buildSystem());
|
||||
}
|
||||
|
||||
void QbsBuildStep::setBuildVariant(const QString &variant)
|
||||
{
|
||||
if (m_qbsConfiguration.value(Constants::QBS_CONFIG_VARIANT_KEY).toString() == variant)
|
||||
@@ -490,8 +491,8 @@ void QbsBuildStep::setCleanInstallRoot(bool clean)
|
||||
void QbsBuildStep::parseProject()
|
||||
{
|
||||
m_parsingProject = true;
|
||||
connect(project(), &Project::parsingFinished, this, &QbsBuildStep::reparsingDone);
|
||||
qbsProject()->parseCurrentBuildConfiguration();
|
||||
connect(target(), &Target::parsingFinished, this, &QbsBuildStep::reparsingDone);
|
||||
qbsBuildSystem()->parseCurrentBuildConfiguration();
|
||||
}
|
||||
|
||||
void QbsBuildStep::build()
|
||||
@@ -503,7 +504,7 @@ void QbsBuildStep::build()
|
||||
options.setLogElapsedTime(!qEnvironmentVariableIsEmpty(Constants::QBS_PROFILING_ENV));
|
||||
|
||||
QString error;
|
||||
m_job = qbsProject()->build(options, m_products, error);
|
||||
m_job = qbsBuildSystem()->build(options, m_products, error);
|
||||
if (!m_job) {
|
||||
emit addOutput(error, OutputFormat::ErrorMessage);
|
||||
emit finished(false);
|
||||
|
@@ -79,6 +79,8 @@ public:
|
||||
}
|
||||
bool isQmlDebuggingEnabled() const { return m_enableQmlDebugging; }
|
||||
|
||||
QbsBuildSystem *qbsBuildSystem() const;
|
||||
|
||||
signals:
|
||||
void qbsConfigurationChanged();
|
||||
void qbsBuildOptionsChanged();
|
||||
|
@@ -81,7 +81,7 @@ QbsCleanStep::~QbsCleanStep()
|
||||
|
||||
bool QbsCleanStep::init()
|
||||
{
|
||||
if (project()->isParsing() || m_job)
|
||||
if (buildSystem()->isParsing() || m_job)
|
||||
return false;
|
||||
|
||||
auto bc = static_cast<QbsBuildConfiguration *>(buildConfiguration());
|
||||
@@ -95,13 +95,12 @@ bool QbsCleanStep::init()
|
||||
|
||||
void QbsCleanStep::doRun()
|
||||
{
|
||||
auto pro = static_cast<QbsProject *>(project());
|
||||
qbs::CleanOptions options;
|
||||
options.setDryRun(m_dryRunAspect->value());
|
||||
options.setKeepGoing(m_keepGoingAspect->value());
|
||||
|
||||
QString error;
|
||||
m_job = pro->clean(options, m_products, error);
|
||||
m_job = qbsBuildSystem()->clean(options, m_products, error);
|
||||
if (!m_job) {
|
||||
emit addOutput(error, OutputFormat::ErrorMessage);
|
||||
emit finished(false);
|
||||
@@ -157,6 +156,11 @@ void QbsCleanStep::createTaskAndOutput(ProjectExplorer::Task::TaskType type, con
|
||||
emit addOutput(message, OutputFormat::Stdout);
|
||||
}
|
||||
|
||||
QbsBuildSystem *QbsCleanStep::qbsBuildSystem() const
|
||||
{
|
||||
return static_cast<QbsBuildSystem *>(buildSystem());
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// QbsCleanStepFactory:
|
||||
// --------------------------------------------------------------------
|
||||
|
@@ -62,6 +62,8 @@ private:
|
||||
ProjectExplorer::BaseBoolAspect *m_dryRunAspect = nullptr;
|
||||
ProjectExplorer::BaseBoolAspect *m_keepGoingAspect = nullptr;
|
||||
|
||||
QbsBuildSystem *qbsBuildSystem() const;
|
||||
|
||||
QStringList m_products;
|
||||
|
||||
qbs::CleanJob *m_job = nullptr;
|
||||
|
@@ -109,14 +109,14 @@ QbsInstallStep::~QbsInstallStep()
|
||||
|
||||
bool QbsInstallStep::init()
|
||||
{
|
||||
QTC_ASSERT(!project()->isParsing() && !m_job, return false);
|
||||
QTC_ASSERT(!buildConfiguration()->buildSystem()->isParsing() && !m_job, return false);
|
||||
return true;
|
||||
}
|
||||
|
||||
void QbsInstallStep::doRun()
|
||||
{
|
||||
auto pro = static_cast<QbsProject *>(project());
|
||||
m_job = pro->install(m_qbsInstallOptions);
|
||||
auto bs = static_cast<QbsBuildSystem *>(buildSystem());
|
||||
m_job = bs->install(m_qbsInstallOptions);
|
||||
|
||||
if (!m_job) {
|
||||
emit finished(false);
|
||||
@@ -336,7 +336,7 @@ QbsInstallStepConfigWidget::QbsInstallStepConfigWidget(QbsInstallStep *step) :
|
||||
connect(m_keepGoingCheckBox, &QAbstractButton::toggled,
|
||||
this, &QbsInstallStepConfigWidget::changeKeepGoing);
|
||||
|
||||
connect(m_step->project(), &Project::parsingFinished,
|
||||
connect(m_step->target(), &Target::parsingFinished,
|
||||
this, &QbsInstallStepConfigWidget::updateState);
|
||||
|
||||
updateState();
|
||||
|
@@ -54,35 +54,6 @@ using namespace ProjectExplorer;
|
||||
namespace QbsProjectManager {
|
||||
namespace Internal {
|
||||
|
||||
static const QbsProjectNode *parentQbsProjectNode(const ProjectExplorer::Node *node)
|
||||
{
|
||||
for (const ProjectExplorer::FolderNode *pn = node->managingProject(); pn; pn = pn->parentProjectNode()) {
|
||||
const auto prjNode = dynamic_cast<const QbsProjectNode *>(pn);
|
||||
if (prjNode)
|
||||
return prjNode;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static const QbsProductNode *parentQbsProductNode(const ProjectExplorer::Node *node)
|
||||
{
|
||||
for (; node; node = node->parentFolderNode()) {
|
||||
const auto prdNode = dynamic_cast<const QbsProductNode *>(node);
|
||||
if (prdNode)
|
||||
return prdNode;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static qbs::GroupData findMainQbsGroup(const qbs::ProductData &productData)
|
||||
{
|
||||
foreach (const qbs::GroupData &grp, productData.groups()) {
|
||||
if (grp.name() == productData.name() && grp.location() == productData.location())
|
||||
return grp;
|
||||
}
|
||||
return qbs::GroupData();
|
||||
}
|
||||
|
||||
class FileTreeNode {
|
||||
public:
|
||||
explicit FileTreeNode(const QString &n = QString(), FileTreeNode *p = nullptr, bool f = false) :
|
||||
@@ -212,16 +183,6 @@ public:
|
||||
};
|
||||
|
||||
|
||||
static bool supportsNodeAction(ProjectAction action, const Node *node)
|
||||
{
|
||||
const QbsProject * const project = parentQbsProjectNode(node)->project();
|
||||
if (!project->isProjectEditable())
|
||||
return false;
|
||||
if (action == RemoveFile || action == Rename)
|
||||
return node->asFileNode();
|
||||
return false;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// QbsGroupNode:
|
||||
// --------------------------------------------------------------------
|
||||
@@ -337,16 +298,11 @@ QbsProjectNode::QbsProjectNode(const Utils::FilePath &projectDirectory) :
|
||||
setIcon(projectIcon);
|
||||
}
|
||||
|
||||
QbsProject *QbsProjectNode::project() const
|
||||
Project *QbsProjectNode::project() const
|
||||
{
|
||||
return static_cast<QbsProjectNode *>(parentFolderNode())->project();
|
||||
}
|
||||
|
||||
const qbs::Project QbsProjectNode::qbsProject() const
|
||||
{
|
||||
return project()->qbsProject();
|
||||
}
|
||||
|
||||
void QbsProjectNode::setProjectData(const qbs::ProjectData &data)
|
||||
{
|
||||
m_projectData = data;
|
||||
@@ -356,156 +312,11 @@ void QbsProjectNode::setProjectData(const qbs::ProjectData &data)
|
||||
// QbsRootProjectNode:
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
QbsRootProjectNode::QbsRootProjectNode(QbsProject *project) :
|
||||
QbsRootProjectNode::QbsRootProjectNode(Project *project) :
|
||||
QbsProjectNode(project->projectDirectory()),
|
||||
m_project(project)
|
||||
{ }
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// QbsBuildSystem:
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
QbsBuildSystem::QbsBuildSystem(Project *project)
|
||||
: BuildSystem(project)
|
||||
{
|
||||
}
|
||||
|
||||
bool QbsBuildSystem::supportsAction(Node *context, ProjectAction action, const Node *node) const
|
||||
{
|
||||
if (dynamic_cast<QbsGroupNode *>(context)) {
|
||||
if (action == AddNewFile || action == AddExistingFile)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (dynamic_cast<QbsProductNode *>(context)) {
|
||||
if (action == AddNewFile || action == AddExistingFile)
|
||||
return true;
|
||||
}
|
||||
|
||||
return supportsNodeAction(action, node);
|
||||
}
|
||||
|
||||
bool QbsBuildSystem::addFiles(Node *context, const QStringList &filePaths, QStringList *notAdded)
|
||||
{
|
||||
if (auto n = dynamic_cast<QbsGroupNode *>(context)) {
|
||||
QStringList notAddedDummy;
|
||||
if (!notAdded)
|
||||
notAdded = ¬AddedDummy;
|
||||
|
||||
const QbsProjectNode *prjNode = parentQbsProjectNode(n);
|
||||
if (!prjNode || !prjNode->qbsProject().isValid()) {
|
||||
*notAdded += filePaths;
|
||||
return false;
|
||||
}
|
||||
|
||||
const QbsProductNode *prdNode = parentQbsProductNode(n);
|
||||
if (!prdNode || !prdNode->qbsProductData().isValid()) {
|
||||
*notAdded += filePaths;
|
||||
return false;
|
||||
}
|
||||
|
||||
return prjNode->project()->addFilesToProduct(filePaths, prdNode->qbsProductData(),
|
||||
n->m_qbsGroupData, notAdded);
|
||||
}
|
||||
|
||||
if (auto n = dynamic_cast<QbsProductNode *>(context)) {
|
||||
QStringList notAddedDummy;
|
||||
if (!notAdded)
|
||||
notAdded = ¬AddedDummy;
|
||||
|
||||
const QbsProjectNode *prjNode = parentQbsProjectNode(n);
|
||||
if (!prjNode || !prjNode->qbsProject().isValid()) {
|
||||
*notAdded += filePaths;
|
||||
return false;
|
||||
}
|
||||
|
||||
qbs::GroupData grp = findMainQbsGroup(n->qbsProductData());
|
||||
if (grp.isValid())
|
||||
return prjNode->project()->addFilesToProduct(filePaths, n->qbsProductData(), grp, notAdded);
|
||||
|
||||
QTC_ASSERT(false, return false);
|
||||
}
|
||||
|
||||
return BuildSystem::addFiles(context, filePaths, notAdded);
|
||||
}
|
||||
|
||||
RemovedFilesFromProject QbsBuildSystem::removeFiles(Node *context, const QStringList &filePaths,
|
||||
QStringList *notRemoved)
|
||||
{
|
||||
if (auto n = dynamic_cast<QbsGroupNode *>(context)) {
|
||||
QStringList notRemovedDummy;
|
||||
if (!notRemoved)
|
||||
notRemoved = ¬RemovedDummy;
|
||||
|
||||
const QbsProjectNode *prjNode = parentQbsProjectNode(n);
|
||||
if (!prjNode || !prjNode->qbsProject().isValid()) {
|
||||
*notRemoved += filePaths;
|
||||
return RemovedFilesFromProject::Error;
|
||||
}
|
||||
|
||||
const QbsProductNode *prdNode = parentQbsProductNode(n);
|
||||
if (!prdNode || !prdNode->qbsProductData().isValid()) {
|
||||
*notRemoved += filePaths;
|
||||
return RemovedFilesFromProject::Error;
|
||||
}
|
||||
|
||||
return project()->removeFilesFromProduct(filePaths, prdNode->qbsProductData(),
|
||||
n->m_qbsGroupData, notRemoved);
|
||||
}
|
||||
|
||||
if (auto n = dynamic_cast<QbsProductNode *>(context)) {
|
||||
QStringList notRemovedDummy;
|
||||
if (!notRemoved)
|
||||
notRemoved = ¬RemovedDummy;
|
||||
|
||||
const QbsProjectNode *prjNode = parentQbsProjectNode(n);
|
||||
if (!prjNode || !prjNode->qbsProject().isValid()) {
|
||||
*notRemoved += filePaths;
|
||||
return RemovedFilesFromProject::Error;
|
||||
}
|
||||
|
||||
qbs::GroupData grp = findMainQbsGroup(n->qbsProductData());
|
||||
if (grp.isValid()) {
|
||||
return prjNode->project()->removeFilesFromProduct(filePaths, n->qbsProductData(), grp,
|
||||
notRemoved);
|
||||
}
|
||||
|
||||
QTC_ASSERT(false, return RemovedFilesFromProject::Error);
|
||||
}
|
||||
|
||||
return BuildSystem::removeFiles(context, filePaths, notRemoved);
|
||||
}
|
||||
|
||||
bool QbsBuildSystem::renameFile(Node *context, const QString &filePath, const QString &newFilePath)
|
||||
{
|
||||
if (auto *n = dynamic_cast<QbsGroupNode *>(context)) {
|
||||
const QbsProjectNode *prjNode = parentQbsProjectNode(n);
|
||||
if (!prjNode || !prjNode->qbsProject().isValid())
|
||||
return false;
|
||||
const QbsProductNode *prdNode = parentQbsProductNode(n);
|
||||
if (!prdNode || !prdNode->qbsProductData().isValid())
|
||||
return false;
|
||||
|
||||
return project()->renameFileInProduct(filePath, newFilePath,
|
||||
prdNode->qbsProductData(), n->m_qbsGroupData);
|
||||
}
|
||||
|
||||
if (auto *n = dynamic_cast<QbsProductNode *>(context)) {
|
||||
const QbsProjectNode * prjNode = parentQbsProjectNode(n);
|
||||
if (!prjNode || !prjNode->qbsProject().isValid())
|
||||
return false;
|
||||
const qbs::GroupData grp = findMainQbsGroup(n->qbsProductData());
|
||||
QTC_ASSERT(grp.isValid(), return false);
|
||||
return prjNode->project()->renameFileInProduct(filePath, newFilePath, n->qbsProductData(), grp);
|
||||
}
|
||||
|
||||
return BuildSystem::renameFile(context, filePath, newFilePath);
|
||||
}
|
||||
|
||||
QbsProject *QbsBuildSystem::project() const
|
||||
{
|
||||
return static_cast<QbsProject *>(BuildSystem::project());
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace QbsProjectManager
|
||||
|
@@ -35,26 +35,7 @@ namespace Internal {
|
||||
|
||||
class QbsNodeTreeBuilder;
|
||||
class QbsProject;
|
||||
|
||||
class QbsBuildSystem : public ProjectExplorer::BuildSystem
|
||||
{
|
||||
public:
|
||||
explicit QbsBuildSystem(ProjectExplorer::Project *project);
|
||||
|
||||
bool supportsAction(ProjectExplorer::Node *context,
|
||||
ProjectExplorer::ProjectAction action,
|
||||
const ProjectExplorer::Node *node) const final;
|
||||
bool addFiles(ProjectExplorer::Node *context,
|
||||
const QStringList &filePaths,
|
||||
QStringList *notAdded = nullptr) override;
|
||||
ProjectExplorer::RemovedFilesFromProject removeFiles(ProjectExplorer::Node *context,
|
||||
const QStringList &filePaths,
|
||||
QStringList *notRemoved = nullptr) override;
|
||||
bool renameFile(ProjectExplorer::Node *context,
|
||||
const QString &filePath, const QString &newFilePath) override;
|
||||
|
||||
QbsProject *project() const;
|
||||
};
|
||||
class QbsBuildSystem;
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// QbsGroupNode:
|
||||
@@ -106,8 +87,7 @@ class QbsProjectNode : public ProjectExplorer::ProjectNode
|
||||
public:
|
||||
explicit QbsProjectNode(const Utils::FilePath &projectDirectory);
|
||||
|
||||
virtual QbsProject *project() const;
|
||||
const qbs::Project qbsProject() const;
|
||||
virtual ProjectExplorer::Project *project() const;
|
||||
const qbs::ProjectData qbsProjectData() const { return m_projectData; }
|
||||
|
||||
void setProjectData(const qbs::ProjectData &data); // FIXME: Needed?
|
||||
@@ -125,12 +105,12 @@ private:
|
||||
class QbsRootProjectNode : public QbsProjectNode
|
||||
{
|
||||
public:
|
||||
explicit QbsRootProjectNode(QbsProject *project);
|
||||
explicit QbsRootProjectNode(ProjectExplorer::Project *project);
|
||||
|
||||
QbsProject *project() const override { return m_project; }
|
||||
ProjectExplorer::Project *project() const override { return m_project; }
|
||||
|
||||
private:
|
||||
QbsProject *const m_project;
|
||||
ProjectExplorer::Project *const m_project;
|
||||
};
|
||||
|
||||
|
||||
|
@@ -203,19 +203,19 @@ QStringList unreferencedBuildSystemFiles(const qbs::Project &p)
|
||||
|
||||
} // namespace
|
||||
|
||||
std::unique_ptr<QbsRootProjectNode> QbsNodeTreeBuilder::buildTree(QbsProject *project)
|
||||
std::unique_ptr<QbsRootProjectNode> QbsNodeTreeBuilder::buildTree(QbsBuildSystem *buildSystem)
|
||||
{
|
||||
if (!project->qbsProjectData().isValid())
|
||||
if (!buildSystem->qbsProjectData().isValid())
|
||||
return {};
|
||||
|
||||
auto root = std::make_unique<QbsRootProjectNode>(project);
|
||||
setupProjectNode(root.get(), project->qbsProjectData(), project->qbsProject());
|
||||
auto root = std::make_unique<QbsRootProjectNode>(buildSystem->project());
|
||||
setupProjectNode(root.get(), buildSystem->qbsProjectData(), buildSystem->qbsProject());
|
||||
|
||||
auto buildSystemFiles = std::make_unique<FolderNode>(project->projectDirectory());
|
||||
auto buildSystemFiles = std::make_unique<FolderNode>(buildSystem->projectDirectory());
|
||||
buildSystemFiles->setDisplayName(QCoreApplication::translate("QbsRootProjectNode", "Qbs files"));
|
||||
|
||||
const FilePath base = project->projectDirectory();
|
||||
const QStringList files = unreferencedBuildSystemFiles(project->qbsProject());
|
||||
const FilePath base = buildSystem->projectDirectory();
|
||||
const QStringList files = unreferencedBuildSystemFiles(buildSystem->qbsProject());
|
||||
for (const QString &f : files) {
|
||||
const FilePath filePath = FilePath::fromString(f);
|
||||
if (filePath.isChildOf(base))
|
||||
|
@@ -39,7 +39,7 @@ namespace Internal {
|
||||
class QbsNodeTreeBuilder
|
||||
{
|
||||
public:
|
||||
static std::unique_ptr<QbsRootProjectNode> buildTree(QbsProject *project);
|
||||
static std::unique_ptr<QbsRootProjectNode> buildTree(QbsBuildSystem *project);
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
@@ -127,57 +127,16 @@ private:
|
||||
|
||||
QbsProject::QbsProject(const FilePath &fileName)
|
||||
: Project(Constants::MIME_TYPE, fileName)
|
||||
, m_cppCodeModelUpdater(new CppTools::CppProjectUpdater)
|
||||
{
|
||||
m_parsingDelay.setInterval(1000); // delay parsing by 1s.
|
||||
|
||||
setId(Constants::PROJECT_ID);
|
||||
setProjectLanguages(Context(ProjectExplorer::Constants::CXX_LANGUAGE_ID));
|
||||
setCanBuildProducts();
|
||||
|
||||
setBuildSystemCreator([](Project *p) { return new QbsBuildSystem(p); });
|
||||
|
||||
rebuildProjectTree();
|
||||
|
||||
connect(this, &Project::activeTargetChanged, this, &QbsProject::changeActiveTarget);
|
||||
connect(this, &Project::addedTarget, this, [this](Target *t) {
|
||||
m_qbsProjects.insert(t, qbs::Project());
|
||||
});
|
||||
connect(this, &Project::removedTarget, this, [this](Target *t) {
|
||||
const auto it = m_qbsProjects.find(t);
|
||||
QTC_ASSERT(it != m_qbsProjects.end(), return);
|
||||
if (it.value() == m_qbsProject) {
|
||||
m_qbsProject = qbs::Project();
|
||||
m_projectData = qbs::ProjectData();
|
||||
}
|
||||
m_qbsProjects.erase(it);
|
||||
});
|
||||
|
||||
connect(this, &Project::activeBuildConfigurationChanged,
|
||||
this, &QbsProject::delayParsing);
|
||||
|
||||
connect(&m_parsingDelay, &QTimer::timeout, this, &QbsProject::startParsing);
|
||||
|
||||
connect(this, &QbsProject::projectFileIsDirty, this, &QbsProject::delayParsing);
|
||||
setDisplayName(fileName.toFileInfo().completeBaseName());
|
||||
}
|
||||
|
||||
QbsProject::~QbsProject()
|
||||
{
|
||||
delete m_cppCodeModelUpdater;
|
||||
delete m_qbsProjectParser;
|
||||
delete m_importer;
|
||||
if (m_qbsUpdateFutureInterface) {
|
||||
m_qbsUpdateFutureInterface->reportCanceled();
|
||||
m_qbsUpdateFutureInterface->reportFinished();
|
||||
delete m_qbsUpdateFutureInterface;
|
||||
m_qbsUpdateFutureInterface = nullptr;
|
||||
}
|
||||
qDeleteAll(m_extraCompilers);
|
||||
}
|
||||
|
||||
void QbsProject::projectLoaded()
|
||||
{
|
||||
m_parsingDelay.start(0);
|
||||
}
|
||||
|
||||
ProjectImporter *QbsProject::projectImporter() const
|
||||
@@ -187,12 +146,223 @@ ProjectImporter *QbsProject::projectImporter() const
|
||||
return m_importer;
|
||||
}
|
||||
|
||||
QVariant QbsProject::additionalData(Id id, const Target *target) const
|
||||
// --------------------------------------------------------------------
|
||||
// QbsBuildSystem:
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
static const QbsProjectNode *parentQbsProjectNode(const ProjectExplorer::Node *node)
|
||||
{
|
||||
for (const ProjectExplorer::FolderNode *pn = node->managingProject(); pn; pn = pn->parentProjectNode()) {
|
||||
const auto prjNode = dynamic_cast<const QbsProjectNode *>(pn);
|
||||
if (prjNode)
|
||||
return prjNode;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static const QbsProductNode *parentQbsProductNode(const ProjectExplorer::Node *node)
|
||||
{
|
||||
for (; node; node = node->parentFolderNode()) {
|
||||
const auto prdNode = dynamic_cast<const QbsProductNode *>(node);
|
||||
if (prdNode)
|
||||
return prdNode;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static bool supportsNodeAction(ProjectAction action, const Node *node)
|
||||
{
|
||||
const Project * const project = parentQbsProjectNode(node)->project();
|
||||
Target *t = project ? project->activeTarget() : nullptr;
|
||||
QbsBuildSystem *bs = t ? static_cast<QbsBuildSystem *>(t->buildSystem()) : nullptr;
|
||||
if (!bs)
|
||||
return false;
|
||||
if (!bs->isProjectEditable())
|
||||
return false;
|
||||
if (action == RemoveFile || action == Rename)
|
||||
return node->asFileNode();
|
||||
return false;
|
||||
}
|
||||
|
||||
static qbs::GroupData findMainQbsGroup(const qbs::ProductData &productData)
|
||||
{
|
||||
foreach (const qbs::GroupData &grp, productData.groups()) {
|
||||
if (grp.name() == productData.name() && grp.location() == productData.location())
|
||||
return grp;
|
||||
}
|
||||
return qbs::GroupData();
|
||||
}
|
||||
|
||||
QbsBuildSystem::QbsBuildSystem(QbsBuildConfiguration *bc)
|
||||
: BuildSystem(bc->target()),
|
||||
m_cppCodeModelUpdater(new CppTools::CppProjectUpdater),
|
||||
m_buildConfiguration(bc)
|
||||
|
||||
{
|
||||
m_parsingDelay.setInterval(1000); // delay parsing by 1s.
|
||||
delayParsing();
|
||||
|
||||
connect(bc->project(), &Project::activeTargetChanged,
|
||||
this, &QbsBuildSystem::changeActiveTarget);
|
||||
|
||||
connect(bc->target(), &Target::activeBuildConfigurationChanged,
|
||||
this, &QbsBuildSystem::delayParsing);
|
||||
|
||||
connect(&m_parsingDelay, &QTimer::timeout, this, &QbsBuildSystem::triggerParsing);
|
||||
|
||||
connect(bc->project(), &Project::projectFileIsDirty, this, &QbsBuildSystem::delayParsing);
|
||||
|
||||
rebuildProjectTree();
|
||||
}
|
||||
|
||||
QbsBuildSystem::~QbsBuildSystem()
|
||||
{
|
||||
delete m_cppCodeModelUpdater;
|
||||
delete m_qbsProjectParser;
|
||||
if (m_qbsUpdateFutureInterface) {
|
||||
m_qbsUpdateFutureInterface->reportCanceled();
|
||||
m_qbsUpdateFutureInterface->reportFinished();
|
||||
delete m_qbsUpdateFutureInterface;
|
||||
m_qbsUpdateFutureInterface = nullptr;
|
||||
}
|
||||
qDeleteAll(m_extraCompilers);
|
||||
}
|
||||
|
||||
bool QbsBuildSystem::supportsAction(Node *context, ProjectAction action, const Node *node) const
|
||||
{
|
||||
if (dynamic_cast<QbsGroupNode *>(context)) {
|
||||
if (action == AddNewFile || action == AddExistingFile)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (dynamic_cast<QbsProductNode *>(context)) {
|
||||
if (action == AddNewFile || action == AddExistingFile)
|
||||
return true;
|
||||
}
|
||||
|
||||
return supportsNodeAction(action, node);
|
||||
}
|
||||
|
||||
bool QbsBuildSystem::addFiles(Node *context, const QStringList &filePaths, QStringList *notAdded)
|
||||
{
|
||||
if (auto n = dynamic_cast<QbsGroupNode *>(context)) {
|
||||
QStringList notAddedDummy;
|
||||
if (!notAdded)
|
||||
notAdded = ¬AddedDummy;
|
||||
|
||||
const QbsProjectNode *prjNode = parentQbsProjectNode(n);
|
||||
if (!prjNode || !qbsProject().isValid()) {
|
||||
*notAdded += filePaths;
|
||||
return false;
|
||||
}
|
||||
|
||||
const QbsProductNode *prdNode = parentQbsProductNode(n);
|
||||
if (!prdNode || !prdNode->qbsProductData().isValid()) {
|
||||
*notAdded += filePaths;
|
||||
return false;
|
||||
}
|
||||
|
||||
return addFilesToProduct(filePaths, prdNode->qbsProductData(), n->m_qbsGroupData, notAdded);
|
||||
}
|
||||
|
||||
if (auto n = dynamic_cast<QbsProductNode *>(context)) {
|
||||
QStringList notAddedDummy;
|
||||
if (!notAdded)
|
||||
notAdded = ¬AddedDummy;
|
||||
|
||||
const QbsProjectNode *prjNode = parentQbsProjectNode(n);
|
||||
if (!prjNode || !qbsProject().isValid()) {
|
||||
*notAdded += filePaths;
|
||||
return false;
|
||||
}
|
||||
|
||||
qbs::GroupData grp = findMainQbsGroup(n->qbsProductData());
|
||||
if (grp.isValid())
|
||||
return addFilesToProduct(filePaths, n->qbsProductData(), grp, notAdded);
|
||||
|
||||
QTC_ASSERT(false, return false);
|
||||
}
|
||||
|
||||
return BuildSystem::addFiles(context, filePaths, notAdded);
|
||||
}
|
||||
|
||||
RemovedFilesFromProject QbsBuildSystem::removeFiles(Node *context, const QStringList &filePaths,
|
||||
QStringList *notRemoved)
|
||||
{
|
||||
if (auto n = dynamic_cast<QbsGroupNode *>(context)) {
|
||||
QStringList notRemovedDummy;
|
||||
if (!notRemoved)
|
||||
notRemoved = ¬RemovedDummy;
|
||||
|
||||
const QbsProjectNode *prjNode = parentQbsProjectNode(n);
|
||||
if (!prjNode || !qbsProject().isValid()) {
|
||||
*notRemoved += filePaths;
|
||||
return RemovedFilesFromProject::Error;
|
||||
}
|
||||
|
||||
const QbsProductNode *prdNode = parentQbsProductNode(n);
|
||||
if (!prdNode || !prdNode->qbsProductData().isValid()) {
|
||||
*notRemoved += filePaths;
|
||||
return RemovedFilesFromProject::Error;
|
||||
}
|
||||
|
||||
return removeFilesFromProduct(filePaths, prdNode->qbsProductData(),
|
||||
n->m_qbsGroupData, notRemoved);
|
||||
}
|
||||
|
||||
if (auto n = dynamic_cast<QbsProductNode *>(context)) {
|
||||
QStringList notRemovedDummy;
|
||||
if (!notRemoved)
|
||||
notRemoved = ¬RemovedDummy;
|
||||
|
||||
const QbsProjectNode *prjNode = parentQbsProjectNode(n);
|
||||
if (!prjNode || !qbsProject().isValid()) {
|
||||
*notRemoved += filePaths;
|
||||
return RemovedFilesFromProject::Error;
|
||||
}
|
||||
|
||||
qbs::GroupData grp = findMainQbsGroup(n->qbsProductData());
|
||||
if (grp.isValid()) {
|
||||
return removeFilesFromProduct(filePaths, n->qbsProductData(), grp, notRemoved);
|
||||
}
|
||||
|
||||
QTC_ASSERT(false, return RemovedFilesFromProject::Error);
|
||||
}
|
||||
|
||||
return BuildSystem::removeFiles(context, filePaths, notRemoved);
|
||||
}
|
||||
|
||||
bool QbsBuildSystem::renameFile(Node *context, const QString &filePath, const QString &newFilePath)
|
||||
{
|
||||
if (auto *n = dynamic_cast<QbsGroupNode *>(context)) {
|
||||
const QbsProjectNode *prjNode = parentQbsProjectNode(n);
|
||||
if (!prjNode || !qbsProject().isValid())
|
||||
return false;
|
||||
const QbsProductNode *prdNode = parentQbsProductNode(n);
|
||||
if (!prdNode || !prdNode->qbsProductData().isValid())
|
||||
return false;
|
||||
|
||||
return renameFileInProduct(filePath, newFilePath,
|
||||
prdNode->qbsProductData(), n->m_qbsGroupData);
|
||||
}
|
||||
|
||||
if (auto *n = dynamic_cast<QbsProductNode *>(context)) {
|
||||
const QbsProjectNode * prjNode = parentQbsProjectNode(n);
|
||||
if (!prjNode || !qbsProject().isValid())
|
||||
return false;
|
||||
const qbs::GroupData grp = findMainQbsGroup(n->qbsProductData());
|
||||
QTC_ASSERT(grp.isValid(), return false);
|
||||
return renameFileInProduct(filePath, newFilePath, n->qbsProductData(), grp);
|
||||
}
|
||||
|
||||
return BuildSystem::renameFile(context, filePath, newFilePath);
|
||||
}
|
||||
|
||||
QVariant QbsBuildSystem::additionalData(Id id) const
|
||||
{
|
||||
if (id == "QmlDesignerImportPath") {
|
||||
const qbs::Project qbsProject = m_qbsProjects.value(const_cast<Target *>(target));
|
||||
const qbs::ProjectData projectData = qbsProject.isValid()
|
||||
? qbsProject.projectData() : qbs::ProjectData();
|
||||
const qbs::ProjectData projectData = m_qbsProject.isValid()
|
||||
? m_qbsProject.projectData() : qbs::ProjectData();
|
||||
QStringList designerImportPaths;
|
||||
foreach (const qbs::ProductData &product, projectData.allProducts()) {
|
||||
designerImportPaths << product.properties()
|
||||
@@ -200,7 +370,7 @@ QVariant QbsProject::additionalData(Id id, const Target *target) const
|
||||
}
|
||||
return designerImportPaths;
|
||||
}
|
||||
return Project::additionalData(id, target);
|
||||
return BuildSystem::additionalData(id);
|
||||
}
|
||||
|
||||
ProjectExplorer::DeploymentKnowledge QbsProject::deploymentKnowledge() const
|
||||
@@ -208,7 +378,7 @@ ProjectExplorer::DeploymentKnowledge QbsProject::deploymentKnowledge() const
|
||||
return DeploymentKnowledge::Perfect;
|
||||
}
|
||||
|
||||
QStringList QbsProject::filesGeneratedFrom(const QString &sourceFile) const
|
||||
QStringList QbsBuildSystem::filesGeneratedFrom(const QString &sourceFile) const
|
||||
{
|
||||
QStringList generated;
|
||||
foreach (const qbs::ProductData &data, m_projectData.allProducts())
|
||||
@@ -216,12 +386,12 @@ QStringList QbsProject::filesGeneratedFrom(const QString &sourceFile) const
|
||||
return generated;
|
||||
}
|
||||
|
||||
bool QbsProject::isProjectEditable() const
|
||||
bool QbsBuildSystem::isProjectEditable() const
|
||||
{
|
||||
return m_qbsProject.isValid() && !isParsing() && !BuildManager::isBuilding();
|
||||
}
|
||||
|
||||
bool QbsProject::ensureWriteableQbsFile(const QString &file)
|
||||
bool QbsBuildSystem::ensureWriteableQbsFile(const QString &file)
|
||||
{
|
||||
// Ensure that the file is not read only
|
||||
QFileInfo fi(file);
|
||||
@@ -242,9 +412,9 @@ bool QbsProject::ensureWriteableQbsFile(const QString &file)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QbsProject::addFilesToProduct(const QStringList &filePaths,
|
||||
const qbs::ProductData productData,
|
||||
const qbs::GroupData groupData, QStringList *notAdded)
|
||||
bool QbsBuildSystem::addFilesToProduct(const QStringList &filePaths,
|
||||
const qbs::ProductData productData,
|
||||
const qbs::GroupData groupData, QStringList *notAdded)
|
||||
{
|
||||
QTC_ASSERT(m_qbsProject.isValid(), return false);
|
||||
QStringList allPaths = groupData.allFilePaths();
|
||||
@@ -267,10 +437,10 @@ bool QbsProject::addFilesToProduct(const QStringList &filePaths,
|
||||
return notAdded->isEmpty();
|
||||
}
|
||||
|
||||
RemovedFilesFromProject QbsProject::removeFilesFromProduct(const QStringList &filePaths,
|
||||
const qbs::ProductData &productData,
|
||||
const qbs::GroupData &groupData,
|
||||
QStringList *notRemoved)
|
||||
RemovedFilesFromProject QbsBuildSystem::removeFilesFromProduct(const QStringList &filePaths,
|
||||
const qbs::ProductData &productData,
|
||||
const qbs::GroupData &groupData,
|
||||
QStringList *notRemoved)
|
||||
{
|
||||
QTC_ASSERT(m_qbsProject.isValid(), return RemovedFilesFromProject::Error);
|
||||
|
||||
@@ -313,9 +483,9 @@ RemovedFilesFromProject QbsProject::removeFilesFromProduct(const QStringList &fi
|
||||
return RemovedFilesFromProject::Ok;
|
||||
}
|
||||
|
||||
bool QbsProject::renameFileInProduct(const QString &oldPath, const QString &newPath,
|
||||
const qbs::ProductData productData,
|
||||
const qbs::GroupData groupData)
|
||||
bool QbsBuildSystem::renameFileInProduct(const QString &oldPath, const QString &newPath,
|
||||
const qbs::ProductData productData,
|
||||
const qbs::GroupData groupData)
|
||||
{
|
||||
if (newPath.isEmpty())
|
||||
return false;
|
||||
@@ -326,7 +496,7 @@ bool QbsProject::renameFileInProduct(const QString &oldPath, const QString &newP
|
||||
}
|
||||
qbs::ProductData newProductData;
|
||||
foreach (const qbs::ProductData &p, m_projectData.allProducts()) {
|
||||
if (uniqueProductName(p) == uniqueProductName(productData)) {
|
||||
if (QbsProject::uniqueProductName(p) == QbsProject::uniqueProductName(productData)) {
|
||||
newProductData = p;
|
||||
break;
|
||||
}
|
||||
@@ -365,8 +535,8 @@ static qbs::AbstractJob *doBuildOrClean(const qbs::Project &project,
|
||||
}
|
||||
|
||||
template<typename Options>
|
||||
qbs::AbstractJob *QbsProject::buildOrClean(const Options &opts, const QStringList &productNames,
|
||||
QString &error)
|
||||
qbs::AbstractJob *QbsBuildSystem::buildOrClean(const Options &opts, const QStringList &productNames,
|
||||
QString &error)
|
||||
{
|
||||
QTC_ASSERT(qbsProject().isValid(), return nullptr);
|
||||
QTC_ASSERT(!isParsing(), return nullptr);
|
||||
@@ -375,7 +545,7 @@ qbs::AbstractJob *QbsProject::buildOrClean(const Options &opts, const QStringLis
|
||||
foreach (const QString &productName, productNames) {
|
||||
bool found = false;
|
||||
foreach (const qbs::ProductData &data, qbsProjectData().allProducts()) {
|
||||
if (uniqueProductName(data) == productName) {
|
||||
if (QbsProject::uniqueProductName(data) == productName) {
|
||||
found = true;
|
||||
products.append(data);
|
||||
break;
|
||||
@@ -391,41 +561,41 @@ qbs::AbstractJob *QbsProject::buildOrClean(const Options &opts, const QStringLis
|
||||
return doBuildOrClean(qbsProject(), products, opts);
|
||||
}
|
||||
|
||||
qbs::BuildJob *QbsProject::build(const qbs::BuildOptions &opts, QStringList productNames,
|
||||
QString &error)
|
||||
qbs::BuildJob *QbsBuildSystem::build(const qbs::BuildOptions &opts, QStringList productNames,
|
||||
QString &error)
|
||||
{
|
||||
return static_cast<qbs::BuildJob *>(buildOrClean(opts, productNames, error));
|
||||
}
|
||||
|
||||
qbs::CleanJob *QbsProject::clean(const qbs::CleanOptions &opts, const QStringList &productNames,
|
||||
QString &error)
|
||||
qbs::CleanJob *QbsBuildSystem::clean(const qbs::CleanOptions &opts, const QStringList &productNames,
|
||||
QString &error)
|
||||
{
|
||||
return static_cast<qbs::CleanJob *>(buildOrClean(opts, productNames, error));
|
||||
}
|
||||
|
||||
qbs::InstallJob *QbsProject::install(const qbs::InstallOptions &opts)
|
||||
qbs::InstallJob *QbsBuildSystem::install(const qbs::InstallOptions &opts)
|
||||
{
|
||||
if (!qbsProject().isValid())
|
||||
return nullptr;
|
||||
return qbsProject().installAllProducts(opts);
|
||||
}
|
||||
|
||||
QString QbsProject::profileForTarget(const Target *t) const
|
||||
QString QbsBuildSystem::profile() const
|
||||
{
|
||||
return QbsManager::profileForKit(t->kit());
|
||||
return QbsManager::profileForKit(target()->kit());
|
||||
}
|
||||
|
||||
qbs::Project QbsProject::qbsProject() const
|
||||
qbs::Project QbsBuildSystem::qbsProject() const
|
||||
{
|
||||
return m_qbsProject;
|
||||
}
|
||||
|
||||
qbs::ProjectData QbsProject::qbsProjectData() const
|
||||
qbs::ProjectData QbsBuildSystem::qbsProjectData() const
|
||||
{
|
||||
return m_projectData;
|
||||
}
|
||||
|
||||
bool QbsProject::checkCancelStatus()
|
||||
bool QbsBuildSystem::checkCancelStatus()
|
||||
{
|
||||
const CancelStatus cancelStatus = m_cancelStatus;
|
||||
m_cancelStatus = CancelStatusNone;
|
||||
@@ -439,7 +609,7 @@ bool QbsProject::checkCancelStatus()
|
||||
return true;
|
||||
}
|
||||
|
||||
void QbsProject::updateAfterParse()
|
||||
void QbsBuildSystem::updateAfterParse()
|
||||
{
|
||||
qCDebug(qbsPmLog) << "Updating data after parse";
|
||||
OpTimer opTimer("updateAfterParse");
|
||||
@@ -448,27 +618,24 @@ void QbsProject::updateAfterParse()
|
||||
updateBuildTargetData();
|
||||
updateCppCodeModel();
|
||||
updateQmlJsCodeModel();
|
||||
emit fileListChanged();
|
||||
emit project()->fileListChanged();
|
||||
m_envCache.clear();
|
||||
emit dataChanged();
|
||||
}
|
||||
|
||||
void QbsProject::delayedUpdateAfterParse()
|
||||
void QbsBuildSystem::delayedUpdateAfterParse()
|
||||
{
|
||||
QTimer::singleShot(0, this, &QbsProject::updateAfterParse);
|
||||
QTimer::singleShot(0, this, &QbsBuildSystem::updateAfterParse);
|
||||
}
|
||||
|
||||
void QbsProject::updateProjectNodes()
|
||||
void QbsBuildSystem::updateProjectNodes()
|
||||
{
|
||||
OpTimer opTimer("updateProjectNodes");
|
||||
rebuildProjectTree();
|
||||
}
|
||||
|
||||
FilePath QbsProject::installRoot()
|
||||
FilePath QbsBuildSystem::installRoot()
|
||||
{
|
||||
if (!activeTarget())
|
||||
return FilePath();
|
||||
const auto dc = activeTarget()->activeDeployConfiguration();
|
||||
const auto dc = target()->activeDeployConfiguration();
|
||||
if (dc) {
|
||||
const QList<BuildStep *> steps = dc->stepList()->steps();
|
||||
for (const BuildStep * const step : steps) {
|
||||
@@ -478,15 +645,11 @@ FilePath QbsProject::installRoot()
|
||||
return FilePath::fromString(qbsInstallStep->installRoot());
|
||||
}
|
||||
}
|
||||
const auto * const bc
|
||||
= qobject_cast<QbsBuildConfiguration *>(activeTarget()->activeBuildConfiguration());
|
||||
if (!bc)
|
||||
return FilePath();
|
||||
const QbsBuildStep * const buildStep = bc->qbsStep();
|
||||
const QbsBuildStep * const buildStep = m_buildConfiguration->qbsStep();
|
||||
return buildStep && buildStep->install() ? buildStep->installRoot() : FilePath();
|
||||
}
|
||||
|
||||
void QbsProject::handleQbsParsingDone(bool success)
|
||||
void QbsBuildSystem::handleQbsParsingDone(bool success)
|
||||
{
|
||||
QTC_ASSERT(m_qbsProjectParser, return);
|
||||
QTC_ASSERT(m_qbsUpdateFutureInterface, return);
|
||||
@@ -499,7 +662,6 @@ void QbsProject::handleQbsParsingDone(bool success)
|
||||
generateErrors(m_qbsProjectParser->error());
|
||||
|
||||
m_qbsProject = m_qbsProjectParser->qbsProject();
|
||||
m_qbsProjects.insert(activeTarget(), m_qbsProject);
|
||||
bool dataChanged = false;
|
||||
bool envChanged = m_lastParseEnv != m_qbsProjectParser->environment();
|
||||
m_lastParseEnv = m_qbsProjectParser->environment();
|
||||
@@ -528,14 +690,14 @@ void QbsProject::handleQbsParsingDone(bool success)
|
||||
m_guard = {};
|
||||
}
|
||||
|
||||
void QbsProject::rebuildProjectTree()
|
||||
void QbsBuildSystem::rebuildProjectTree()
|
||||
{
|
||||
std::unique_ptr<QbsRootProjectNode> newRoot = Internal::QbsNodeTreeBuilder::buildTree(this);
|
||||
setDisplayName(newRoot ? newRoot->displayName() : projectFilePath().toFileInfo().completeBaseName());
|
||||
setRootProjectNode(std::move(newRoot));
|
||||
project()->setDisplayName(newRoot ? newRoot->displayName() : projectFilePath().toFileInfo().completeBaseName());
|
||||
project()->setRootProjectNode(std::move(newRoot));
|
||||
}
|
||||
|
||||
void QbsProject::handleRuleExecutionDone()
|
||||
void QbsBuildSystem::handleRuleExecutionDone()
|
||||
{
|
||||
qCDebug(qbsPmLog) << "Rule execution done";
|
||||
|
||||
@@ -553,28 +715,17 @@ void QbsProject::handleRuleExecutionDone()
|
||||
updateAfterParse();
|
||||
}
|
||||
|
||||
void QbsProject::changeActiveTarget(Target *t)
|
||||
void QbsBuildSystem::changeActiveTarget(Target *t)
|
||||
{
|
||||
bool targetFound = false;
|
||||
for (auto it = m_qbsProjects.begin(); it != m_qbsProjects.end(); ++it) {
|
||||
qbs::Project &qbsProjectForTarget = it.value();
|
||||
if (it.key() == t) {
|
||||
m_qbsProject = qbsProjectForTarget;
|
||||
targetFound = true;
|
||||
} else if (qbsProjectForTarget.isValid() && !BuildManager::isBuilding(it.key())) {
|
||||
qbsProjectForTarget = qbs::Project();
|
||||
}
|
||||
}
|
||||
QTC_ASSERT(targetFound || !t, m_qbsProject = qbs::Project());
|
||||
if (t && t->isActive())
|
||||
if (t)
|
||||
delayParsing();
|
||||
}
|
||||
|
||||
void QbsProject::startParsing()
|
||||
void QbsBuildSystem::triggerParsing()
|
||||
{
|
||||
// Qbs does update the build graph during the build. So we cannot
|
||||
// start to parse while a build is running or we will lose information.
|
||||
if (BuildManager::isBuilding(this)) {
|
||||
if (BuildManager::isBuilding(project())) {
|
||||
scheduleParsing();
|
||||
return;
|
||||
}
|
||||
@@ -582,12 +733,13 @@ void QbsProject::startParsing()
|
||||
parseCurrentBuildConfiguration();
|
||||
}
|
||||
|
||||
void QbsProject::delayParsing()
|
||||
void QbsBuildSystem::delayParsing()
|
||||
{
|
||||
m_parsingDelay.start();
|
||||
if (m_buildConfiguration->isActive())
|
||||
m_parsingDelay.start();
|
||||
}
|
||||
|
||||
void QbsProject::parseCurrentBuildConfiguration()
|
||||
void QbsBuildSystem::parseCurrentBuildConfiguration()
|
||||
{
|
||||
m_parsingScheduled = false;
|
||||
if (m_cancelStatus == CancelStatusCancelingForReparse)
|
||||
@@ -598,12 +750,6 @@ void QbsProject::parseCurrentBuildConfiguration()
|
||||
// but of course not while canceling is in progress).
|
||||
QTC_ASSERT(m_cancelStatus == CancelStatusNone, return);
|
||||
|
||||
if (!activeTarget())
|
||||
return;
|
||||
auto bc = qobject_cast<QbsBuildConfiguration *>(activeTarget()->activeBuildConfiguration());
|
||||
if (!bc)
|
||||
return;
|
||||
|
||||
// New parse requests override old ones.
|
||||
// NOTE: We need to wait for the current operation to finish, since otherwise there could
|
||||
// be a conflict. Consider the case where the old qbs::ProjectSetupJob is writing
|
||||
@@ -616,28 +762,44 @@ void QbsProject::parseCurrentBuildConfiguration()
|
||||
return;
|
||||
}
|
||||
|
||||
parse(bc->qbsConfiguration(), bc->environment(), bc->buildDirectory().toString(),
|
||||
bc->configurationName());
|
||||
QVariantMap config = m_buildConfiguration->qbsConfiguration();
|
||||
Environment env = m_buildConfiguration->environment();
|
||||
QString dir = m_buildConfiguration->buildDirectory().toString();
|
||||
|
||||
m_guard = guardParsingRun();
|
||||
|
||||
prepareForParsing();
|
||||
|
||||
m_parsingDelay.stop();
|
||||
|
||||
QTC_ASSERT(!m_qbsProjectParser, return);
|
||||
m_qbsProjectParser = new QbsProjectParser(this, m_qbsUpdateFutureInterface);
|
||||
|
||||
connect(m_qbsProjectParser, &QbsProjectParser::ruleExecutionDone,
|
||||
this, &QbsBuildSystem::handleRuleExecutionDone);
|
||||
connect(m_qbsProjectParser, &QbsProjectParser::done,
|
||||
this, &QbsBuildSystem::handleQbsParsingDone);
|
||||
|
||||
QbsManager::updateProfileIfNecessary(target()->kit());
|
||||
m_qbsProjectParser->parse(config, env, dir, m_buildConfiguration->configurationName());
|
||||
}
|
||||
|
||||
void QbsProject::cancelParsing()
|
||||
void QbsBuildSystem::cancelParsing()
|
||||
{
|
||||
QTC_ASSERT(m_qbsProjectParser, return);
|
||||
m_cancelStatus = CancelStatusCancelingAltoghether;
|
||||
m_qbsProjectParser->cancel();
|
||||
}
|
||||
|
||||
void QbsProject::updateAfterBuild()
|
||||
void QbsBuildSystem::updateAfterBuild()
|
||||
{
|
||||
OpTimer opTimer("updateAfterBuild");
|
||||
QTC_ASSERT(m_qbsProject.isValid(), return);
|
||||
const qbs::ProjectData &projectData = m_qbsProject.projectData();
|
||||
if (projectData == m_projectData) {
|
||||
if (activeTarget()) {
|
||||
DeploymentData deploymentData = activeTarget()->deploymentData();
|
||||
deploymentData.setLocalInstallRoot(installRoot());
|
||||
activeTarget()->setDeploymentData(deploymentData);
|
||||
}
|
||||
DeploymentData deploymentDataTmp = deploymentData();
|
||||
deploymentDataTmp.setLocalInstallRoot(installRoot());
|
||||
setDeploymentData(deploymentDataTmp);
|
||||
return;
|
||||
}
|
||||
qCDebug(qbsPmLog) << "Updating data after build";
|
||||
@@ -649,29 +811,9 @@ void QbsProject::updateAfterBuild()
|
||||
updateCppCodeModel();
|
||||
}
|
||||
m_envCache.clear();
|
||||
emit dataChanged();
|
||||
}
|
||||
|
||||
void QbsProject::registerQbsProjectParser(QbsProjectParser *p)
|
||||
{
|
||||
m_parsingDelay.stop();
|
||||
|
||||
if (m_qbsProjectParser) {
|
||||
m_qbsProjectParser->disconnect(this);
|
||||
m_qbsProjectParser->deleteLater();
|
||||
}
|
||||
|
||||
m_qbsProjectParser = p;
|
||||
|
||||
if (p) {
|
||||
connect(m_qbsProjectParser, &QbsProjectParser::ruleExecutionDone,
|
||||
this, &QbsProject::handleRuleExecutionDone);
|
||||
connect(m_qbsProjectParser, &QbsProjectParser::done,
|
||||
this, &QbsProject::handleQbsParsingDone);
|
||||
}
|
||||
}
|
||||
|
||||
void QbsProject::generateErrors(const qbs::ErrorInfo &e)
|
||||
void QbsBuildSystem::generateErrors(const qbs::ErrorInfo &e)
|
||||
{
|
||||
foreach (const qbs::ErrorItem &item, e.items())
|
||||
TaskHub::addTask(Task::Error, item.description(),
|
||||
@@ -697,24 +839,11 @@ void QbsProject::configureAsExampleProject()
|
||||
}
|
||||
}
|
||||
setup(infoList);
|
||||
prepareForParsing();
|
||||
if (activeTarget())
|
||||
static_cast<QbsBuildSystem *>(activeTarget()->buildSystem())->prepareForParsing();
|
||||
}
|
||||
|
||||
void QbsProject::parse(const QVariantMap &config, const Environment &env, const QString &dir,
|
||||
const QString &configName)
|
||||
{
|
||||
m_guard = guardParsingRun();
|
||||
|
||||
prepareForParsing();
|
||||
QTC_ASSERT(!m_qbsProjectParser, return);
|
||||
|
||||
registerQbsProjectParser(new QbsProjectParser(this, m_qbsUpdateFutureInterface));
|
||||
|
||||
QbsManager::updateProfileIfNecessary(activeTarget()->kit());
|
||||
m_qbsProjectParser->parse(config, env, dir, configName);
|
||||
}
|
||||
|
||||
void QbsProject::prepareForParsing()
|
||||
void QbsBuildSystem::prepareForParsing()
|
||||
{
|
||||
TaskHub::clearTasks(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM);
|
||||
if (m_qbsUpdateFutureInterface) {
|
||||
@@ -727,11 +856,11 @@ void QbsProject::prepareForParsing()
|
||||
m_qbsUpdateFutureInterface = new QFutureInterface<bool>();
|
||||
m_qbsUpdateFutureInterface->setProgressRange(0, 0);
|
||||
ProgressManager::addTask(m_qbsUpdateFutureInterface->future(),
|
||||
tr("Reading Project \"%1\"").arg(displayName()), "Qbs.QbsEvaluate");
|
||||
tr("Reading Project \"%1\"").arg(project()->displayName()), "Qbs.QbsEvaluate");
|
||||
m_qbsUpdateFutureInterface->reportStarted();
|
||||
}
|
||||
|
||||
void QbsProject::updateDocuments(const std::set<QString> &files)
|
||||
void QbsBuildSystem::updateDocuments(const std::set<QString> &files)
|
||||
{
|
||||
OpTimer opTimer("updateDocuments");
|
||||
|
||||
@@ -742,7 +871,7 @@ void QbsProject::updateDocuments(const std::set<QString> &files)
|
||||
[buildDir](const FilePath &p) {
|
||||
return !p.isChildOf(buildDir);
|
||||
});
|
||||
setExtraProjectFiles(nonBuildDirFilePaths);
|
||||
project()->setExtraProjectFiles(nonBuildDirFilePaths);
|
||||
}
|
||||
|
||||
static QString getMimeType(const qbs::ArtifactData &sourceFile)
|
||||
@@ -870,21 +999,20 @@ static void getExpandedCompilerFlags(QStringList &cFlags, QStringList &cxxFlags,
|
||||
}
|
||||
}
|
||||
|
||||
void QbsProject::updateCppCodeModel()
|
||||
void QbsBuildSystem::updateCppCodeModel()
|
||||
{
|
||||
OpTimer optimer("updateCppCodeModel");
|
||||
if (!m_projectData.isValid())
|
||||
return;
|
||||
|
||||
QList<ProjectExplorer::ExtraCompilerFactory *> factories =
|
||||
ProjectExplorer::ExtraCompilerFactory::extraCompilerFactories();
|
||||
const QList<ExtraCompilerFactory *> factories = ExtraCompilerFactory::extraCompilerFactories();
|
||||
const auto factoriesBegin = factories.constBegin();
|
||||
const auto factoriesEnd = factories.constEnd();
|
||||
|
||||
qDeleteAll(m_extraCompilers);
|
||||
m_extraCompilers.clear();
|
||||
|
||||
QtSupport::CppKitInfo kitInfo(this);
|
||||
QtSupport::CppKitInfo kitInfo(project());
|
||||
QTC_ASSERT(kitInfo.isValid(), return);
|
||||
|
||||
RawProjectParts rpps;
|
||||
@@ -959,7 +1087,7 @@ void QbsProject::updateCppCodeModel()
|
||||
rpp.setDisplayName(grp.name());
|
||||
rpp.setProjectFileLocation(grp.location().filePath(),
|
||||
grp.location().line(), grp.location().column());
|
||||
rpp.setBuildSystemTarget(uniqueProductName(prd));
|
||||
rpp.setBuildSystemTarget(QbsProject::uniqueProductName(prd));
|
||||
rpp.setBuildTargetType(prd.isRunnable() ? ProjectExplorer::BuildTargetType::Executable
|
||||
: ProjectExplorer::BuildTargetType::Library);
|
||||
|
||||
@@ -996,7 +1124,7 @@ void QbsProject::updateCppCodeModel()
|
||||
return Utils::FilePath::fromString(s);
|
||||
});
|
||||
m_extraCompilers.append((*i)->create(
|
||||
this, FilePath::fromString(source.filePath()), fileNames));
|
||||
project(), FilePath::fromString(source.filePath()), fileNames));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1038,10 +1166,10 @@ void QbsProject::updateCppCodeModel()
|
||||
}
|
||||
|
||||
CppTools::GeneratedCodeModelSupport::update(m_extraCompilers);
|
||||
m_cppCodeModelUpdater->update({this, kitInfo, activeParseEnvironment(), rpps});
|
||||
m_cppCodeModelUpdater->update({project(), kitInfo, activeParseEnvironment(), rpps});
|
||||
}
|
||||
|
||||
void QbsProject::updateQmlJsCodeModel()
|
||||
void QbsBuildSystem::updateQmlJsCodeModel()
|
||||
{
|
||||
OpTimer optimer("updateQmlJsCodeModel");
|
||||
QmlJS::ModelManagerInterface *modelManager = QmlJS::ModelManagerInterface::instance();
|
||||
@@ -1049,7 +1177,7 @@ void QbsProject::updateQmlJsCodeModel()
|
||||
return;
|
||||
|
||||
QmlJS::ModelManagerInterface::ProjectInfo projectInfo =
|
||||
modelManager->defaultProjectInfoForProject(this);
|
||||
modelManager->defaultProjectInfoForProject(project());
|
||||
foreach (const qbs::ProductData &product, m_projectData.allProducts()) {
|
||||
static const QString propertyName = QLatin1String("qmlImportPaths");
|
||||
foreach (const QString &path, product.properties().value(propertyName).toStringList()) {
|
||||
@@ -1058,12 +1186,12 @@ void QbsProject::updateQmlJsCodeModel()
|
||||
}
|
||||
}
|
||||
|
||||
setProjectLanguage(ProjectExplorer::Constants::QMLJS_LANGUAGE_ID,
|
||||
project()->setProjectLanguage(ProjectExplorer::Constants::QMLJS_LANGUAGE_ID,
|
||||
!projectInfo.sourceFiles.isEmpty());
|
||||
modelManager->updateProjectInfo(projectInfo, this);
|
||||
modelManager->updateProjectInfo(projectInfo, project());
|
||||
}
|
||||
|
||||
void QbsProject::updateApplicationTargets()
|
||||
void QbsBuildSystem::updateApplicationTargets()
|
||||
{
|
||||
QList<BuildTargetInfo> applications;
|
||||
foreach (const qbs::ProductData &productData, m_projectData.allProducts()) {
|
||||
@@ -1125,11 +1253,10 @@ void QbsProject::updateApplicationTargets()
|
||||
|
||||
applications.append(bti);
|
||||
}
|
||||
if (activeTarget())
|
||||
activeTarget()->setApplicationTargets(applications);
|
||||
setApplicationTargets(applications);
|
||||
}
|
||||
|
||||
void QbsProject::updateDeploymentInfo()
|
||||
void QbsBuildSystem::updateDeploymentInfo()
|
||||
{
|
||||
DeploymentData deploymentData;
|
||||
if (m_qbsProject.isValid()) {
|
||||
@@ -1139,11 +1266,10 @@ void QbsProject::updateDeploymentInfo()
|
||||
}
|
||||
}
|
||||
deploymentData.setLocalInstallRoot(installRoot());
|
||||
if (activeTarget())
|
||||
activeTarget()->setDeploymentData(deploymentData);
|
||||
setDeploymentData(deploymentData);
|
||||
}
|
||||
|
||||
void QbsProject::updateBuildTargetData()
|
||||
void QbsBuildSystem::updateBuildTargetData()
|
||||
{
|
||||
OpTimer optimer("updateBuildTargetData");
|
||||
updateApplicationTargets();
|
||||
|
@@ -41,12 +41,12 @@
|
||||
#include <QHash>
|
||||
#include <QTimer>
|
||||
|
||||
namespace Core { class IDocument; }
|
||||
namespace CppTools { class CppProjectUpdater; }
|
||||
|
||||
namespace QbsProjectManager {
|
||||
namespace Internal {
|
||||
|
||||
class QbsBuildConfiguration;
|
||||
class QbsProjectParser;
|
||||
|
||||
class QbsProject : public ProjectExplorer::Project
|
||||
@@ -55,9 +55,43 @@ class QbsProject : public ProjectExplorer::Project
|
||||
|
||||
public:
|
||||
explicit QbsProject(const Utils::FilePath &filename);
|
||||
~QbsProject() override;
|
||||
~QbsProject();
|
||||
|
||||
QStringList filesGeneratedFrom(const QString &sourceFile) const override;
|
||||
ProjectExplorer::ProjectImporter *projectImporter() const override;
|
||||
|
||||
ProjectExplorer::DeploymentKnowledge deploymentKnowledge() const override;
|
||||
|
||||
void configureAsExampleProject() final;
|
||||
|
||||
static QString uniqueProductName(const qbs::ProductData &product);
|
||||
|
||||
private:
|
||||
mutable ProjectExplorer::ProjectImporter *m_importer = nullptr;
|
||||
};
|
||||
|
||||
class QbsBuildSystem : public ProjectExplorer::BuildSystem
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit QbsBuildSystem(QbsBuildConfiguration *bc);
|
||||
~QbsBuildSystem() final;
|
||||
|
||||
void triggerParsing() final;
|
||||
bool supportsAction(ProjectExplorer::Node *context,
|
||||
ProjectExplorer::ProjectAction action,
|
||||
const ProjectExplorer::Node *node) const final;
|
||||
bool addFiles(ProjectExplorer::Node *context,
|
||||
const QStringList &filePaths,
|
||||
QStringList *notAdded = nullptr) final;
|
||||
ProjectExplorer::RemovedFilesFromProject removeFiles(ProjectExplorer::Node *context,
|
||||
const QStringList &filePaths,
|
||||
QStringList *notRemoved = nullptr) final;
|
||||
bool renameFile(ProjectExplorer::Node *context,
|
||||
const QString &filePath, const QString &newFilePath) final;
|
||||
|
||||
QStringList filesGeneratedFrom(const QString &sourceFile) const final;
|
||||
QVariant additionalData(Core::Id id) const final;
|
||||
|
||||
bool isProjectEditable() const;
|
||||
// qbs::ProductData and qbs::GroupData are held by the nodes in the project tree.
|
||||
@@ -81,39 +115,27 @@ public:
|
||||
|
||||
static ProjectExplorer::FileType fileTypeFor(const QSet<QString> &tags);
|
||||
|
||||
QString profileForTarget(const ProjectExplorer::Target *t) const;
|
||||
QString profile() const;
|
||||
void parseCurrentBuildConfiguration();
|
||||
void scheduleParsing() { m_parsingScheduled = true; }
|
||||
bool parsingScheduled() const { return m_parsingScheduled; }
|
||||
void cancelParsing();
|
||||
void updateAfterBuild();
|
||||
|
||||
void registerQbsProjectParser(QbsProjectParser *p);
|
||||
|
||||
qbs::Project qbsProject() const;
|
||||
qbs::ProjectData qbsProjectData() const;
|
||||
|
||||
void generateErrors(const qbs::ErrorInfo &e);
|
||||
|
||||
static QString uniqueProductName(const qbs::ProductData &product);
|
||||
|
||||
void configureAsExampleProject() final;
|
||||
|
||||
void delayParsing();
|
||||
|
||||
signals:
|
||||
void dataChanged();
|
||||
|
||||
private:
|
||||
friend class QbsProject;
|
||||
void handleQbsParsingDone(bool success);
|
||||
|
||||
void rebuildProjectTree();
|
||||
|
||||
void changeActiveTarget(ProjectExplorer::Target *t);
|
||||
void startParsing();
|
||||
|
||||
void parse(const QVariantMap &config, const Utils::Environment &env, const QString &dir,
|
||||
const QString &configName);
|
||||
|
||||
void prepareForParsing();
|
||||
void updateDocuments(const std::set<QString> &files);
|
||||
@@ -129,19 +151,12 @@ private:
|
||||
void updateProjectNodes();
|
||||
Utils::FilePath installRoot();
|
||||
|
||||
void projectLoaded() override;
|
||||
ProjectExplorer::ProjectImporter *projectImporter() const override;
|
||||
QVariant additionalData(Core::Id id, const ProjectExplorer::Target *target) const final;
|
||||
|
||||
ProjectExplorer::DeploymentKnowledge deploymentKnowledge() const override;
|
||||
|
||||
static bool ensureWriteableQbsFile(const QString &file);
|
||||
|
||||
template<typename Options> qbs::AbstractJob *buildOrClean(const Options &opts,
|
||||
const QStringList &productNames, QString &error);
|
||||
|
||||
QHash<ProjectExplorer::Target *, qbs::Project> m_qbsProjects;
|
||||
qbs::Project m_qbsProject; // for activeTarget()
|
||||
qbs::Project m_qbsProject;
|
||||
qbs::ProjectData m_projectData; // Cached m_qbsProject.projectData()
|
||||
Utils::Environment m_lastParseEnv;
|
||||
|
||||
@@ -158,15 +173,14 @@ private:
|
||||
|
||||
CppTools::CppProjectUpdater *m_cppCodeModelUpdater = nullptr;
|
||||
|
||||
mutable ProjectExplorer::ProjectImporter *m_importer = nullptr;
|
||||
|
||||
QTimer m_parsingDelay;
|
||||
QList<ProjectExplorer::ExtraCompiler *> m_extraCompilers;
|
||||
bool m_extraCompilersPending = false;
|
||||
|
||||
QHash<QString, Utils::Environment> m_envCache;
|
||||
|
||||
ParseGuard m_guard;
|
||||
ProjectExplorer::BuildSystem::ParseGuard m_guard;
|
||||
QbsBuildConfiguration *m_buildConfiguration = nullptr;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
@@ -246,9 +246,9 @@ bool QbsProjectManagerPlugin::initialize(const QStringList &arguments, QString *
|
||||
connect(Core::EditorManager::instance(), &Core::EditorManager::currentEditorChanged,
|
||||
this, &QbsProjectManagerPlugin::updateBuildActions);
|
||||
|
||||
connect(SessionManager::instance(), &SessionManager::projectAdded,
|
||||
this, &QbsProjectManagerPlugin::projectWasAdded);
|
||||
connect(SessionManager::instance(), &SessionManager::projectRemoved,
|
||||
connect(SessionManager::instance(), &SessionManager::targetAdded,
|
||||
this, &QbsProjectManagerPlugin::targetWasAdded);
|
||||
connect(SessionManager::instance(), &SessionManager::targetRemoved,
|
||||
this, &QbsProjectManagerPlugin::updateBuildActions);
|
||||
connect(SessionManager::instance(), &SessionManager::startupProjectChanged,
|
||||
this, &QbsProjectManagerPlugin::updateReparseQbsAction);
|
||||
@@ -264,16 +264,14 @@ bool QbsProjectManagerPlugin::initialize(const QStringList &arguments, QString *
|
||||
void QbsProjectManagerPlugin::extensionsInitialized()
|
||||
{ }
|
||||
|
||||
void QbsProjectManagerPlugin::projectWasAdded(Project *project)
|
||||
void QbsProjectManagerPlugin::targetWasAdded(Target *target)
|
||||
{
|
||||
auto qbsProject = qobject_cast<QbsProject *>(project);
|
||||
|
||||
if (!qbsProject)
|
||||
if (!qobject_cast<QbsProject *>(target->project()))
|
||||
return;
|
||||
|
||||
connect(qbsProject, &Project::parsingStarted,
|
||||
connect(target, &Target::parsingStarted,
|
||||
this, &QbsProjectManagerPlugin::projectChanged);
|
||||
connect(qbsProject, &Project::parsingFinished,
|
||||
connect(target, &Target::parsingFinished,
|
||||
this, &QbsProjectManagerPlugin::projectChanged);
|
||||
}
|
||||
|
||||
@@ -282,7 +280,8 @@ void QbsProjectManagerPlugin::updateContextActions()
|
||||
auto project = qobject_cast<Internal::QbsProject *>(ProjectTree::currentProject());
|
||||
const Node *node = ProjectTree::currentNode();
|
||||
bool isEnabled = !BuildManager::isBuilding(project)
|
||||
&& project && !project->isParsing()
|
||||
&& project && project->activeTarget()
|
||||
&& !project->activeTarget()->buildSystem()->isParsing()
|
||||
&& node && node->isEnabled();
|
||||
|
||||
const bool isFile = project && node && node->asFileNode();
|
||||
@@ -305,7 +304,8 @@ void QbsProjectManagerPlugin::updateReparseQbsAction()
|
||||
auto project = qobject_cast<QbsProject *>(SessionManager::startupProject());
|
||||
m_reparseQbs->setEnabled(project
|
||||
&& !BuildManager::isBuilding(project)
|
||||
&& !project->isParsing());
|
||||
&& project && project->activeTarget()
|
||||
&& !project->activeTarget()->buildSystem()->isParsing());
|
||||
}
|
||||
|
||||
void QbsProjectManagerPlugin::updateBuildActions()
|
||||
@@ -334,7 +334,9 @@ void QbsProjectManagerPlugin::updateBuildActions()
|
||||
}
|
||||
|
||||
if (QbsProject *editorProject = currentEditorProject()) {
|
||||
enabled = !BuildManager::isBuilding(editorProject) && !editorProject->isParsing();
|
||||
enabled = !BuildManager::isBuilding(editorProject)
|
||||
&& editorProject->activeTarget()
|
||||
&& !editorProject->activeTarget()->buildSystem()->isParsing();
|
||||
fileVisible = productNode
|
||||
|| dynamic_cast<QbsProjectNode *>(parentProjectNode)
|
||||
|| dynamic_cast<QbsGroupNode *>(parentProjectNode);
|
||||
@@ -567,12 +569,20 @@ void QbsProjectManagerPlugin::reparseProject(QbsProject *project)
|
||||
if (!project)
|
||||
return;
|
||||
|
||||
Target *t = project->activeTarget();
|
||||
if (!t)
|
||||
return;
|
||||
|
||||
QbsBuildSystem *bs = static_cast<QbsBuildSystem *>(t->buildSystem());
|
||||
if (!bs)
|
||||
return;
|
||||
|
||||
// Qbs does update the build graph during the build. So we cannot
|
||||
// start to parse while a build is running or we will lose information.
|
||||
if (BuildManager::isBuilding(project))
|
||||
project->scheduleParsing();
|
||||
bs->scheduleParsing();
|
||||
else
|
||||
project->parseCurrentBuildConfiguration();
|
||||
bs->parseCurrentBuildConfiguration();
|
||||
}
|
||||
|
||||
void QbsProjectManagerPlugin::buildNamedProduct(QbsProject *project, const QString &product)
|
||||
|
@@ -29,7 +29,7 @@
|
||||
#include <extensionsystem/iplugin.h>
|
||||
#include <utils/parameteraction.h>
|
||||
|
||||
namespace ProjectExplorer { class Project; }
|
||||
namespace ProjectExplorer { class Target; }
|
||||
|
||||
namespace QbsProjectManager {
|
||||
namespace Internal {
|
||||
@@ -51,7 +51,7 @@ private:
|
||||
bool initialize(const QStringList &arguments, QString *errorMessage) final;
|
||||
void extensionsInitialized() final;
|
||||
|
||||
void projectWasAdded(ProjectExplorer::Project *project);
|
||||
void targetWasAdded(ProjectExplorer::Target *target);
|
||||
void projectChanged();
|
||||
|
||||
void buildFileContextMenu();
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user