aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/corelib/language/moduleproviderloader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/corelib/language/moduleproviderloader.cpp')
-rw-r--r--src/lib/corelib/language/moduleproviderloader.cpp374
1 files changed, 0 insertions, 374 deletions
diff --git a/src/lib/corelib/language/moduleproviderloader.cpp b/src/lib/corelib/language/moduleproviderloader.cpp
deleted file mode 100644
index 22605bf9f..000000000
--- a/src/lib/corelib/language/moduleproviderloader.cpp
+++ /dev/null
@@ -1,374 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 The Qt Company Ltd.
-** 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 "moduleproviderloader.h"
-
-#include "builtindeclarations.h"
-#include "evaluator.h"
-#include "item.h"
-#include "itemreader.h"
-#include "probesresolver.h"
-
-#include <language/scriptengine.h>
-#include <language/value.h>
-
-#include <logging/categories.h>
-#include <logging/translator.h>
-
-#include <tools/fileinfo.h>
-#include <tools/jsliterals.h>
-#include <tools/scripttools.h>
-#include <tools/setupprojectparameters.h>
-#include <tools/stlutils.h>
-#include <tools/stringconstants.h>
-
-#include <QtCore/qtemporaryfile.h>
-
-namespace qbs {
-namespace Internal {
-
-ModuleProviderLoader::ModuleProviderLoader(
- const SetupProjectParameters &parameters, ItemReader &reader, Evaluator &evaluator,
- ProbesResolver &probesResolver, Logger &logger)
- : m_parameters(parameters)
- , m_reader(reader)
- , m_evaluator(evaluator)
- , m_probesResolver(probesResolver)
- , m_logger(logger)
-{
-}
-
-ModuleProviderLoader::ModuleProviderResult ModuleProviderLoader::executeModuleProviders(
- const ProductContext &productContext,
- const CodeLocation &dependsItemLocation,
- const QualifiedId &moduleName,
- FallbackMode fallbackMode)
-{
- ModuleProviderLoader::ModuleProviderResult result;
- std::vector<Provider> providersToRun;
- qCDebug(lcModuleLoader) << "Module" << moduleName.toString()
- << "not found, checking for module providers";
- const auto providerNames = getModuleProviders(productContext.productItem);
- if (providerNames) {
- providersToRun = transformed<std::vector<Provider>>(*providerNames, [](const auto &name) {
- return Provider{name, ModuleProviderLookup::Named}; });
- } else {
- for (QualifiedId providerName = moduleName; !providerName.empty();
- providerName.pop_back()) {
- providersToRun.push_back({providerName, ModuleProviderLookup::Scoped});
- }
- }
- result = executeModuleProvidersHelper(productContext, dependsItemLocation, providersToRun);
-
- if (fallbackMode == FallbackMode::Enabled
- && !result.providerFound
- && !providerNames) {
- qCDebug(lcModuleLoader) << "Specific module provider not found for"
- << moduleName.toString() << ", setting up fallback.";
- result = executeModuleProvidersHelper(
- productContext,
- dependsItemLocation,
- {{moduleName, ModuleProviderLookup::Fallback}});
- }
-
- return result;
-}
-
-ModuleProviderLoader::ModuleProviderResult ModuleProviderLoader::executeModuleProvidersHelper(
- const ProductContext &product,
- const CodeLocation &dependsItemLocation,
- const std::vector<Provider> &providers)
-{
- if (providers.empty())
- return {};
- QStringList allSearchPaths;
- ModuleProviderResult result;
- result.providerConfig = product.providerConfig ? *product.providerConfig
- : getModuleProviderConfig(product);
- const auto qbsModule = evaluateQbsModule(product);
- for (const auto &[name, lookupType] : providers) {
- const QVariantMap config = result.providerConfig.value(name.toString()).toMap();
- ModuleProviderInfo &info = m_storedModuleProviderInfo.providers[
- {name.toString(), config, qbsModule, int(lookupType)}];
- const bool fromCache = !info.name.isEmpty();
- if (!fromCache) {
- info.name = name;
- info.config = config;
- info.providerFile = findModuleProviderFile(name, lookupType);
- if (!info.providerFile.isEmpty()) {
- qCDebug(lcModuleLoader) << "Running provider" << name << "at" << info.providerFile;
- const auto evalResult = evaluateModuleProvider(
- product, dependsItemLocation, name, info.providerFile, config, qbsModule);
- info.searchPaths = evalResult.first;
- result.probes << evalResult.second;
- info.transientOutput = m_parameters.dryRun();
- }
- }
- if (info.providerFile.isEmpty()) {
- if (lookupType == ModuleProviderLookup::Named)
- throw ErrorInfo(Tr::tr("Unknown provider '%1'").arg(name.toString()));
- continue;
- }
- if (fromCache)
- qCDebug(lcModuleLoader) << "Re-using provider" << name.toString() << "from cache";
-
- result.providerFound = true;
- if (info.searchPaths.empty()) {
- qCDebug(lcModuleLoader)
- << "Module provider did run, but did not set up any modules.";
- continue;
- }
- qCDebug(lcModuleLoader) << "Module provider added" << info.searchPaths.size()
- << "new search path(s)";
-
- allSearchPaths << info.searchPaths;
- }
- if (allSearchPaths.isEmpty())
- return result;
-
- result.searchPaths = std::move(allSearchPaths);
-
- return result;
-}
-
-QVariantMap ModuleProviderLoader::getModuleProviderConfig(const ProductContext &product)
-{
- QVariantMap providerConfig;
- const ItemValueConstPtr configItemValue =
- product.productItem->itemProperty(StringConstants::moduleProviders());
- if (configItemValue) {
- const std::function<void(const Item *, QualifiedId)> collectMap
- = [this, &providerConfig, &collectMap](const Item *item, const QualifiedId &name) {
- const Item::PropertyMap &props = item->properties();
- for (auto it = props.begin(); it != props.end(); ++it) {
- QVariant value;
- switch (it.value()->type()) {
- case Value::ItemValueType: {
- const auto childItem = static_cast<ItemValue *>(it.value().get())->item();
- childItem->setScope(item->scope());
- collectMap(childItem, QualifiedId(name) << it.key());
- continue;
- }
- case Value::JSSourceValueType: {
- const ScopedJsValue sv(m_evaluator.engine()->context(),
- m_evaluator.value(item, it.key()));
- value = getJsVariant(m_evaluator.engine()->context(), sv);
- break;
- }
- case Value::VariantValueType:
- value = static_cast<VariantValue *>(it.value().get())->value();
- break;
- }
- QVariantMap m = providerConfig.value(name.toString()).toMap();
- m.insert(it.key(), value);
- providerConfig.insert(name.toString(), m);
- }
- };
- configItemValue->item()->setScope(product.productItem);
- collectMap(configItemValue->item(), QualifiedId());
- }
- for (auto it = product.moduleProperties.begin(); it != product.moduleProperties.end(); ++it) {
- if (!it.key().startsWith(QStringLiteral("moduleProviders.")))
- continue;
- const QString provider = it.key().mid(QStringLiteral("moduleProviders.").size());
- const QVariantMap providerConfigFromBuildConfig = it.value().toMap();
- if (providerConfigFromBuildConfig.empty())
- continue;
- QVariantMap currentMapForProvider = providerConfig.value(provider).toMap();
- for (auto propIt = providerConfigFromBuildConfig.begin();
- propIt != providerConfigFromBuildConfig.end(); ++propIt) {
- currentMapForProvider.insert(propIt.key(), propIt.value());
- }
- providerConfig.insert(provider, currentMapForProvider);
- }
- return providerConfig;
-}
-
-std::optional<std::vector<QualifiedId>> ModuleProviderLoader::getModuleProviders(Item *item)
-{
- while (item) {
- const auto providers =
- m_evaluator.optionalStringListValue(item, StringConstants::qbsModuleProviders());
- if (providers) {
- return transformed<std::vector<QualifiedId>>(*providers, [](const auto &provider) {
- return QualifiedId::fromString(provider); });
- }
- item = item->parent();
- }
- return std::nullopt;
-}
-
-QString ModuleProviderLoader::findModuleProviderFile(
- const QualifiedId &name, ModuleProviderLookup lookupType)
-{
- for (const QString &path : m_reader.allSearchPaths()) {
- QString fullPath = FileInfo::resolvePath(path, QStringLiteral("module-providers"));
- switch (lookupType) {
- case ModuleProviderLookup::Named: {
- const auto result =
- FileInfo::resolvePath(fullPath, name.toString() + QStringLiteral(".qbs"));
- if (FileInfo::exists(result)) {
- fullPath = result;
- break;
- }
- [[fallthrough]];
- }
- case ModuleProviderLookup::Scoped:
- for (const QString &component : name)
- fullPath = FileInfo::resolvePath(fullPath, component);
- fullPath = FileInfo::resolvePath(fullPath, QStringLiteral("provider.qbs"));
- break;
- case ModuleProviderLookup::Fallback:
- fullPath = FileInfo::resolvePath(fullPath, QStringLiteral("__fallback/provider.qbs"));
- break;
- }
- if (!FileInfo::exists(fullPath)) {
- qCDebug(lcModuleLoader) << "No module provider found at" << fullPath;
- continue;
- }
- return fullPath;
- }
- return {};
-}
-
-QVariantMap ModuleProviderLoader::evaluateQbsModule(const ProductContext &product) const
-{
- const QString properties[] = {
- QStringLiteral("sysroot"),
- QStringLiteral("toolchain"),
- };
- const auto qbsItemValue = std::static_pointer_cast<ItemValue>(
- product.productItem->property(StringConstants::qbsModule()));
- QVariantMap result;
- for (const auto &property : properties) {
- const ScopedJsValue val(m_evaluator.engine()->context(),
- m_evaluator.value(qbsItemValue->item(), property));
- auto value = getJsVariant(m_evaluator.engine()->context(), val);
- if (!value.isValid())
- continue;
-
- // The xcode module sets qbs.sysroot; the resulting value is bogus before the probes
- // have run.
- if (property == QLatin1String("sysroot") && !FileInfo::isAbsolute(value.toString()))
- continue;
-
- result[property] = std::move(value);
- }
- return result;
-}
-
-Item *ModuleProviderLoader::createProviderScope(const ProductContext &product, const QVariantMap &qbsModule)
-{
- const auto qbsItemValue = std::static_pointer_cast<ItemValue>(
- product.productItem->property(StringConstants::qbsModule()));
-
- Item *fakeQbsModule = Item::create(product.productItem->pool(), ItemType::Scope);
-
- for (auto it = qbsModule.begin(), end = qbsModule.end(); it != end; ++it) {
- fakeQbsModule->setProperty(it.key(), VariantValue::create(it.value()));
- }
-
- Item *scope = Item::create(product.productItem->pool(), ItemType::Scope);
- scope->setFile(qbsItemValue->item()->file());
- scope->setProperty(StringConstants::qbsModule(), ItemValue::create(fakeQbsModule));
- return scope;
-}
-
-std::pair<QStringList, std::vector<ProbeConstPtr> > ModuleProviderLoader::evaluateModuleProvider(const ProductContext &product,
- const CodeLocation &dependsItemLocation,
- const QualifiedId &name,
- const QString &providerFile,
- const QVariantMap &moduleConfig,
- const QVariantMap &qbsModule)
-{
- QTemporaryFile dummyItemFile;
- if (!dummyItemFile.open()) {
- throw ErrorInfo(Tr::tr("Failed to create temporary file for running module provider "
- "for dependency '%1': %2").arg(name.toString(),
- dummyItemFile.errorString()));
- }
- m_tempQbsFiles << dummyItemFile.fileName();
- qCDebug(lcModuleLoader) << "Instantiating module provider at" << providerFile;
- const QString projectBuildDir = product.projectItem->variantProperty(
- StringConstants::buildDirectoryProperty())->value().toString();
- const QString searchPathBaseDir = ModuleProviderInfo::outputDirPath(projectBuildDir, name);
-
- // include qbs module into hash
- auto jsConfig = moduleConfig;
- jsConfig[StringConstants::qbsModule()] = qbsModule;
-
- QTextStream stream(&dummyItemFile);
- using Qt::endl;
- setupDefaultCodec(stream);
- stream << "import qbs.FileInfo" << endl;
- stream << "import qbs.Utilities" << endl;
- stream << "import '" << providerFile << "' as Provider" << endl;
- stream << "Provider {" << endl;
- stream << " name: " << toJSLiteral(name.toString()) << endl;
- stream << " property var config: (" << toJSLiteral(jsConfig) << ')' << endl;
- stream << " outputBaseDir: FileInfo.joinPaths(baseDirPrefix, "
- " Utilities.getHash(JSON.stringify(config)))" << endl;
- stream << " property string baseDirPrefix: " << toJSLiteral(searchPathBaseDir) << endl;
- stream << " property stringList searchPaths: (relativeSearchPaths || [])"
- " .map(function(p) { return FileInfo.joinPaths(outputBaseDir, p); })"
- << endl;
- stream << "}" << endl;
- stream.flush();
- Item * const providerItem = m_reader.setupItemFromFile(
- dummyItemFile.fileName(), dependsItemLocation, m_evaluator);
- if (providerItem->type() != ItemType::ModuleProvider) {
- throw ErrorInfo(Tr::tr("File '%1' declares an item of type '%2', "
- "but '%3' was expected.")
- .arg(providerFile, providerItem->typeName(),
- BuiltinDeclarations::instance().nameForType(ItemType::ModuleProvider)));
- }
-
- providerItem->setScope(createProviderScope(product, qbsModule));
- providerItem->overrideProperties(moduleConfig, name, m_parameters, m_logger);
- std::vector<ProbeConstPtr> probes = m_probesResolver.resolveProbes(
- {product.name, product.uniqueName}, providerItem);
-
- EvalContextSwitcher contextSwitcher(m_evaluator.engine(), EvalContext::ModuleProvider);
- return std::make_pair(m_evaluator.stringListValue(providerItem, QStringLiteral("searchPaths")),
- std::move(probes));
-}
-
-} // namespace Internal
-} // namespace qbs