aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Kandeler <christian.kandeler@digia.com>2012-11-14 14:40:57 +0100
committerJoerg Bornemann <joerg.bornemann@digia.com>2012-11-15 15:07:45 +0100
commit8933dc98541a2ca545b7532f1efd0ac13ae43343 (patch)
tree8a76b3e328ad5fc90344c5dbdffd06876380fe6a
parent6f706911ed74859fd8498d3f80e6ff7f5f520650 (diff)
Refactor Loader::resolveProject().
Split it up into smaller functions to make it easier to see what is going on and get rid of the last parameter, which is not used by any callers. Also remove the Loader class' "protected" section, since it is not intended to be inherited from. Change-Id: I19dca9eab438b00134de7651dba4ba9edfb7db58 Reviewed-by: Joerg Bornemann <joerg.bornemann@digia.com>
-rw-r--r--src/lib/language/loader.cpp419
-rw-r--r--src/lib/language/loader.h17
2 files changed, 229 insertions, 207 deletions
diff --git a/src/lib/language/loader.cpp b/src/lib/language/loader.cpp
index d492f75ff..b0533cda0 100644
--- a/src/lib/language/loader.cpp
+++ b/src/lib/language/loader.cpp
@@ -1821,7 +1821,7 @@ static bool checkCondition(EvaluationObject *object)
}
ResolvedProject::Ptr Loader::resolveProject(ProjectFile::Ptr projectFile, const QString &buildRoot,
- const QVariantMap &userProperties, bool resolveProductDependencies)
+ const QVariantMap &userProperties)
{
Q_ASSERT(FileInfo::isAbsolute(buildRoot));
if (qbsLogLevel(LoggerTrace))
@@ -1854,8 +1854,7 @@ ResolvedProject::Ptr Loader::resolveProject(ProjectFile::Ptr projectFile, const
scope,
dummyModule);
- QSet<QString> uniqueStrings;
- QMultiMap<QString, ResolvedProduct::Ptr> resolvedProducts;
+ ProductMap resolvedProducts;
QHash<ResolvedProduct::Ptr, ProductData>::iterator it = projectData.products.begin();
if (m_progressObserver)
m_progressObserver->initialize(Tr::tr("Loading project"), projectData.products.count());
@@ -1865,132 +1864,12 @@ ResolvedProject::Ptr Loader::resolveProject(ProjectFile::Ptr projectFile, const
throw Error(Tr::tr("Loading canceled."));
m_progressObserver->incrementProgressValue();
}
- ResolvedProduct::Ptr rproduct = it.key();
- ProductData &data = it.value();
- Scope *productProps = data.product->scope.data();
-
- rproduct->name = productProps->stringValue("name");
- rproduct->targetName = productProps->stringValue("targetName");
- rproduct->properties = PropertyMap::create();
-
- // insert property "buildDirectory"
- {
- Property p(m_engine->toScriptValue(rproject->buildDirectory));
- productProps->properties.insert("buildDirectory", p);
- }
-
- rproduct->fileTags = productProps->stringListValue("type");
- rproduct->destinationDirectory = productProps->stringValue("destination");
- foreach (const Rule::Ptr &rule, globalRules)
- rproduct->rules.insert(rule);
- foreach (const FileTagger::ConstPtr &fileTagger, globalFileTaggers)
- rproduct->fileTaggers.insert(fileTagger);
- const QString lowerProductName = rproduct->name.toLower();
- uniqueStrings.insert(lowerProductName);
- resolvedProducts.insert(lowerProductName, rproduct);
-
- // resolve the modules for this product
- for (QHash<QString, Module::Ptr>::const_iterator modIt = data.product->modules.begin();
- modIt != data.product->modules.end(); ++modIt)
- {
- resolveModule(rproduct, modIt.key(), modIt.value()->object);
- }
-
- QList<EvaluationObject *> unresolvedChildren = resolveCommonItems(data.product->children, rproduct, dummyModule);
-
- // fill the product's configuration
- QVariantMap productCfg = evaluateAll(rproduct, data.product->scope);
- rproduct->properties->setValue(productCfg);
-
- // handle the 'Product.files' property
- {
- QScriptValue files = data.product->scope->property("files");
- if (files.isValid()) {
- resolveGroup(rproduct, data.product, data.product);
- }
- }
-
- foreach (EvaluationObject *child, unresolvedChildren) {
- const uint prototypeNameHash = qHash(child->prototype);
- if (prototypeNameHash == hashName_Group) {
- resolveGroup(rproduct, data.product, child);
- } else if (prototypeNameHash == hashName_ProductModule) {
- child->scope->properties.insert("product", Property(data.product));
- resolveProductModule(rproduct, child);
- data.usedProductsFromProductModule += child->unknownModules;
- }
- }
-
- // Apply file taggers.
- foreach (const SourceArtifact::Ptr &artifact, rproduct->allFiles())
- applyFileTaggers(artifact, rproduct);
- foreach (const ResolvedTransformer::Ptr &transformer, rproduct->transformers)
- foreach (const SourceArtifact::Ptr &artifact, transformer->outputs)
- applyFileTaggers(artifact, rproduct);
-
- // Merge duplicate artifacts.
- QHash<QString, QPair<ResolvedGroup::Ptr, SourceArtifact::Ptr> > uniqueArtifacts;
- foreach (const ResolvedGroup::Ptr &group, rproduct->groups) {
- Q_ASSERT(group->properties);
-
- QList<SourceArtifact::Ptr> artifactsInGroup = group->files;
- if (group->wildcards)
- artifactsInGroup += group->wildcards->files;
-
- foreach (const SourceArtifact::Ptr &artifact, artifactsInGroup) {
- QPair<ResolvedGroup::Ptr, SourceArtifact::Ptr> p = uniqueArtifacts.value(artifact->absoluteFilePath);
- SourceArtifact::Ptr existing = p.second;
- if (existing) {
- // if an artifact is in the product and in a group, prefer the group configuration
- if (existing->properties != rproduct->properties)
- throw Error(Tr::tr("Artifact '%1' is in more than one group.").arg(artifact->absoluteFilePath),
- CodeLocation(m_project->fileName));
-
- // Remove the artifact that's in the product's group.
- p.first->files.removeOne(existing);
-
- // Merge artifacts.
- if (!artifact->overrideFileTags)
- artifact->fileTags.unite(existing->fileTags);
- }
- uniqueArtifacts.insert(artifact->absoluteFilePath, qMakePair(group, artifact));
- }
- }
-
- rproject->products.append(rproduct);
+ resolveProduct(it.key(), rproject, it.value(), resolvedProducts, globalRules,
+ globalFileTaggers, dummyModule);
}
// Check, if the userProperties contain invalid items.
- {
- QSet<QString> allowedUserPropertyNames;
- allowedUserPropertyNames << QLatin1String("project");
- for (QHash<ResolvedProduct::Ptr, ProductData>::const_iterator it = projectData.products.constBegin();
- it != projectData.products.constEnd(); ++it)
- {
- const ResolvedProduct::Ptr &product = it.key();
- const ProductData &productData = it.value();
- allowedUserPropertyNames += product->name;
- allowedUserPropertyNames += productData.originalProductName;
- foreach (const ResolvedModule::ConstPtr &module, product->modules) {
- allowedUserPropertyNames += module->name;
- foreach (const QString &dependency, module->moduleDependencies)
- allowedUserPropertyNames += dependency;
- }
- }
- foreach (const ProductData &productData, projectData.removedProducts) {
- allowedUserPropertyNames += productData.originalProductName;
- allowedUserPropertyNames += productData.product->scope->stringValue("name");
- }
-
- for (QVariantMap::const_iterator it = userProperties.begin(); it != userProperties.end(); ++it) {
- const QString &propertyName = it.key();
- if (allowedUserPropertyNames.contains(propertyName))
- continue;
- if (existsModuleInSearchPath(propertyName))
- continue;
- throw Error(Tr::tr("%1 is not a product or a module.").arg(propertyName));
- }
- }
+ checkUserProperties(projectData, userProperties);
// Check all modules for unresolved dependencies.
foreach (ResolvedProduct::Ptr rproduct, rproject->products)
@@ -1998,83 +1877,7 @@ ResolvedProject::Ptr Loader::resolveProject(ProjectFile::Ptr projectFile, const
checkModuleDependencies(module);
// Resolve inter-product dependencies.
- if (resolveProductDependencies) {
-
- // Collect product dependencies from ProductModules.
- bool productDependenciesAdded;
- do {
- productDependenciesAdded = false;
- foreach (ResolvedProduct::Ptr rproduct, rproject->products) {
- ProductData &productData = projectData.products[rproduct];
- foreach (const UnknownModule::Ptr &unknownModule, productData.usedProducts) {
- const QString &usedProductName = unknownModule->name;
- QList<ResolvedProduct::Ptr> usedProductCandidates = resolvedProducts.values(usedProductName);
- if (usedProductCandidates.count() < 1) {
- if (!unknownModule->required) {
- if (!unknownModule->failureMessage.isEmpty())
- qbsWarning() << unknownModule->failureMessage;
- continue;
- }
- throw Error(Tr::tr("Product dependency '%1' not found in '%2'.").arg(usedProductName, rproduct->qbsFile),
- CodeLocation(m_project->fileName));
- }
- if (usedProductCandidates.count() > 1)
- throw Error(Tr::tr("Product dependency '%1' is ambiguous.").arg(usedProductName),
- CodeLocation(m_project->fileName));
- ResolvedProduct::Ptr usedProduct = usedProductCandidates.first();
- const ProductData &usedProductData = projectData.products.value(usedProduct);
- bool added;
- productData.addUsedProducts(usedProductData.usedProductsFromProductModule, &added);
- if (added)
- productDependenciesAdded = true;
- }
- }
- } while (productDependenciesAdded);
-
- // Resolve all inter-product dependencies.
- foreach (ResolvedProduct::Ptr rproduct, rproject->products) {
- foreach (const UnknownModule::Ptr &unknownModule, projectData.products.value(rproduct).usedProducts) {
- const QString &usedProductName = unknownModule->name;
- QList<ResolvedProduct::Ptr> usedProductCandidates = resolvedProducts.values(usedProductName);
- if (usedProductCandidates.count() < 1) {
- if (!unknownModule->required) {
- if (!unknownModule->failureMessage.isEmpty())
- qbsWarning() << unknownModule->failureMessage;
- continue;
- }
- throw Error(Tr::tr("Product dependency '%1' not found.").arg(usedProductName),
- CodeLocation(m_project->fileName));
- }
- if (usedProductCandidates.count() > 1)
- throw Error(Tr::tr("Product dependency '%1' is ambiguous.").arg(usedProductName),
- CodeLocation(m_project->fileName));
- ResolvedProduct::Ptr usedProduct = usedProductCandidates.first();
- rproduct->dependencies.insert(usedProduct);
-
- // insert the configuration of the ProductModule into the product's configuration
- const QVariantMap productModuleConfig = m_productModules.value(usedProductName);
- if (productModuleConfig.isEmpty())
- continue;
-
- QVariantMap productProperties = rproduct->properties->value();
- QVariantMap modules = productProperties.value("modules").toMap();
- modules.insert(usedProductName, productModuleConfig);
- productProperties.insert("modules", modules);
- rproduct->properties->setValue(productProperties);
-
- // insert the configuration of the ProductModule into the artifact configurations
- foreach (SourceArtifact::Ptr artifact, rproduct->allFiles()) {
- if (artifact->properties == rproduct->properties)
- continue; // Already inserted above.
- QVariantMap sourceArtifactProperties = artifact->properties->value();
- QVariantMap modules = sourceArtifactProperties.value("modules").toMap();
- modules.insert(usedProductName, productModuleConfig);
- sourceArtifactProperties.insert("modules", modules);
- artifact->properties->setValue(sourceArtifactProperties);
- }
- }
- }
- }
+ resolveProductDependencies(rproject, projectData, resolvedProducts);
return rproject;
}
@@ -2991,6 +2794,216 @@ void Loader::resolveTopLevel(const ResolvedProject::Ptr &rproject,
projectData->products.insert(rproduct, productData);
}
+void Loader::checkUserProperties(const Loader::ProjectData &projectData,
+ const QVariantMap &userProperties)
+{
+ QSet<QString> allowedUserPropertyNames;
+ allowedUserPropertyNames << QLatin1String("project");
+ for (QHash<ResolvedProduct::Ptr, ProductData>::const_iterator it = projectData.products.constBegin();
+ it != projectData.products.constEnd(); ++it)
+ {
+ const ResolvedProduct::Ptr &product = it.key();
+ const ProductData &productData = it.value();
+ allowedUserPropertyNames += product->name;
+ allowedUserPropertyNames += productData.originalProductName;
+ foreach (const ResolvedModule::ConstPtr &module, product->modules) {
+ allowedUserPropertyNames += module->name;
+ foreach (const QString &dependency, module->moduleDependencies)
+ allowedUserPropertyNames += dependency;
+ }
+ }
+ foreach (const ProductData &productData, projectData.removedProducts) {
+ allowedUserPropertyNames += productData.originalProductName;
+ allowedUserPropertyNames += productData.product->scope->stringValue("name");
+ }
+
+ for (QVariantMap::const_iterator it = userProperties.begin(); it != userProperties.end(); ++it) {
+ const QString &propertyName = it.key();
+ if (allowedUserPropertyNames.contains(propertyName))
+ continue;
+ if (existsModuleInSearchPath(propertyName))
+ continue;
+ throw Error(Tr::tr("%1 is not a product or a module.").arg(propertyName));
+ }
+}
+
+void Loader::resolveProduct(const ResolvedProduct::Ptr &rproduct,
+ const ResolvedProject::Ptr &project, ProductData &data, Loader::ProductMap &products,
+ const QList<Rule::Ptr> &globalRules, const QList<FileTagger::ConstPtr> &globalFileTaggers,
+ const ResolvedModule::ConstPtr &dummyModule)
+{
+ Scope *productProps = data.product->scope.data();
+
+ rproduct->name = productProps->stringValue("name");
+ rproduct->targetName = productProps->stringValue("targetName");
+ rproduct->properties = PropertyMap::create();
+
+ // insert property "buildDirectory"
+ {
+ Property p(m_engine->toScriptValue(project->buildDirectory));
+ productProps->properties.insert("buildDirectory", p);
+ }
+
+ rproduct->fileTags = productProps->stringListValue("type");
+ rproduct->destinationDirectory = productProps->stringValue("destination");
+ foreach (const Rule::Ptr &rule, globalRules)
+ rproduct->rules.insert(rule);
+ foreach (const FileTagger::ConstPtr &fileTagger, globalFileTaggers)
+ rproduct->fileTaggers.insert(fileTagger);
+ const QString lowerProductName = rproduct->name.toLower();
+ products.insert(lowerProductName, rproduct);
+
+ // resolve the modules for this product
+ for (QHash<QString, Module::Ptr>::const_iterator modIt = data.product->modules.begin();
+ modIt != data.product->modules.end(); ++modIt)
+ {
+ resolveModule(rproduct, modIt.key(), modIt.value()->object);
+ }
+
+ QList<EvaluationObject *> unresolvedChildren
+ = resolveCommonItems(data.product->children, rproduct, dummyModule);
+
+ // fill the product's configuration
+ QVariantMap productCfg = evaluateAll(rproduct, data.product->scope);
+ rproduct->properties->setValue(productCfg);
+
+ // handle the 'Product.files' property
+ {
+ QScriptValue files = data.product->scope->property("files");
+ if (files.isValid()) {
+ resolveGroup(rproduct, data.product, data.product);
+ }
+ }
+
+ foreach (EvaluationObject *child, unresolvedChildren) {
+ const uint prototypeNameHash = qHash(child->prototype);
+ if (prototypeNameHash == hashName_Group) {
+ resolveGroup(rproduct, data.product, child);
+ } else if (prototypeNameHash == hashName_ProductModule) {
+ child->scope->properties.insert("product", Property(data.product));
+ resolveProductModule(rproduct, child);
+ data.usedProductsFromProductModule += child->unknownModules;
+ }
+ }
+
+ // Apply file taggers.
+ foreach (const SourceArtifact::Ptr &artifact, rproduct->allFiles())
+ applyFileTaggers(artifact, rproduct);
+ foreach (const ResolvedTransformer::Ptr &transformer, rproduct->transformers)
+ foreach (const SourceArtifact::Ptr &artifact, transformer->outputs)
+ applyFileTaggers(artifact, rproduct);
+
+ // Merge duplicate artifacts.
+ QHash<QString, QPair<ResolvedGroup::Ptr, SourceArtifact::Ptr> > uniqueArtifacts;
+ foreach (const ResolvedGroup::Ptr &group, rproduct->groups) {
+ Q_ASSERT(group->properties);
+
+ QList<SourceArtifact::Ptr> artifactsInGroup = group->files;
+ if (group->wildcards)
+ artifactsInGroup += group->wildcards->files;
+
+ foreach (const SourceArtifact::Ptr &artifact, artifactsInGroup) {
+ QPair<ResolvedGroup::Ptr, SourceArtifact::Ptr> p = uniqueArtifacts.value(artifact->absoluteFilePath);
+ SourceArtifact::Ptr existing = p.second;
+ if (existing) {
+ // if an artifact is in the product and in a group, prefer the group configuration
+ if (existing->properties != rproduct->properties)
+ throw Error(Tr::tr("Artifact '%1' is in more than one group.").arg(artifact->absoluteFilePath),
+ CodeLocation(m_project->fileName));
+
+ // Remove the artifact that's in the product's group.
+ p.first->files.removeOne(existing);
+
+ // Merge artifacts.
+ if (!artifact->overrideFileTags)
+ artifact->fileTags.unite(existing->fileTags);
+ }
+ uniqueArtifacts.insert(artifact->absoluteFilePath, qMakePair(group, artifact));
+ }
+ }
+
+ project->products.append(rproduct);
+}
+
+void Loader::resolveProductDependencies(const ResolvedProject::Ptr &project,
+ ProjectData &projectData, const ProductMap &resolvedProducts)
+{
+ // Collect product dependencies from ProductModules.
+ bool productDependenciesAdded;
+ do {
+ productDependenciesAdded = false;
+ foreach (ResolvedProduct::Ptr rproduct, project->products) {
+ ProductData &productData = projectData.products[rproduct];
+ foreach (const UnknownModule::Ptr &unknownModule, productData.usedProducts) {
+ const QString &usedProductName = unknownModule->name;
+ QList<ResolvedProduct::Ptr> usedProductCandidates = resolvedProducts.values(usedProductName);
+ if (usedProductCandidates.count() < 1) {
+ if (!unknownModule->required) {
+ if (!unknownModule->failureMessage.isEmpty())
+ qbsWarning() << unknownModule->failureMessage;
+ continue;
+ }
+ throw Error(Tr::tr("Product dependency '%1' not found in '%2'.").arg(usedProductName, rproduct->qbsFile),
+ CodeLocation(m_project->fileName));
+ }
+ if (usedProductCandidates.count() > 1)
+ throw Error(Tr::tr("Product dependency '%1' is ambiguous.").arg(usedProductName),
+ CodeLocation(m_project->fileName));
+ ResolvedProduct::Ptr usedProduct = usedProductCandidates.first();
+ const ProductData &usedProductData = projectData.products.value(usedProduct);
+ bool added;
+ productData.addUsedProducts(usedProductData.usedProductsFromProductModule, &added);
+ if (added)
+ productDependenciesAdded = true;
+ }
+ }
+ } while (productDependenciesAdded);
+
+ // Resolve all inter-product dependencies.
+ foreach (ResolvedProduct::Ptr rproduct, project->products) {
+ foreach (const UnknownModule::Ptr &unknownModule, projectData.products.value(rproduct).usedProducts) {
+ const QString &usedProductName = unknownModule->name;
+ QList<ResolvedProduct::Ptr> usedProductCandidates = resolvedProducts.values(usedProductName);
+ if (usedProductCandidates.count() < 1) {
+ if (!unknownModule->required) {
+ if (!unknownModule->failureMessage.isEmpty())
+ qbsWarning() << unknownModule->failureMessage;
+ continue;
+ }
+ throw Error(Tr::tr("Product dependency '%1' not found.").arg(usedProductName),
+ CodeLocation(m_project->fileName));
+ }
+ if (usedProductCandidates.count() > 1)
+ throw Error(Tr::tr("Product dependency '%1' is ambiguous.").arg(usedProductName),
+ CodeLocation(m_project->fileName));
+ ResolvedProduct::Ptr usedProduct = usedProductCandidates.first();
+ rproduct->dependencies.insert(usedProduct);
+
+ // insert the configuration of the ProductModule into the product's configuration
+ const QVariantMap productModuleConfig = m_productModules.value(usedProductName);
+ if (productModuleConfig.isEmpty())
+ continue;
+
+ QVariantMap productProperties = rproduct->properties->value();
+ QVariantMap modules = productProperties.value("modules").toMap();
+ modules.insert(usedProductName, productModuleConfig);
+ productProperties.insert("modules", modules);
+ rproduct->properties->setValue(productProperties);
+
+ // insert the configuration of the ProductModule into the artifact configurations
+ foreach (SourceArtifact::Ptr artifact, rproduct->allFiles()) {
+ if (artifact->properties == rproduct->properties)
+ continue; // Already inserted above.
+ QVariantMap sourceArtifactProperties = artifact->properties->value();
+ QVariantMap modules = sourceArtifactProperties.value("modules").toMap();
+ modules.insert(usedProductName, productModuleConfig);
+ sourceArtifactProperties.insert("modules", modules);
+ artifact->properties->setValue(sourceArtifactProperties);
+ }
+ }
+ }
+}
+
ProjectFile::ProjectFile()
: m_destructing(false)
{
diff --git a/src/lib/language/loader.h b/src/lib/language/loader.h
index 336e499d6..9f0560a39 100644
--- a/src/lib/language/loader.h
+++ b/src/lib/language/loader.h
@@ -34,6 +34,7 @@
#include <tools/settings.h>
#include <tools/codelocation.h>
+#include <QMultiMap>
#include <QScriptClass>
#include <QStringList>
#include <QVariant>
@@ -368,8 +369,8 @@ public:
void setSearchPaths(const QStringList &searchPaths);
ProjectFile::Ptr loadProject(const QString &fileName);
ResolvedProject::Ptr resolveProject(ProjectFile::Ptr projectFile, const QString &buildRoot,
- const QVariantMap &userProperties, bool resolveProductDependencies = true);
-protected:
+ const QVariantMap &userProperties);
+private:
ProjectFile::Ptr parseFile(const QString &fileName);
void clearScopesCache();
@@ -438,14 +439,22 @@ protected:
const ScopeChain::Ptr &scope,
const ResolvedModule::ConstPtr &dummyModule);
-private:
+ void checkUserProperties(const ProjectData &projectData, const QVariantMap &userProperties);
+ typedef QMultiMap<QString, ResolvedProduct::Ptr> ProductMap;
+ void resolveProduct(const ResolvedProduct::Ptr &product, const ResolvedProject::Ptr &project,
+ ProductData &data, ProductMap &products,
+ const QList<Rule::Ptr> &globalRules,
+ const QList<FileTagger::ConstPtr> &globalFileTaggers,
+ const ResolvedModule::ConstPtr &dummyModule);
+ void resolveProductDependencies(const ResolvedProject::Ptr &project, ProjectData &projectData,
+ const ProductMap &resolvedProducts);
+
static Loader *get(QScriptEngine *engine);
static QScriptValue js_getHostOS(QScriptContext *context, QScriptEngine *engine);
static QScriptValue js_getHostDefaultArchitecture(QScriptContext *context, QScriptEngine *engine);
static QScriptValue js_getenv(QScriptContext *context, QScriptEngine *engine);
static QScriptValue js_configurationValue(QScriptContext *context, QScriptEngine *engine);
-
ProgressObserver *m_progressObserver;
QStringList m_searchPaths;
QStringList m_moduleSearchPaths;