aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJake Petroules <jake.petroules@qt.io>2016-07-07 13:07:20 -0700
committerJake Petroules <jake.petroules@qt.io>2016-07-14 16:05:05 +0000
commit65cb4cba999b47a643e820a102b3185f861b97c1 (patch)
tree943c30a1389fca4b7709d9a23ba05a0d77658019 /src
parent8d4d75b9ad62e48e9a3920df9815f391b2e81e6e (diff)
Introduce the --wait-lock command line option
This allows multiple qbs processes competing for the same configuration instance to be launched simultaneously, and the inactive instances will wait indefinitely for the lock file to be released. This is primarily intended for use by the IDE generator plugins like Visual Studio where the "Build Solution" command builds all projects in the solution in parallel (and this cannot be disabled). Change-Id: I13c37a21dd8386e3dfdab1f769b8242bfcfc2e45 Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
Diffstat (limited to 'src')
-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;