summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Kandeler <christian.kandeler@qt.io>2017-07-21 16:53:56 +0200
committerChristian Kandeler <christian.kandeler@qt.io>2017-08-01 12:14:54 +0000
commitcccf7a64cb312e6dfb89343cc6087d43cdfeb427 (patch)
treedbe429b66ff40393bcb1c7764fe61ff4c07653af
parentd4c4d5743d11fd4af3b3b536cf446e1735773d44 (diff)
downloadqbs-cccf7a64cb312e6dfb89343cc6087d43cdfeb427.tar.gz
Introduce the Profile item
Allows users to provide project-specific profiles. Useful for when a project has specific, well-known requirements regarding the build environment and/or target platform. [ChangeLog] Profiles can now be defined within a project using the Profile item. Task-number: QBS-895 Change-Id: Idf902fbb095bb153c15e31d2aa8eb73448b69936 Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
-rw-r--r--doc/reference/items/language/product.qdoc2
-rw-r--r--doc/reference/items/language/profile.qdoc95
-rw-r--r--doc/reference/items/language/project.qdoc2
-rw-r--r--src/lib/corelib/language/builtindeclarations.cpp13
-rw-r--r--src/lib/corelib/language/builtindeclarations.h1
-rw-r--r--src/lib/corelib/language/itemtype.h1
-rwxr-xr-xsrc/lib/corelib/language/moduleloader.cpp111
-rw-r--r--src/lib/corelib/language/moduleloader.h7
-rw-r--r--tests/auto/api/testdata/local-profiles/local-profiles.qbs44
-rw-r--r--tests/auto/api/tst_api.cpp120
-rw-r--r--tests/auto/api/tst_api.h2
11 files changed, 392 insertions, 6 deletions
diff --git a/doc/reference/items/language/product.qdoc b/doc/reference/items/language/product.qdoc
index b96752f9f..9574190dc 100644
--- a/doc/reference/items/language/product.qdoc
+++ b/doc/reference/items/language/product.qdoc
@@ -28,7 +28,7 @@
\contentspage list-of-language-items.html
\previouspage probe-item.html
\page product-item.html
- \nextpage project-item.html
+ \nextpage profile-item.html
\ingroup list-of-language-items
\ingroup list-of-items
\keyword QML.Product
diff --git a/doc/reference/items/language/profile.qdoc b/doc/reference/items/language/profile.qdoc
new file mode 100644
index 000000000..c9dcc64cd
--- /dev/null
+++ b/doc/reference/items/language/profile.qdoc
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qbs.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** 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 Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+/*!
+ \contentspage list-of-language-items.html
+ \previouspage product-item.html
+ \page profile-item.html
+ \nextpage project-item.html
+ \ingroup list-of-language-items
+ \ingroup list-of-items
+ \keyword QML.Properties
+
+ \title Profile Item
+ \brief Creates a profile within the project
+
+ The profiles used by \QBS are normally set up on a user's machine and are then available
+ to all projects. See the \l Configuring section for information on how to set up and
+ use profiles on the command line.
+ In some rare cases, however, the creator of a project has complete knowledge about the system
+ on which that project is to be built. Then it can make sense to integrate the profile into
+ the project:
+
+ \code
+ Product {
+ // ...
+ Profile {
+ name: "my-special-profile"
+ qbs.toolchain: ["gcc"]
+ qbs.targetOS: ["linux"]
+ qbs.architecture: "arm"
+ cpp.toolchainInstallPath: "/opt/special-gcc/bin"
+ cpp.toolchainPrefix: "arm-linux-special-"
+ }
+ qbs.profiles: ["my-special-profile"]
+ // ...
+ }
+ \endcode
+
+ The project in the above example can be built in a particular well-known environment
+ without any additional setup.
+
+ \c Profile items can appear inside \l{Product Item}{Product} and \l{Project Item}{Project}
+ items.
+
+ \section1 Profile Properties
+
+ \table
+ \header
+ \li Property
+ \li Type
+ \li Default
+ \li Description
+ \row
+ \li baseProfile
+ \li \c string
+ \li \c undefined
+ \li The name of a profile from which this profile inherits. If the same property is
+ set in both this profile and the base profile, the value from this profile
+ takes precedence.
+ \row
+ \li condition
+ \li \c bool
+ \li \c true
+ \li If this property is set to \c false, the profile cannot be used.
+ \row
+ \li name
+ \li \c string
+ \li \c undefined
+ \li The name under which the profile can be referenced later. Setting this property
+ is required. The value must be unique among all profiles in an entire project.
+ \endtable
+*/
diff --git a/doc/reference/items/language/project.qdoc b/doc/reference/items/language/project.qdoc
index 581d20e21..18330f574 100644
--- a/doc/reference/items/language/project.qdoc
+++ b/doc/reference/items/language/project.qdoc
@@ -26,7 +26,7 @@
****************************************************************************/
/*!
\contentspage list-of-language-items.html
- \previouspage product-item.html
+ \previouspage profile-item.html
\page project-item.html
\nextpage properties-item.html
\ingroup list-of-language-items
diff --git a/src/lib/corelib/language/builtindeclarations.cpp b/src/lib/corelib/language/builtindeclarations.cpp
index fec9d8783..9eda212b7 100644
--- a/src/lib/corelib/language/builtindeclarations.cpp
+++ b/src/lib/corelib/language/builtindeclarations.cpp
@@ -71,6 +71,7 @@ BuiltinDeclarations::BuiltinDeclarations()
{ QLatin1String("Parameters"), ItemType::Parameters },
{ QLatin1String("Probe"), ItemType::Probe },
{ QLatin1String("Product"), ItemType::Product },
+ { QLatin1String("Profile"), ItemType::Profile },
{ QLatin1String("Project"), ItemType::Project },
{ QLatin1String("Properties"), ItemType::Properties }, // Callers have to handle the SubProject case.
{ QLatin1String("PropertyOptions"), ItemType::PropertyOptions },
@@ -88,6 +89,7 @@ BuiltinDeclarations::BuiltinDeclarations()
addModuleItem();
addProbeItem();
addProductItem();
+ addProfileItem();
addProjectItem();
addPropertiesItem();
addPropertyOptionsItem();
@@ -317,6 +319,7 @@ void BuiltinDeclarations::addProductItem()
<< ItemType::FileTagger
<< ItemType::Export
<< ItemType::Probe
+ << ItemType::Profile
<< ItemType::PropertyOptions
<< ItemType::Rule);
item << conditionProperty();
@@ -359,6 +362,15 @@ void BuiltinDeclarations::addProductItem()
insert(item);
}
+void BuiltinDeclarations::addProfileItem()
+{
+ ItemDeclaration item(ItemType::Profile);
+ item << conditionProperty();
+ item << nameProperty();
+ item << PropertyDeclaration(QLatin1String("baseProfile"), PropertyDeclaration::String);
+ insert(item);
+}
+
void BuiltinDeclarations::addProjectItem()
{
ItemDeclaration item(ItemType::Project);
@@ -367,6 +379,7 @@ void BuiltinDeclarations::addProjectItem()
<< ItemType::PropertyOptions
<< ItemType::SubProject
<< ItemType::Product
+ << ItemType::Profile
<< ItemType::Probe
<< ItemType::FileTagger
<< ItemType::Rule);
diff --git a/src/lib/corelib/language/builtindeclarations.h b/src/lib/corelib/language/builtindeclarations.h
index 745a5766f..8106b8a74 100644
--- a/src/lib/corelib/language/builtindeclarations.h
+++ b/src/lib/corelib/language/builtindeclarations.h
@@ -79,6 +79,7 @@ private:
static ItemDeclaration moduleLikeItem(ItemType type);
void addProbeItem();
void addProductItem();
+ void addProfileItem();
void addProjectItem();
void addPropertiesItem();
void addPropertyOptionsItem();
diff --git a/src/lib/corelib/language/itemtype.h b/src/lib/corelib/language/itemtype.h
index 4901cbbe4..c0e76c94b 100644
--- a/src/lib/corelib/language/itemtype.h
+++ b/src/lib/corelib/language/itemtype.h
@@ -58,6 +58,7 @@ enum class ItemType {
Parameters,
Probe,
Product,
+ Profile,
Project,
Properties,
PropertiesInSubProject,
diff --git a/src/lib/corelib/language/moduleloader.cpp b/src/lib/corelib/language/moduleloader.cpp
index 7a5f2da8f..954367f78 100755
--- a/src/lib/corelib/language/moduleloader.cpp
+++ b/src/lib/corelib/language/moduleloader.cpp
@@ -385,6 +385,8 @@ ModuleLoaderResult ModuleLoader::load(const SetupProjectParameters &parameters)
Set<QString>() << QDir::cleanPath(parameters.projectFilePath()));
result.root = root;
result.qbsFiles = m_reader->filesRead();
+ for (auto it = m_localProfiles.cbegin(); it != m_localProfiles.cend(); ++it)
+ result.profileConfigs.remove(it.key());
printProfilingInfo();
return result;
}
@@ -634,6 +636,8 @@ void ModuleLoader::handleProject(ModuleLoaderResult *loadResult,
m_qbsVersion.toString()));
}
+ handleProfileItems(projectItem, &projectContext);
+
QList<Item *> multiplexedProducts;
for (Item * const child : projectItem->children()) {
child->setScope(projectContext.scope);
@@ -969,6 +973,8 @@ void ModuleLoader::prepareProduct(ProjectContext *projectContext, Item *productI
m_logger.qbsTrace() << "[MODLDR] prepareProduct " << productItem->file()->filePath();
ProductContext productContext;
+ productContext.item = productItem;
+ productContext.project = projectContext;
productContext.name = m_evaluator->stringValue(productItem, QLatin1String("name"));
QBS_CHECK(!productContext.name.isEmpty());
bool profilePropertySet;
@@ -979,7 +985,13 @@ void ModuleLoader::prepareProduct(ProjectContext *projectContext, Item *productI
QBS_CHECK(profilePropertySet);
const auto it = projectContext->result->profileConfigs.constFind(productContext.profileName);
if (it == projectContext->result->profileConfigs.constEnd()) {
- const Profile profile(productContext.profileName, m_settings.get());
+ const Profile profile(productContext.profileName, m_settings.get(), m_localProfiles);
+ if (!profile.exists()) {
+ ErrorInfo error(Tr::tr("Profile '%1' does not exist.").arg(profile.name()),
+ productItem->location());
+ handleProductError(error, &productContext);
+ return;
+ }
const QVariantMap buildConfig = SetupProjectParameters::expandedBuildConfiguration(
profile, m_parameters.configurationName());
productContext.moduleProperties = SetupProjectParameters::finalBuildConfigurationTree(
@@ -989,8 +1001,6 @@ void ModuleLoader::prepareProduct(ProjectContext *projectContext, Item *productI
} else {
productContext.moduleProperties = it.value().toMap();
}
- productContext.item = productItem;
- productContext.project = projectContext;
initProductProperties(productContext);
ItemValuePtr itemValue = ItemValue::create(productItem);
@@ -1356,8 +1366,10 @@ QList<Item *> ModuleLoader::loadReferencedFile(const QString &relativePath,
subItem->setParent(dummyContext.project->item);
QList<Item *> loadedItems;
loadedItems << subItem;
- if (subItem->type() == ItemType::Product)
+ if (subItem->type() == ItemType::Product) {
+ handleProfileItems(subItem, dummyContext.project);
loadedItems << multiplexProductItem(&dummyContext, subItem);
+ }
return loadedItems;
}
@@ -1642,6 +1654,97 @@ Item *ModuleLoader::loadItemFromFile(const QString &filePath)
return item;
}
+void ModuleLoader::handleProfileItems(Item *item, ProjectContext *projectContext)
+{
+ const std::vector<Item *> profileItems = collectProfileItems(item, projectContext);
+ for (Item * const profileItem : profileItems) {
+ try {
+ handleProfile(profileItem);
+ } catch (const ErrorInfo &e) {
+ handlePropertyError(e, m_parameters, m_logger);
+ }
+ }
+}
+
+std::vector<Item *> ModuleLoader::collectProfileItems(Item *item, ProjectContext *projectContext)
+{
+ QList<Item *> childItems = item->children();
+ std::vector<Item *> profileItems;
+ Item * scope = item->type() == ItemType::Project ? projectContext->scope : nullptr;
+ for (auto it = childItems.begin(); it != childItems.end();) {
+ Item * const childItem = *it;
+ if (childItem->type() == ItemType::Profile) {
+ if (!scope) {
+ const ItemValuePtr itemValue = ItemValue::create(item);
+ scope = Item::create(m_pool, ItemType::Scope);
+ scope->setProperty(QLatin1String("product"), itemValue);
+ scope->setFile(item->file());
+ scope->setScope(projectContext->scope);
+ }
+ childItem->setScope(scope);
+ profileItems.push_back(childItem);
+ it = childItems.erase(it);
+ } else {
+ if (childItem->type() == ItemType::Product) {
+ for (Item * const profileItem : collectProfileItems(childItem, projectContext))
+ profileItems.push_back(profileItem);
+ }
+ ++it;
+ }
+ }
+ if (!profileItems.empty())
+ item->setChildren(childItems);
+ return profileItems;
+}
+
+void ModuleLoader::evaluateProfileValues(const QualifiedId &namePrefix, Item *item,
+ Item *profileItem, QVariantMap &values)
+{
+ const Item::PropertyMap &props = item->properties();
+ for (auto it = props.begin(); it != props.end(); ++it) {
+ QualifiedId name = namePrefix;
+ name << it.key();
+ switch (it.value()->type()) {
+ case Value::ItemValueType:
+ evaluateProfileValues(name, std::static_pointer_cast<ItemValue>(it.value())->item(),
+ profileItem, values);
+ break;
+ case Value::VariantValueType:
+ values.insert(name.join(QLatin1Char('.')),
+ std::static_pointer_cast<VariantValue>(it.value())->value());
+ break;
+ case Value::JSSourceValueType:
+ item->setType(ItemType::ModulePrefix); // TODO: Introduce new item type
+ if (item != profileItem)
+ item->setScope(profileItem);
+ values.insert(name.join(QLatin1Char('.')),
+ m_evaluator->value(item, it.key()).toVariant());
+ break;
+ }
+ }
+}
+
+void ModuleLoader::handleProfile(Item *profileItem)
+{
+ QVariantMap values;
+ evaluateProfileValues(QualifiedId(), profileItem, profileItem, values);
+ const bool condition = values.take(QLatin1String("condition")).toBool();
+ if (!condition)
+ return;
+ const QString profileName = values.take(QLatin1String("name")).toString();
+ if (profileName.isEmpty())
+ throw ErrorInfo(Tr::tr("Every Profile item must have a name"), profileItem->location());
+ if (profileName == Profile::fallbackName()) {
+ throw ErrorInfo(Tr::tr("Reserved name '%1' cannot be used for an actual profile.")
+ .arg(profileName), profileItem->location());
+ }
+ if (m_localProfiles.contains(profileName)) {
+ throw ErrorInfo(Tr::tr("Local profile '%1' redefined.").arg(profileName),
+ profileItem->location());
+ }
+ m_localProfiles.insert(profileName, values);
+}
+
void ModuleLoader::propagateModulesFromParent(ProductContext *productContext, Item *groupItem,
const ModuleDependencies &reverseDepencencies)
{
diff --git a/src/lib/corelib/language/moduleloader.h b/src/lib/corelib/language/moduleloader.h
index 99b824b57..3d62525aa 100644
--- a/src/lib/corelib/language/moduleloader.h
+++ b/src/lib/corelib/language/moduleloader.h
@@ -327,6 +327,12 @@ private:
QualifiedIdSet gatherModulePropertiesSetInGroup(const Item *group);
Item *loadItemFromFile(const QString &filePath);
+ void handleProfileItems(Item *item, ProjectContext *projectContext);
+ std::vector<Item *> collectProfileItems(Item *item, ProjectContext *projectContext);
+ void evaluateProfileValues(const QualifiedId &namePrefix, Item *item, Item *profileItem,
+ QVariantMap &values);
+ void handleProfile(Item *profileItem);
+
ItemPool *m_pool;
Logger &m_logger;
ProgressObserver *m_progressObserver;
@@ -357,6 +363,7 @@ private:
QHash<QString, QList<ProbeConstPtr>> m_oldProductProbes;
QHash<CodeLocation, QList<ProbeConstPtr>> m_currentProbes;
QVariantMap m_storedProfiles;
+ QVariantMap m_localProfiles;
std::multimap<QString, const ProductContext *> m_productsByName;
SetupProjectParameters m_parameters;
std::unique_ptr<Settings> m_settings;
diff --git a/tests/auto/api/testdata/local-profiles/local-profiles.qbs b/tests/auto/api/testdata/local-profiles/local-profiles.qbs
new file mode 100644
index 000000000..bc37f1229
--- /dev/null
+++ b/tests/auto/api/testdata/local-profiles/local-profiles.qbs
@@ -0,0 +1,44 @@
+import qbs
+
+Project {
+ property string windowsProfile: "windowsProfile"
+ property bool enableProfiles
+ property stringList mingwToolchain: ["mingw", "gcc"]
+ Profile {
+ name: windowsProfile
+ qbs.targetOS: ["windows"]
+ }
+
+ Profile {
+ name: "mingwProfile"
+ condition: enableProfiles
+ baseProfile: project.windowsProfile
+ qbs.toolchain: project.mingwToolchain
+ }
+
+ Application {
+ name: "app"
+ Depends { name: "cpp"; required: false }
+ multiplexByQbsProperties: ["buildVariants", "profiles"]
+ qbs.buildVariants: ["debug", "release"]
+ qbs.profiles: ["mingwProfile"]
+ }
+ DynamicLibrary {
+ name: "lib"
+
+ Depends { name: "cpp"; required: false }
+
+ property stringList clangToolchain: ["clang", "llvm", "gcc"]
+ property string clangProfileName: "clangProfile"
+
+ Profile {
+ name: product.clangProfileName
+ condition: project.enableProfiles
+ qbs.targetOS: ["linux", "unix"]
+ qbs.toolchain: product.clangToolchain
+ }
+
+ multiplexByQbsProperties: ["profiles"]
+ qbs.profiles: ["mingwProfile", "clangProfile"]
+ }
+}
diff --git a/tests/auto/api/tst_api.cpp b/tests/auto/api/tst_api.cpp
index 0b46f04ba..f101bb8e0 100644
--- a/tests/auto/api/tst_api.cpp
+++ b/tests/auto/api/tst_api.cpp
@@ -1489,6 +1489,126 @@ void TestApi::listBuildSystemFiles()
+ "/subproject2/subproject3/subproject3.qbs"));
}
+void TestApi::localProfiles()
+{
+ QFETCH(bool, enableProfiles);
+ qbs::SetupProjectParameters setupParams
+ = defaultSetupParameters("local-profiles/local-profiles.qbs");
+ setupParams.setOverriddenValues(
+ {std::make_pair(QString("project.enableProfiles"), enableProfiles)});
+ QScopedPointer<qbs::SetupProjectJob> job(qbs::Project().setupProject(setupParams,
+ m_logSink, 0));
+ QString taskDescriptions;
+ const auto taskDescHandler = [&taskDescriptions](const QString &desc, int, qbs::AbstractJob *) {
+ taskDescriptions += '\n' + desc;
+ };
+ connect(job.data(), &qbs::AbstractJob::taskStarted, taskDescHandler);
+ waitForFinished(job.data());
+ const QString error = job->error().toString();
+ QVERIFY2(job->error().hasError() == !enableProfiles, qPrintable(error));
+ if (!enableProfiles) {
+ QVERIFY2(error.contains("does not exist"), qPrintable(error));
+ return;
+ }
+ QVERIFY2(taskDescriptions.contains("Resolving"), qPrintable(taskDescriptions));
+
+ qbs::ProjectData project = job->project().projectData();
+ QList<qbs::ProductData> products = project.allProducts();
+ QCOMPARE(products.count(), 4);
+ qbs::ProductData libMingw;
+ qbs::ProductData libClang;
+ qbs::ProductData appDebug;
+ qbs::ProductData appRelease;
+ for (const qbs::ProductData &p : qAsConst(products)) {
+ if (p.name() == "lib") {
+ if (p.profile() == "mingwProfile")
+ libMingw = p;
+ else if (p.profile() == "clangProfile")
+ libClang = p;
+ } else if (p.name() == "app") {
+ const QString buildVariant
+ = p.moduleProperties().getModuleProperty("qbs", "buildVariant").toString();
+ if (buildVariant == "debug")
+ appDebug = p;
+ else if (buildVariant == "release")
+ appRelease = p;
+
+ }
+ }
+ QVERIFY(libMingw.isValid());
+ QVERIFY((libClang.isValid()));
+ QVERIFY(appDebug.isValid());
+ QVERIFY(appRelease.isValid());
+ QCOMPARE(appDebug.profile(), QLatin1String("mingwProfile"));
+ QCOMPARE(appRelease.profile(), QLatin1String("mingwProfile"));
+
+ qbs::PropertyMap moduleProps = libMingw.moduleProperties();
+ QCOMPARE(moduleProps.getModuleProperty("qbs", "targetOS").toStringList(),
+ QStringList({"windows"}));
+ QCOMPARE(moduleProps.getModuleProperty("qbs", "toolchain").toStringList(),
+ QStringList({"mingw", "gcc"}));
+ if (moduleProps.getModuleProperty("cpp", "present").toBool()) {
+ QCOMPARE(moduleProps.getModuleProperty("cpp", "cxxCompilerName").toString(),
+ QString("g++"));
+ }
+ moduleProps = libClang.moduleProperties();
+ QCOMPARE(moduleProps.getModuleProperty("qbs", "targetOS").toStringList(),
+ QStringList({"linux", "unix"}));
+ QCOMPARE(moduleProps.getModuleProperty("qbs", "toolchain").toStringList(),
+ QStringList({"clang", "llvm", "gcc"}));
+ if (moduleProps.getModuleProperty("cpp", "present").toBool()) {
+ QCOMPARE(moduleProps.getModuleProperty("cpp", "cxxCompilerName").toString(),
+ QString("clang++"));
+ }
+ moduleProps = appDebug.moduleProperties();
+ if (moduleProps.getModuleProperty("cpp", "present").toBool())
+ QCOMPARE(moduleProps.getModuleProperty("cpp", "optimization").toString(), QString("none"));
+ moduleProps = appRelease.moduleProperties();
+ if (moduleProps.getModuleProperty("cpp", "present").toBool())
+ QCOMPARE(moduleProps.getModuleProperty("cpp", "optimization").toString(), QString("fast"));
+
+ taskDescriptions.clear();
+ job.reset(qbs::Project().setupProject(setupParams, m_logSink, 0));
+ connect(job.data(), &qbs::AbstractJob::taskStarted, taskDescHandler);
+ waitForFinished(job.data());
+ QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString()));
+ QVERIFY2(!taskDescriptions.contains("Resolving"), qPrintable(taskDescriptions));
+
+ WAIT_FOR_NEW_TIMESTAMP();
+ QFile projectFile(setupParams.projectFilePath());
+ QVERIFY2(projectFile.open(QIODevice::ReadWrite), qPrintable(projectFile.errorString()));
+ QByteArray content = projectFile.readAll();
+ content.replace("\"clang\", \"llvm\", ", QByteArray());
+ projectFile.resize(0);
+ projectFile.write(content);
+ projectFile.close();
+ job.reset(qbs::Project().setupProject(setupParams, m_logSink, 0));
+ waitForFinished(job.data());
+ QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString()));
+ project = job->project().projectData();
+ products = project.allProducts();
+ QCOMPARE(products.count(), 4);
+ int clangProfiles = 0;
+ for (const qbs::ProductData &p : qAsConst(products)) {
+ if (p.profile() == "clangProfile") {
+ ++clangProfiles;
+ moduleProps = p.moduleProperties();
+ if (moduleProps.getModuleProperty("cpp", "present").toBool()) {
+ QCOMPARE(moduleProps.getModuleProperty("cpp", "cxxCompilerName").toString(),
+ QString("g++"));
+ }
+ }
+ }
+ QCOMPARE(clangProfiles, 1);
+}
+
+void TestApi::localProfiles_data()
+{
+ QTest::addColumn<bool>("enableProfiles");
+ QTest::newRow("profiles enabled") << true;
+ QTest::newRow("profiles disabled") << false;
+}
+
void TestApi::missingSourceFile()
{
qbs::SetupProjectParameters setupParams
diff --git a/tests/auto/api/tst_api.h b/tests/auto/api/tst_api.h
index beb0ab4ac..b70c69afb 100644
--- a/tests/auto/api/tst_api.h
+++ b/tests/auto/api/tst_api.h
@@ -100,6 +100,8 @@ private slots:
void linkDynamicAndStaticLibs();
void linkStaticAndDynamicLibs();
void listBuildSystemFiles();
+ void localProfiles();
+ void localProfiles_data();
void missingSourceFile();
void mocCppIncluded();
void multiArch();