diff options
author | Christian Kandeler <christian.kandeler@digia.com> | 2014-05-22 12:02:12 +0200 |
---|---|---|
committer | Christian Kandeler <christian.kandeler@digia.com> | 2014-07-02 16:46:11 +0200 |
commit | e264281c4810bb0afb07e8f590fc31e504d5e4d0 (patch) | |
tree | 1bf8a9f0aaf1f6734e4acf53003a681048156efd /src/lib/corelib/language | |
parent | 9297ea217284e2279f2d4471b3f8fc754dc5fe71 (diff) |
Make it possible to set profiles per product.
Use case 1: Build product A for architecture X and product B
for architecture Y (e.g. host tools vs target libraries).
Use case 2: Build product A for architectures X and Y and
product B only for architecture X (e.g. Android
multi-arch packages).
Change-Id: I2eb721c37cdd12c298ee12bad60e21e94b04676b
Reviewed-by: Joerg Bornemann <joerg.bornemann@digia.com>
Diffstat (limited to 'src/lib/corelib/language')
-rw-r--r-- | src/lib/corelib/language/builtindeclarations.cpp | 7 | ||||
-rw-r--r-- | src/lib/corelib/language/language.cpp | 15 | ||||
-rw-r--r-- | src/lib/corelib/language/language.h | 4 | ||||
-rw-r--r-- | src/lib/corelib/language/moduleloader.cpp | 130 | ||||
-rw-r--r-- | src/lib/corelib/language/moduleloader.h | 16 | ||||
-rw-r--r-- | src/lib/corelib/language/projectresolver.cpp | 31 | ||||
-rw-r--r-- | src/lib/corelib/language/tst_language.cpp | 8 |
7 files changed, 162 insertions, 49 deletions
diff --git a/src/lib/corelib/language/builtindeclarations.cpp b/src/lib/corelib/language/builtindeclarations.cpp index ca028cc4f..2f97d7158 100644 --- a/src/lib/corelib/language/builtindeclarations.cpp +++ b/src/lib/corelib/language/builtindeclarations.cpp @@ -146,6 +146,9 @@ void BuiltinDeclarations::addDependsItem() PropertyDeclaration requiredDecl(QLatin1String("required"), PropertyDeclaration::Boolean); requiredDecl.setInitialValueSource(QLatin1String("true")); item << requiredDecl; + PropertyDeclaration profileDecl(QLatin1String("profiles"), PropertyDeclaration::StringList); + profileDecl.setInitialValueSource(QLatin1String("[product.profile]")); + item << profileDecl; insert(item); } @@ -245,6 +248,10 @@ void BuiltinDeclarations::addProductItem() decl.setInitialValueSource(QLatin1String("[]")); item << decl; item << nameProperty(); + decl = PropertyDeclaration(QLatin1String("profiles"), PropertyDeclaration::StringList); + decl.setInitialValueSource(QLatin1String("[project.profile]")); + item << decl; + item << PropertyDeclaration(QLatin1String("profile"), PropertyDeclaration::String); // Internal decl = PropertyDeclaration(QLatin1String("targetName"), PropertyDeclaration::String); decl.setInitialValueSource(QLatin1String("name")); item << buildDirProperty(); diff --git a/src/lib/corelib/language/language.cpp b/src/lib/corelib/language/language.cpp index 324739aaa..300b41d2d 100644 --- a/src/lib/corelib/language/language.cpp +++ b/src/lib/corelib/language/language.cpp @@ -462,6 +462,7 @@ void ResolvedProduct::load(PersistentPool &pool) >> enabled >> fileTags >> name + >> profile >> targetName >> sourceDirectory >> destinationDirectory @@ -485,6 +486,7 @@ void ResolvedProduct::store(PersistentPool &pool) const << enabled << fileTags << name + << profile << targetName << sourceDirectory << destinationDirectory @@ -792,7 +794,18 @@ ArtifactSet ResolvedProduct::targetArtifacts() const TopLevelProject *ResolvedProduct::topLevelProject() const { - return project->topLevelProject(); + return project->topLevelProject(); +} + +QString ResolvedProduct::uniqueName(const QString &name, const QString &profile) +{ + QBS_CHECK(!profile.isEmpty()); + return name + QLatin1Char('.') + profile; +} + +QString ResolvedProduct::uniqueName() const +{ + return uniqueName(name, profile); } static QStringList findGeneratedFiles(const Artifact *base, const FileTags &tags) diff --git a/src/lib/corelib/language/language.h b/src/lib/corelib/language/language.h index f62e63333..c1605394a 100644 --- a/src/lib/corelib/language/language.h +++ b/src/lib/corelib/language/language.h @@ -355,6 +355,7 @@ public: FileTags fileTags; QString name; QString targetName; + QString profile; QString sourceDirectory; QString destinationDirectory; CodeLocation location; @@ -398,6 +399,9 @@ public: TopLevelProject *topLevelProject() const; + static QString uniqueName(const QString &name, const QString &profile); + QString uniqueName() const; + QStringList generatedFiles(const QString &baseFile, const FileTags &tags) const; QString buildDirectory() const; diff --git a/src/lib/corelib/language/moduleloader.cpp b/src/lib/corelib/language/moduleloader.cpp index 23b0d5980..3c70fa532 100644 --- a/src/lib/corelib/language/moduleloader.cpp +++ b/src/lib/corelib/language/moduleloader.cpp @@ -44,13 +44,17 @@ #include <tools/error.h> #include <tools/fileinfo.h> #include <tools/hostosinfo.h> +#include <tools/profile.h> #include <tools/progressobserver.h> #include <tools/qbsassert.h> #include <tools/qttools.h> +#include <tools/scripttools.h> +#include <tools/settings.h> #include <QDebug> #include <QDir> #include <QDirIterator> +#include <QPair> namespace qbs { namespace Internal { @@ -216,6 +220,7 @@ void ModuleLoader::handleProject(ModuleLoaderResult *loadResult, Item *item, ProductContext dummyProductContext; dummyProductContext.project = &projectContext; + dummyProductContext.moduleProperties = m_parameters.finalBuildConfigurationTree(); loadBaseModule(&dummyProductContext, item); overrideItemProperties(item, QLatin1String("project"), m_parameters.overriddenValuesTree()); @@ -230,6 +235,13 @@ void ModuleLoader::handleProject(ModuleLoaderResult *loadResult, Item *item, foreach (Item *child, item->children()) { child->setScope(projectContext.scope); if (child->typeName() == QLatin1String("Product")) { + foreach (Item * const additionalProductItem, multiplexProductItem(child)) + Item::addChild(item, additionalProductItem); + } + } + + foreach (Item *child, item->children()) { + if (child->typeName() == QLatin1String("Product")) { handleProduct(&projectContext, child); } else if (child->typeName() == QLatin1String("SubProject")) { handleSubProject(&projectContext, child, referencedFilePaths); @@ -241,6 +253,8 @@ void ModuleLoader::handleProject(ModuleLoaderResult *loadResult, Item *item, const QString projectFileDirPath = FileInfo::path(item->file()->filePath()); const QStringList refs = m_evaluator->stringListValue(item, QLatin1String("references")); + typedef QPair<Item *, QString> ItemAndRefPath; + QList<ItemAndRefPath> additionalProjectChildren; foreach (const QString &filePath, refs) { QString absReferencePath = FileInfo::resolvePath(projectFileDirPath, filePath); if (FileInfo(absReferencePath).isDir()) { @@ -267,15 +281,21 @@ void ModuleLoader::handleProject(ModuleLoaderResult *loadResult, Item *item, Item *subItem = m_reader->readFile(absReferencePath); subItem->setScope(projectContext.scope); subItem->setParent(projectContext.item); - QList<Item *> projectChildren = projectContext.item->children(); - projectChildren += subItem; - projectContext.item->setChildren(projectChildren); + additionalProjectChildren << qMakePair(subItem, absReferencePath); + if (subItem->typeName() == QLatin1String("Product")) { + foreach (Item * const additionalProductItem, multiplexProductItem(subItem)) + additionalProjectChildren << qMakePair(additionalProductItem, absReferencePath); + } + } + foreach (const ItemAndRefPath &irp, additionalProjectChildren) { + Item * const subItem = irp.first; + Item::addChild(projectContext.item, subItem); if (subItem->typeName() == QLatin1String("Product")) { handleProduct(&projectContext, subItem); } else if (subItem->typeName() == QLatin1String("Project")) { copyProperties(item, subItem); handleProject(loadResult, subItem, buildDirectory, - QSet<QString>(referencedFilePaths) << absReferencePath); + QSet<QString>(referencedFilePaths) << irp.second); } else { throw ErrorInfo(Tr::tr("The top-level item of a file in a \"references\" list must be " "a Product or a Project, but it is \"%1\".").arg(subItem->typeName()), @@ -291,6 +311,43 @@ void ModuleLoader::handleProject(ModuleLoaderResult *loadResult, Item *item, m_reader->popExtraSearchPaths(); } +QList<Item *> ModuleLoader::multiplexProductItem(Item *productItem) +{ + // Overriding the product item properties must be done here already, because otherwise + // the "profiles" property would not be overridable. + QString productName = m_evaluator->stringValue(productItem, QLatin1String("name")); + if (productName.isEmpty()) { + productName = FileInfo::completeBaseName(productItem->file()->filePath()); + productItem->setProperty(QLatin1String("name"), VariantValue::create(productName)); + } + overrideItemProperties(productItem, productName, m_parameters.overriddenValuesTree()); + + const QString profilesKey = QLatin1String("profiles"); + const ValueConstPtr profilesValue = productItem->property(profilesKey); + QBS_CHECK(profilesValue); // Default value set in BuiltinDeclarations. + const QStringList profileNames = m_evaluator->stringListValue(productItem, profilesKey); + if (profileNames.isEmpty()) { + throw ErrorInfo(Tr::tr("The 'profiles' property cannot be an empty list."), + profilesValue->location()); + } + foreach (const QString &profileName, profileNames) { + if (profileNames.count(profileName) > 1) { + throw ErrorInfo(Tr::tr("The profile '%1' appears in the 'profiles' list twice, " + "which is not allowed.").arg(profileName), profilesValue->location()); + } + } + + QList<Item *> additionalProductItems; + const QString profileKey = QLatin1String("profile"); + productItem->setProperty(profileKey, VariantValue::create(profileNames.first())); + for (int i = 1; i < profileNames.count(); ++i) { + Item * const cloned = productItem->clone(productItem->pool()); + cloned->setProperty(profileKey, VariantValue::create(profileNames.at(i))); + additionalProductItems << cloned; + } + return additionalProductItems; +} + void ModuleLoader::handleProduct(ProjectContext *projectContext, Item *item) { checkCancelation(); @@ -299,6 +356,15 @@ void ModuleLoader::handleProduct(ProjectContext *projectContext, Item *item) initProductProperties(projectContext, item); ProductContext productContext; + bool profilePropertySet; + productContext.profileName = m_evaluator->stringValue(item, QLatin1String("profile"), + QString(), &profilePropertySet); + QBS_CHECK(profilePropertySet); + const QVariantMap buildConfig = SetupProjectParameters::expandedBuildConfiguration( + m_parameters.settingsDirectory(), productContext.profileName, + m_parameters.buildVariant()); + productContext.moduleProperties = SetupProjectParameters::finalBuildConfigurationTree( + buildConfig, m_parameters.overriddenValues()); productContext.project = projectContext; bool extraSearchPathsSet = false; const QStringList extraSearchPaths = readExtraSearchPaths(item, &extraSearchPathsSet); @@ -308,6 +374,7 @@ void ModuleLoader::handleProduct(ProjectContext *projectContext, Item *item) } else { productContext.extraSearchPaths = projectContext->extraSearchPaths; } + productContext.item = item; ItemValuePtr itemValue = ItemValue::create(item); productContext.scope = Item::create(m_pool); @@ -342,15 +409,13 @@ void ModuleLoader::handleProduct(ProjectContext *projectContext, Item *item) void ModuleLoader::initProductProperties(const ProjectContext *project, Item *item) { - QString productName = m_evaluator->stringValue(item, QLatin1String("name")); - if (productName.isEmpty()) { - productName = FileInfo::completeBaseName(item->file()->filePath()); - item->setProperty(QLatin1String("name"), VariantValue::create(productName)); - } - + const QString productName = m_evaluator->stringValue(item, QLatin1String("name")); + const QString profile = m_evaluator->stringValue(item, QLatin1String("profile")); + QBS_CHECK(!profile.isEmpty()); + const QString uniqueName = ResolvedProduct::uniqueName(productName, profile); item->setProperty(QLatin1String("buildDirectory"), VariantValue::create( - FileInfo::resolvePath(project->buildDirectory, productName))); + FileInfo::resolvePath(project->buildDirectory, uniqueName))); item->setProperty(QLatin1String("sourceDirectory"), VariantValue::create( @@ -613,12 +678,20 @@ void ModuleLoader::resolveDependsItem(DependsContext *dependsContext, Item *item result.item = moduleItem; moduleResults->append(result); } else { - ModuleLoaderResult::ProductInfo::Dependency dependency; - dependency.name = moduleName; - dependency.required = m_evaluator->property(item, QLatin1String("required")).toBool(); - dependency.failureMessage - = m_evaluator->property(item, QLatin1String("failureMessage")).toString(); - productResults->append(ProductDependencyResult(dependsItem, dependency)); + const QString profilesKey = QLatin1String("profiles"); + const QStringList profiles = m_evaluator->stringListValue(dependsItem, profilesKey); + if (profiles.isEmpty()) { + throw ErrorInfo(Tr::tr("Empty 'profiles' list not allowed in 'Depends' item."), + dependsItem->property(profilesKey)->location()); + } + const bool required = m_evaluator->property(item, QLatin1String("required")).toBool(); + foreach (const QString &profile, profiles) { + ModuleLoaderResult::ProductInfo::Dependency dependency; + dependency.name = moduleName; + dependency.profile = profile; + dependency.required = required; + productResults->append(ProductDependencyResult(dependsItem, dependency)); + } } } } @@ -787,14 +860,15 @@ Item *ModuleLoader::loadModuleFile(ProductContext *productContext, const QString if (m_logger.traceEnabled()) m_logger.qbsTrace() << "[MODLDR] trying to load " << fullModuleName << " from " << filePath; - Item *module = productContext->moduleItemCache.value(filePath); + const ContextBase::ModuleItemCache::key_type cacheKey(filePath, productContext->profileName); + Item *module = productContext->moduleItemCache.value(cacheKey); if (module) { m_logger.qbsTrace() << "[LDR] loadModuleFile cache hit for " << filePath; *cacheHit = true; return module; } - module = productContext->project->moduleItemCache.value(filePath); + module = productContext->project->moduleItemCache.value(cacheKey); if (module) { m_logger.qbsTrace() << "[LDR] loadModuleFile returns clone for " << filePath; *cacheHit = true; @@ -817,20 +891,21 @@ Item *ModuleLoader::loadModuleFile(ProductContext *productContext, const QString // Module properties that are defined in the profile are used as default values. const QVariantMap profileModuleProperties - = m_parameters.buildConfigurationTree().value(fullModuleName).toMap(); + = productContext->moduleProperties.value(fullModuleName).toMap(); for (QVariantMap::const_iterator vmit = profileModuleProperties.begin(); vmit != profileModuleProperties.end(); ++vmit) { if (Q_UNLIKELY(!module->hasProperty(vmit.key()))) throw ErrorInfo(Tr::tr("Unknown property: %1.%2").arg(fullModuleName, vmit.key())); const PropertyDeclaration decl = module->propertyDeclaration(vmit.key()); - module->setProperty(vmit.key(), - VariantValue::create(convertToPropertyType(vmit.value(), decl.type(), - QStringList(fullModuleName), vmit.key()))); + VariantValuePtr v = VariantValue::create(convertToPropertyType(vmit.value(), decl.type(), + QStringList(fullModuleName), vmit.key())); + module->setProperty(vmit.key(), v); } - productContext->moduleItemCache.insert(filePath, module); - productContext->project->moduleItemCache.insert(filePath, module); + productContext->moduleItemCache.insert(cacheKey, module); + productContext->project->moduleItemCache.insert(cacheKey, module); + return module; } @@ -1175,5 +1250,10 @@ void ModuleLoader::overrideItemProperties(Item *item, const QString &buildConfig } } +QString ModuleLoaderResult::ProductInfo::Dependency::uniqueName() const +{ + return ResolvedProduct::uniqueName(name, profile); +} + } // namespace Internal } // namespace qbs diff --git a/src/lib/corelib/language/moduleloader.h b/src/lib/corelib/language/moduleloader.h index 5df1747fc..42e82046f 100644 --- a/src/lib/corelib/language/moduleloader.h +++ b/src/lib/corelib/language/moduleloader.h @@ -69,8 +69,10 @@ struct ModuleLoaderResult struct Dependency { QString name; + QString profile; bool required; - QString failureMessage; + + QString uniqueName() const; }; QList<Dependency> usedProducts; @@ -102,8 +104,6 @@ public: ModuleLoaderResult load(const SetupProjectParameters ¶meters); static QString fullModuleName(const QStringList &moduleName); - static void overrideItemProperties(Item *item, const QString &buildConfigKey, - const QVariantMap &buildConfig); private: class ContextBase @@ -116,7 +116,8 @@ private: Item *item; Item *scope; QStringList extraSearchPaths; - QMap<QString, Item *> moduleItemCache; + typedef QMap<QPair<QString, QString>, Item *> ModuleItemCache; + ModuleItemCache moduleItemCache; }; class ProjectContext : public ContextBase @@ -132,8 +133,10 @@ private: public: ProjectContext *project; ModuleLoaderResult::ProductInfo info; + QString profileName; QSet<FileContextConstPtr> filesWithExportItem; QList<Item *> exportItems; + QVariantMap moduleProperties; }; class DependsContext @@ -148,6 +151,7 @@ private: void handleProject(ModuleLoaderResult *loadResult, Item *item, const QString &buildDirectory, const QSet<QString> &referencedFilePaths); + QList<Item *> multiplexProductItem(Item *productItem); void handleProduct(ProjectContext *projectContext, Item *item); void initProductProperties(const ProjectContext *project, Item *item); void handleSubProject(ProjectContext *projectContext, Item *item, @@ -188,6 +192,10 @@ private: const QStringList &moduleName); static void copyProperty(const QString &propertyName, const Item *source, Item *destination); static void setScopeForDescendants(Item *item, Item *scope); + static void overrideItemProperties(Item *item, const QString &buildConfigKey, + const QVariantMap &buildConfig); + + ScriptEngine *m_engine; ItemPool *m_pool; diff --git a/src/lib/corelib/language/projectresolver.cpp b/src/lib/corelib/language/projectresolver.cpp index bf01fd0d8..ebe60e032 100644 --- a/src/lib/corelib/language/projectresolver.cpp +++ b/src/lib/corelib/language/projectresolver.cpp @@ -87,12 +87,12 @@ static void checkForDuplicateProductNames(const TopLevelProjectConstPtr &project const QList<ResolvedProductPtr> allProducts = project->allProducts(); for (int i = 0; i < allProducts.count(); ++i) { const ResolvedProductConstPtr product1 = allProducts.at(i); - const QString productName = product1->name; + const QString productName = product1->uniqueName(); for (int j = i + 1; j < allProducts.count(); ++j) { const ResolvedProductConstPtr product2 = allProducts.at(j); - if (product2->name == productName) { + if (product2->uniqueName() == productName) { ErrorInfo error; - error.append(Tr::tr("Duplicate product name '%1'.").arg(productName)); + error.append(Tr::tr("Duplicate product name '%1'.").arg(product1->name)); error.append(Tr::tr("First product defined here."), product1->location); error.append(Tr::tr("Second product defined here."), product2->location); throw error; @@ -286,10 +286,12 @@ void ProjectResolver::resolveProduct(Item *item, ProjectContext *projectContext) projectContext->project->products += product; productContext.product = product; product->name = m_evaluator->stringValue(item, QLatin1String("name")); - m_logger.qbsTrace() << "[PR] resolveProduct " << product->name; // product->buildDirectory() isn't valid yet, because the productProperties map is not ready. productContext.buildDirectory = m_evaluator->stringValue(item, QLatin1String("buildDirectory")); + product->profile = m_evaluator->stringValue(item, QLatin1String("profile")); + QBS_CHECK(!product->profile.isEmpty()); + m_logger.qbsTrace() << "[PR] resolveProduct " << product->uniqueName(); if (std::find_if(item->modules().begin(), item->modules().end(), ModuleNameEquals(product->name)) != item->modules().end()) { @@ -298,8 +300,7 @@ void ProjectResolver::resolveProduct(Item *item, ProjectContext *projectContext) item->location()); } - ModuleLoader::overrideItemProperties(item, product->name, m_setupParams.overriddenValuesTree()); - m_productsByName.insert(product->name, product); + m_productsByName.insert(product->uniqueName(), product); product->enabled = m_evaluator->boolValue(item, QLatin1String("condition")); // TODO: Remove in 1.3. @@ -802,7 +803,7 @@ void ProjectResolver::resolveExport(Item *item, ProjectContext *projectContext) { Q_UNUSED(projectContext); checkCancelation(); - const QString &productName = m_productContext->product->name; + const QString &productName = m_productContext->product->uniqueName(); m_exports[productName] = evaluateModuleValues(item); } @@ -826,10 +827,10 @@ static void addUsedProducts(ModuleLoaderResult::ProductInfo *productInfo, QSet<QString> usedProductNames; foreach (const ModuleLoaderResult::ProductInfo::Dependency &usedProduct, productInfo->usedProducts) - usedProductNames += usedProduct.name; + usedProductNames += usedProduct.uniqueName(); foreach (const ModuleLoaderResult::ProductInfo::Dependency &usedProduct, usedProductInfo.usedProductsFromExportItem) { - if (!usedProductNames.contains(usedProduct.name)) + if (!usedProductNames.contains(usedProduct.uniqueName())) productInfo->usedProducts += usedProduct; } *productsAdded = (oldCount != productInfo->usedProducts.count()); @@ -850,11 +851,11 @@ void ProjectResolver::resolveProductDependencies(ProjectContext *projectContext) = projectContext->loadResult->productInfos[productItem]; foreach (const ModuleLoaderResult::ProductInfo::Dependency &dependency, productInfo.usedProducts) { - ResolvedProductPtr usedProduct - = m_productsByName.value(dependency.name); - if (Q_UNLIKELY(!usedProduct)) - throw ErrorInfo(Tr::tr("Product dependency '%1' not found.").arg(dependency.name), - productItem->location()); + ResolvedProductPtr usedProduct = m_productsByName.value(dependency.uniqueName()); + if (Q_UNLIKELY(!usedProduct)) { + throw ErrorInfo(Tr::tr("Product dependency '%1' not found for profile '%2'.") + .arg(dependency.name, dependency.profile), productItem->location()); + } Item *usedProductItem = m_productItemMap.value(usedProduct); const ModuleLoaderResult::ProductInfo usedProductInfo = projectContext->loadResult->productInfos.value(usedProductItem); @@ -873,7 +874,7 @@ void ProjectResolver::resolveProductDependencies(ProjectContext *projectContext) Item *productItem = m_productItemMap.value(rproduct); foreach (const ModuleLoaderResult::ProductInfo::Dependency &dependency, projectContext->loadResult->productInfos.value(productItem).usedProducts) { - const QString &usedProductName = dependency.name; + const QString &usedProductName = dependency.uniqueName(); ResolvedProductPtr usedProduct = m_productsByName.value(usedProductName); if (Q_UNLIKELY(!usedProduct)) throw ErrorInfo(Tr::tr("Product dependency '%1' not found.").arg(usedProductName), diff --git a/src/lib/corelib/language/tst_language.cpp b/src/lib/corelib/language/tst_language.cpp index d8c47c90b..333968450 100644 --- a/src/lib/corelib/language/tst_language.cpp +++ b/src/lib/corelib/language/tst_language.cpp @@ -400,7 +400,7 @@ void TestLanguage::exports() ResolvedProductPtr product; product = products.value("myapp"); QVERIFY(product); - QStringList propertyName = QStringList() << "modules" << "mylib" + QStringList propertyName = QStringList() << "modules" << "mylib.qbs_autotests" << "modules" << "dummy" << "defines"; QVariant propertyValue = getConfigProperty(product->moduleProperties->value(), propertyName); QCOMPARE(propertyValue.toStringList(), QStringList() << "USE_MYLIB"); @@ -428,11 +428,11 @@ void TestLanguage::exports() product = products.value("myapp2"); QVERIFY(product); - propertyName = QStringList() << "modules" << "productWithInheritedExportItem" + propertyName = QStringList() << "modules" << "productWithInheritedExportItem.qbs_autotests" << "modules" << "dummy" << "cxxFlags"; propertyValue = getConfigProperty(product->moduleProperties->value(), propertyName); QCOMPARE(propertyValue.toStringList(), QStringList() << "-bar"); - propertyName = QStringList() << "modules" << "productWithInheritedExportItem" + propertyName = QStringList() << "modules" << "productWithInheritedExportItem.qbs_autotests" << "modules" << "dummy" << "defines"; propertyValue = getConfigProperty(product->moduleProperties->value(), propertyName); QCOMPARE(propertyValue.toStringList(), QStringList() << "ABC"); @@ -1114,7 +1114,7 @@ void TestLanguage::productDirectories() QVERIFY(product); const QVariantMap config = product->productProperties; QCOMPARE(config.value(QLatin1String("buildDirectory")).toString(), - buildDir(defaultParameters) + QLatin1Char('/') + product->name); + buildDir(defaultParameters) + QLatin1Char('/') + product->uniqueName()); QCOMPARE(config.value(QLatin1String("sourceDirectory")).toString(), testDataDir()); } catch (const ErrorInfo &e) { |