diff options
-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; |