aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/qmakeprojectmanager/qmakeproject.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/qmakeprojectmanager/qmakeproject.cpp')
-rw-r--r--src/plugins/qmakeprojectmanager/qmakeproject.cpp248
1 files changed, 158 insertions, 90 deletions
diff --git a/src/plugins/qmakeprojectmanager/qmakeproject.cpp b/src/plugins/qmakeprojectmanager/qmakeproject.cpp
index 00d23d3f75..7a5eb09c4d 100644
--- a/src/plugins/qmakeprojectmanager/qmakeproject.cpp
+++ b/src/plugins/qmakeprojectmanager/qmakeproject.cpp
@@ -25,14 +25,13 @@
#include "qmakeproject.h"
-#include "qmakeprojectmanager.h"
-#include "qmakeprojectimporter.h"
+#include "qmakebuildconfiguration.h"
#include "qmakebuildinfo.h"
-#include "qmakestep.h"
#include "qmakenodes.h"
#include "qmakenodetreebuilder.h"
+#include "qmakeprojectimporter.h"
#include "qmakeprojectmanagerconstants.h"
-#include "qmakebuildconfiguration.h"
+#include "qmakestep.h"
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/icontext.h>
@@ -74,6 +73,7 @@
#include <QDir>
#include <QFileSystemWatcher>
#include <QLoggingCategory>
+#include <QTimer>
using namespace QmakeProjectManager::Internal;
using namespace ProjectExplorer;
@@ -87,6 +87,17 @@ const int UPDATE_INTERVAL = 3000;
static Q_LOGGING_CATEGORY(qmakeBuildSystemLog, "qtc.qmake.buildsystem", QtWarningMsg);
+#define TRACE(msg) \
+ if (qmakeBuildSystemLog().isDebugEnabled()) { \
+ qCDebug(qmakeBuildSystemLog) \
+ << qPrintable(buildConfiguration()->displayName()) \
+ << ", guards project: " << int(m_guard.guardsProject()) \
+ << ", isParsing: " << int(isParsing()) \
+ << ", hasParsingData: " << int(hasParsingData()) \
+ << ", " << __FUNCTION__ \
+ << msg; \
+ }
+
/// Watches folders for QmakePriFile nodes
/// use one file system watcher to watch all folders
/// such minimizing system ressouce usage
@@ -171,33 +182,32 @@ DeploymentKnowledge QmakeProject::deploymentKnowledge() const
//
QmakeBuildSystem::QmakeBuildSystem(QmakeBuildConfiguration *bc)
- : BuildSystem(bc),
- m_qmakeVfs(new QMakeVfs),
- m_cppCodeModelUpdater(new CppTools::CppProjectUpdater),
- m_buildConfiguration(bc)
+ : BuildSystem(bc)
+ , m_qmakeVfs(new QMakeVfs)
+ , m_cppCodeModelUpdater(new CppTools::CppProjectUpdater)
{
const QTextCodec *codec = Core::EditorManager::defaultTextCodec();
m_qmakeVfs->setTextCodec(codec);
- m_asyncUpdateTimer.setSingleShot(true);
- m_asyncUpdateTimer.setInterval(0);
- connect(&m_asyncUpdateTimer, &QTimer::timeout, this, &QmakeBuildSystem::asyncUpdate);
+ setParseDelay(0);
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->target(),
+ &Target::activeBuildConfigurationChanged,
+ this,
+ [this](BuildConfiguration *bc) {
+ if (bc == 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);
@@ -212,7 +222,7 @@ QmakeBuildSystem::QmakeBuildSystem(QmakeBuildConfiguration *bc)
connect(ToolChainManager::instance(), &ToolChainManager::toolChainUpdated,
this, [this](ToolChain *tc) {
- if (ToolChainKitAspect::toolChain(kit(), ProjectExplorer::Constants::CXX_LANGUAGE_ID) == tc)
+ if (ToolChainKitAspect::cxxToolChain(kit()) == tc)
scheduleUpdateAllNowOrLater();
});
@@ -248,7 +258,7 @@ QmakeBuildSystem::~QmakeBuildSystem()
void QmakeBuildSystem::updateCodeModels()
{
- if (!m_buildConfiguration->isActive())
+ if (!buildConfiguration()->isActive())
return;
updateCppCodeModel();
@@ -280,10 +290,18 @@ void QmakeBuildSystem::updateCppCodeModel()
rpp.setDisplayName(pro->displayName());
rpp.setProjectFileLocation(pro->filePath().toString());
rpp.setBuildSystemTarget(pro->filePath().toString());
- const bool isExecutable = pro->projectType() == ProjectType::ApplicationTemplate;
- rpp.setBuildTargetType(isExecutable ? ProjectExplorer::BuildTargetType::Executable
- : ProjectExplorer::BuildTargetType::Library);
-
+ switch (pro->projectType()) {
+ case ProjectType::ApplicationTemplate:
+ rpp.setBuildTargetType(BuildTargetType::Executable);
+ break;
+ case ProjectType::SharedLibraryTemplate:
+ case ProjectType::StaticLibraryTemplate:
+ rpp.setBuildTargetType(BuildTargetType::Library);
+ break;
+ default:
+ rpp.setBuildTargetType(BuildTargetType::Unknown);
+ break;
+ }
rpp.setFlagsForCxx({kitInfo.cxxToolChain, pro->variableValue(Variable::CppFlags)});
rpp.setFlagsForC({kitInfo.cToolChain, pro->variableValue(Variable::CFlags)});
rpp.setMacros(ProjectExplorer::Macro::toMacros(pro->cxxDefines()));
@@ -449,23 +467,38 @@ void QmakeBuildSystem::scheduleAsyncUpdateFile(QmakeProFile *file, QmakeProFile:
void QmakeBuildSystem::scheduleUpdateAllNowOrLater()
{
- qCDebug(qmakeBuildSystemLog) << __FUNCTION__ << m_firstParseNeeded;
if (m_firstParseNeeded)
scheduleUpdateAll(QmakeProFile::ParseNow);
else
scheduleUpdateAll(QmakeProFile::ParseLater);
}
+QmakeBuildConfiguration *QmakeBuildSystem::qmakeBuildConfiguration() const
+{
+ return static_cast<QmakeBuildConfiguration *>(BuildSystem::buildConfiguration());
+}
+
void QmakeBuildSystem::scheduleUpdateAll(QmakeProFile::AsyncUpdateDelay delay)
{
- if (m_asyncUpdateState == ShuttingDown)
+ if (m_asyncUpdateState == ShuttingDown) {
+ TRACE("suppressed: we are shutting down");
return;
+ }
if (m_cancelEvaluate) { // we are in progress of canceling
// and will start the evaluation after that
+ TRACE("suppressed: was previously canceled");
+ return;
+ }
+
+ if (!buildConfiguration()->isActive()) {
+ TRACE("firstParseNeeded: " << int(m_firstParseNeeded)
+ << ", suppressed: buildconfig not active");
return;
}
+ TRACE("firstParseNeeded: " << int(m_firstParseNeeded) << ", delay: " << delay);
+
rootProFile()->setParseInProgressRecursive(true);
if (m_asyncUpdateState == AsyncUpdateInProgress) {
@@ -484,18 +517,15 @@ void QmakeBuildSystem::scheduleUpdateAll(QmakeProFile::AsyncUpdateDelay delay)
void QmakeBuildSystem::startAsyncTimer(QmakeProFile::AsyncUpdateDelay delay)
{
- if (!m_buildConfiguration->isActive()) {
- qCDebug(qmakeBuildSystemLog) << __FUNCTION__ << "skipped, not active";
+ if (!buildConfiguration()->isActive()) {
+ TRACE("skipped, not active")
return;
- }
+ }
- const int interval = qMin(m_asyncUpdateTimer.interval(),
+ const int interval = qMin(parseDelay(),
delay == QmakeProFile::ParseLater ? UPDATE_INTERVAL : 0);
- qCDebug(qmakeBuildSystemLog) << __FUNCTION__ << interval;
-
- m_asyncUpdateTimer.stop();
- m_asyncUpdateTimer.setInterval(interval);
- m_asyncUpdateTimer.start();
+ TRACE("interval: " << interval);
+ requestParseWithCustomDelay(interval);
}
void QmakeBuildSystem::incrementPendingEvaluateFutures()
@@ -508,6 +538,7 @@ void QmakeBuildSystem::incrementPendingEvaluateFutures()
m_guard = guardParsingRun();
}
++m_pendingEvaluateFuturesCount;
+ TRACE("pending inc to: " << m_pendingEvaluateFuturesCount);
m_asyncUpdateFutureInterface.setProgressRange(m_asyncUpdateFutureInterface.progressMinimum(),
m_asyncUpdateFutureInterface.progressMaximum() + 1);
}
@@ -515,9 +546,12 @@ void QmakeBuildSystem::incrementPendingEvaluateFutures()
void QmakeBuildSystem::decrementPendingEvaluateFutures()
{
--m_pendingEvaluateFuturesCount;
+ TRACE("pending dec to: " << m_pendingEvaluateFuturesCount);
- if (!rootProFile())
+ if (!rootProFile()) {
+ TRACE("closing project");
return; // We are closing the project!
+ }
m_asyncUpdateFutureInterface.setProgressValue(m_asyncUpdateFutureInterface.progressValue() + 1);
if (m_pendingEvaluateFuturesCount == 0) {
@@ -544,10 +578,11 @@ void QmakeBuildSystem::decrementPendingEvaluateFutures()
updateDocuments();
target()->updateDefaultDeployConfigurations();
m_guard.markAsSuccess(); // Qmake always returns (some) data, even when it failed:-)
+ TRACE("success" << int(m_guard.isSuccess()));
m_guard = {}; // This triggers emitParsingFinished by destroying the previous guard.
- qCDebug(qmakeBuildSystemLog) << __FUNCTION__ << "first parse succeeded";
m_firstParseNeeded = false;
+ TRACE("first parse succeeded");
emitBuildSystemUpdated();
}
@@ -561,8 +596,8 @@ bool QmakeBuildSystem::wasEvaluateCanceled()
void QmakeBuildSystem::asyncUpdate()
{
- m_asyncUpdateTimer.setInterval(UPDATE_INTERVAL);
- qCDebug(qmakeBuildSystemLog) << __FUNCTION__;
+ setParseDelay(UPDATE_INTERVAL);
+ TRACE("");
if (m_invalidateQmakeVfsContents) {
m_invalidateQmakeVfsContents = false;
@@ -578,12 +613,13 @@ void QmakeBuildSystem::asyncUpdate()
m_asyncUpdateFutureInterface.reportStarted();
- const Kit * const kit = target()->kit();
- QtSupport::BaseQtVersion * const qtVersion = QtSupport::QtKitAspect::qtVersion(kit);
+ const Kit *const k = kit();
+ QtSupport::BaseQtVersion *const qtVersion = QtSupport::QtKitAspect::qtVersion(k);
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(project()->displayName(), kit->displayName())
+ const QString errorMessage
+ = k ? tr("Cannot parse project \"%1\": The currently selected kit \"%2\" does not "
+ "have a valid Qt.")
+ .arg(project()->displayName(), k->displayName())
: tr("Cannot parse project \"%1\": No kit selected.").arg(project()->displayName());
proFileParseError(errorMessage);
m_asyncUpdateFutureInterface.reportCanceled();
@@ -616,7 +652,7 @@ Tasks QmakeProject::projectIssues(const Kit *k) const
result.append(createProjectTask(Task::TaskType::Error, tr("No Qt version set in kit.")));
else if (!qtFromKit->isValid())
result.append(createProjectTask(Task::TaskType::Error, tr("Qt version is invalid.")));
- if (!ToolChainKitAspect::toolChain(k, ProjectExplorer::Constants::CXX_LANGUAGE_ID))
+ if (!ToolChainKitAspect::cxxToolChain(k))
result.append(createProjectTask(Task::TaskType::Error, tr("No C++ compiler set in kit.")));
// A project can be considered part of more than one Qt version, for instance if it is an
@@ -664,6 +700,17 @@ static FileNode *fileNodeOf(FolderNode *in, const FilePath &fileName)
return nullptr;
}
+FilePath QmakeBuildSystem::buildDir(const FilePath &proFilePath) const
+{
+ const QDir srcDirRoot = QDir(projectDirectory().toString());
+ const QString relativeDir = srcDirRoot.relativeFilePath(proFilePath.parentDir().toString());
+ const QString buildConfigBuildDir = buildConfiguration()->buildDirectory().toString();
+ const QString buildDir = buildConfigBuildDir.isEmpty()
+ ? projectDirectory().toString()
+ : buildConfigBuildDir;
+ return FilePath::fromString(QDir::cleanPath(QDir(buildDir).absoluteFilePath(relativeDir)));
+}
+
void QmakeBuildSystem::proFileParseError(const QString &errorMessage)
{
Core::MessageManager::write(errorMessage);
@@ -677,13 +724,14 @@ QtSupport::ProFileReader *QmakeBuildSystem::createProFileReader(const QmakeProFi
QStringList qmakeArgs;
- Target *t = target();
- Kit *k = t->kit();
- Environment env = m_buildConfiguration->environment();
- if (QMakeStep *qs = m_buildConfiguration->qmakeStep())
+ Kit *k = kit();
+ QmakeBuildConfiguration *bc = qmakeBuildConfiguration();
+
+ Environment env = bc->environment();
+ if (QMakeStep *qs = bc->qmakeStep())
qmakeArgs = qs->parserArguments();
else
- qmakeArgs = m_buildConfiguration->configCommandLineArguments();
+ qmakeArgs = bc->configCommandLineArguments();
QtSupport::BaseQtVersion *qtVersion = QtSupport::QtKitAspect::qtVersion(k);
m_qmakeSysroot = SysRootKitAspect::sysRoot(k).toString();
@@ -693,13 +741,13 @@ QtSupport::ProFileReader *QmakeBuildSystem::createProFileReader(const QmakeProFi
qtVersion->applyProperties(m_qmakeGlobals.get());
}
m_qmakeGlobals->setDirectories(rootProFile()->sourceDir().toString(),
- rootProFile()->buildDir().toString());
+ buildDir(rootProFile()->filePath()).toString());
Environment::const_iterator eit = env.constBegin(), eend = env.constEnd();
for (; eit != eend; ++eit)
m_qmakeGlobals->environment.insert(env.key(eit), env.expandedValueForKey(env.key(eit)));
- m_qmakeGlobals->setCommandLineArguments(rootProFile()->buildDir().toString(), qmakeArgs);
+ m_qmakeGlobals->setCommandLineArguments(buildDir(rootProFile()->filePath()).toString(), qmakeArgs);
QtSupport::ProFileCacheManager::instance()->incRefCount();
@@ -721,7 +769,7 @@ QtSupport::ProFileReader *QmakeBuildSystem::createProFileReader(const QmakeProFi
auto reader = new QtSupport::ProFileReader(m_qmakeGlobals.get(), m_qmakeVfs);
- reader->setOutputDir(qmakeProFile->buildDir().toString());
+ reader->setOutputDir(buildDir(qmakeProFile->filePath()).toString());
return reader;
}
@@ -766,7 +814,7 @@ void QmakeBuildSystem::deregisterFromCacheManager()
void QmakeBuildSystem::activeTargetWasChanged(Target *t)
{
// We are only interested in our own target.
- if (t != m_buildConfiguration->target())
+ if (t != target())
return;
m_invalidateQmakeVfsContents = true;
@@ -964,10 +1012,14 @@ void CentralizedFolderWatcher::delayedFolderChanged(const QString &folder)
m_buildSystem->updateCodeModels();
}
-void QmakeProject::configureAsExampleProject()
+void QmakeProject::configureAsExampleProject(Kit *kit)
{
QList<BuildInfo> infoList;
- const QList<Kit *> kits = KitManager::kits();
+ QList<Kit *> kits;
+ if (kit)
+ kits.append(kit);
+ else
+ kits = KitManager::kits();
for (Kit *k : kits) {
if (QtSupport::QtKitAspect::qtVersion(k) != nullptr) {
if (auto factory = BuildConfigurationFactory::find(k, projectFilePath()))
@@ -1052,7 +1104,7 @@ void QmakeBuildSystem::updateBuildSystemData()
if (!libDirectories.isEmpty()) {
QmakeProFile *proFile = node->proFile();
QTC_ASSERT(proFile, return);
- const QString proDirectory = proFile->buildDir().toString();
+ const QString proDirectory = buildDir(proFile->filePath()).toString();
foreach (QString dir, libDirectories) {
// Fix up relative entries like "LIBS+=-L.."
const QFileInfo fi(dir);
@@ -1061,7 +1113,7 @@ void QmakeBuildSystem::updateBuildSystemData()
libraryPaths.append(dir);
}
}
- QtSupport::BaseQtVersion *qtVersion = QtSupport::QtKitAspect::qtVersion(target()->kit());
+ QtSupport::BaseQtVersion *qtVersion = QtSupport::QtKitAspect::qtVersion(kit());
if (qtVersion)
libraryPaths.append(qtVersion->librarySearchPath().toString());
@@ -1135,8 +1187,7 @@ void QmakeBuildSystem::collectLibraryData(const QmakeProFile *file, DeploymentDa
const QString targetPath = file->installsList().targetPath;
if (targetPath.isEmpty())
return;
- const Kit * const kit = target()->kit();
- const ToolChain * const toolchain = ToolChainKitAspect::toolChain(kit, ProjectExplorer::Constants::CXX_LANGUAGE_ID);
+ const ToolChain *const toolchain = ToolChainKitAspect::cxxToolChain(kit());
if (!toolchain)
return;
@@ -1245,12 +1296,7 @@ void QmakeBuildSystem::testToolChain(ToolChain *tc, const FilePath &path) const
return;
const Utils::FilePath expected = tc->compilerCommand();
-
- Target *t = target();
- QTC_ASSERT(t, return);
-
- QTC_ASSERT(m_buildConfiguration, return);
- Environment env = m_buildConfiguration->environment();
+ Environment env = buildConfiguration()->environment();
if (env.isSameExecutable(path.toString(), expected.toString()))
return;
@@ -1265,35 +1311,29 @@ void QmakeBuildSystem::testToolChain(ToolChain *tc, const FilePath &path) const
return;
}
TaskHub::addTask(
- BuildSystemTask(Task::Warning,
- QCoreApplication::translate(
- "QmakeProjectManager",
- "\"%1\" is used by qmake, but \"%2\" is configured in the kit.\n"
- "Please update your kit (%3) or choose a mkspec for qmake that matches "
- "your target environment better.")
- .arg(path.toUserOutput())
- .arg(expected.toUserOutput())
- .arg(t->kit()->displayName())));
+ BuildSystemTask(Task::Warning,
+ QCoreApplication::translate(
+ "QmakeProjectManager",
+ "\"%1\" is used by qmake, but \"%2\" is configured in the kit.\n"
+ "Please update your kit (%3) or choose a mkspec for qmake that matches "
+ "your target environment better.")
+ .arg(path.toUserOutput())
+ .arg(expected.toUserOutput())
+ .arg(kit()->displayName())));
m_toolChainWarnings.insert(pair);
}
void QmakeBuildSystem::warnOnToolChainMismatch(const QmakeProFile *pro) const
{
- const Target *t = target();
- const BuildConfiguration *bc = t ? t->activeBuildConfiguration() : nullptr;
- if (!bc)
- return;
-
- testToolChain(ToolChainKitAspect::toolChain(t->kit(), ProjectExplorer::Constants::C_LANGUAGE_ID),
- getFullPathOf(pro, Variable::QmakeCc, bc));
- testToolChain(ToolChainKitAspect::toolChain(t->kit(), ProjectExplorer::Constants::CXX_LANGUAGE_ID),
+ const BuildConfiguration *bc = buildConfiguration();
+ testToolChain(ToolChainKitAspect::cToolChain(kit()), getFullPathOf(pro, Variable::QmakeCc, bc));
+ testToolChain(ToolChainKitAspect::cxxToolChain(kit()),
getFullPathOf(pro, Variable::QmakeCxx, bc));
}
QString QmakeBuildSystem::executableFor(const QmakeProFile *file)
{
- const Kit *const kit = target()->kit();
- const ToolChain *const tc = ToolChainKitAspect::toolChain(kit, ProjectExplorer::Constants::CXX_LANGUAGE_ID);
+ const ToolChain *const tc = ToolChainKitAspect::cxxToolChain(kit());
if (!tc)
return QString();
@@ -1346,20 +1386,48 @@ QStringList QmakeBuildSystem::filesGeneratedFrom(const QString &input) const
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),
+ return Utils::transform(proFile->generatedFiles(buildDir(pro->filePath()),
file->filePath(), file->fileType()),
&FilePath::toString);
}
return {};
}
-QVariant QmakeBuildSystem::additionalData(Core::Id id) const
+QVariant QmakeBuildSystem::additionalData(Utils::Id id) const
{
if (id == "QmlDesignerImportPath")
return m_rootProFile->variableValue(Variable::QmlDesignerImportPath);
return BuildSystem::additionalData(id);
}
+void QmakeBuildSystem::buildHelper(Action action, bool isFileBuild, QmakeProFileNode *profile,
+ FileNode *buildableFile)
+{
+ auto bc = qmakeBuildConfiguration();
+
+ if (!profile || !buildableFile)
+ isFileBuild = false;
+
+ if (profile) {
+ if (profile != project()->rootProjectNode() || isFileBuild)
+ bc->setSubNodeBuild(profile->proFileNode());
+ }
+
+ if (isFileBuild)
+ bc->setFileNodeBuild(buildableFile);
+ if (ProjectExplorerPlugin::saveModifiedFiles()) {
+ if (action == BUILD)
+ BuildManager::buildList(bc->buildSteps());
+ else if (action == CLEAN)
+ BuildManager::buildList(bc->cleanSteps());
+ else if (action == REBUILD)
+ BuildManager::buildLists({bc->cleanSteps(), bc->buildSteps()});
+ }
+
+ bc->setSubNodeBuild(nullptr);
+ bc->setFileNodeBuild(nullptr);
+}
+
} // QmakeProjectManager
#include "qmakeproject.moc"