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:
@@ -90,7 +90,7 @@ class CentralizedFolderWatcher : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
CentralizedFolderWatcher(QmakeProject *parent);
|
||||
CentralizedFolderWatcher(QmakeBuildSystem *BuildSystem);
|
||||
|
||||
void watchFolders(const QList<QString> &folders, QmakePriFile *file);
|
||||
void unwatchFolders(const QList<QString> &folders, QmakePriFile *file);
|
||||
@@ -100,7 +100,7 @@ private:
|
||||
void onTimer();
|
||||
void delayedFolderChanged(const QString &folder);
|
||||
|
||||
QmakeProject *m_project;
|
||||
QmakeBuildSystem *m_buildSystem;
|
||||
QSet<QString> recursiveDirs(const QString &folder);
|
||||
QFileSystemWatcher m_watcher;
|
||||
QMultiMap<QString, QmakePriFile *> m_map;
|
||||
@@ -110,8 +110,6 @@ private:
|
||||
QSet<QString> m_changedFolders;
|
||||
};
|
||||
|
||||
static QList<QmakeProject *> s_projects;
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
/*!
|
||||
@@ -120,61 +118,35 @@ static QList<QmakeProject *> s_projects;
|
||||
QmakeProject manages information about an individual Qt 4 (.pro) project file.
|
||||
*/
|
||||
|
||||
QmakeProject::QmakeProject(const FilePath &fileName) :
|
||||
Project(QmakeProjectManager::Constants::PROFILE_MIMETYPE, fileName),
|
||||
m_qmakeVfs(new QMakeVfs),
|
||||
m_cppCodeModelUpdater(new CppTools::CppProjectUpdater)
|
||||
static bool matchesKit(const Project *p, const Kit *kit)
|
||||
{
|
||||
FilePath filePath = p->projectFilePath();
|
||||
QtSupport::BaseQtVersion *version = QtSupport::QtKitAspect::qtVersion(kit);
|
||||
|
||||
return QtSupport::QtVersionManager::version([&filePath, version](const QtSupport::BaseQtVersion *v) {
|
||||
return v->isValid() && v->isSubProject(filePath) && v == version;
|
||||
});
|
||||
}
|
||||
|
||||
QmakeProject::QmakeProject(const FilePath &fileName) :
|
||||
Project(QmakeProjectManager::Constants::PROFILE_MIMETYPE, fileName)
|
||||
{
|
||||
s_projects.append(this);
|
||||
setId(Constants::QMAKEPROJECT_ID);
|
||||
setProjectLanguages(Core::Context(ProjectExplorer::Constants::CXX_LANGUAGE_ID));
|
||||
setDisplayName(fileName.toFileInfo().completeBaseName());
|
||||
setCanBuildProducts();
|
||||
setHasMakeInstallEquivalent(true);
|
||||
|
||||
const QTextCodec *codec = Core::EditorManager::defaultTextCodec();
|
||||
m_qmakeVfs->setTextCodec(codec);
|
||||
|
||||
m_asyncUpdateTimer.setSingleShot(true);
|
||||
m_asyncUpdateTimer.setInterval(UPDATE_INTERVAL);
|
||||
connect(&m_asyncUpdateTimer, &QTimer::timeout, this, &QmakeProject::asyncUpdate);
|
||||
|
||||
m_rootProFile = std::make_unique<QmakeProFile>(this, projectFilePath());
|
||||
|
||||
connect(BuildManager::instance(), &BuildManager::buildQueueFinished,
|
||||
this, &QmakeProject::buildFinished);
|
||||
|
||||
setPreferredKitPredicate([this](const Kit *kit) -> bool { return matchesKit(kit); });
|
||||
setBuildSystemCreator([](Project *p) { return new QmakeBuildSystem(p); });
|
||||
setPreferredKitPredicate([this](const Kit *kit) -> bool { return matchesKit(this, kit); });
|
||||
}
|
||||
|
||||
QmakeProject::~QmakeProject()
|
||||
{
|
||||
s_projects.removeOne(this);
|
||||
delete m_projectImporter;
|
||||
m_projectImporter = nullptr;
|
||||
delete m_cppCodeModelUpdater;
|
||||
m_cppCodeModelUpdater = nullptr;
|
||||
m_asyncUpdateState = ShuttingDown;
|
||||
|
||||
// Make sure root node (and associated readers) are shut hown before proceeding
|
||||
setRootProjectNode(nullptr);
|
||||
m_rootProFile.reset();
|
||||
|
||||
m_cancelEvaluate = true;
|
||||
Q_ASSERT(m_qmakeGlobalsRefCnt == 0);
|
||||
delete m_qmakeVfs;
|
||||
|
||||
if (m_asyncUpdateFutureInterface) {
|
||||
m_asyncUpdateFutureInterface->reportCanceled();
|
||||
m_asyncUpdateFutureInterface->reportFinished();
|
||||
delete m_asyncUpdateFutureInterface;
|
||||
}
|
||||
}
|
||||
|
||||
QmakeProFile *QmakeProject::rootProFile() const
|
||||
{
|
||||
return m_rootProFile.get();
|
||||
}
|
||||
|
||||
Project::RestoreResult QmakeProject::fromMap(const QVariantMap &map, QString *errorMessage)
|
||||
@@ -193,17 +165,6 @@ Project::RestoreResult QmakeProject::fromMap(const QVariantMap &map, QString *er
|
||||
}
|
||||
}
|
||||
|
||||
// On active buildconfiguration changes, reevaluate the .pro files
|
||||
m_activeTarget = activeTarget();
|
||||
if (m_activeTarget) {
|
||||
connect(m_activeTarget, &Target::activeBuildConfigurationChanged,
|
||||
this, &QmakeProject::scheduleAsyncUpdateLater);
|
||||
scheduleAsyncUpdate(QmakeProFile::ParseNow);
|
||||
}
|
||||
|
||||
connect(this, &Project::activeTargetChanged,
|
||||
this, &QmakeProject::activeTargetWasChanged);
|
||||
|
||||
return RestoreResult::Ok;
|
||||
}
|
||||
|
||||
@@ -212,20 +173,78 @@ DeploymentKnowledge QmakeProject::deploymentKnowledge() const
|
||||
return DeploymentKnowledge::Approximative; // E.g. QTCREATORBUG-21855
|
||||
}
|
||||
|
||||
void QmakeProject::updateCodeModels()
|
||||
//
|
||||
// QmakeBuildSystem
|
||||
//
|
||||
|
||||
QmakeBuildSystem::QmakeBuildSystem(QmakeBuildConfiguration *bc)
|
||||
: BuildSystem(bc),
|
||||
m_qmakeVfs(new QMakeVfs),
|
||||
m_cppCodeModelUpdater(new CppTools::CppProjectUpdater),
|
||||
m_buildConfiguration(bc)
|
||||
{
|
||||
if (activeTarget() && !activeTarget()->activeBuildConfiguration())
|
||||
const QTextCodec *codec = Core::EditorManager::defaultTextCodec();
|
||||
m_qmakeVfs->setTextCodec(codec);
|
||||
|
||||
m_asyncUpdateTimer.setSingleShot(true);
|
||||
m_asyncUpdateTimer.setInterval(UPDATE_INTERVAL);
|
||||
connect(&m_asyncUpdateTimer, &QTimer::timeout, this, &QmakeBuildSystem::asyncUpdate);
|
||||
|
||||
m_rootProFile = std::make_unique<QmakeProFile>(this, projectFilePath());
|
||||
|
||||
connect(BuildManager::instance(), &BuildManager::buildQueueFinished,
|
||||
this, &QmakeBuildSystem::buildFinished);
|
||||
|
||||
connect(bc->target(), &Target::activeBuildConfigurationChanged,
|
||||
this, [this](BuildConfiguration *bc) {
|
||||
if (bc == m_buildConfiguration)
|
||||
scheduleUpdateAllNowOrLater();
|
||||
// FIXME: This is too eager in the presence of not handling updates
|
||||
// when the build configuration is not active, see startAsyncTimer
|
||||
// below.
|
||||
// else
|
||||
// m_cancelEvaluate = true;
|
||||
});
|
||||
|
||||
connect(bc->project(), &Project::activeTargetChanged,
|
||||
this, &QmakeBuildSystem::activeTargetWasChanged);
|
||||
|
||||
connect(bc->project(), &Project::projectFileIsDirty,
|
||||
this, &QmakeBuildSystem::scheduleUpdateAllLater);
|
||||
}
|
||||
|
||||
QmakeBuildSystem::~QmakeBuildSystem()
|
||||
{
|
||||
delete m_cppCodeModelUpdater;
|
||||
m_cppCodeModelUpdater = nullptr;
|
||||
m_asyncUpdateState = ShuttingDown;
|
||||
|
||||
// Make sure root node (and associated readers) are shut hown before proceeding
|
||||
m_rootProFile.reset();
|
||||
|
||||
m_cancelEvaluate = true;
|
||||
QTC_CHECK(m_qmakeGlobalsRefCnt == 0);
|
||||
delete m_qmakeVfs;
|
||||
m_qmakeVfs = nullptr;
|
||||
|
||||
m_asyncUpdateFutureInterface.reportCanceled();
|
||||
m_asyncUpdateFutureInterface.reportFinished();
|
||||
}
|
||||
|
||||
void QmakeBuildSystem::updateCodeModels()
|
||||
{
|
||||
if (!m_buildConfiguration->isActive())
|
||||
return;
|
||||
|
||||
updateCppCodeModel();
|
||||
updateQmlJSCodeModel();
|
||||
}
|
||||
|
||||
void QmakeProject::updateCppCodeModel()
|
||||
void QmakeBuildSystem::updateCppCodeModel()
|
||||
{
|
||||
m_toolChainWarnings.clear();
|
||||
|
||||
QtSupport::CppKitInfo kitInfo(this);
|
||||
QtSupport::CppKitInfo kitInfo(project());
|
||||
QTC_ASSERT(kitInfo.isValid(), return);
|
||||
|
||||
QList<ProjectExplorer::ExtraCompiler *> generators;
|
||||
@@ -286,17 +305,17 @@ void QmakeProject::updateCppCodeModel()
|
||||
}
|
||||
|
||||
CppTools::GeneratedCodeModelSupport::update(generators);
|
||||
m_cppCodeModelUpdater->update({this, kitInfo, activeParseEnvironment(), rpps});
|
||||
m_cppCodeModelUpdater->update({project(), kitInfo, activeParseEnvironment(), rpps});
|
||||
}
|
||||
|
||||
void QmakeProject::updateQmlJSCodeModel()
|
||||
void QmakeBuildSystem::updateQmlJSCodeModel()
|
||||
{
|
||||
QmlJS::ModelManagerInterface *modelManager = QmlJS::ModelManagerInterface::instance();
|
||||
if (!modelManager)
|
||||
return;
|
||||
|
||||
QmlJS::ModelManagerInterface::ProjectInfo projectInfo =
|
||||
modelManager->defaultProjectInfoForProject(this);
|
||||
modelManager->defaultProjectInfoForProject(project());
|
||||
|
||||
const QList<QmakeProFile *> proFiles = rootProFile()->allProFiles();
|
||||
|
||||
@@ -339,15 +358,15 @@ void QmakeProject::updateQmlJSCodeModel()
|
||||
// This assumption fails when there are no QDeclarativeEngine/QDeclarativeView (QtQuick 1)
|
||||
// or QQmlEngine/QQuickView (QtQuick 2) instances.
|
||||
if (hasQmlLib)
|
||||
addProjectLanguage(ProjectExplorer::Constants::QMLJS_LANGUAGE_ID);
|
||||
project()->addProjectLanguage(ProjectExplorer::Constants::QMLJS_LANGUAGE_ID);
|
||||
|
||||
projectInfo.activeResourceFiles.removeDuplicates();
|
||||
projectInfo.allResourceFiles.removeDuplicates();
|
||||
|
||||
modelManager->updateProjectInfo(projectInfo, this);
|
||||
modelManager->updateProjectInfo(projectInfo, project());
|
||||
}
|
||||
|
||||
void QmakeProject::scheduleAsyncUpdate(QmakeProFile *file, QmakeProFile::AsyncUpdateDelay delay)
|
||||
void QmakeBuildSystem::scheduleAsyncUpdateFile(QmakeProFile *file, QmakeProFile::AsyncUpdateDelay delay)
|
||||
{
|
||||
if (m_asyncUpdateState == ShuttingDown)
|
||||
return;
|
||||
@@ -400,11 +419,21 @@ void QmakeProject::scheduleAsyncUpdate(QmakeProFile *file, QmakeProFile::AsyncUp
|
||||
// change a partial update gets in progress and then another
|
||||
// batch of changes come in, which triggers a full update
|
||||
// even if that's not really needed
|
||||
scheduleAsyncUpdate(delay);
|
||||
scheduleUpdateAll(delay);
|
||||
}
|
||||
}
|
||||
|
||||
void QmakeProject::scheduleAsyncUpdate(QmakeProFile::AsyncUpdateDelay delay)
|
||||
void QmakeBuildSystem::scheduleUpdateAllNowOrLater()
|
||||
{
|
||||
if (m_firstParseNeeded) {
|
||||
m_firstParseNeeded = false;
|
||||
scheduleUpdateAll(QmakeProFile::ParseNow);
|
||||
} else {
|
||||
scheduleUpdateAll(QmakeProFile::ParseLater);
|
||||
}
|
||||
}
|
||||
|
||||
void QmakeBuildSystem::scheduleUpdateAll(QmakeProFile::AsyncUpdateDelay delay)
|
||||
{
|
||||
if (m_asyncUpdateState == ShuttingDown)
|
||||
return;
|
||||
@@ -430,8 +459,11 @@ void QmakeProject::scheduleAsyncUpdate(QmakeProFile::AsyncUpdateDelay delay)
|
||||
startAsyncTimer(delay);
|
||||
}
|
||||
|
||||
void QmakeProject::startAsyncTimer(QmakeProFile::AsyncUpdateDelay delay)
|
||||
void QmakeBuildSystem::startAsyncTimer(QmakeProFile::AsyncUpdateDelay delay)
|
||||
{
|
||||
if (!m_buildConfiguration->isActive())
|
||||
return;
|
||||
|
||||
m_asyncUpdateTimer.stop();
|
||||
m_asyncUpdateTimer.setInterval(qMin(m_asyncUpdateTimer.interval(),
|
||||
delay == QmakeProFile::ParseLater ? UPDATE_INTERVAL : 0));
|
||||
@@ -439,33 +471,31 @@ void QmakeProject::startAsyncTimer(QmakeProFile::AsyncUpdateDelay delay)
|
||||
m_asyncUpdateTimer.start();
|
||||
}
|
||||
|
||||
void QmakeProject::incrementPendingEvaluateFutures()
|
||||
void QmakeBuildSystem::incrementPendingEvaluateFutures()
|
||||
{
|
||||
if (m_pendingEvaluateFuturesCount == 0)
|
||||
m_guard = guardParsingRun();
|
||||
++m_pendingEvaluateFuturesCount;
|
||||
m_asyncUpdateFutureInterface->setProgressRange(m_asyncUpdateFutureInterface->progressMinimum(),
|
||||
m_asyncUpdateFutureInterface->progressMaximum() + 1);
|
||||
m_asyncUpdateFutureInterface.setProgressRange(m_asyncUpdateFutureInterface.progressMinimum(),
|
||||
m_asyncUpdateFutureInterface.progressMaximum() + 1);
|
||||
}
|
||||
|
||||
void QmakeProject::decrementPendingEvaluateFutures()
|
||||
void QmakeBuildSystem::decrementPendingEvaluateFutures()
|
||||
{
|
||||
--m_pendingEvaluateFuturesCount;
|
||||
|
||||
if (!rootProFile())
|
||||
return; // We are closing the project!
|
||||
|
||||
m_asyncUpdateFutureInterface->setProgressValue(m_asyncUpdateFutureInterface->progressValue() + 1);
|
||||
m_asyncUpdateFutureInterface.setProgressValue(m_asyncUpdateFutureInterface.progressValue() + 1);
|
||||
if (m_pendingEvaluateFuturesCount == 0) {
|
||||
// We are done!
|
||||
setRootProjectNode(QmakeNodeTreeBuilder::buildTree(this));
|
||||
project()->setRootProjectNode(QmakeNodeTreeBuilder::buildTree(this));
|
||||
|
||||
if (!m_rootProFile->validParse())
|
||||
m_asyncUpdateFutureInterface->reportCanceled();
|
||||
m_asyncUpdateFutureInterface.reportCanceled();
|
||||
|
||||
m_asyncUpdateFutureInterface->reportFinished();
|
||||
delete m_asyncUpdateFutureInterface;
|
||||
m_asyncUpdateFutureInterface = nullptr;
|
||||
m_asyncUpdateFutureInterface.reportFinished();
|
||||
m_cancelEvaluate = false;
|
||||
|
||||
// TODO clear the profile cache ?
|
||||
@@ -479,20 +509,19 @@ void QmakeProject::decrementPendingEvaluateFutures()
|
||||
m_asyncUpdateState = Base;
|
||||
updateBuildSystemData();
|
||||
updateCodeModels();
|
||||
if (activeTarget())
|
||||
activeTarget()->updateDefaultDeployConfigurations();
|
||||
target()->updateDefaultDeployConfigurations();
|
||||
m_guard.markAsSuccess(); // Qmake always returns (some) data, even when it failed:-)
|
||||
m_guard = {};
|
||||
m_guard = {}; // This triggers emitParsingFinished by destroying the previous guard.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool QmakeProject::wasEvaluateCanceled()
|
||||
bool QmakeBuildSystem::wasEvaluateCanceled()
|
||||
{
|
||||
return m_cancelEvaluate;
|
||||
}
|
||||
|
||||
void QmakeProject::asyncUpdate()
|
||||
void QmakeBuildSystem::asyncUpdate()
|
||||
{
|
||||
m_asyncUpdateTimer.setInterval(UPDATE_INTERVAL);
|
||||
|
||||
@@ -503,28 +532,23 @@ void QmakeProject::asyncUpdate()
|
||||
m_qmakeVfs->invalidateCache();
|
||||
}
|
||||
|
||||
Q_ASSERT(!m_asyncUpdateFutureInterface);
|
||||
m_asyncUpdateFutureInterface = new QFutureInterface<void>();
|
||||
|
||||
m_asyncUpdateFutureInterface->setProgressRange(0, 0);
|
||||
Core::ProgressManager::addTask(m_asyncUpdateFutureInterface->future(),
|
||||
tr("Reading Project \"%1\"").arg(displayName()),
|
||||
m_asyncUpdateFutureInterface.setProgressRange(0, 0);
|
||||
Core::ProgressManager::addTask(m_asyncUpdateFutureInterface.future(),
|
||||
tr("Reading Project \"%1\"").arg(project()->displayName()),
|
||||
Constants::PROFILE_EVALUATE);
|
||||
|
||||
m_asyncUpdateFutureInterface->reportStarted();
|
||||
m_asyncUpdateFutureInterface.reportStarted();
|
||||
|
||||
const Kit * const kit = activeTarget() ? activeTarget()->kit() : nullptr;
|
||||
const Kit * const kit = target()->kit();
|
||||
QtSupport::BaseQtVersion * const qtVersion = QtSupport::QtKitAspect::qtVersion(kit);
|
||||
if (!qtVersion || !qtVersion->isValid()) {
|
||||
const QString errorMessage = kit
|
||||
? tr("Cannot parse project \"%1\": The currently selected kit \"%2\" does not "
|
||||
"have a valid Qt.").arg(displayName(), kit->displayName())
|
||||
: tr("Cannot parse project \"%1\": No kit selected.").arg(displayName());
|
||||
"have a valid Qt.").arg(project()->displayName(), kit->displayName())
|
||||
: tr("Cannot parse project \"%1\": No kit selected.").arg(project()->displayName());
|
||||
proFileParseError(errorMessage);
|
||||
m_asyncUpdateFutureInterface->reportCanceled();
|
||||
m_asyncUpdateFutureInterface->reportFinished();
|
||||
delete m_asyncUpdateFutureInterface;
|
||||
m_asyncUpdateFutureInterface = nullptr;
|
||||
m_asyncUpdateFutureInterface.reportCanceled();
|
||||
m_asyncUpdateFutureInterface.reportFinished();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -539,7 +563,7 @@ void QmakeProject::asyncUpdate()
|
||||
m_asyncUpdateState = AsyncUpdateInProgress;
|
||||
}
|
||||
|
||||
void QmakeProject::buildFinished(bool success)
|
||||
void QmakeBuildSystem::buildFinished(bool success)
|
||||
{
|
||||
if (success)
|
||||
m_invalidateQmakeVfsContents = true;
|
||||
@@ -584,51 +608,28 @@ static FileNode *fileNodeOf(FolderNode *in, const FilePath &fileName)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QStringList QmakeProject::filesGeneratedFrom(const QString &input) const
|
||||
{
|
||||
if (!rootProjectNode())
|
||||
return { };
|
||||
|
||||
if (const FileNode *file = fileNodeOf(rootProjectNode(), FilePath::fromString(input))) {
|
||||
const QmakeProFileNode *pro = static_cast<QmakeProFileNode *>(file->parentFolderNode());
|
||||
QTC_ASSERT(pro, return {});
|
||||
if (const QmakeProFile *proFile = pro->proFile())
|
||||
return Utils::transform(proFile->generatedFiles(FilePath::fromString(pro->buildDir()),
|
||||
file->filePath(), file->fileType()),
|
||||
&FilePath::toString);
|
||||
}
|
||||
return { };
|
||||
}
|
||||
|
||||
void QmakeProject::proFileParseError(const QString &errorMessage)
|
||||
void QmakeBuildSystem::proFileParseError(const QString &errorMessage)
|
||||
{
|
||||
Core::MessageManager::write(errorMessage);
|
||||
}
|
||||
|
||||
QtSupport::ProFileReader *QmakeProject::createProFileReader(const QmakeProFile *qmakeProFile)
|
||||
QtSupport::ProFileReader *QmakeBuildSystem::createProFileReader(const QmakeProFile *qmakeProFile)
|
||||
{
|
||||
if (!m_qmakeGlobals) {
|
||||
m_qmakeGlobals = std::make_unique<QMakeGlobals>();
|
||||
m_qmakeGlobalsRefCnt = 0;
|
||||
|
||||
Kit *k = KitManager::defaultKit();
|
||||
Environment env = Environment::systemEnvironment();
|
||||
QStringList qmakeArgs;
|
||||
|
||||
if (Target *t = activeTarget()) {
|
||||
k = t->kit();
|
||||
if (auto bc = static_cast<QmakeBuildConfiguration *>(t->activeBuildConfiguration())) {
|
||||
env = bc->environment();
|
||||
if (QMakeStep *qs = bc->qmakeStep())
|
||||
qmakeArgs = qs->parserArguments();
|
||||
else
|
||||
qmakeArgs = bc->configCommandLineArguments();
|
||||
}
|
||||
} else {
|
||||
// Set up a better default environment without using a build configuration:
|
||||
QmakeBuildConfiguration::setupBuildEnvironment(k, env);
|
||||
if (k)
|
||||
k->addToEnvironment(env);
|
||||
Target *t = target();
|
||||
Kit *k = t->kit();
|
||||
if (auto bc = static_cast<QmakeBuildConfiguration *>(t->activeBuildConfiguration())) {
|
||||
env = bc->environment();
|
||||
if (QMakeStep *qs = bc->qmakeStep())
|
||||
qmakeArgs = qs->parserArguments();
|
||||
else
|
||||
qmakeArgs = bc->configCommandLineArguments();
|
||||
}
|
||||
|
||||
QtSupport::BaseQtVersion *qtVersion = QtSupport::QtKitAspect::qtVersion(k);
|
||||
@@ -672,22 +673,22 @@ QtSupport::ProFileReader *QmakeProject::createProFileReader(const QmakeProFile *
|
||||
return reader;
|
||||
}
|
||||
|
||||
QMakeGlobals *QmakeProject::qmakeGlobals()
|
||||
QMakeGlobals *QmakeBuildSystem::qmakeGlobals()
|
||||
{
|
||||
return m_qmakeGlobals.get();
|
||||
}
|
||||
|
||||
QMakeVfs *QmakeProject::qmakeVfs()
|
||||
QMakeVfs *QmakeBuildSystem::qmakeVfs()
|
||||
{
|
||||
return m_qmakeVfs;
|
||||
}
|
||||
|
||||
QString QmakeProject::qmakeSysroot()
|
||||
QString QmakeBuildSystem::qmakeSysroot()
|
||||
{
|
||||
return m_qmakeSysroot;
|
||||
}
|
||||
|
||||
void QmakeProject::destroyProFileReader(QtSupport::ProFileReader *reader)
|
||||
void QmakeBuildSystem::destroyProFileReader(QtSupport::ProFileReader *reader)
|
||||
{
|
||||
delete reader;
|
||||
if (!--m_qmakeGlobalsRefCnt) {
|
||||
@@ -701,36 +702,21 @@ void QmakeProject::destroyProFileReader(QtSupport::ProFileReader *reader)
|
||||
}
|
||||
}
|
||||
|
||||
QmakeProFileNode *QmakeProject::rootProjectNode() const
|
||||
void QmakeBuildSystem::activeTargetWasChanged(Target *t)
|
||||
{
|
||||
return static_cast<QmakeProFileNode *>(Project::rootProjectNode());
|
||||
}
|
||||
|
||||
void QmakeProject::activeTargetWasChanged()
|
||||
{
|
||||
const bool hadActiveTarget = m_activeTarget;
|
||||
if (hadActiveTarget) {
|
||||
disconnect(m_activeTarget, &Target::activeBuildConfigurationChanged,
|
||||
this, &QmakeProject::scheduleAsyncUpdateLater);
|
||||
}
|
||||
|
||||
m_activeTarget = activeTarget();
|
||||
m_invalidateQmakeVfsContents = true;
|
||||
|
||||
if (!m_activeTarget)
|
||||
// We are only interested in our own target.
|
||||
if (t != m_buildConfiguration->target())
|
||||
return;
|
||||
|
||||
connect(m_activeTarget, &Target::activeBuildConfigurationChanged,
|
||||
this, &QmakeProject::scheduleAsyncUpdateLater);
|
||||
|
||||
scheduleAsyncUpdate(hadActiveTarget ? QmakeProFile::ParseLater : QmakeProFile::ParseNow);
|
||||
m_invalidateQmakeVfsContents = true;
|
||||
scheduleUpdateAll(QmakeProFile::ParseLater);
|
||||
}
|
||||
|
||||
static void notifyChangedHelper(const FilePath &fileName, QmakeProFile *file)
|
||||
{
|
||||
if (file->filePath() == fileName) {
|
||||
QtSupport::ProFileCacheManager::instance()->discardFile(
|
||||
fileName.toString(), file->project()->qmakeVfs());
|
||||
fileName.toString(), file->buildSystem()->qmakeVfs());
|
||||
file->scheduleUpdate(QmakeProFile::ParseNow);
|
||||
}
|
||||
|
||||
@@ -740,19 +726,19 @@ static void notifyChangedHelper(const FilePath &fileName, QmakeProFile *file)
|
||||
}
|
||||
}
|
||||
|
||||
void QmakeProject::notifyChanged(const FilePath &name)
|
||||
void QmakeBuildSystem::notifyChanged(const FilePath &name)
|
||||
{
|
||||
for (QmakeProject *project : s_projects) {
|
||||
if (!project
|
||||
->files([&name](const ProjectExplorer::Node *n) {
|
||||
return Project::SourceFiles(n) && n->filePath() == name;
|
||||
})
|
||||
.isEmpty())
|
||||
notifyChangedHelper(name, project->rootProFile());
|
||||
}
|
||||
FilePathList files = project()->files([&name](const Node *n) {
|
||||
return Project::SourceFiles(n) && n->filePath() == name;
|
||||
});
|
||||
|
||||
if (files.isEmpty())
|
||||
return;
|
||||
|
||||
notifyChangedHelper(name, m_rootProFile.get());
|
||||
}
|
||||
|
||||
void QmakeProject::watchFolders(const QStringList &l, QmakePriFile *file)
|
||||
void QmakeBuildSystem::watchFolders(const QStringList &l, QmakePriFile *file)
|
||||
{
|
||||
if (l.isEmpty())
|
||||
return;
|
||||
@@ -761,7 +747,7 @@ void QmakeProject::watchFolders(const QStringList &l, QmakePriFile *file)
|
||||
m_centralizedFolderWatcher->watchFolders(l, file);
|
||||
}
|
||||
|
||||
void QmakeProject::unwatchFolders(const QStringList &l, QmakePriFile *file)
|
||||
void QmakeBuildSystem::unwatchFolders(const QStringList &l, QmakePriFile *file)
|
||||
{
|
||||
if (m_centralizedFolderWatcher && !l.isEmpty())
|
||||
m_centralizedFolderWatcher->unwatchFolders(l, file);
|
||||
@@ -772,8 +758,8 @@ void QmakeProject::unwatchFolders(const QStringList &l, QmakePriFile *file)
|
||||
////////////
|
||||
|
||||
// All the folder have a trailing slash!
|
||||
CentralizedFolderWatcher::CentralizedFolderWatcher(QmakeProject *parent)
|
||||
: QObject(parent), m_project(parent)
|
||||
CentralizedFolderWatcher::CentralizedFolderWatcher(QmakeBuildSystem *parent)
|
||||
: QObject(parent), m_buildSystem(parent)
|
||||
{
|
||||
m_compressTimer.setSingleShot(true);
|
||||
m_compressTimer.setInterval(200);
|
||||
@@ -914,7 +900,7 @@ void CentralizedFolderWatcher::delayedFolderChanged(const QString &folder)
|
||||
}
|
||||
|
||||
if (newOrRemovedFiles)
|
||||
m_project->updateCodeModels();
|
||||
m_buildSystem->updateCodeModels();
|
||||
}
|
||||
|
||||
void QmakeProject::configureAsExampleProject()
|
||||
@@ -930,22 +916,19 @@ void QmakeProject::configureAsExampleProject()
|
||||
setup(infoList);
|
||||
}
|
||||
|
||||
void QmakeProject::updateBuildSystemData()
|
||||
void QmakeBuildSystem::updateBuildSystemData()
|
||||
{
|
||||
Target *const target = activeTarget();
|
||||
if (!target)
|
||||
return;
|
||||
const QmakeProFile *const file = rootProFile();
|
||||
if (!file || file->parseInProgress())
|
||||
return;
|
||||
|
||||
DeploymentData deploymentData;
|
||||
collectData(file, deploymentData);
|
||||
target->setDeploymentData(deploymentData);
|
||||
setDeploymentData(deploymentData);
|
||||
|
||||
QList<BuildTargetInfo> appTargetList;
|
||||
|
||||
rootProjectNode()->forEachProjectNode([this, target, &appTargetList](const ProjectNode *pn) {
|
||||
project()->rootProjectNode()->forEachProjectNode([this, &appTargetList](const ProjectNode *pn) {
|
||||
auto node = dynamic_cast<const QmakeProFileNode *>(pn);
|
||||
if (!node || !node->includedInExactParse())
|
||||
return;
|
||||
@@ -1017,7 +1000,7 @@ void QmakeProject::updateBuildSystemData()
|
||||
libraryPaths.append(dir);
|
||||
}
|
||||
}
|
||||
QtSupport::BaseQtVersion *qtVersion = QtSupport::QtKitAspect::qtVersion(target->kit());
|
||||
QtSupport::BaseQtVersion *qtVersion = QtSupport::QtKitAspect::qtVersion(target()->kit());
|
||||
if (qtVersion)
|
||||
libraryPaths.append(qtVersion->librarySearchPath().toString());
|
||||
|
||||
@@ -1030,10 +1013,10 @@ void QmakeProject::updateBuildSystemData()
|
||||
appTargetList.append(bti);
|
||||
});
|
||||
|
||||
target->setApplicationTargets(appTargetList);
|
||||
setApplicationTargets(appTargetList);
|
||||
}
|
||||
|
||||
void QmakeProject::collectData(const QmakeProFile *file, DeploymentData &deploymentData)
|
||||
void QmakeBuildSystem::collectData(const QmakeProFile *file, DeploymentData &deploymentData)
|
||||
{
|
||||
if (!file->isSubProjectDeployable(file->filePath()))
|
||||
return;
|
||||
@@ -1069,7 +1052,7 @@ void QmakeProject::collectData(const QmakeProFile *file, DeploymentData &deploym
|
||||
}
|
||||
}
|
||||
|
||||
void QmakeProject::collectApplicationData(const QmakeProFile *file, DeploymentData &deploymentData)
|
||||
void QmakeBuildSystem::collectApplicationData(const QmakeProFile *file, DeploymentData &deploymentData)
|
||||
{
|
||||
QString executable = executableFor(file);
|
||||
if (!executable.isEmpty())
|
||||
@@ -1086,12 +1069,12 @@ static FilePath destDirFor(const TargetInformation &ti)
|
||||
return ti.destDir;
|
||||
}
|
||||
|
||||
void QmakeProject::collectLibraryData(const QmakeProFile *file, DeploymentData &deploymentData)
|
||||
void QmakeBuildSystem::collectLibraryData(const QmakeProFile *file, DeploymentData &deploymentData)
|
||||
{
|
||||
const QString targetPath = file->installsList().targetPath;
|
||||
if (targetPath.isEmpty())
|
||||
return;
|
||||
const Kit * const kit = activeTarget()->kit();
|
||||
const Kit * const kit = target()->kit();
|
||||
const ToolChain * const toolchain = ToolChainKitAspect::toolChain(kit, ProjectExplorer::Constants::CXX_LANGUAGE_ID);
|
||||
if (!toolchain)
|
||||
return;
|
||||
@@ -1176,16 +1159,6 @@ void QmakeProject::collectLibraryData(const QmakeProFile *file, DeploymentData &
|
||||
}
|
||||
}
|
||||
|
||||
bool QmakeProject::matchesKit(const Kit *kit)
|
||||
{
|
||||
FilePath filePath = projectFilePath();
|
||||
QtSupport::BaseQtVersion *version = QtSupport::QtKitAspect::qtVersion(kit);
|
||||
|
||||
return QtSupport::QtVersionManager::version([&filePath, version](const QtSupport::BaseQtVersion *v) {
|
||||
return v->isValid() && v->isSubProject(filePath) && v == version;
|
||||
});
|
||||
}
|
||||
|
||||
static Utils::FilePath getFullPathOf(const QmakeProFile *pro, Variable variable,
|
||||
const BuildConfiguration *bc)
|
||||
{
|
||||
@@ -1205,7 +1178,7 @@ static Utils::FilePath getFullPathOf(const QmakeProFile *pro, Variable variable,
|
||||
return bc->environment().searchInPath(exe);
|
||||
}
|
||||
|
||||
void QmakeProject::testToolChain(ToolChain *tc, const Utils::FilePath &path) const
|
||||
void QmakeBuildSystem::testToolChain(ToolChain *tc, const FilePath &path) const
|
||||
{
|
||||
if (!tc || path.isEmpty())
|
||||
return;
|
||||
@@ -1213,15 +1186,14 @@ void QmakeProject::testToolChain(ToolChain *tc, const Utils::FilePath &path) con
|
||||
const Utils::FilePath expected = tc->compilerCommand();
|
||||
|
||||
Environment env = Environment::systemEnvironment();
|
||||
Kit *k = nullptr;
|
||||
if (Target *t = activeTarget()) {
|
||||
k = t->kit();
|
||||
if (BuildConfiguration *bc = t->activeBuildConfiguration())
|
||||
env = bc->environment();
|
||||
else
|
||||
k->addToEnvironment(env);
|
||||
}
|
||||
QTC_ASSERT(k, return);
|
||||
Target *t = target();
|
||||
QTC_ASSERT(t, return);
|
||||
|
||||
Kit *k = t->kit();
|
||||
if (BuildConfiguration *bc = t->activeBuildConfiguration())
|
||||
env = bc->environment();
|
||||
else
|
||||
k->addToEnvironment(env);
|
||||
|
||||
if (env.isSameExecutable(path.toString(), expected.toString()))
|
||||
return;
|
||||
@@ -1247,9 +1219,9 @@ void QmakeProject::testToolChain(ToolChain *tc, const Utils::FilePath &path) con
|
||||
m_toolChainWarnings.insert(pair);
|
||||
}
|
||||
|
||||
void QmakeProject::warnOnToolChainMismatch(const QmakeProFile *pro) const
|
||||
void QmakeBuildSystem::warnOnToolChainMismatch(const QmakeProFile *pro) const
|
||||
{
|
||||
const Target *t = activeTarget();
|
||||
const Target *t = target();
|
||||
const BuildConfiguration *bc = t ? t->activeBuildConfiguration() : nullptr;
|
||||
if (!bc)
|
||||
return;
|
||||
@@ -1260,9 +1232,9 @@ void QmakeProject::warnOnToolChainMismatch(const QmakeProFile *pro) const
|
||||
getFullPathOf(pro, Variable::QmakeCxx, bc));
|
||||
}
|
||||
|
||||
QString QmakeProject::executableFor(const QmakeProFile *file)
|
||||
QString QmakeBuildSystem::executableFor(const QmakeProFile *file)
|
||||
{
|
||||
const Kit *const kit = activeTarget() ? activeTarget()->kit() : nullptr;
|
||||
const Kit *const kit = target()->kit();
|
||||
const ToolChain *const tc = ToolChainKitAspect::toolChain(kit, ProjectExplorer::Constants::CXX_LANGUAGE_ID);
|
||||
if (!tc)
|
||||
return QString();
|
||||
@@ -1285,11 +1257,6 @@ QString QmakeProject::executableFor(const QmakeProFile *file)
|
||||
return QDir(destDirFor(ti).toString()).absoluteFilePath(target);
|
||||
}
|
||||
|
||||
void QmakeProject::emitBuildDirectoryInitialized()
|
||||
{
|
||||
emit buildDirectoryInitialized();
|
||||
}
|
||||
|
||||
ProjectImporter *QmakeProject::projectImporter() const
|
||||
{
|
||||
if (!m_projectImporter)
|
||||
@@ -1297,24 +1264,44 @@ ProjectImporter *QmakeProject::projectImporter() const
|
||||
return m_projectImporter;
|
||||
}
|
||||
|
||||
QmakeProject::AsyncUpdateState QmakeProject::asyncUpdateState() const
|
||||
QmakeBuildSystem::AsyncUpdateState QmakeBuildSystem::asyncUpdateState() const
|
||||
{
|
||||
return m_asyncUpdateState;
|
||||
}
|
||||
|
||||
QString QmakeProject::mapProFilePathToTarget(const FilePath &proFilePath)
|
||||
QmakeProFile *QmakeBuildSystem::rootProFile() const
|
||||
{
|
||||
const QmakeProFile *pro = rootProFile()->findProFile(proFilePath);
|
||||
return pro ? pro->targetInformation().target : QString();
|
||||
return m_rootProFile.get();
|
||||
}
|
||||
|
||||
QVariant QmakeProject::additionalData(Core::Id id, const Target *target) const
|
||||
void QmakeBuildSystem::triggerParsing()
|
||||
{
|
||||
asyncUpdate();
|
||||
}
|
||||
|
||||
QStringList QmakeBuildSystem::filesGeneratedFrom(const QString &input) const
|
||||
{
|
||||
if (!project()->rootProjectNode())
|
||||
return {};
|
||||
|
||||
if (const FileNode *file = fileNodeOf(project()->rootProjectNode(), FilePath::fromString(input))) {
|
||||
const QmakeProFileNode *pro = dynamic_cast<QmakeProFileNode *>(file->parentFolderNode());
|
||||
QTC_ASSERT(pro, return {});
|
||||
if (const QmakeProFile *proFile = pro->proFile())
|
||||
return Utils::transform(proFile->generatedFiles(pro->buildDir(nullptr),
|
||||
file->filePath(), file->fileType()),
|
||||
&FilePath::toString);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
QVariant QmakeBuildSystem::additionalData(Core::Id id) const
|
||||
{
|
||||
if (id == "QmlDesignerImportPath")
|
||||
return rootProjectNode()->variableValue(Variable::QmlDesignerImportPath);
|
||||
return Project::additionalData(id, target);
|
||||
return m_rootProFile->variableValue(Variable::QmlDesignerImportPath);
|
||||
return BuildSystem::additionalData(id);
|
||||
}
|
||||
|
||||
} // namespace QmakeProjectManager
|
||||
} // QmakeProjectManager
|
||||
|
||||
#include "qmakeproject.moc"
|
||||
|
||||
Reference in New Issue
Block a user