diff options
Diffstat (limited to 'src/lib/language/qbsengine.cpp')
-rw-r--r-- | src/lib/language/qbsengine.cpp | 668 |
1 files changed, 0 insertions, 668 deletions
diff --git a/src/lib/language/qbsengine.cpp b/src/lib/language/qbsengine.cpp deleted file mode 100644 index 7f559f046..000000000 --- a/src/lib/language/qbsengine.cpp +++ /dev/null @@ -1,668 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt Build Suite. -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "qbsengine.h" - -#include "publicobjectsmap.h" - -#include <buildgraph/artifact.h> -#include <buildgraph/artifactcleaner.h> -#include <buildgraph/executor.h> -#include <language/scriptengine.h> -#include <language/loader.h> -#include <logging/logger.h> -#include <logging/translator.h> -#include <tools/platform.h> -#include <tools/runenvironment.h> -#include <tools/scannerpluginmanager.h> -#include <tools/scripttools.h> -#include <tools/settings.h> - -#include <QEventLoop> -#include <QHash> -#include <QList> -#include <QMutex> -#include <QMutexLocker> -#include <QPair> - -namespace qbs { -using namespace Internal; - -class QbsEngine::QbsEnginePrivate -{ -public: - QbsEnginePrivate() : observer(0) {} - - void loadPlugins(); - BuildProject::Ptr setupBuildProject(const ResolvedProject::ConstPtr &project); - QVariantMap expandedBuildConfiguration(const QVariantMap &userBuildConfig); - void buildProducts(const QList<BuildProduct::Ptr> &buildProducts, - const BuildOptions &buildOptions); - void buildProducts(const QList<ResolvedProduct::ConstPtr> &products, - const BuildOptions &buildOptions, bool needsDepencencyResolving); - void cleanBuildProducts(const QList<BuildProduct::Ptr> &buildProducts, - const BuildOptions &buildOptions, QbsEngine::CleanType cleanType); - - void storeBuildGraphs(const QList<BuildProduct::Ptr> &buildProducts, - const BuildOptions &buildOptions); - - ScriptEngine engine; - ProgressObserver *observer; - QList<ResolvedProject::Ptr> resolvedProjects; - QList<BuildProject::Ptr> buildProjects; - Settings settings; - PublicObjectsMap publicObjectsMap; - - // Potentially stored temporarily between calls to setupResolvedProject() and setupBuildProject(). - QHash<ResolvedProject::ConstPtr, BuildProject::Ptr> discardedBuildProjects; - -private: - QVariantMap createBuildConfiguration(const QVariantMap &userBuildConfig); - - // First: Unexpanded config (coming in via the API), second: fully expanded config - typedef QPair<QVariantMap, QVariantMap> BuildConfigPair; - QList<BuildConfigPair> m_buildConfigurations; - - static bool pluginsLoaded; - static QMutex pluginsLoadedMutex; -}; - -bool QbsEngine::QbsEnginePrivate::pluginsLoaded = false; -QMutex QbsEngine::QbsEnginePrivate::pluginsLoadedMutex; - - -/*! - * \class QbsEngine - * \brief The \c QbsEngine class is the central facility of the qbs API. - * It offers services such as building a project and accessing its structure. - */ - -/*! - * \fn QbsEngine::QbsEngine() - * \brief Creates a \c QbsEngine object. - */ -QbsEngine::QbsEngine() : d(new QbsEnginePrivate) -{ - d->loadPlugins(); -} - -/*! - * \fn QbsEngine::~QbsEngine() - * \brief Destroys a \c QbsEngine object. - */ -QbsEngine::~QbsEngine() -{ - delete d; -} - -/*! - * \brief Sets an observer to be used in subsequent operations. - */ -void QbsEngine::setProgressObserver(ProgressObserver *observer) -{ - d->observer = observer; -} - -/*! - * \brief Reads a project from a source file. - * The \a projectFilePath parameter is the path to the project file, typically ending in ".qbs". - * The \a buildConfig parameter is the set of properties used for resolving the project. Note that - * calling this function with the same \a projectFilePath and a different \a buildConfig will - * result in two distinct projects, since the different properties will potentially cause the - * bindings in the project file to evaluate to different values. - * The \a buildRoot parameter is the base directory for building the project. It will be used - * to derive the actual build directory and is required here because the project information might - * already exist on disk, in which case it will be available faster. If you know that the project - * has never been built and you do not plan to do so later, \a buildRoot can be an arbitrary string. - * The return value is the unique id of the resolved project, which can then be used for - * services related to the project. - * This function will throw qbs::Error if something goes wrong. - * \sa Error - */ -Project::Id QbsEngine::setupProject(const QString &projectFilePath, const QVariantMap &_buildConfig, - const QString &buildRoot) -{ - const QVariantMap buildConfig = d->expandedBuildConfiguration(_buildConfig); - QScopedPointer<BuildGraph> buildGraph(new BuildGraph(&d->engine)); - buildGraph->setProgressObserver(d->observer); - const BuildProject::LoadResult loadResult = BuildProject::load(projectFilePath, - buildGraph.data(), buildRoot, buildConfig, d->settings.searchPaths()); - - BuildProject::Ptr bProject; - ResolvedProject::Ptr rProject; - if (loadResult.loadedProject) - buildGraph.take(); - if (!loadResult.discardLoadedProject) - bProject = loadResult.loadedProject; - if (bProject) { - d->buildProjects << bProject; - rProject = bProject->resolvedProject(); - } else { - if (loadResult.changedResolvedProject) { - rProject = loadResult.changedResolvedProject; - } else { - Loader loader(&d->engine); - loader.setSearchPaths(d->settings.searchPaths()); - loader.setProgressObserver(d->observer); - rProject = loader.loadProject(projectFilePath, buildRoot, buildConfig); - } - if (rProject->products.isEmpty()) - throw Error(QString("'%1' does not contain products.").arg(projectFilePath)); - if (loadResult.loadedProject) - d->discardedBuildProjects.insert(rProject, loadResult.loadedProject); - } - - // copy the environment from the platform config into the project's config - const QVariantMap platformEnvironment = buildConfig.value("environment").toMap(); - rProject->platformEnvironment = platformEnvironment; - - qbsDebug("for %s:", qPrintable(rProject->id())); - foreach (const ResolvedProduct::ConstPtr &p, rProject->products) { - qbsDebug(" - [%s] %s as %s" - ,qPrintable(p->fileTags.join(", ")) - ,qPrintable(p->name) - ,qPrintable(p->project->id()) - ); - } - qbsDebug(""); - - d->resolvedProjects << rProject; - const Project::Id id(quintptr(rProject.data())); - d->publicObjectsMap.insertProject(id, rProject); - return id; -} - -/*! - * \brief Builds a number of projects set up earlier via setupProject(). - * Building potentially happens in parallel. If something goes wrong, qbs::Error is thrown. - * \sa QbsEngine::setupProject() - * \sa Error - */ -void QbsEngine::buildProjects(const QList<Project::Id> &projectIds, const BuildOptions &buildOptions) -{ - QList<ResolvedProduct::ConstPtr> products; - foreach (const Project::Id projectId, projectIds) { - const ResolvedProject::ConstPtr resolvedProject = d->publicObjectsMap.project(projectId); - if (!resolvedProject) - throw Error(Tr::tr("Cannot build: No such project.")); - foreach (const ResolvedProduct::ConstPtr &product, resolvedProject->products) - products << product; - } - d->buildProducts(products, buildOptions, false); -} - -static QList<Project::Id> projectListToIdList(const QList<Project> &projects) -{ - QList<Project::Id> projectIds; - foreach (const Project &project, projects) - projectIds << project.id(); - return projectIds; -} - -/*! - * \brief Convenience function taking a list of projects instead of ids. - * \sa QbsEngine::buildProjects(const QList<Project::Id> &, const BuildOptions &) - */ -void QbsEngine::buildProjects(const QList<Project> &projects, const BuildOptions &buildOptions) -{ - buildProjects(projectListToIdList(projects), buildOptions); -} - -/*! - * \brief Convenience function for building a single project. - * \sa QbsEngine::buildProjects(const QList<Project::Id> &, const BuildOptions &) - */ -void QbsEngine::buildProject(Project::Id projectId, const BuildOptions &buildOptions) -{ - buildProjects(QList<Project::Id>() << projectId, buildOptions); -} - -/*! - * \brief Builds a number of products. - * Use this function if you want to build only a subset of a project's products. If any of - * \a products depend on other products not listed in \a products, those will be added. - * This function will throw qbs::Error if something goes wrong. - * \sa Error - */ -void QbsEngine::buildProducts(const QList<Product> &products, const BuildOptions &buildOptions) -{ - QList<ResolvedProduct::ConstPtr> resolvedProducts; - foreach (const Product &product, products) { - const ResolvedProduct::ConstPtr resolvedProduct = d->publicObjectsMap.product(product.id()); - if (!resolvedProduct) - throw Error(Tr::tr("Cannot build: No such product.")); - resolvedProducts << resolvedProduct; - } - d->buildProducts(resolvedProducts, buildOptions, true); -} - -/*! - * \brief Convenience function for building a single product. - * \sa QbsEngine::buildProducts(const QList<Product> &, const BuildOptions &) - */ -void QbsEngine::buildProduct(const Product &product, const BuildOptions &buildOptions) -{ - buildProducts(QList<Product>() << product, buildOptions); -} - -/*! - * \enum QbsEngine::CleanType - * This enum type specifies which kind of build artifacts to remove. - * \value CleanupAll Indicates that all files created by the build process should be removed. - * \value CleanupTemporaries Indicates that only intermediate build artifacts should be removed. - * If, for example, the product to clean up for is a Linux shared library, the .so file - * would be left on the disk, but the .o files would be removed. - */ - -/*! - * \brief Removes the build artifacts of the given projects. - * This function will throw qbs::Error if something goes wrong. - * \sa Error - */ -void QbsEngine::cleanProjects(const QList<Project::Id> &projectIds, - const BuildOptions &buildOptions, CleanType cleanType) -{ - QList<BuildProduct::Ptr> products; - foreach (const Project::Id id, projectIds) { - const ResolvedProject::ConstPtr rProject = d->publicObjectsMap.project(id); - if (!rProject) - throw Error(Tr::tr("Cleaning up failed: Project not found.")); - const BuildProject::ConstPtr bProject = d->setupBuildProject(rProject); - foreach (const BuildProduct::Ptr &product, bProject->buildProducts()) - products << product; - } - d->cleanBuildProducts(products, buildOptions, cleanType); -} - -/*! - * \brief Convenience function taking a list of projects instead of ids. - * \sa QbsEngine::cleanProjects(const QList<Project::Id> &, const BuildOptions &, CleanType) - */ -void QbsEngine::cleanProjects(const QList<Project> &projects, const BuildOptions &buildOptions, - CleanType cleanType) -{ - cleanProjects(projectListToIdList(projects), buildOptions, cleanType); -} - -/*! - * Convenience function taking a single project id. - * \sa QbsEngine::cleanProjects(const QList<Project::Id> &, const BuildOptions &, QbsEngine::CleanType) - */ -void QbsEngine::cleanProject(Project::Id projectId, const BuildOptions &buildOptions, - QbsEngine::CleanType cleanType) -{ - cleanProjects(QList<Project::Id>() << projectId, buildOptions, cleanType); -} - -/*! - * \brief Removes the build artifacts of the given products. - * This function will throw qbs::Error if something goes wrong. - * \sa Error - */ -void QbsEngine::cleanProducts(const QList<Product> &products, const BuildOptions &buildOptions, - QbsEngine::CleanType cleanType) -{ - QList<BuildProduct::Ptr> buildProducts; - foreach (const Product &product, products) { - const ResolvedProduct::ConstPtr rProduct = d->publicObjectsMap.product(product.id()); - if (!rProduct) - throw Error(Tr::tr("Cleaning up failed: Product not found.")); - const ResolvedProject::ConstPtr rProject = rProduct->project.toStrongRef(); - const BuildProject::ConstPtr bProject = d->setupBuildProject(rProject); - foreach (const BuildProduct::Ptr &bProduct, bProject->buildProducts()) { - if (bProduct->rProduct == rProduct) { - buildProducts << bProduct; - break; - } - } - } - d->cleanBuildProducts(buildProducts, buildOptions, cleanType); -} - -/*! - * \brief Convenience function taking a single product - * \sa QbsEngine::cleanProducts(const QList<Product> &, const BuildOptions &, QbsEngine::CleanType) - */ -void QbsEngine::cleanProduct(const Product &product, const BuildOptions &buildOptions, QbsEngine::CleanType cleanType) -{ - cleanProducts(QList<Product>() << product, buildOptions, cleanType); -} - -/*! - * \brief Retrieves information for a given project. - * Call this function if you need insight into the project structure, e.g. because you want to know - * which products or files are in it. If you just want to build it, the id is enough. - * This function will throw qbs::Error if something goes wrong. - * \sa Error - */ -Project QbsEngine::retrieveProject(Project::Id projectId) const -{ - const ResolvedProject::ConstPtr resolvedProject = d->publicObjectsMap.project(projectId); - if (!resolvedProject) - throw Error(Tr::tr("Cannot retrieve project: No such project.")); - Project project(projectId); - project.m_qbsFilePath = resolvedProject->qbsFile; - foreach (const ResolvedProduct::Ptr &resolvedProduct, resolvedProject->products) { - Product product(Product::Id(quintptr(resolvedProduct.data()))); - product.m_name = resolvedProduct->name; - product.m_qbsFilePath = resolvedProduct->qbsFile; - product.m_qbsLine = resolvedProduct->qbsLine; - product.m_fileTags = resolvedProduct->fileTags; - foreach (const ResolvedGroup::Ptr &resolvedGroup, resolvedProduct->groups) { - Group group(Group::Id(quintptr(resolvedGroup.data()))); - group.m_name = resolvedGroup->name; - group.m_qbsLine = resolvedGroup->qbsLine; - foreach (const SourceArtifact::ConstPtr &sa, resolvedGroup->files) - group.m_filePaths << sa->absoluteFilePath; - if (resolvedGroup->wildcards) { - foreach (const SourceArtifact::ConstPtr &sa, resolvedGroup->wildcards->files) - group.m_expandedWildcards << sa->absoluteFilePath; - } - group.m_properties = resolvedGroup->properties->value(); - product.m_groups << group; - d->publicObjectsMap.insertGroup(group.m_id, resolvedGroup); - } - project.m_products << product; - d->publicObjectsMap.insertProduct(product.m_id, resolvedProduct); - } - return project; -} - -RunEnvironment QbsEngine::getRunEnvironment(const Product &product, - const QProcessEnvironment &environment) -{ - return RunEnvironment(&d->engine, product, d->publicObjectsMap, environment); -} - -/*! - * \brief Returns the file path of the executable associated with the given product. - * If the product is not an application, an empty string is returned. - * This function will throw qbs::Error if something goes wrong. - * \sa Error - */ -QString QbsEngine::targetExecutable(const Product &product) -{ - const ResolvedProduct::ConstPtr resolvedProduct = d->publicObjectsMap.product(product.id()); - if (!resolvedProduct) - throw Error(Tr::tr("Unknown product.")); - if (!resolvedProduct->fileTags.contains(QLatin1String("application"))) - return QString(); - ResolvedProject::ConstPtr resolvedProject; - foreach (const ResolvedProject::ConstPtr &p, d->resolvedProjects) { - if (p == resolvedProduct->project) { - resolvedProject = p; - break; - } - } - if (!resolvedProject) - throw Error(Tr::tr("Unknown product '%1'.").arg(resolvedProduct->name)); - - const BuildProject::ConstPtr buildProject = d->setupBuildProject(resolvedProject); - Q_ASSERT(buildProject->resolvedProject() == resolvedProject); - BuildProduct::ConstPtr buildProduct; - foreach (const BuildProduct::ConstPtr &bp, buildProject->buildProducts()) { - if (bp->rProduct == resolvedProduct) { - buildProduct = bp; - break; - } - } - Q_ASSERT(buildProduct); - - foreach (const Artifact * const artifact, buildProduct->targetArtifacts) { - if (artifact->fileTags.contains(QLatin1String("application"))) - return artifact->filePath(); - } - return QString(); -} - -void QbsEngine::QbsEnginePrivate::loadPlugins() -{ - QMutexLocker locker(&pluginsLoadedMutex); - if (pluginsLoaded) - return; - - QStringList pluginPaths; - foreach (const QString &pluginPath, settings.pluginPaths()) { - if (!FileInfo::exists(pluginPath)) { - qbsWarning() << Tr::tr("Plugin path '%1' does not exist.") - .arg(QDir::toNativeSeparators(pluginPath)); - } else { - pluginPaths << pluginPath; - } - } - ScannerPluginManager::instance()->loadPlugins(pluginPaths); - - pluginsLoaded = true; -} - -BuildProject::Ptr QbsEngine::QbsEnginePrivate::setupBuildProject(const ResolvedProject::ConstPtr &project) -{ - foreach (const BuildProject::Ptr &buildProject, buildProjects) { - if (buildProject->resolvedProject() == project) - return buildProject; - } - - ResolvedProject::Ptr mutableRProject; - foreach (const ResolvedProject::Ptr &p, resolvedProjects) { - if (p == project) { - mutableRProject = p; - break; - } - } - if (!mutableRProject) - throw Error(Tr::tr("Unknown project.")); - - TimedActivityLogger resolveLogger(QLatin1String("Resolving build project")); - BuildGraph * const buildGraph = new BuildGraph(&engine); - buildGraph->setProgressObserver(observer); - const BuildProject::Ptr buildProject = buildGraph->resolveProject(mutableRProject); - const QHash<ResolvedProject::ConstPtr, BuildProject::Ptr>::Iterator it - = discardedBuildProjects.find(project); - if (it != discardedBuildProjects.end()) { - buildProject->rescueDependencies(it.value()); - discardedBuildProjects.erase(it); - } - - buildProjects << buildProject; - return buildProject; -} - -QVariantMap QbsEngine::QbsEnginePrivate::expandedBuildConfiguration(const QVariantMap &userBuildConfig) -{ - foreach (const QbsEnginePrivate::BuildConfigPair &configPair, m_buildConfigurations) { - if (configPair.first == userBuildConfig) - return configPair.second; - } - const QbsEnginePrivate::BuildConfigPair configPair - = qMakePair(userBuildConfig, createBuildConfiguration(userBuildConfig)); - m_buildConfigurations << configPair; - return configPair.second; -} - -void QbsEngine::QbsEnginePrivate::buildProducts(const QList<BuildProduct::Ptr> &buildProducts, - const BuildOptions &buildOptions) -{ - Executor executor; - QEventLoop execLoop; - QObject::connect(&executor, SIGNAL(finished()), &execLoop, SLOT(quit()), Qt::QueuedConnection); - QObject::connect(&executor, SIGNAL(error()), &execLoop, SLOT(quit()), Qt::QueuedConnection); - executor.setEngine(&engine); - executor.setProgressObserver(observer); - executor.setBuildOptions(buildOptions); - TimedActivityLogger buildLogger(QLatin1String("Building products"), QString(), LoggerInfo); - executor.build(buildProducts); - execLoop.exec(); - buildLogger.finishActivity(); - storeBuildGraphs(buildProducts, buildOptions); - if (executor.buildResult() != Executor::SuccessfulBuild) - throw Error(Tr::tr("Build failed.")); -} - -void QbsEngine::QbsEnginePrivate::buildProducts(const QList<ResolvedProduct::ConstPtr> &products, - const BuildOptions &buildOptions, bool needsDepencencyResolving) -{ - // Make sure all products are set up first. - QSet<ResolvedProject::ConstPtr> rProjects; - foreach (const ResolvedProduct::ConstPtr &product, products) - rProjects << product->project.toStrongRef(); - foreach (const ResolvedProject::ConstPtr &rProject, rProjects) - setupBuildProject(rProject); - - // Gather build products. - QList<BuildProduct::Ptr> productsToBuild; - foreach (const ResolvedProduct::ConstPtr &rProduct, products) { - foreach (const BuildProject::ConstPtr &buildProject, buildProjects) { - foreach (const BuildProduct::Ptr &buildProduct, buildProject->buildProducts()) { - if (buildProduct->rProduct == rProduct) - productsToBuild << buildProduct; - } - } - } - - if (needsDepencencyResolving) { - for (int i = 0; i < productsToBuild.count(); ++i) { - const BuildProduct::ConstPtr &product = productsToBuild.at(i); - foreach (const BuildProduct::Ptr &dependency, product->dependencies) - productsToBuild << dependency; - } - } - - productsToBuild = productsToBuild.toSet().toList(); // make products unique - buildProducts(productsToBuild, buildOptions); -} - -void QbsEngine::QbsEnginePrivate::cleanBuildProducts(const QList<BuildProduct::Ptr> &buildProducts, - const BuildOptions &buildOptions, QbsEngine::CleanType cleanType) -{ - try { - ArtifactCleaner cleaner; - cleaner.cleanup(buildProducts, cleanType == QbsEngine::CleanupAll, buildOptions); - } catch (const Error &) { - storeBuildGraphs(buildProducts, buildOptions); - throw; - } - storeBuildGraphs(buildProducts, buildOptions); -} - -void QbsEngine::QbsEnginePrivate::storeBuildGraphs(const QList<BuildProduct::Ptr> &buildProducts, - const BuildOptions &buildOptions) -{ - if (buildOptions.dryRun) - return; - QSet<BuildProject *> buildProjects; - foreach (const BuildProduct::ConstPtr &bProduct, buildProducts) - buildProjects += bProduct->project; - foreach (const BuildProject * const bProject, buildProjects) - bProject->store(); -} - -QVariantMap QbsEngine::QbsEnginePrivate::createBuildConfiguration(const QVariantMap &userBuildConfig) -{ - QHash<QString, Platform::Ptr > platforms = Platform::platforms(); - if (platforms.isEmpty()) - throw Error(Tr::tr("No platforms configured. You must run 'qbs platforms probe' first.")); - - QVariantMap expandedConfig = userBuildConfig; - - // Fill in buildCfg in this order (making sure not to overwrite a key already set by a previous stage) - // 1) Things specified on command line (already in buildCfg at this point) - // 2) Everything from the profile key (in reverse order) - // 3) Everything from the platform - // 4) Any remaining keys from modules keyspace - QString profileName = expandedConfig.value("qbs.profile").toString(); - if (profileName.isNull()) { - profileName = settings.value("profile").toString(); - if (profileName.isNull()) - throw Error(Tr::tr("No profile given.\n" - "Either set the configuration value 'profile' to a valid profile's name\n" - "or specify the profile with the command line parameter 'profile:name'.")); - expandedConfig.insert("qbs.profile", profileName); - } - - // (2) - const QString profileGroup = QString("profiles/%1").arg(profileName); - const QStringList profileKeys = settings.allKeysWithPrefix(profileGroup); - if (profileKeys.isEmpty()) - throw Error(Tr::tr("Unknown profile '%1'.").arg(profileName)); - foreach (const QString &profileKey, profileKeys) { - QString fixedKey(profileKey); - fixedKey.replace(QChar('/'), QChar('.')); - if (!expandedConfig.contains(fixedKey)) - expandedConfig.insert(fixedKey, settings.value(profileGroup + "/" + profileKey)); - } - - // (3) Need to make sure we have a value for qbs.platform before going any further - QVariant platformName = expandedConfig.value("qbs.platform"); - if (!platformName.isValid()) { - platformName = settings.moduleValue("qbs/platform", profileName); - if (!platformName.isValid()) - throw Error(Tr::tr("No platform given and no default set.")); - expandedConfig.insert("qbs.platform", platformName); - } - Platform::Ptr platform = platforms.value(platformName.toString()); - if (platform.isNull()) - throw Error(Tr::tr("Unknown platform '%1'.").arg(platformName.toString())); - foreach (const QString &key, platform->settings.allKeys()) { - if (key.startsWith(Platform::internalKey())) - continue; - QString fixedKey = key; - int idx = fixedKey.lastIndexOf(QChar('/')); - if (idx > 0) - fixedKey[idx] = QChar('.'); - if (!expandedConfig.contains(fixedKey)) - expandedConfig.insert(fixedKey, platform->settings.value(key)); - } - // Now finally do (4) - foreach (const QString &defaultKey, settings.allKeysWithPrefix("modules")) { - QString fixedKey(defaultKey); - fixedKey.replace(QChar('/'), QChar('.')); - if (!expandedConfig.contains(fixedKey)) - expandedConfig.insert(fixedKey, settings.value(QString("modules/") + defaultKey)); - } - - if (!expandedConfig.value("qbs.buildVariant").isValid()) - throw Error(Tr::tr("Property 'qbs.buildVariant' missing in build configuration.")); - - foreach (const QString &property, expandedConfig.keys()) { - QStringList nameElements = property.split('.'); - if (nameElements.count() == 1 && nameElements.first() != "project") // ### Still need this because platform doesn't supply fully-qualified properties (yet), need to fix this - nameElements.prepend("qbs"); - if (nameElements.count() > 2) { // ### workaround for submodules being represented internally as a single module of name "module/submodule" rather than two nested modules "module" and "submodule" - QStringList newElements(QStringList(nameElements.mid(0, nameElements.count()-1)).join("/")); - newElements.append(nameElements.last()); - nameElements = newElements; - } - setConfigProperty(expandedConfig, nameElements, expandedConfig.value(property)); - expandedConfig.remove(property); - } - - return expandedConfig; -} - -} // namespace qbs |