aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/app/qbs/commandlinefrontend.cpp1
-rw-r--r--src/app/qbs/parser/command.cpp3
-rw-r--r--src/app/qbs/parser/commandlineoption.cpp12
-rw-r--r--src/app/qbs/parser/commandlineoption.h11
-rw-r--r--src/app/qbs/parser/commandlineoptionpool.cpp8
-rw-r--r--src/app/qbs/parser/commandlineoptionpool.h1
-rw-r--r--src/app/qbs/parser/commandlineparser.cpp5
-rw-r--r--src/app/qbs/parser/commandlineparser.h1
-rw-r--r--src/lib/corelib/api/internaljobs.cpp2
-rw-r--r--src/lib/corelib/tools/buildgraphlocker.cpp23
-rw-r--r--src/lib/corelib/tools/buildgraphlocker.h5
-rw-r--r--src/lib/corelib/tools/setupprojectparameters.cpp20
-rw-r--r--src/lib/corelib/tools/setupprojectparameters.h3
13 files changed, 86 insertions, 9 deletions
diff --git a/src/app/qbs/commandlinefrontend.cpp b/src/app/qbs/commandlinefrontend.cpp
index 4c84ed77f..4b60b06d0 100644
--- a/src/app/qbs/commandlinefrontend.cpp
+++ b/src/app/qbs/commandlinefrontend.cpp
@@ -134,6 +134,7 @@ void CommandLineFrontend::start()
params.setIgnoreDifferentProjectFilePath(m_parser.force());
params.setDryRun(m_parser.dryRun());
params.setForceProbeExecution(m_parser.forceProbesExecution());
+ params.setWaitLockBuildGraph(m_parser.waitLockBuildGraph());
params.setLogElapsedTime(m_parser.logTime());
params.setSettingsDirectory(m_settings->baseDirectory());
if (!m_parser.buildBeforeInstalling() || m_parser.command() == DumpNodesTreeCommandType)
diff --git a/src/app/qbs/parser/command.cpp b/src/app/qbs/parser/command.cpp
index b67daefad..48e48aa02 100644
--- a/src/app/qbs/parser/command.cpp
+++ b/src/app/qbs/parser/command.cpp
@@ -253,7 +253,8 @@ static QList<CommandLineOption::Type> buildOptions()
<< CommandLineOption::VersionOptionType
<< CommandLineOption::CommandEchoModeOptionType
<< CommandLineOption::NoInstallOptionType
- << CommandLineOption::RemoveFirstOptionType;
+ << CommandLineOption::RemoveFirstOptionType
+ << CommandLineOption::WaitLockOptionType;
}
QList<CommandLineOption::Type> BuildCommand::supportedOptions() const
diff --git a/src/app/qbs/parser/commandlineoption.cpp b/src/app/qbs/parser/commandlineoption.cpp
index 4dd12c6f9..895eb42b8 100644
--- a/src/app/qbs/parser/commandlineoption.cpp
+++ b/src/app/qbs/parser/commandlineoption.cpp
@@ -641,4 +641,16 @@ void CommandEchoModeOption::doParse(const QString &representation, QStringList &
m_echoMode = commandEchoModeFromName(mode);
}
+QString WaitLockOption::description(CommandType command) const
+{
+ Q_UNUSED(command);
+ return Tr::tr("%1\n\tWait indefinitely for other processes to release the build graph lock.\n")
+ .arg(longRepresentation());
+}
+
+QString WaitLockOption::longRepresentation() const
+{
+ return QLatin1String("--wait-lock");
+}
+
} // namespace qbs
diff --git a/src/app/qbs/parser/commandlineoption.h b/src/app/qbs/parser/commandlineoption.h
index d986856a9..e27ef9518 100644
--- a/src/app/qbs/parser/commandlineoption.h
+++ b/src/app/qbs/parser/commandlineoption.h
@@ -62,7 +62,8 @@ public:
LogTimeOptionType,
CommandEchoModeOptionType,
SettingsDirOptionType,
- GeneratorOptionType
+ GeneratorOptionType,
+ WaitLockOptionType
};
virtual ~CommandLineOption();
@@ -382,6 +383,14 @@ private:
QString m_settingsDir;
};
+class WaitLockOption : public OnOffOption
+{
+public:
+ QString description(CommandType command) const;
+ QString shortRepresentation() const { return QString(); }
+ QString longRepresentation() const;
+};
+
} // namespace qbs
#endif // QBS_COMMANDLINEOPTION_H
diff --git a/src/app/qbs/parser/commandlineoptionpool.cpp b/src/app/qbs/parser/commandlineoptionpool.cpp
index fd77c791c..66e1c1699 100644
--- a/src/app/qbs/parser/commandlineoptionpool.cpp
+++ b/src/app/qbs/parser/commandlineoptionpool.cpp
@@ -116,6 +116,9 @@ CommandLineOption *CommandLineOptionPool::getOption(CommandLineOption::Type type
case CommandLineOption::GeneratorOptionType:
option = new GeneratorOption;
break;
+ case CommandLineOption::WaitLockOptionType:
+ option = new WaitLockOption;
+ break;
default:
qFatal("Unknown option type %d", type);
}
@@ -253,4 +256,9 @@ GeneratorOption *CommandLineOptionPool::generatorOption() const
return static_cast<GeneratorOption *>(getOption(CommandLineOption::GeneratorOptionType));
}
+WaitLockOption *CommandLineOptionPool::waitLockOption() const
+{
+ return static_cast<WaitLockOption *>(getOption(CommandLineOption::WaitLockOptionType));
+}
+
} // namespace qbs
diff --git a/src/app/qbs/parser/commandlineoptionpool.h b/src/app/qbs/parser/commandlineoptionpool.h
index 9cc9eb0ca..53578b423 100644
--- a/src/app/qbs/parser/commandlineoptionpool.h
+++ b/src/app/qbs/parser/commandlineoptionpool.h
@@ -67,6 +67,7 @@ public:
CommandEchoModeOption *commandEchoModeOption() const;
SettingsDirOption *settingsDirOption() const;
GeneratorOption *generatorOption() const;
+ WaitLockOption *waitLockOption() const;
private:
mutable QHash<CommandLineOption::Type, CommandLineOption *> m_options;
diff --git a/src/app/qbs/parser/commandlineparser.cpp b/src/app/qbs/parser/commandlineparser.cpp
index addaffaef..6abc9a83b 100644
--- a/src/app/qbs/parser/commandlineparser.cpp
+++ b/src/app/qbs/parser/commandlineparser.cpp
@@ -221,6 +221,11 @@ bool CommandLineParser::forceProbesExecution() const
return d->optionPool.forceProbesOption()->enabled();
}
+bool CommandLineParser::waitLockBuildGraph() const
+{
+ return d->optionPool.waitLockOption()->enabled();
+}
+
bool CommandLineParser::logTime() const
{
return d->logTime;
diff --git a/src/app/qbs/parser/commandlineparser.h b/src/app/qbs/parser/commandlineparser.h
index 2732b3c04..2c409bcfc 100644
--- a/src/app/qbs/parser/commandlineparser.h
+++ b/src/app/qbs/parser/commandlineparser.h
@@ -66,6 +66,7 @@ public:
bool forceOutputCheck() const;
bool dryRun() const;
bool forceProbesExecution() const;
+ bool waitLockBuildGraph() const;
bool logTime() const;
bool withNonDefaultProducts() const;
bool buildBeforeInstalling() const;
diff --git a/src/lib/corelib/api/internaljobs.cpp b/src/lib/corelib/api/internaljobs.cpp
index 681a4856b..c00e88138 100644
--- a/src/lib/corelib/api/internaljobs.cpp
+++ b/src/lib/corelib/api/internaljobs.cpp
@@ -241,7 +241,7 @@ void InternalSetupProjectJob::start()
if (!m_existingProject) {
bgLocker = new BuildGraphLocker(ProjectBuildData::deriveBuildGraphFilePath(buildDir,
projectId),
- logger());
+ logger(), m_parameters.waitLockBuildGraph(), observer());
}
execute();
if (m_existingProject)
diff --git a/src/lib/corelib/tools/buildgraphlocker.cpp b/src/lib/corelib/tools/buildgraphlocker.cpp
index 11f14e4a7..d5be262d8 100644
--- a/src/lib/corelib/tools/buildgraphlocker.cpp
+++ b/src/lib/corelib/tools/buildgraphlocker.cpp
@@ -33,6 +33,7 @@
#include "error.h"
#include "hostosinfo.h"
#include "processutils.h"
+#include "progressobserver.h"
#include "version.h"
#include <logging/translator.h>
@@ -59,23 +60,35 @@ static bool hasQtBug53392()
return qtVersion == Version(5, 7, 0) || qtVersion < Version(5, 6, 2);
}
-BuildGraphLocker::BuildGraphLocker(const QString &buildGraphFilePath, const Logger &logger)
- : m_lockFile(buildGraphFilePath + QLatin1String(".lock"))
- , m_logger(logger)
+static void tryCreateBuildDirectory(const QString &buildDir, const QString &buildGraphFilePath)
{
- const QString buildDir = QFileInfo(buildGraphFilePath).absolutePath();
- rememberCreatedDirectories(buildDir);
if (!QDir::root().mkpath(buildDir)) {
throw ErrorInfo(Tr::tr("Cannot lock build graph file '%1': Failed to create directory.")
.arg(buildGraphFilePath));
}
+}
+
+BuildGraphLocker::BuildGraphLocker(const QString &buildGraphFilePath, const Logger &logger,
+ bool waitIndefinitely, ProgressObserver *observer)
+ : m_lockFile(buildGraphFilePath + QLatin1String(".lock"))
+ , m_logger(logger)
+{
+ const QString buildDir = QFileInfo(buildGraphFilePath).absolutePath();
+ rememberCreatedDirectories(buildDir);
+ if (waitIndefinitely)
+ m_logger.qbsDebug() << "Waiting to acquire lock file...";
m_lockFile.setStaleLockTime(0);
int attemptsToGetInfo = 0;
do {
+ if (observer->canceled())
+ break;
+ tryCreateBuildDirectory(buildDir, buildGraphFilePath);
if (m_lockFile.tryLock(250))
return;
switch (m_lockFile.error()) {
case QLockFile::LockFailedError: {
+ if (waitIndefinitely)
+ continue;
qint64 pid;
QString hostName;
QString appName;
diff --git a/src/lib/corelib/tools/buildgraphlocker.h b/src/lib/corelib/tools/buildgraphlocker.h
index 496296af5..307f8adee 100644
--- a/src/lib/corelib/tools/buildgraphlocker.h
+++ b/src/lib/corelib/tools/buildgraphlocker.h
@@ -40,10 +40,13 @@
namespace qbs {
namespace Internal {
+class ProgressObserver;
+
class BuildGraphLocker
{
public:
- explicit BuildGraphLocker(const QString &buildGraphFilePath, const Logger &logger);
+ explicit BuildGraphLocker(const QString &buildGraphFilePath, const Logger &logger,
+ bool waitIndefinitely, ProgressObserver *observer);
~BuildGraphLocker();
private:
diff --git a/src/lib/corelib/tools/setupprojectparameters.cpp b/src/lib/corelib/tools/setupprojectparameters.cpp
index 392b7dc4d..17fae5b28 100644
--- a/src/lib/corelib/tools/setupprojectparameters.cpp
+++ b/src/lib/corelib/tools/setupprojectparameters.cpp
@@ -54,6 +54,7 @@ public:
, dryRun(false)
, logElapsedTime(false)
, forceProbeExecution(false)
+ , waitLockBuildGraph(false)
, restoreBehavior(SetupProjectParameters::RestoreAndTrackChanges)
, propertyCheckingMode(ErrorHandlingMode::Relaxed)
, productErrorMode(ErrorHandlingMode::Strict)
@@ -78,6 +79,7 @@ public:
bool dryRun;
bool logElapsedTime;
bool forceProbeExecution;
+ bool waitLockBuildGraph;
SetupProjectParameters::RestoreBehavior restoreBehavior;
ErrorHandlingMode propertyCheckingMode;
ErrorHandlingMode productErrorMode;
@@ -498,6 +500,24 @@ void SetupProjectParameters::setForceProbeExecution(bool force)
}
/*!
+ * \brief Returns true if qbs should wait for the build graph lock to become available,
+ * otherwise qbs will exit immediately if the lock cannot be acquired.
+ */
+bool SetupProjectParameters::waitLockBuildGraph() const
+{
+ return d->waitLockBuildGraph;
+}
+
+/*!
+ * Controls whether to wait indefinitely for the build graph lock to be released.
+ * This allows multiple conflicting qbs processes to be spawned simultaneously.
+ */
+void SetupProjectParameters::setWaitLockBuildGraph(bool wait)
+{
+ d->waitLockBuildGraph = wait;
+}
+
+/*!
* \brief Gets the environment used while resolving the project.
*/
QProcessEnvironment SetupProjectParameters::environment() const
diff --git a/src/lib/corelib/tools/setupprojectparameters.h b/src/lib/corelib/tools/setupprojectparameters.h
index d05a3b8ab..8c2aa71d6 100644
--- a/src/lib/corelib/tools/setupprojectparameters.h
+++ b/src/lib/corelib/tools/setupprojectparameters.h
@@ -106,6 +106,9 @@ public:
bool forceProbeExecution() const;
void setForceProbeExecution(bool force);
+ bool waitLockBuildGraph() const;
+ void setWaitLockBuildGraph(bool wait);
+
QProcessEnvironment environment() const;
void setEnvironment(const QProcessEnvironment &env);
QProcessEnvironment adjustedEnvironment() const;