diff options
author | Jake Petroules <jake.petroules@qt.io> | 2016-07-07 13:07:20 -0700 |
---|---|---|
committer | Jake Petroules <jake.petroules@qt.io> | 2016-07-14 16:05:05 +0000 |
commit | 65cb4cba999b47a643e820a102b3185f861b97c1 (patch) | |
tree | 943c30a1389fca4b7709d9a23ba05a0d77658019 /src | |
parent | 8d4d75b9ad62e48e9a3920df9815f391b2e81e6e (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.cpp | 1 | ||||
-rw-r--r-- | src/app/qbs/parser/command.cpp | 3 | ||||
-rw-r--r-- | src/app/qbs/parser/commandlineoption.cpp | 12 | ||||
-rw-r--r-- | src/app/qbs/parser/commandlineoption.h | 11 | ||||
-rw-r--r-- | src/app/qbs/parser/commandlineoptionpool.cpp | 8 | ||||
-rw-r--r-- | src/app/qbs/parser/commandlineoptionpool.h | 1 | ||||
-rw-r--r-- | src/app/qbs/parser/commandlineparser.cpp | 5 | ||||
-rw-r--r-- | src/app/qbs/parser/commandlineparser.h | 1 | ||||
-rw-r--r-- | src/lib/corelib/api/internaljobs.cpp | 2 | ||||
-rw-r--r-- | src/lib/corelib/tools/buildgraphlocker.cpp | 23 | ||||
-rw-r--r-- | src/lib/corelib/tools/buildgraphlocker.h | 5 | ||||
-rw-r--r-- | src/lib/corelib/tools/setupprojectparameters.cpp | 20 | ||||
-rw-r--r-- | src/lib/corelib/tools/setupprojectparameters.h | 3 |
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; |