diff options
Diffstat (limited to 'src/lib/corelib')
-rw-r--r-- | src/lib/corelib/CMakeLists.txt | 3 | ||||
-rw-r--r-- | src/lib/corelib/corelib.pro | 2 | ||||
-rw-r--r-- | src/lib/corelib/corelib.qbs | 3 | ||||
-rw-r--r-- | src/lib/corelib/jsextensions/jsextensions.cpp | 1 | ||||
-rw-r--r-- | src/lib/corelib/jsextensions/jsextensions.pri | 4 | ||||
-rw-r--r-- | src/lib/corelib/jsextensions/pkgconfigjs.cpp | 211 | ||||
-rw-r--r-- | src/lib/corelib/jsextensions/pkgconfigjs.h | 106 | ||||
-rw-r--r-- | src/lib/corelib/tools/stlutils.h | 6 |
8 files changed, 335 insertions, 1 deletions
diff --git a/src/lib/corelib/CMakeLists.txt b/src/lib/corelib/CMakeLists.txt index 2a38a4943..d4b2d8d38 100644 --- a/src/lib/corelib/CMakeLists.txt +++ b/src/lib/corelib/CMakeLists.txt @@ -158,6 +158,8 @@ set(JS_EXTENSIONS_SOURCES jsextensions.h moduleproperties.cpp moduleproperties.h + pkgconfigjs.cpp + pkgconfigjs.h process.cpp temporarydir.cpp textfile.cpp @@ -426,6 +428,7 @@ add_qbs_library(qbscore Qt${QT_VERSION_MAJOR}::Network Qt${QT_VERSION_MAJOR}::Xml Qt6Core5Compat + qbspkgconfig qbsscriptengine PUBLIC_DEPENDS Qt${QT_VERSION_MAJOR}::Core diff --git a/src/lib/corelib/corelib.pro b/src/lib/corelib/corelib.pro index 799aebda1..afe07f48f 100644 --- a/src/lib/corelib/corelib.pro +++ b/src/lib/corelib/corelib.pro @@ -8,6 +8,8 @@ qbs_use_bundled_qtscript { QT += script } +include(../pkgconfig/use_pkgconfig.pri) + isEmpty(QBS_RELATIVE_LIBEXEC_PATH) { win32:QBS_RELATIVE_LIBEXEC_PATH=../bin else:QBS_RELATIVE_LIBEXEC_PATH=../libexec/qbs diff --git a/src/lib/corelib/corelib.qbs b/src/lib/corelib/corelib.qbs index 0648a051f..6656d638b 100644 --- a/src/lib/corelib/corelib.qbs +++ b/src/lib/corelib/corelib.qbs @@ -16,6 +16,7 @@ QbsLibrary { name: "qbsscriptengine" condition: qbsbuildconfig.useBundledQtScript || !Qt.script.present } + Depends { name: "qbspkgconfig" } name: "qbscore" property stringList bundledQtScriptIncludes: qbsbuildconfig.useBundledQtScript || !Qt.script.present ? qbsscriptengine.includePaths : [] @@ -235,6 +236,8 @@ QbsLibrary { "jsextensions.h", "moduleproperties.cpp", "moduleproperties.h", + "pkgconfigjs.cpp", + "pkgconfigjs.h", "process.cpp", "temporarydir.cpp", "textfile.cpp", diff --git a/src/lib/corelib/jsextensions/jsextensions.cpp b/src/lib/corelib/jsextensions/jsextensions.cpp index 052fb79e4..fc464b44d 100644 --- a/src/lib/corelib/jsextensions/jsextensions.cpp +++ b/src/lib/corelib/jsextensions/jsextensions.cpp @@ -57,6 +57,7 @@ static InitializerMap setupMap() ADD_JS_EXTENSION(Environment); ADD_JS_EXTENSION(File); ADD_JS_EXTENSION(FileInfo); + ADD_JS_EXTENSION(PkgConfig); ADD_JS_EXTENSION(Process); ADD_JS_EXTENSION(PropertyList); ADD_JS_EXTENSION(TemporaryDir); diff --git a/src/lib/corelib/jsextensions/jsextensions.pri b/src/lib/corelib/jsextensions/jsextensions.pri index 004a3e42a..d77f5a687 100644 --- a/src/lib/corelib/jsextensions/jsextensions.pri +++ b/src/lib/corelib/jsextensions/jsextensions.pri @@ -2,7 +2,8 @@ QT += xml HEADERS += \ $$PWD/moduleproperties.h \ - $$PWD/jsextensions.h + $$PWD/jsextensions.h \ + $$PWD/pkgconfigjs.h SOURCES += \ $$PWD/environmentextension.cpp \ @@ -11,6 +12,7 @@ SOURCES += \ $$PWD/temporarydir.cpp \ $$PWD/textfile.cpp \ $$PWD/binaryfile.cpp \ + $$PWD/pkgconfigjs.cpp \ $$PWD/process.cpp \ $$PWD/moduleproperties.cpp \ $$PWD/domxml.cpp \ diff --git a/src/lib/corelib/jsextensions/pkgconfigjs.cpp b/src/lib/corelib/jsextensions/pkgconfigjs.cpp new file mode 100644 index 000000000..4490a14a7 --- /dev/null +++ b/src/lib/corelib/jsextensions/pkgconfigjs.cpp @@ -0,0 +1,211 @@ +/**************************************************************************** +** +** Copyright (C) 2021 Ivan Komissarov (abbapoh@gmail.com) +** 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 "pkgconfigjs.h" + +#include <language/scriptengine.h> + +#include <QtScript/qscriptengine.h> +#include <QtScript/qscriptvalue.h> + +#include <QtCore/QProcessEnvironment> + +#include <stdexcept> + +namespace qbs { +namespace Internal { + +namespace { + +template<typename C, typename F> QVariantList convert(const C &c, F &&f) +{ + QVariantList result; + result.reserve(c.size()); + std::transform(c.begin(), c.end(), std::back_inserter(result), f); + return result; +} + +QVariantMap packageToMap(const PcPackage &package) +{ + QVariantMap result; + result[QStringLiteral("filePath")] = QString::fromStdString(package.filePath); + result[QStringLiteral("baseFileName")] = QString::fromStdString(package.baseFileName); + result[QStringLiteral("name")] = QString::fromStdString(package.name); + result[QStringLiteral("version")] = QString::fromStdString(package.version); + result[QStringLiteral("description")] = QString::fromStdString(package.description); + result[QStringLiteral("url")] = QString::fromStdString(package.url); + + const auto flagToMap = [](const PcPackage::Flag &flag) + { + QVariantMap result; + const auto value = QString::fromStdString(flag.value); + result[QStringLiteral("type")] = QVariant::fromValue(qint32(flag.type)); + result[QStringLiteral("value")] = value; + return result; + }; + + const auto requiredVersionToMap = [](const PcPackage::RequiredVersion &version) + { + QVariantMap result; + result[QStringLiteral("name")] = QString::fromStdString(version.name); + result[QStringLiteral("version")] = QString::fromStdString(version.version); + result[QStringLiteral("comparison")] = QVariant::fromValue(qint32(version.comparison)); + return result; + }; + + result[QStringLiteral("libs")] = convert(package.libs, flagToMap); + result[QStringLiteral("libsPrivate")] = convert(package.libsPrivate, flagToMap); + result[QStringLiteral("cflags")] = convert(package.cflags, flagToMap); + result[QStringLiteral("requires")] = convert(package.requiresPublic, requiredVersionToMap); + result[QStringLiteral("requiresPrivate")] = + convert(package.requiresPrivate, requiredVersionToMap); + result[QStringLiteral("conflicts")] = convert(package.conflicts, requiredVersionToMap); + + return result; +}; + +QVariantMap brokenPackageToMap(const PcBrokenPackage &package) +{ + QVariantMap result; + result[QStringLiteral("filePath")] = QString::fromStdString(package.filePath); + result[QStringLiteral("errorText")] = QString::fromStdString(package.errorText); + return result; +} + +PcPackage::VariablesMap envToVariablesMap(const QProcessEnvironment &env) +{ + PcPackage::VariablesMap result; + const auto keys = env.keys(); + for (const auto &key : keys) + result[key.toStdString()] = env.value(key).toStdString(); + return result; +} + +PcPackage::VariablesMap variablesFromQVariantMap(const QVariantMap &map) +{ + PcPackage::VariablesMap result; + for (auto it = map.cbegin(), end = map.cend(); it != end; ++it) + result[it.key().toStdString()] = it.value().toString().toStdString(); + return result; +} + +std::vector<std::string> stringListToStdVector(const QStringList &list) +{ + std::vector<std::string> result; + result.reserve(list.size()); + for (const auto &string : list) + result.push_back(string.toStdString()); + return result; +} + +} // namespace + +QScriptValue PkgConfigJs::ctor(QScriptContext *context, QScriptEngine *engine) +{ + try { + PkgConfigJs *e = nullptr; + switch (context->argumentCount()) { + case 0: + e = new PkgConfigJs(context, engine); + break; + case 1: + e = new PkgConfigJs(context, engine, context->argument(0).toVariant().toMap()); + break; + + default: + return context->throwError( + QStringLiteral("TextFile constructor takes at most three parameters.")); + } + + return engine->newQObject(e, QScriptEngine::ScriptOwnership); + } catch (const PcException &e) { + return context->throwError(QString::fromUtf8(e.what())); + } +} + +PkgConfigJs::PkgConfigJs( + QScriptContext *context, QScriptEngine *engine, const QVariantMap &options) : + m_pkgConfig(std::make_unique<PkgConfig>( + convertOptions(static_cast<ScriptEngine *>(engine)->environment(), options))) +{ + Q_UNUSED(context); + for (const auto &package : m_pkgConfig->packages()) + m_packages.insert(QString::fromStdString(package.baseFileName), packageToMap(package)); + + for (const auto &package : m_pkgConfig->brokenPackages()) + m_brokenPackages.push_back(brokenPackageToMap(package)); +} + +PkgConfig::Options PkgConfigJs::convertOptions(const QProcessEnvironment &env, const QVariantMap &map) +{ + PkgConfig::Options result; + result.searchPaths = + stringListToStdVector(map.value(QStringLiteral("searchPaths")).toStringList()); + result.sysroot = map.value(QStringLiteral("sysroot")).toString().toStdString(); + result.topBuildDir = map.value(QStringLiteral("topBuildDir")).toString().toStdString(); + result.allowSystemLibraryPaths = + map.value(QStringLiteral("allowSystemLibraryPaths"), false).toBool(); + const auto systemLibraryPaths = map.value(QStringLiteral("systemLibraryPaths")).toStringList(); + result.systemLibraryPaths.reserve(systemLibraryPaths.size()); + std::transform( + systemLibraryPaths.begin(), + systemLibraryPaths.end(), + std::back_inserter(result.systemLibraryPaths), + [](const QString &str){ return str.toStdString(); }); + result.disableUninstalled = map.value(QStringLiteral("disableUninstalled"), true).toBool(); + result.globalVariables = + variablesFromQVariantMap(map.value(QStringLiteral("globalVariables")).toMap()); + result.systemVariables = envToVariablesMap(env); + + return result; +} + +} // namespace Internal +} // namespace qbs + +void initializeJsExtensionPkgConfig(QScriptValue extensionObject) +{ + using namespace qbs::Internal; + QScriptEngine *engine = extensionObject.engine(); + QScriptValue obj = engine->newQMetaObject( + &PkgConfigJs::staticMetaObject, engine->newFunction(&PkgConfigJs::ctor)); + extensionObject.setProperty(QStringLiteral("PkgConfig"), obj); +} + +Q_DECLARE_METATYPE(qbs::Internal::PkgConfigJs *) diff --git a/src/lib/corelib/jsextensions/pkgconfigjs.h b/src/lib/corelib/jsextensions/pkgconfigjs.h new file mode 100644 index 000000000..66575d8f3 --- /dev/null +++ b/src/lib/corelib/jsextensions/pkgconfigjs.h @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2021 Ivan Komissarov (abbapoh@gmail.com) +** 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 "tools/qbs_export.h" +#include <tools/stlutils.h> + +#include <pkgconfig.h> + +#include <QtCore/qobject.h> +#include <QtCore/qvariant.h> + +#include <QtScript/qscriptable.h> + +#include <memory> + +class QProcessEnvironment; + +namespace qbs { +namespace Internal { + +class QBS_AUTOTEST_EXPORT PkgConfigJs : public QObject, QScriptable +{ + Q_OBJECT +public: + + // can we trick moc here to avoid duplication? + enum class FlagType { + LibraryName = toUnderlying(PcPackage::Flag::Type::LibraryName), + LibraryPath = toUnderlying(PcPackage::Flag::Type::LibraryPath), + StaticLibraryName = toUnderlying(PcPackage::Flag::Type::StaticLibraryName), + Framework = toUnderlying(PcPackage::Flag::Type::Framework), + FrameworkPath = toUnderlying(PcPackage::Flag::Type::FrameworkPath), + LinkerFlags = toUnderlying(PcPackage::Flag::Type::LinkerFlag), + IncludePath = toUnderlying(PcPackage::Flag::Type::IncludePath), + SystemIncludePath = toUnderlying(PcPackage::Flag::Type::SystemIncludePath), + Define = toUnderlying(PcPackage::Flag::Type::Define), + CompilerFlags = toUnderlying(PcPackage::Flag::Type::CompilerFlag), + }; + Q_ENUM(FlagType); + + enum class ComparisonType { + LessThan, + GreaterThan, + LessThanEqual, + GreaterThanEqual, + Equal, + NotEqual, + AlwaysMatch + }; + Q_ENUM(ComparisonType); + + static QScriptValue ctor(QScriptContext *context, QScriptEngine *engine); + + explicit PkgConfigJs( + QScriptContext *context, QScriptEngine *engine, const QVariantMap &options = {}); + + Q_INVOKABLE QVariantMap packages() const { return m_packages; } + Q_INVOKABLE QVariantList brokenPackages() const { return m_brokenPackages; } + + // also used in tests + static PkgConfig::Options convertOptions(const QProcessEnvironment &env, const QVariantMap &map); + +private: + std::unique_ptr<PkgConfig> m_pkgConfig; + QVariantMap m_packages; + QVariantList m_brokenPackages; +}; + +} // namespace Internal +} // namespace qbs diff --git a/src/lib/corelib/tools/stlutils.h b/src/lib/corelib/tools/stlutils.h index 2a069cbe1..5aff5cc54 100644 --- a/src/lib/corelib/tools/stlutils.h +++ b/src/lib/corelib/tools/stlutils.h @@ -219,6 +219,12 @@ C rangeTo(R &&r) return C(std::begin(r), std::end(r)); } +template<class Enum> +constexpr std::underlying_type_t<Enum> toUnderlying(Enum e) noexcept +{ + return static_cast<std::underlying_type_t<Enum>>(e); +} + } // namespace Internal } // namespace qbs |