diff options
Diffstat (limited to 'src/lib/corelib/tools')
-rw-r--r-- | src/lib/corelib/tools/buildoptions.cpp | 41 | ||||
-rw-r--r-- | src/lib/corelib/tools/buildoptions.h | 10 | ||||
-rw-r--r-- | src/lib/corelib/tools/fileinfo.cpp | 11 | ||||
-rw-r--r-- | src/lib/corelib/tools/filetime.cpp | 19 | ||||
-rw-r--r-- | src/lib/corelib/tools/joblimits.cpp | 185 | ||||
-rw-r--r-- | src/lib/corelib/tools/joblimits.h | 102 | ||||
-rw-r--r-- | src/lib/corelib/tools/persistence.cpp | 75 | ||||
-rw-r--r-- | src/lib/corelib/tools/persistence.h | 130 | ||||
-rw-r--r-- | src/lib/corelib/tools/preferences.cpp | 26 | ||||
-rw-r--r-- | src/lib/corelib/tools/preferences.h | 2 | ||||
-rw-r--r-- | src/lib/corelib/tools/profile.h | 4 | ||||
-rw-r--r-- | src/lib/corelib/tools/qbspluginmanager.cpp | 6 | ||||
-rw-r--r-- | src/lib/corelib/tools/qttools.cpp | 9 | ||||
-rw-r--r-- | src/lib/corelib/tools/qttools.h | 5 | ||||
-rw-r--r-- | src/lib/corelib/tools/settingsmodel.h | 18 | ||||
-rw-r--r-- | src/lib/corelib/tools/setupprojectparameters.h | 4 | ||||
-rw-r--r-- | src/lib/corelib/tools/stringconstants.h | 2 | ||||
-rw-r--r-- | src/lib/corelib/tools/tools.pri | 3 |
18 files changed, 550 insertions, 102 deletions
diff --git a/src/lib/corelib/tools/buildoptions.cpp b/src/lib/corelib/tools/buildoptions.cpp index ac8e39867..5507e0842 100644 --- a/src/lib/corelib/tools/buildoptions.cpp +++ b/src/lib/corelib/tools/buildoptions.cpp @@ -58,6 +58,8 @@ public: QStringList changedFiles; QStringList filesToConsider; QStringList activeFileTags; + JobLimits jobLimits; + QString settingsDir; int maxJobCount; bool dryRun; bool keepGoing; @@ -68,6 +70,7 @@ public: bool install; bool removeExistingInstallation; bool onlyExecuteRules; + bool jobLimitsFromProjectTakePrecedence = false; }; } // namespace Internal @@ -189,6 +192,44 @@ void BuildOptions::setMaxJobCount(int jobCount) } /*! + * \brief The base directory for qbs settings. + * This value is used to locate profiles and preferences. + */ +QString BuildOptions::settingsDirectory() const +{ + return d->settingsDir; +} + +/*! + * \brief Sets the base directory for qbs settings. + * \param settingsBaseDir Will be used to locate profiles and preferences. + */ +void BuildOptions::setSettingsDirectory(const QString &settingsBaseDir) +{ + d->settingsDir = settingsBaseDir; +} + +JobLimits BuildOptions::jobLimits() const +{ + return d->jobLimits; +} + +void BuildOptions::setJobLimits(const JobLimits &jobLimits) +{ + d->jobLimits = jobLimits; +} + +bool BuildOptions::projectJobLimitsTakePrecedence() const +{ + return d->jobLimitsFromProjectTakePrecedence; +} + +void BuildOptions::setProjectJobLimitsTakePrecedence(bool toggle) +{ + d->jobLimitsFromProjectTakePrecedence = toggle; +} + +/*! * \brief Returns true iff qbs will not actually execute any commands, but just show what * would happen. * The default is false. diff --git a/src/lib/corelib/tools/buildoptions.h b/src/lib/corelib/tools/buildoptions.h index 630a6aa22..cea89d0ea 100644 --- a/src/lib/corelib/tools/buildoptions.h +++ b/src/lib/corelib/tools/buildoptions.h @@ -42,6 +42,7 @@ #include "qbs_export.h" #include "commandechomode.h" +#include "joblimits.h" #include <QtCore/qshareddata.h> @@ -73,6 +74,15 @@ public: int maxJobCount() const; void setMaxJobCount(int jobCount); + QString settingsDirectory() const; + void setSettingsDirectory(const QString &settingsBaseDir); + + JobLimits jobLimits() const; + void setJobLimits(const JobLimits &jobLimits); + + bool projectJobLimitsTakePrecedence() const; + void setProjectJobLimitsTakePrecedence(bool toggle); + bool dryRun() const; void setDryRun(bool dryRun); diff --git a/src/lib/corelib/tools/fileinfo.cpp b/src/lib/corelib/tools/fileinfo.cpp index 3adacc883..15a8e8783 100644 --- a/src/lib/corelib/tools/fileinfo.cpp +++ b/src/lib/corelib/tools/fileinfo.cpp @@ -295,15 +295,10 @@ bool FileInfo::fileExists(const QFileInfo &fi) #define z(x) reinterpret_cast<WIN32_FILE_ATTRIBUTE_DATA*>(const_cast<FileInfo::InternalStatType*>(&x)) -template<bool> struct CompileTimeAssert; -template<> struct CompileTimeAssert<true> {}; - FileInfo::FileInfo(const QString &fileName) { - static CompileTimeAssert< - sizeof(FileInfo::InternalStatType) == sizeof(WIN32_FILE_ATTRIBUTE_DATA) - > internal_type_has_wrong_size; - Q_UNUSED(internal_type_has_wrong_size); + static_assert(sizeof(FileInfo::InternalStatType) == sizeof(WIN32_FILE_ATTRIBUTE_DATA), + "FileInfo::InternalStatType has wrong size."); QString filePath = fileName; @@ -368,7 +363,7 @@ FileInfo::FileInfo(const QString &fileName) bool FileInfo::exists() const { - return m_stat.st_mtime != 0; + return m_stat.st_mode != 0; } FileTime FileInfo::lastModified() const diff --git a/src/lib/corelib/tools/filetime.cpp b/src/lib/corelib/tools/filetime.cpp index 14680ef6e..263950d9c 100644 --- a/src/lib/corelib/tools/filetime.cpp +++ b/src/lib/corelib/tools/filetime.cpp @@ -50,11 +50,6 @@ namespace qbs { namespace Internal { -#ifdef Q_OS_WIN -template<bool> struct CompileTimeAssert; -template<> struct CompileTimeAssert<true> {}; -#endif - #ifdef APPLE_CUSTOM_CLOCK_GETTIME #include <sys/time.h> @@ -77,8 +72,8 @@ int clock_gettime(int /*clk_id*/, struct timespec *t) FileTime::FileTime() { #ifdef Q_OS_WIN - static CompileTimeAssert<sizeof(FileTime::InternalType) == sizeof(FILETIME)> internal_type_has_wrong_size; - Q_UNUSED(internal_type_has_wrong_size); + static_assert(sizeof(FileTime::InternalType) == sizeof(FILETIME), + "FileTime::InternalType has wrong size."); m_fileTime = 0; #elif HAS_CLOCK_GETTIME m_fileTime = {0, 0}; @@ -98,8 +93,8 @@ FileTime::FileTime(const FileTime::InternalType &ft) : m_fileTime(ft) int FileTime::compare(const FileTime &other) const { #ifdef Q_OS_WIN - const FILETIME *const t1 = reinterpret_cast<const FILETIME *>(&m_fileTime); - const FILETIME *const t2 = reinterpret_cast<const FILETIME *>(&other.m_fileTime); + auto const t1 = reinterpret_cast<const FILETIME *>(&m_fileTime); + auto const t2 = reinterpret_cast<const FILETIME *>(&other.m_fileTime); return CompareFileTime(t1, t2); #elif HAS_CLOCK_GETTIME if (m_fileTime.tv_sec < other.m_fileTime.tv_sec) @@ -140,7 +135,7 @@ FileTime FileTime::currentTime() FileTime result; SYSTEMTIME st; GetSystemTime(&st); - FILETIME *const ft = reinterpret_cast<FILETIME *>(&result.m_fileTime); + auto const ft = reinterpret_cast<FILETIME *>(&result.m_fileTime); SystemTimeToFileTime(&st, ft); return result; #elif defined APPLE_CUSTOM_CLOCK_GETTIME @@ -173,7 +168,7 @@ FileTime FileTime::oldestTime() 0 }; FileTime result; - FILETIME *const ft = reinterpret_cast<FILETIME *>(&result.m_fileTime); + auto const ft = reinterpret_cast<FILETIME *>(&result.m_fileTime); SystemTimeToFileTime(&st, ft); return result; #elif HAS_CLOCK_GETTIME @@ -195,7 +190,7 @@ double FileTime::asDouble() const QString FileTime::toString() const { #ifdef Q_OS_WIN - const FILETIME *const ft = reinterpret_cast<const FILETIME *>(&m_fileTime); + auto const ft = reinterpret_cast<const FILETIME *>(&m_fileTime); SYSTEMTIME stUTC, stLocal; FileTimeToSystemTime(ft, &stUTC); SystemTimeToTzSpecificLocalTime(NULL, &stUTC, &stLocal); diff --git a/src/lib/corelib/tools/joblimits.cpp b/src/lib/corelib/tools/joblimits.cpp new file mode 100644 index 000000000..3b1fde83d --- /dev/null +++ b/src/lib/corelib/tools/joblimits.cpp @@ -0,0 +1,185 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qbs. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "joblimits.h" + +#include <tools/persistence.h> + +#include <utility> +#include <vector> + +namespace qbs { +namespace Internal { + +static int transformLimit(int limitFromUser) +{ + return limitFromUser == 0 + ? std::numeric_limits<int>::max() + : limitFromUser < -1 ? -1 + : limitFromUser; +} + +class JobLimitPrivate : public QSharedData +{ +public: + JobLimitPrivate(const QString &pool, int limit) + : jobLimit(std::make_pair(pool, transformLimit(limit))) + { + } + template<PersistentPool::OpType opType> void serializationOp(PersistentPool &pool) + { + pool.serializationOp<opType>(jobLimit); + } + std::pair<QString, int> jobLimit; +}; + +class JobLimitsPrivate : public QSharedData +{ +public: + template<PersistentPool::OpType opType> void serializationOp(PersistentPool &pool) + { + pool.serializationOp<opType>(jobLimits); + } + std::vector<JobLimit> jobLimits; +}; + +} // namespace Internal + +JobLimit::JobLimit() : JobLimit(QString(), -1) +{ +} +JobLimit::JobLimit(const QString &pool, int limit) : d(new Internal::JobLimitPrivate(pool, limit)) +{ +} +JobLimit::JobLimit(const JobLimit &other) : d(other.d) { } +JobLimit &JobLimit::operator=(const JobLimit &other) +{ + d = other.d; + return *this; +} +JobLimit::~JobLimit() {} +QString JobLimit::pool() const { return d->jobLimit.first; } +int JobLimit::limit() const { return d->jobLimit.second; } + +void JobLimit::load(Internal::PersistentPool &pool) +{ + d->serializationOp<Internal::PersistentPool::Load>(pool); +} + +void JobLimit::store(Internal::PersistentPool &pool) +{ + d->serializationOp<Internal::PersistentPool::Store>(pool); +} + +JobLimits::JobLimits() : d(new Internal::JobLimitsPrivate) { } +JobLimits::JobLimits(const JobLimits &other) : d(other.d) { } +JobLimits &JobLimits::operator=(const JobLimits &other) +{ + d = other.d; + return *this; +} +JobLimits::~JobLimits() {} + +void JobLimits::setJobLimit(const JobLimit &limit) +{ + for (std::size_t i = 0; i < d->jobLimits.size(); ++i) { + JobLimit ¤tLimit = d->jobLimits.at(i); + if (currentLimit.pool() == limit.pool()) { + if (currentLimit.limit() != limit.limit()) + currentLimit = limit; + return; + } + } + d->jobLimits.push_back(limit); +} + +void JobLimits::setJobLimit(const QString &pool, int limit) +{ + setJobLimit(JobLimit(pool, limit)); +} + +int JobLimits::getLimit(const QString &pool) const +{ + for (const JobLimit &l : d->jobLimits) { + if (l.pool() == pool) + return l.limit(); + } + return -1; +} + +bool JobLimits::isEmpty() const +{ + return d->jobLimits.empty(); +} + +int JobLimits::count() const +{ + return d->jobLimits.size(); +} + +JobLimit JobLimits::jobLimitAt(int i) const +{ + return d->jobLimits.at(i); +} + +JobLimits &JobLimits::update(const JobLimits &other) +{ + if (isEmpty()) { + *this = other; + } else { + for (int i = 0; i < other.count(); ++i) { + const JobLimit &l = other.jobLimitAt(i); + if (l.limit() != -1) + setJobLimit(l); + } + } + return *this; +} + +void JobLimits::load(Internal::PersistentPool &pool) +{ + d->serializationOp<Internal::PersistentPool::Load>(pool); +} + +void JobLimits::store(Internal::PersistentPool &pool) +{ + d->serializationOp<Internal::PersistentPool::Store>(pool); +} + +} // namespace qbs diff --git a/src/lib/corelib/tools/joblimits.h b/src/lib/corelib/tools/joblimits.h new file mode 100644 index 000000000..de95f5513 --- /dev/null +++ b/src/lib/corelib/tools/joblimits.h @@ -0,0 +1,102 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qbs. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef QBS_JOB_LIMITS_H +#define QBS_JOB_LIMITS_H + +#include "qbs_export.h" + +#include <QtCore/qshareddata.h> + +QT_BEGIN_NAMESPACE +class QString; +QT_END_NAMESPACE + +namespace qbs { +namespace Internal { +class JobLimitPrivate; +class JobLimitsPrivate; +class PersistentPool; +} + +class QBS_EXPORT JobLimit +{ +public: + JobLimit(); + JobLimit(const QString &pool, int limit); + JobLimit(const JobLimit &other); + JobLimit &operator=(const JobLimit &other); + ~JobLimit(); + + QString pool() const; + int limit() const; + + void load(Internal::PersistentPool &pool); + void store(Internal::PersistentPool &pool); +private: + QSharedDataPointer<Internal::JobLimitPrivate> d; +}; + +class QBS_EXPORT JobLimits +{ +public: + JobLimits(); + JobLimits(const JobLimits &other); + JobLimits &operator=(const JobLimits &other); + ~JobLimits(); + + void setJobLimit(const JobLimit &limit); + void setJobLimit(const QString &pool, int limit); + int getLimit(const QString &pool) const; + bool hasLimit(const QString &pool) const { return getLimit(pool) != -1; } + bool isEmpty() const; + + int count() const; + JobLimit jobLimitAt(int i) const; + + JobLimits &update(const JobLimits &other); + + void load(Internal::PersistentPool &pool); + void store(Internal::PersistentPool &pool); +private: + QSharedDataPointer<Internal::JobLimitsPrivate> d; +}; + +} // namespace qbs + +#endif // include guard diff --git a/src/lib/corelib/tools/persistence.cpp b/src/lib/corelib/tools/persistence.cpp index 996c8415d..ec412cf3b 100644 --- a/src/lib/corelib/tools/persistence.cpp +++ b/src/lib/corelib/tools/persistence.cpp @@ -42,14 +42,13 @@ #include "fileinfo.h" #include <logging/translator.h> #include <tools/error.h> -#include <tools/qbsassert.h> #include <QtCore/qdir.h> namespace qbs { namespace Internal { -static const char QBS_PERSISTENCE_MAGIC[] = "QBSPERSISTENCE-120"; +static const char QBS_PERSISTENCE_MAGIC[] = "QBSPERSISTENCE-124"; NoBuildGraphError::NoBuildGraphError(const QString &filePath) : ErrorInfo(Tr::tr("Build graph not found for configuration '%1'. Expected location was '%2'.") @@ -82,7 +81,7 @@ void PersistentPool::load(const QString &filePath) QByteArray magic; m_stream >> magic; if (magic != QBS_PERSISTENCE_MAGIC) { - m_stream.setDevice(0); + m_stream.setDevice(nullptr); throw ErrorInfo(Tr::tr("Cannot use stored build graph at '%1': Incompatible file format. " "Expected magic token '%2', got '%3'.") .arg(filePath, QString::fromLatin1(QBS_PERSISTENCE_MAGIC), @@ -121,6 +120,8 @@ void PersistentPool::setupWriteStream(const QString &filePath) m_stream << QByteArray(qstrlen(QBS_PERSISTENCE_MAGIC), 0) << m_headData.projectConfig; m_lastStoredObjectId = 0; m_lastStoredStringId = 0; + m_lastStoredEnvId = 0; + m_lastStoredStringListId = 0; } void PersistentPool::finalizeWriteStream() @@ -153,7 +154,7 @@ void PersistentPool::storeVariant(const QVariant &variant) m_stream << type; switch (type) { case QMetaType::QString: - storeString(variant.toString()); + store(variant.toString()); break; case QMetaType::QStringList: store(variant.toStringList()); @@ -175,7 +176,7 @@ QVariant PersistentPool::loadVariant() QVariant value; switch (type) { case QMetaType::QString: - value = idLoadString(); + value = load<QString>(); break; case QMetaType::QStringList: value = load<QStringList>(); @@ -200,50 +201,48 @@ void PersistentPool::clear() m_inverseStringStorage.clear(); } -const int StringNotFoundId = -1; -const int NullStringId = -2; - -void PersistentPool::storeString(const QString &t) +void PersistentPool::doLoadValue(QString &s) { - if (t.isNull()) { - m_stream << NullStringId; - return; - } - - int id = m_inverseStringStorage.value(t, StringNotFoundId); - if (id < 0) { - id = m_lastStoredStringId++; - m_inverseStringStorage.insert(t, id); - m_stream << id << t; - } else { - m_stream << id; - } + m_stream >> s; } -QString PersistentPool::loadString(int id) +void PersistentPool::doLoadValue(QStringList &l) { - if (id == NullStringId) - return QString(); + int size; + m_stream >> size; + for (int i = 0; i < size; ++i) + l << load<QString>(); +} - QBS_CHECK(id >= 0); +void PersistentPool::doLoadValue(QProcessEnvironment &env) +{ + const QStringList keys = load<QStringList>(); + for (const QString &key : keys) + env.insert(key, load<QString>()); +} - if (id >= static_cast<int>(m_stringStorage.size())) { - QString s; - m_stream >> s; - m_stringStorage.resize(id + 1); - m_stringStorage[id] = s; - return s; - } +void PersistentPool::doStoreValue(const QString &s) +{ + m_stream << s; +} - return m_stringStorage.at(id); +void PersistentPool::doStoreValue(const QStringList &l) +{ + m_stream << l.size(); + for (const QString &s : l) + store(s); } -QString PersistentPool::idLoadString() +void PersistentPool::doStoreValue(const QProcessEnvironment &env) { - int id; - m_stream >> id; - return loadString(id); + const QStringList &keys = env.keys(); + store(keys); + for (const QString &key : keys) + store(env.value(key)); } +const PersistentPool::PersistentObjectId PersistentPool::ValueNotFoundId; +const PersistentPool::PersistentObjectId PersistentPool::EmptyValueId; + } // namespace Internal } // namespace qbs diff --git a/src/lib/corelib/tools/persistence.h b/src/lib/corelib/tools/persistence.h index 2687d6120..e8d938ad3 100644 --- a/src/lib/corelib/tools/persistence.h +++ b/src/lib/corelib/tools/persistence.h @@ -42,6 +42,8 @@ #include "error.h" #include <logging/logger.h> +#include <tools/qbsassert.h> +#include <tools/qttools.h> #include <QtCore/qdatastream.h> #include <QtCore/qflags.h> @@ -137,20 +139,34 @@ private: template <typename T> T *idLoad(); template <class T> std::shared_ptr<T> idLoadS(); + template <typename T> T idLoadValue(); + + void doLoadValue(QString &s); + void doLoadValue(QStringList &l); + void doLoadValue(QProcessEnvironment &env); template<typename T> void storeSharedObject(const T *object); void storeVariant(const QVariant &variant); QVariant loadVariant(); - void storeString(const QString &t); - QString loadString(int id); - QString idLoadString(); + template <typename T> void idStoreValue(const T &value); + + void doStoreValue(const QString &s); + void doStoreValue(const QStringList &l); + void doStoreValue(const QProcessEnvironment &env); + + template<typename T> std::vector<T> &idStorage(); + template<typename T> QHash<T, PersistentObjectId> &idMap(); + template<typename T> PersistentObjectId &lastStoredId(); // Recursion termination void store() {} void load() {} + static const PersistentObjectId ValueNotFoundId = -1; + static const PersistentObjectId EmptyValueId = -2; + QDataStream m_stream; HeadData m_headData; std::vector<void *> m_loadedRaw; @@ -161,6 +177,12 @@ private: std::vector<QString> m_stringStorage; QHash<QString, int> m_inverseStringStorage; PersistentObjectId m_lastStoredStringId; + std::vector<QProcessEnvironment> m_envStorage; + QHash<QProcessEnvironment, int> m_inverseEnvStorage; + PersistentObjectId m_lastStoredEnvId; + std::vector<QStringList> m_stringListStorage; + QHash<QStringList, int> m_inverseStringListStorage; + PersistentObjectId m_lastStoredStringListId; Logger &m_logger; template<typename T, typename Enable> @@ -209,6 +231,42 @@ template <typename T> inline T *PersistentPool::idLoad() return t; } +template<> inline std::vector<QString> &PersistentPool::idStorage() { return m_stringStorage; } +template<> inline QHash<QString, PersistentPool::PersistentObjectId> &PersistentPool::idMap() +{ + return m_inverseStringStorage; +} +template<> inline PersistentPool::PersistentObjectId &PersistentPool::lastStoredId<QString>() +{ + return m_lastStoredStringId; +} +template<> inline std::vector<QStringList> &PersistentPool::idStorage() +{ + return m_stringListStorage; +} +template<> inline QHash<QStringList, PersistentPool::PersistentObjectId> &PersistentPool::idMap() +{ + return m_inverseStringListStorage; +} +template<> inline PersistentPool::PersistentObjectId &PersistentPool::lastStoredId<QStringList>() +{ + return m_lastStoredStringListId; +} +template<> inline std::vector<QProcessEnvironment> &PersistentPool::idStorage() +{ + return m_envStorage; +} +template<> inline QHash<QProcessEnvironment, PersistentPool::PersistentObjectId> +&PersistentPool::idMap() +{ + return m_inverseEnvStorage; +} +template<> inline PersistentPool::PersistentObjectId +&PersistentPool::lastStoredId<QProcessEnvironment>() +{ + return m_lastStoredEnvId; +} + template <class T> inline std::shared_ptr<T> PersistentPool::idLoadS() { PersistentObjectId id; @@ -227,6 +285,41 @@ template <class T> inline std::shared_ptr<T> PersistentPool::idLoadS() return t; } +template<typename T> inline T PersistentPool::idLoadValue() +{ + int id; + m_stream >> id; + if (id == EmptyValueId) + return T(); + QBS_CHECK(id >= 0); + if (id >= static_cast<int>(idStorage<T>().size())) { + T value; + doLoadValue(value); + idStorage<T>().resize(id + 1); + idStorage<T>()[id] = value; + return value; + } + return idStorage<T>().at(id); +} + +template<typename T> +void PersistentPool::idStoreValue(const T &value) +{ + if (value.isEmpty()) { + m_stream << EmptyValueId; + return; + } + int id = idMap<T>().value(value, ValueNotFoundId); + if (id < 0) { + id = lastStoredId<T>()++; + idMap<T>().insert(value, id); + m_stream << id; + doStoreValue(value); + } else { + m_stream << id; + } +} + // We need a helper class template, because we require partial specialization for some of // the aggregate types, which is not possible with function templates. // The generic implementation assumes that T is of class type and has load() and store() @@ -320,10 +413,11 @@ template<typename T> struct PPHelper<T *> static void load(T* &value, PersistentPool *pool) { value = pool->idLoad<T>(); } }; -template<> struct PPHelper<QString> +template<typename T> struct PPHelper<T, std::enable_if_t<std::is_same<T, QString>::value + || std::is_same<T, QStringList>::value || std::is_same<T, QProcessEnvironment>::value>> { - static void store(const QString &s, PersistentPool *pool) { pool->storeString(s); } - static void load(QString &s, PersistentPool *pool) { s = pool->idLoadString(); } + static void store(const T &v, PersistentPool *pool) { pool->idStoreValue(v); } + static void load(T &v, PersistentPool *pool) { v = pool->idLoadValue<T>(); } }; template<> struct PPHelper<QVariant> @@ -335,30 +429,9 @@ template<> struct PPHelper<QVariant> template<> struct PPHelper<QRegExp> { static void store(const QRegExp &re, PersistentPool *pool) { pool->store(re.pattern()); } - static void load(QRegExp &re, PersistentPool *pool) { re.setPattern(pool->idLoadString()); } + static void load(QRegExp &re, PersistentPool *pool) { re.setPattern(pool->load<QString>()); } }; -template<> struct PPHelper<QProcessEnvironment> -{ - static void store(const QProcessEnvironment &env, PersistentPool *pool) - { - const QStringList &keys = env.keys(); - pool->store(keys.size()); - for (const QString &key : keys) { - pool->store(key); - pool->store(env.value(key)); - } - } - static void load(QProcessEnvironment &env, PersistentPool *pool) - { - const int count = pool->load<int>(); - for (int i = 0; i < count; ++i) { - const auto &key = pool->load<QString>(); - const auto &value = pool->load<QString>(); - env.insert(key, value); - } - } -}; template<typename T, typename U> struct PPHelper<std::pair<T, U>> { static void store(const std::pair<T, U> &pair, PersistentPool *pool) @@ -387,7 +460,6 @@ template<typename T> struct PPHelper<QFlags<T>> }; template<typename T> struct IsSimpleContainer : std::false_type { }; -template<> struct IsSimpleContainer<QStringList> : std::true_type { }; template<typename T> struct IsSimpleContainer<QList<T>> : std::true_type { }; template<typename T> struct IsSimpleContainer<std::vector<T>> : std::true_type { }; diff --git a/src/lib/corelib/tools/preferences.cpp b/src/lib/corelib/tools/preferences.cpp index 66803a0f5..12af4e9c7 100644 --- a/src/lib/corelib/tools/preferences.cpp +++ b/src/lib/corelib/tools/preferences.cpp @@ -124,6 +124,32 @@ QStringList Preferences::pluginPaths(const QString &baseDir) const return pathList(QLatin1String("pluginsPath"), baseDir + QLatin1String("/qbs/plugins")); } +/*! + * \brief Returns the per-pool job limits. + */ +JobLimits Preferences::jobLimits() const +{ + const QString prefix = QLatin1String("preferences.jobLimit"); + JobLimits limits; + for (const QString &key : m_settings->allKeysWithPrefix(prefix, Settings::allScopes())) { + limits.setJobLimit(key, m_settings->value(prefix + QLatin1Char('.') + key, + Settings::allScopes()).toInt()); + } + const QString fullPrefix = prefix + QLatin1Char('.'); + if (!m_profile.isEmpty()) { + Profile p(m_profile, m_settings, m_profileContents); + for (const QString &key : p.allKeys(Profile::KeySelectionRecursive)) { + if (!key.startsWith(fullPrefix)) + continue; + const QString jobPool = key.mid(fullPrefix.size()); + const int limit = p.value(key).toInt(); + if (limit >= 0) + limits.setJobLimit(jobPool, limit); + } + } + return limits; +} + QVariant Preferences::getPreference(const QString &key, const QVariant &defaultValue) const { static const QString keyPrefix = QLatin1String("preferences"); diff --git a/src/lib/corelib/tools/preferences.h b/src/lib/corelib/tools/preferences.h index 07f0edcd7..661b39d7f 100644 --- a/src/lib/corelib/tools/preferences.h +++ b/src/lib/corelib/tools/preferences.h @@ -42,6 +42,7 @@ #include "qbs_export.h" #include "commandechomode.h" +#include "joblimits.h" #include "settings.h" #include <QtCore/qstringlist.h> @@ -63,6 +64,7 @@ public: CommandEchoMode defaultEchoMode() const; QStringList searchPaths(const QString &baseDir = QString()) const; QStringList pluginPaths(const QString &baseDir = QString()) const; + JobLimits jobLimits() const; private: QVariant getPreference(const QString &key, const QVariant &defaultValue = QVariant()) const; diff --git a/src/lib/corelib/tools/profile.h b/src/lib/corelib/tools/profile.h index a4c6a91f1..2ccc99def 100644 --- a/src/lib/corelib/tools/profile.h +++ b/src/lib/corelib/tools/profile.h @@ -59,7 +59,7 @@ public: bool exists() const; QVariant value(const QString &key, const QVariant &defaultValue = QVariant(), - ErrorInfo *error = 0) const; + ErrorInfo *error = nullptr) const; void setValue(const QString &key, const QVariant &value); void remove(const QString &key); @@ -72,7 +72,7 @@ public: void removeProfile(); enum KeySelection { KeySelectionRecursive, KeySelectionNonRecursive }; - QStringList allKeys(KeySelection selection, ErrorInfo *error = 0) const; + QStringList allKeys(KeySelection selection, ErrorInfo *error = nullptr) const; static QString cleanName(const QString &name); diff --git a/src/lib/corelib/tools/qbspluginmanager.cpp b/src/lib/corelib/tools/qbspluginmanager.cpp index a8d22f458..d0be73891 100644 --- a/src/lib/corelib/tools/qbspluginmanager.cpp +++ b/src/lib/corelib/tools/qbspluginmanager.cpp @@ -80,8 +80,7 @@ QbsPluginManager::~QbsPluginManager() unloadStaticPlugins(); for (QLibrary * const lib : qAsConst(d->libs)) { - QbsPluginUnloadFunction unload = reinterpret_cast<QbsPluginUnloadFunction>( - lib->resolve("QbsPluginUnload")); + auto unload = reinterpret_cast<QbsPluginUnloadFunction>(lib->resolve("QbsPluginUnload")); if (unload) unload(); lib->unload(); @@ -146,8 +145,7 @@ void QbsPluginManager::loadPlugins(const std::vector<std::string> &pluginPaths, continue; } - QbsPluginLoadFunction load = reinterpret_cast<QbsPluginLoadFunction>( - lib->resolve("QbsPluginLoad")); + auto load = reinterpret_cast<QbsPluginLoadFunction>(lib->resolve("QbsPluginLoad")); if (load) { load(); qCDebug(lcPluginManager) << "plugin" << QDir::toNativeSeparators(fileName) diff --git a/src/lib/corelib/tools/qttools.cpp b/src/lib/corelib/tools/qttools.cpp index 4e20a7f45..ffd336d56 100644 --- a/src/lib/corelib/tools/qttools.cpp +++ b/src/lib/corelib/tools/qttools.cpp @@ -39,7 +39,10 @@ #include "qttools.h" +#include <QtCore/qprocess.h> + QT_BEGIN_NAMESPACE + uint qHash(const QStringList &list) { uint s = 0; @@ -47,4 +50,10 @@ uint qHash(const QStringList &list) s ^= qHash(n) + 0x9e3779b9 + (s << 6) + (s >> 2); return s; } + +uint qHash(const QProcessEnvironment &env) +{ + return qHash(env.toStringList()); +} + QT_END_NAMESPACE diff --git a/src/lib/corelib/tools/qttools.h b/src/lib/corelib/tools/qttools.h index 50b2829d1..2252c12d3 100644 --- a/src/lib/corelib/tools/qttools.h +++ b/src/lib/corelib/tools/qttools.h @@ -45,6 +45,10 @@ #include <functional> +QT_BEGIN_NAMESPACE +class QProcessEnvironment; +QT_END_NAMESPACE + namespace std { template<> struct hash<QString> { std::size_t operator()(const QString &s) const { return qHash(s); } @@ -53,6 +57,7 @@ template<> struct hash<QString> { QT_BEGIN_NAMESPACE uint qHash(const QStringList &list); +uint qHash(const QProcessEnvironment &env); QT_END_NAMESPACE #endif // QBSQTTOOLS_H diff --git a/src/lib/corelib/tools/settingsmodel.h b/src/lib/corelib/tools/settingsmodel.h index 6f9631585..27936ba52 100644 --- a/src/lib/corelib/tools/settingsmodel.h +++ b/src/lib/corelib/tools/settingsmodel.h @@ -68,14 +68,16 @@ public: void addNewKey(const QModelIndex &parent); void removeKey(const QModelIndex &index); - Qt::ItemFlags flags(const QModelIndex &index) const; - QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; - int columnCount(const QModelIndex &parent = QModelIndex()) const; - int rowCount(const QModelIndex &parent = QModelIndex()) const; - QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; - bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); - QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; - QModelIndex parent(const QModelIndex &child) const; + Qt::ItemFlags flags(const QModelIndex &index) const override; + QVariant headerData(int section, Qt::Orientation orientation, + int role = Qt::DisplayRole) const override; + int columnCount(const QModelIndex &parent = QModelIndex()) const override; + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; + QModelIndex index(int row, int column, + const QModelIndex &parent = QModelIndex()) const override; + QModelIndex parent(const QModelIndex &child) const override; private: class SettingsModelPrivate; diff --git a/src/lib/corelib/tools/setupprojectparameters.h b/src/lib/corelib/tools/setupprojectparameters.h index fd73d0748..fe7e3d487 100644 --- a/src/lib/corelib/tools/setupprojectparameters.h +++ b/src/lib/corelib/tools/setupprojectparameters.h @@ -97,7 +97,9 @@ public: void setOverriddenValues(const QVariantMap &values); QVariantMap overriddenValuesTree() const; - static QVariantMap expandedBuildConfiguration(const Profile &profile, const QString &configurationName, ErrorInfo *errorInfo = 0); + static QVariantMap expandedBuildConfiguration(const Profile &profile, + const QString &configurationName, + ErrorInfo *errorInfo = nullptr); ErrorInfo expandBuildConfiguration(); QVariantMap buildConfiguration() const; QVariantMap buildConfigurationTree() const; diff --git a/src/lib/corelib/tools/stringconstants.h b/src/lib/corelib/tools/stringconstants.h index f2666e070..6fcf3002b 100644 --- a/src/lib/corelib/tools/stringconstants.h +++ b/src/lib/corelib/tools/stringconstants.h @@ -104,6 +104,8 @@ public: QBS_STRING_CONSTANT(installPrefixProperty, "installPrefix") QBS_STRING_CONSTANT(installDirProperty, "installDir") QBS_STRING_CONSTANT(installSourceBaseProperty, "installSourceBase") + QBS_STRING_CONSTANT(jobCountProperty, "jobCount") + QBS_STRING_CONSTANT(jobPoolProperty, "jobPool") QBS_STRING_CONSTANT(lengthProperty, "length") QBS_STRING_CONSTANT(limitToSubProjectProperty, "limitToSubProject") QBS_STRING_CONSTANT(minimumQbsVersionProperty, "minimumQbsVersion") diff --git a/src/lib/corelib/tools/tools.pri b/src/lib/corelib/tools/tools.pri index bb3a55f12..f9c6be9a5 100644 --- a/src/lib/corelib/tools/tools.pri +++ b/src/lib/corelib/tools/tools.pri @@ -21,6 +21,7 @@ HEADERS += \ $$PWD/generateoptions.h \ $$PWD/id.h \ $$PWD/iosutils.h \ + $$PWD/joblimits.h \ $$PWD/jsliterals.h \ $$PWD/launcherinterface.h \ $$PWD/launcherpackets.h \ @@ -75,6 +76,7 @@ SOURCES += \ $$PWD/filetime.cpp \ $$PWD/generateoptions.cpp \ $$PWD/id.cpp \ + $$PWD/joblimits.cpp \ $$PWD/jsliterals.cpp \ $$PWD/launcherinterface.cpp \ $$PWD/launcherpackets.cpp \ @@ -124,6 +126,7 @@ osx { $$PWD/error.h \ $$PWD/generateoptions.h \ $$PWD/installoptions.h \ + $$PWD/joblimits.h \ $$PWD/preferences.h \ $$PWD/processresult.h \ $$PWD/profile.h \ |