summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoerg Bornemann <joerg.bornemann@digia.com>2013-11-14 14:31:13 +0100
committerJoerg Bornemann <joerg.bornemann@digia.com>2013-11-14 14:40:22 +0100
commite91f6b50957c504bd05bba20734c56eb8d6f2f23 (patch)
tree9bd7e563e8530b8db4fb7fdc90b83edfb4f252b3
parent154b78e01ad4fdec9c68ca84b9ac0afd8d5a22e8 (diff)
parent4d97182f31e19881d8246324bc1a119b7d77e28a (diff)
downloadqbs-e91f6b50957c504bd05bba20734c56eb8d6f2f23.tar.gz
Merge remote-tracking branch 'origin/1.1'
Change-Id: I7475c4a71c15c83c59400c44ef96d73d15caea58
-rw-r--r--doc/reference/modules/cpp-module.qdoc20
-rw-r--r--share/qbs/modules/cpp/CppModule.qbs2
-rw-r--r--share/qbs/modules/cpp/GenericGCC.qbs6
-rw-r--r--share/qbs/modules/cpp/msvc.js2
-rw-r--r--share/qbs/modules/cpp/windows-msvc.qbs1
-rw-r--r--src/app/detect-toolchains/probe.cpp9
-rw-r--r--src/lib/buildgraph/buildgraphloader.cpp22
-rw-r--r--src/lib/buildgraph/buildgraphloader.h7
-rw-r--r--src/lib/jsextensions/moduleproperties.cpp22
-rw-r--r--src/lib/jsextensions/moduleproperties.h1
-rw-r--r--src/lib/language/builtindeclarations.cpp5
-rw-r--r--src/lib/language/builtindeclarations.h1
-rw-r--r--src/lib/language/language.cpp50
-rw-r--r--src/lib/language/language.h10
-rw-r--r--src/lib/language/moduleloader.cpp16
-rw-r--r--src/lib/language/projectresolver.cpp10
-rw-r--r--src/lib/language/testdata/Banana1
-rw-r--r--src/lib/language/testdata/erroneous/unknown_item_type.qbs3
-rw-r--r--src/lib/language/testdata/filetags.qbs9
-rw-r--r--src/lib/language/tst_language.cpp3
-rw-r--r--tests/auto/blackbox/testdata/codegen/codegen.qbs6
-rw-r--r--tests/auto/blackbox/testdata/propertyChanges/modules/TestModule/module.qbs28
-rw-r--r--tests/auto/blackbox/testdata/propertyChanges/project.qbs4
-rw-r--r--tests/auto/blackbox/testdata/propertyChanges/ruletest.qbs7
-rw-r--r--tests/auto/blackbox/testdata/propertyChanges/test.in1
-rw-r--r--tests/auto/blackbox/tst_blackbox.cpp73
26 files changed, 281 insertions, 38 deletions
diff --git a/doc/reference/modules/cpp-module.qdoc b/doc/reference/modules/cpp-module.qdoc
index f5a05425f..564ca7e24 100644
--- a/doc/reference/modules/cpp-module.qdoc
+++ b/doc/reference/modules/cpp-module.qdoc
@@ -322,7 +322,7 @@
\row \li \b{Default:} \li determined by qbs-detect-toolchains
\endtable
- Directory where the compiler binary is located. This is set in the build profile.
+ Full path of the compiler binary. This is set in the build profile.
\section2 compilerWrapper
@@ -334,6 +334,24 @@
Wrapper binary and its arguments for wrapping compiler calls.
This is useful for compiler wrappers like ccache and alike.
+ \section2 linkerName
+
+ \table
+ \row \li \b{Type:} \li \c{string}
+ \row \li \b{Default:} \li determined by qbs-detect-toolchains
+ \endtable
+
+ Name of the linker binary. This is set in the build profile.
+
+ \section2 linkerPath
+
+ \table
+ \row \li \b{Type:} \li \c{string}
+ \row \li \b{Default:} \li determined by qbs-detect-toolchains
+ \endtable
+
+ Full path of the linker binary. This is set in the build profile.
+
\section2 supportedStaticLibrarySuffixes
\table
diff --git a/share/qbs/modules/cpp/CppModule.qbs b/share/qbs/modules/cpp/CppModule.qbs
index f6c339d14..ce98fa154 100644
--- a/share/qbs/modules/cpp/CppModule.qbs
+++ b/share/qbs/modules/cpp/CppModule.qbs
@@ -85,6 +85,8 @@ Module {
property string compilerName
property string compilerPath: compilerName
property stringList compilerWrapper
+ property string linkerName
+ property string linkerPath: linkerName
property string staticLibraryPrefix
property string dynamicLibraryPrefix
property string executablePrefix
diff --git a/share/qbs/modules/cpp/GenericGCC.qbs b/share/qbs/modules/cpp/GenericGCC.qbs
index 023708e3a..9bbb152c5 100644
--- a/share/qbs/modules/cpp/GenericGCC.qbs
+++ b/share/qbs/modules/cpp/GenericGCC.qbs
@@ -13,6 +13,7 @@ CppModule {
property string toolchainPrefix
property path toolchainInstallPath
compilerName: 'g++'
+ linkerName: "g++"
property string archiverName: 'ar'
property path sysroot: qbs.sysroot
property path platformPath
@@ -30,6 +31,7 @@ CppModule {
}
compilerPath: toolchainPathPrefix + compilerName
+ linkerPath: toolchainPathPrefix + linkerName
property path archiverPath: { return toolchainPathPrefix + archiverName }
readonly property bool shouldCreateSymlinks: {
@@ -135,7 +137,7 @@ CppModule {
args.push(libFilePath);
args = args.concat(Gcc.libraryLinkerFlags(product, inputs));
args = args.concat(Gcc.additionalCompilerAndLinkerFlags(product));
- var cmd = new Command(ModUtils.moduleProperty(product, "compilerPath"), args);
+ var cmd = new Command(ModUtils.moduleProperty(product, "linkerPath"), args);
cmd.description = 'linking ' + FileInfo.fileName(libFilePath);
cmd.highlight = 'linker';
cmd.responseFileUsagePrefix = '@';
@@ -262,7 +264,7 @@ CppModule {
args = args.concat(Gcc.libraryLinkerFlags(product, inputs));
args = args.concat(Gcc.additionalCompilerAndLinkerFlags(product));
- var cmd = new Command(ModUtils.moduleProperty(product, "compilerPath"), args);
+ var cmd = new Command(ModUtils.moduleProperty(product, "linkerPath"), args);
cmd.description = 'linking ' + FileInfo.fileName(output.fileName);
cmd.highlight = 'linker'
cmd.responseFileUsagePrefix = '@';
diff --git a/share/qbs/modules/cpp/msvc.js b/share/qbs/modules/cpp/msvc.js
index f71b3db99..01986c16e 100644
--- a/share/qbs/modules/cpp/msvc.js
+++ b/share/qbs/modules/cpp/msvc.js
@@ -196,7 +196,7 @@ function prepareLinker(product, inputs, outputs, libraryPaths, dynamicLibraries,
args = args.concat(linkerFlags);
var commands = [];
- var cmd = new Command("link.exe", args)
+ var cmd = new Command(product.moduleProperty("cpp", "linkerPath"), args)
cmd.description = 'linking ' + FileInfo.fileName(primaryOutput.fileName)
cmd.highlight = 'linker';
cmd.workingDirectory = FileInfo.path(primaryOutput.fileName)
diff --git a/share/qbs/modules/cpp/windows-msvc.qbs b/share/qbs/modules/cpp/windows-msvc.qbs
index 944a9e1fc..0c121c820 100644
--- a/share/qbs/modules/cpp/windows-msvc.qbs
+++ b/share/qbs/modules/cpp/windows-msvc.qbs
@@ -17,6 +17,7 @@ CppModule {
compilerDefines: ['_WIN32']
warningLevel: "default"
compilerName: "cl.exe"
+ linkerName: "link.exe"
property bool generateManifestFiles: true
property path toolchainInstallPath
diff --git a/src/app/detect-toolchains/probe.cpp b/src/app/detect-toolchains/probe.cpp
index d7c1530bd..e6b7bb239 100644
--- a/src/app/detect-toolchains/probe.cpp
+++ b/src/app/detect-toolchains/probe.cpp
@@ -203,6 +203,11 @@ static void mingwProbe(Settings *settings, QList<Profile> &profiles)
return;
}
+ QByteArray architecture = gccMachineName.split('-').first();
+ if (architecture == "mingw32")
+ architecture = "x86";
+ else if (architecture == "mingw64")
+ architecture = "x86_64";
Profile profile(QString::fromLocal8Bit(gccMachineName), settings);
qbsInfo() << Tr::tr("Platform '%1' detected in '%2'.").arg(profile.name(), mingwPath);
@@ -210,6 +215,10 @@ static void mingwProbe(Settings *settings, QList<Profile> &profiles)
profile.setValue("cpp.toolchainInstallPath", mingwBinPath);
profile.setValue("cpp.compilerName", QLatin1String("g++.exe"));
profile.setValue("qbs.toolchain", QStringList() << "mingw" << "gcc");
+ profile.setValue(QLatin1String("qbs.architecture"),
+ HostOsInfo::canonicalArchitecture(QString::fromLatin1(architecture)));
+ profile.setValue(QLatin1String("qbs.endianness"),
+ QLatin1String("little"));
profiles << profile;
}
diff --git a/src/lib/buildgraph/buildgraphloader.cpp b/src/lib/buildgraph/buildgraphloader.cpp
index 1ef1f8dcc..7ebca9703 100644
--- a/src/lib/buildgraph/buildgraphloader.cpp
+++ b/src/lib/buildgraph/buildgraphloader.cpp
@@ -205,9 +205,19 @@ void BuildGraphLoader::trackProjectChanges(const SetupProjectParameters &paramet
productsWithChangedFiles);
QSharedPointer<ProjectBuildData> oldBuildData;
+ ChildListHash childLists;
if (!changedProducts.isEmpty() || !productsWithChangedFiles.isEmpty()) {
oldBuildData = QSharedPointer<ProjectBuildData>(
new ProjectBuildData(restoredProject->buildData.data()));
+ foreach (const ResolvedProductConstPtr &product, allRestoredProducts) {
+ if (!product->buildData)
+ continue;
+
+ // If the product gets temporarily removed, its artifacts will get disconnected
+ // and this structural information will no longer be directly available from them.
+ foreach (const Artifact * const a, product->buildData->artifacts)
+ childLists.insert(a, a->children);
+ }
}
// For products with "serious" changes such as different prepare scripts, we set up the
@@ -285,7 +295,7 @@ void BuildGraphLoader::trackProjectChanges(const SetupProjectParameters &paramet
foreach (const ResolvedProductConstPtr &changedProduct, changedProducts) {
rescueOldBuildData(changedProduct, freshProductsByName.value(changedProduct->name),
- oldBuildData.data());
+ oldBuildData.data(), childLists);
}
doSanityChecks(m_result.newlyResolvedProject, m_logger);
@@ -413,6 +423,8 @@ bool BuildGraphLoader::checkProductForChanges(const ResolvedProductPtr &restored
{
return !transformerListsAreEqual(restoredProduct->transformers,
newlyResolvedProduct->transformers)
+ || !ruleListsAreEqual(restoredProduct->rules.toList(),
+ newlyResolvedProduct->rules.toList())
|| !dependenciesAreEqual(restoredProduct, newlyResolvedProduct)
|| checkForPropertyChanges(restoredProduct, newlyResolvedProduct);
// TODO: Check for more stuff.
@@ -698,7 +710,7 @@ static bool commandsEqual(const TransformerConstPtr &t1, const TransformerConstP
*/
void BuildGraphLoader::rescueOldBuildData(const ResolvedProductConstPtr &restoredProduct,
const ResolvedProductPtr &newlyResolvedProduct,
- const ProjectBuildData *oldBuildData)
+ const ProjectBuildData *oldBuildData, const ChildListHash &childLists)
{
if (!restoredProduct->enabled || !newlyResolvedProduct->enabled)
return;
@@ -731,11 +743,7 @@ void BuildGraphLoader::rescueOldBuildData(const ResolvedProductConstPtr &restore
}
artifact->setTimestamp(oldArtifact->timestamp());
- foreach (Artifact * const oldChild, oldArtifact->children) {
- // skip transform edges
- if (oldArtifact->transformer->inputs.contains(oldChild))
- continue;
-
+ foreach (Artifact * const oldChild, childLists.value(oldArtifact)) {
foreach (FileResourceBase *childFileRes,
newlyResolvedProduct->topLevelProject()->buildData->lookupFiles(oldChild)) {
Artifact * const child = dynamic_cast<Artifact *>(childFileRes);
diff --git a/src/lib/buildgraph/buildgraphloader.h b/src/lib/buildgraph/buildgraphloader.h
index f13749f26..4806daad3 100644
--- a/src/lib/buildgraph/buildgraphloader.h
+++ b/src/lib/buildgraph/buildgraphloader.h
@@ -31,6 +31,7 @@
#include "forward_decls.h"
+#include <buildgraph/artifactlist.h>
#include <language/forward_decls.h>
#include <logging/logger.h>
@@ -41,7 +42,6 @@ namespace qbs {
class SetupProjectParameters;
namespace Internal {
-class ArtifactList;
class FileDependency;
class FileResourceBase;
class FileTime;
@@ -97,9 +97,12 @@ private:
const PropertyMapConstPtr &newProperties);
void replaceFileDependencyWithArtifact(const ResolvedProductPtr &fileDepProduct,
FileDependency *filedep, Artifact *artifact);
+
+ typedef QHash<const Artifact *, ArtifactList> ChildListHash;
void rescueOldBuildData(const ResolvedProductConstPtr &restoredProduct,
const ResolvedProductPtr &newlyResolvedProduct,
- const ProjectBuildData *oldBuildData);
+ const ProjectBuildData *oldBuildData,
+ const ChildListHash &childLists);
RulesEvaluationContextPtr m_evalContext;
BuildGraphLoadResult m_result;
diff --git a/src/lib/jsextensions/moduleproperties.cpp b/src/lib/jsextensions/moduleproperties.cpp
index 0f2833754..cc9102b73 100644
--- a/src/lib/jsextensions/moduleproperties.cpp
+++ b/src/lib/jsextensions/moduleproperties.cpp
@@ -33,6 +33,7 @@
#include <language/language.h>
#include <language/scriptengine.h>
#include <logging/translator.h>
+#include <tools/error.h>
#include <tools/propertyfinder.h>
#include <QScriptEngine>
@@ -70,12 +71,20 @@ void ModuleProperties::init(QScriptValue objectWithProperties, const void *ptr,
QScriptValue ModuleProperties::js_moduleProperties(QScriptContext *context, QScriptEngine *engine)
{
- return moduleProperties(context, engine, false);
+ try {
+ return moduleProperties(context, engine, false);
+ } catch (const ErrorInfo &e) {
+ return context->throwError(e.toString());
+ }
}
QScriptValue ModuleProperties::js_moduleProperty(QScriptContext *context, QScriptEngine *engine)
{
- return moduleProperties(context, engine, true);
+ try {
+ return moduleProperties(context, engine, true);
+ } catch (const ErrorInfo &e) {
+ return context->throwError(e.toString());
+ }
}
QScriptValue ModuleProperties::moduleProperties(QScriptContext *context, QScriptEngine *engine,
@@ -112,7 +121,7 @@ QScriptValue ModuleProperties::moduleProperties(QScriptContext *context, QScript
}
ScriptEngine * const qbsEngine = static_cast<ScriptEngine *>(engine);
- const QString moduleName = context->argument(0).toString();
+ const QString moduleName = internalModuleName(context->argument(0).toString());
const QString propertyName = context->argument(1).toString();
QVariant value = qbsEngine->retrieveFromPropertyCache(moduleName, propertyName, properties);
@@ -134,5 +143,12 @@ QScriptValue ModuleProperties::moduleProperties(QScriptContext *context, QScript
return engine->toScriptValue(value);
}
+QString ModuleProperties::internalModuleName(const QString &name)
+{
+ QString result = name;
+ result.replace(QLatin1Char('.'), QLatin1Char('/'));
+ return result;
+}
+
} // namespace Internal
} // namespace qbs
diff --git a/src/lib/jsextensions/moduleproperties.h b/src/lib/jsextensions/moduleproperties.h
index 644f5f25c..9032d83ee 100644
--- a/src/lib/jsextensions/moduleproperties.h
+++ b/src/lib/jsextensions/moduleproperties.h
@@ -53,6 +53,7 @@ private:
static QScriptValue moduleProperties(QScriptContext *context, QScriptEngine *engine,
bool oneValue);
+ static QString internalModuleName(const QString &name);
};
} // namespace Internal
diff --git a/src/lib/language/builtindeclarations.cpp b/src/lib/language/builtindeclarations.cpp
index 87beda2fd..ebc876b60 100644
--- a/src/lib/language/builtindeclarations.cpp
+++ b/src/lib/language/builtindeclarations.cpp
@@ -124,6 +124,11 @@ QByteArray BuiltinDeclarations::qmlTypeInfo() const
return result;
}
+bool BuiltinDeclarations::containsType(const QString &typeName) const
+{
+ return m_builtins.contains(typeName);
+}
+
QList<PropertyDeclaration> BuiltinDeclarations::declarationsForType(const QString &typeName) const
{
return m_builtins.value(typeName);
diff --git a/src/lib/language/builtindeclarations.h b/src/lib/language/builtindeclarations.h
index 1f0c26e69..4cbd352a7 100644
--- a/src/lib/language/builtindeclarations.h
+++ b/src/lib/language/builtindeclarations.h
@@ -47,6 +47,7 @@ public:
QString languageVersion() const;
QByteArray qmlTypeInfo() const;
+ bool containsType(const QString &typeName) const;
QList<PropertyDeclaration> declarationsForType(const QString &typeName) const;
void setupItemForBuiltinType(qbs::Internal::Item *item) const;
diff --git a/src/lib/language/language.cpp b/src/lib/language/language.cpp
index 131b5e4b4..9241af3da 100644
--- a/src/lib/language/language.cpp
+++ b/src/lib/language/language.cpp
@@ -1015,6 +1015,7 @@ template<typename T> bool listsAreEqual(const QList<T> &l1, const QList<T> &l2)
QString keyFromElem(const SourceArtifactPtr &sa) { return sa->absoluteFilePath; }
QString keyFromElem(const ResolvedTransformerConstPtr &t) { return t->transform->sourceCode; }
+QString keyFromElem(const RulePtr &r) { return r->toString(); }
bool operator==(const SourceArtifact &sa1, const SourceArtifact &sa2)
{
@@ -1048,5 +1049,54 @@ bool transformerListsAreEqual(const QList<ResolvedTransformerConstPtr> &l1,
return listsAreEqual(l1, l2);
}
+bool operator==(const Rule &r1, const Rule &r2)
+{
+ if (&r1 == &r2)
+ return true;
+ if (!&r1 != !&r2)
+ return false;
+ if (r1.artifacts.count() != r2.artifacts.count())
+ return false;
+ for (int i = 0; i < r1.artifacts.count(); ++i) {
+ if (*r1.artifacts.at(i) != *r2.artifacts.at(i))
+ return false;
+ }
+
+ return r1.module->name == r2.module->name
+ && r1.script->sourceCode == r2.script->sourceCode
+ && r1.inputs == r2.inputs
+ && r1.auxiliaryInputs == r2.auxiliaryInputs
+ && r1.usings == r2.usings
+ && r1.explicitlyDependsOn == r2.explicitlyDependsOn
+ && r1.multiplex == r2.multiplex;
+}
+
+bool ruleListsAreEqual(const QList<RulePtr> &l1, const QList<RulePtr> &l2)
+{
+ return listsAreEqual(l1, l2);
+}
+
+bool operator==(const RuleArtifact &a1, const RuleArtifact &a2)
+{
+ if (&a1 == &a2)
+ return true;
+ if (!&a1 != !&a2)
+ return false;
+ return a1.fileName == a2.fileName
+ && a1.fileTags == a2.fileTags
+ && a1.alwaysUpdated == a2.alwaysUpdated
+ && a1.bindings.toList().toSet() == a2.bindings.toList().toSet();
+}
+
+bool operator==(const RuleArtifact::Binding &b1, const RuleArtifact::Binding &b2)
+{
+ return b1.code == b2.code && b1.name == b2.name;
+}
+
+uint qHash(const RuleArtifact::Binding &b)
+{
+ return qHash(qMakePair(b.code, b.name.join(QLatin1String(","))));
+}
+
} // namespace Internal
} // namespace qbs
diff --git a/src/lib/language/language.h b/src/lib/language/language.h
index 98bf2f7f1..a41f1f948 100644
--- a/src/lib/language/language.h
+++ b/src/lib/language/language.h
@@ -113,6 +113,13 @@ private:
void load(PersistentPool &pool);
void store(PersistentPool &pool) const;
};
+uint qHash(const RuleArtifact::Binding &b);
+bool operator==(const RuleArtifact::Binding &b1, const RuleArtifact::Binding &b2);
+inline bool operator!=(const RuleArtifact::Binding &b1, const RuleArtifact::Binding &b2) {
+ return !(b1 == b2);
+}
+bool operator==(const RuleArtifact &a1, const RuleArtifact &a2);
+inline bool operator!=(const RuleArtifact &a1, const RuleArtifact &a2) { return !(a1 == a2); }
class SourceArtifact : public PersistentObject
{
@@ -289,6 +296,9 @@ private:
void load(PersistentPool &pool);
void store(PersistentPool &pool) const;
};
+bool operator==(const Rule &r1, const Rule &r2);
+inline bool operator!=(const Rule &r1, const Rule &r2) { return !(r1 == r2); }
+bool ruleListsAreEqual(const QList<RulePtr> &l1, const QList<RulePtr> &l2);
class ResolvedTransformer : public PersistentObject
{
diff --git a/src/lib/language/moduleloader.cpp b/src/lib/language/moduleloader.cpp
index c5d722710..c26e55d76 100644
--- a/src/lib/language/moduleloader.cpp
+++ b/src/lib/language/moduleloader.cpp
@@ -125,14 +125,17 @@ ModuleLoaderResult ModuleLoader::load(const QString &filePath,
class PropertyDeclarationCheck : public ValueHandler
{
+ const BuiltinDeclarations *m_builtins;
const QHash<Item *, QSet<QString> > &m_validItemPropertyNamesPerItem;
const QSet<Item *> &m_disabledItems;
Item *m_parentItem;
QString m_currentName;
public:
- PropertyDeclarationCheck(const QHash<Item *, QSet<QString> > &validItemPropertyNamesPerItem,
+ PropertyDeclarationCheck(const BuiltinDeclarations *builtins,
+ const QHash<Item *, QSet<QString> > &validItemPropertyNamesPerItem,
const QSet<Item *> &disabledItems)
- : m_validItemPropertyNamesPerItem(validItemPropertyNamesPerItem)
+ : m_builtins(builtins)
+ , m_validItemPropertyNamesPerItem(validItemPropertyNamesPerItem)
, m_disabledItems(disabledItems)
, m_parentItem(0)
{
@@ -169,6 +172,12 @@ private:
void handleItem(Item *item)
{
+ if (Q_UNLIKELY(!item->typeName().isEmpty()
+ && !m_builtins->containsType(item->typeName()))) {
+ const QString msg = Tr::tr("Unexpected item type '%1'.");
+ throw ErrorInfo(msg.arg(item->typeName()), item->location());
+ }
+
if (m_disabledItems.contains(item) || item->typeName() == QLatin1String("SubProject"))
return;
@@ -249,7 +258,8 @@ void ModuleLoader::handleProject(ModuleLoaderResult *loadResult, Item *item,
}
}
- PropertyDeclarationCheck check(m_validItemPropertyNamesPerItem, m_disabledItems);
+ PropertyDeclarationCheck check(m_reader->builtins(), m_validItemPropertyNamesPerItem,
+ m_disabledItems);
check(item);
m_reader->popExtraSearchPaths();
diff --git a/src/lib/language/projectresolver.cpp b/src/lib/language/projectresolver.cpp
index af6f0a164..b71f16f2f 100644
--- a/src/lib/language/projectresolver.cpp
+++ b/src/lib/language/projectresolver.cpp
@@ -840,13 +840,14 @@ void ProjectResolver::applyFileTaggers(const SourceArtifactPtr &artifact,
const ResolvedProductConstPtr &product) const
{
if (!artifact->overrideFileTags || artifact->fileTags.isEmpty()) {
- const FileTags fileTags = product->fileTagsForFileName(artifact->absoluteFilePath);
+ const QString fileName = FileInfo::fileName(artifact->absoluteFilePath);
+ const FileTags fileTags = product->fileTagsForFileName(fileName);
artifact->fileTags.unite(fileTags);
if (artifact->fileTags.isEmpty())
artifact->fileTags.insert(unknownFileTag());
if (m_logger.traceEnabled())
m_logger.qbsTrace() << "[PR] adding file tags " << artifact->fileTags
- << " to " << FileInfo::fileName(artifact->absoluteFilePath);
+ << " to " << fileName;
}
}
@@ -974,10 +975,7 @@ void ProjectResolver::callItemFunction(const ItemFuncMap &mappings, Item *item,
{
const QByteArray typeName = item->typeName().toLocal8Bit();
ItemFuncPtr f = mappings.value(typeName);
- if (Q_UNLIKELY(!f)) {
- const QString msg = Tr::tr("Unexpected item type '%1'.");
- throw ErrorInfo(msg.arg(item->typeName()), item->location());
- }
+ QBS_CHECK(f);
if (typeName == "Project") {
ProjectContext subProjectContext = createProjectContext(projectContext);
(this->*f)(item, &subProjectContext);
diff --git a/src/lib/language/testdata/Banana b/src/lib/language/testdata/Banana
new file mode 100644
index 000000000..53164be8a
--- /dev/null
+++ b/src/lib/language/testdata/Banana
@@ -0,0 +1 @@
+Peanut butter jelly time!
diff --git a/src/lib/language/testdata/erroneous/unknown_item_type.qbs b/src/lib/language/testdata/erroneous/unknown_item_type.qbs
new file mode 100644
index 000000000..9e34e9243
--- /dev/null
+++ b/src/lib/language/testdata/erroneous/unknown_item_type.qbs
@@ -0,0 +1,3 @@
+Narf {
+ zort: 1 // This invalid binding should not hide the "Unexpected item type" error.
+}
diff --git a/src/lib/language/testdata/filetags.qbs b/src/lib/language/testdata/filetags.qbs
index 97cccd510..38182e5f1 100644
--- a/src/lib/language/testdata/filetags.qbs
+++ b/src/lib/language/testdata/filetags.qbs
@@ -21,6 +21,15 @@ Project {
}
Product {
+ name: "filetagger_static_pattern"
+ files: "Banana"
+ FileTagger {
+ patterns: "Banana"
+ fileTags: ["yellow"]
+ }
+ }
+
+ Product {
name: "unknown_file_tag"
files: "narf.zort"
}
diff --git a/src/lib/language/tst_language.cpp b/src/lib/language/tst_language.cpp
index 268711ab0..bb984c3fc 100644
--- a/src/lib/language/tst_language.cpp
+++ b/src/lib/language/tst_language.cpp
@@ -347,6 +347,8 @@ void TestLanguage::erroneousFiles_data()
<< "Item 'cpp' is not declared.";
QTest::newRow("undeclared_property")
<< "Property 'doesntexist' is not declared.";
+ QTest::newRow("unknown_item_type")
+ << "Unexpected item type 'Narf'";
}
void TestLanguage::erroneousFiles()
@@ -1154,6 +1156,7 @@ void TestLanguage::fileTags_data()
QTest::newRow("init") << 0 << QStringList();
QTest::newRow("filetagger_project_scope") << 1 << (QStringList() << "cpp");
QTest::newRow("filetagger_product_scope") << 1 << (QStringList() << "asm");
+ QTest::newRow("filetagger_static_pattern") << 1 << (QStringList() << "yellow");
QTest::newRow("unknown_file_tag") << 1 << (QStringList() << "unknown-file-tag");
QTest::newRow("set_file_tag_via_group") << 2 << (QStringList() << "c++");
QTest::newRow("override_file_tag_via_group") << 2 << (QStringList() << "c++");
diff --git a/tests/auto/blackbox/testdata/codegen/codegen.qbs b/tests/auto/blackbox/testdata/codegen/codegen.qbs
index d7210e21c..bb71a5540 100644
--- a/tests/auto/blackbox/testdata/codegen/codegen.qbs
+++ b/tests/auto/blackbox/testdata/codegen/codegen.qbs
@@ -18,6 +18,7 @@ Project {
fileTags: ['text']
}
Depends { name: 'cpp' }
+ Depends { name: 'Qt.core' }
}
Rule {
@@ -40,6 +41,11 @@ Project {
return str;
}
+ // check whether multipart module name translation is working
+ var actual = product.moduleProperty("Qt.core", "mocName");
+ if (!actual || !actual.contains("moc"))
+ throw "multipart module name translation is broken";
+
// check whether we can access project properties here
var expected = "CODEGEN_" + product.moduleProperty("qbs", "targetOS")[0].toUpperCase();
if (project.osSpecificName !== expected)
diff --git a/tests/auto/blackbox/testdata/propertyChanges/modules/TestModule/module.qbs b/tests/auto/blackbox/testdata/propertyChanges/modules/TestModule/module.qbs
new file mode 100644
index 000000000..ef14d3f47
--- /dev/null
+++ b/tests/auto/blackbox/testdata/propertyChanges/modules/TestModule/module.qbs
@@ -0,0 +1,28 @@
+import qbs
+import qbs.File
+
+Module {
+ FileTagger {
+ pattern: "*.in"
+ fileTags: "test-input"
+ }
+
+ Rule {
+ inputs: ['test-input']
+ Artifact {
+ fileTags: "test-output"
+ fileName: input.fileName + ".out"
+ }
+
+ prepare: {
+ var cmd = new JavaScriptCommand();
+ cmd.highlight = "codegen";
+ cmd.description = "Making output from input";
+ cmd.sourceCode = function() {
+ // print('Change in source code');
+ File.copy(input.fileName, output.fileName);
+ }
+ return cmd;
+ }
+ }
+}
diff --git a/tests/auto/blackbox/testdata/propertyChanges/project.qbs b/tests/auto/blackbox/testdata/propertyChanges/project.qbs
index d1f0ab5ee..b2de04e84 100644
--- a/tests/auto/blackbox/testdata/propertyChanges/project.qbs
+++ b/tests/auto/blackbox/testdata/propertyChanges/project.qbs
@@ -44,4 +44,8 @@ Project {
}
}
}
+
+ references: "ruletest.qbs"
+
+ qbsSearchPaths: "."
}
diff --git a/tests/auto/blackbox/testdata/propertyChanges/ruletest.qbs b/tests/auto/blackbox/testdata/propertyChanges/ruletest.qbs
new file mode 100644
index 000000000..02088da7b
--- /dev/null
+++ b/tests/auto/blackbox/testdata/propertyChanges/ruletest.qbs
@@ -0,0 +1,7 @@
+import qbs
+
+Product {
+ type: "test-output"
+ Depends { name: "TestModule" }
+ files: "test.in"
+}
diff --git a/tests/auto/blackbox/testdata/propertyChanges/test.in b/tests/auto/blackbox/testdata/propertyChanges/test.in
new file mode 100644
index 000000000..8633abf18
--- /dev/null
+++ b/tests/auto/blackbox/testdata/propertyChanges/test.in
@@ -0,0 +1 @@
+blubb
diff --git a/tests/auto/blackbox/tst_blackbox.cpp b/tests/auto/blackbox/tst_blackbox.cpp
index 30b62dc41..0700df165 100644
--- a/tests/auto/blackbox/tst_blackbox.cpp
+++ b/tests/auto/blackbox/tst_blackbox.cpp
@@ -1055,41 +1055,45 @@ void TestBlackbox::propertyChanges()
{
QDir::setCurrent(testDataDir + "/propertyChanges");
QFile projectFile("project.qbs");
+ QbsRunParameters params(QStringList() << "-f" << "project.qbs");
// Initial build.
- QCOMPARE(runQbs(), 0);
+ QCOMPARE(runQbs(params), 0);
QVERIFY(m_qbsStdout.contains("compiling source1.cpp"));
QVERIFY(m_qbsStdout.contains("compiling source2.cpp"));
QVERIFY(m_qbsStdout.contains("compiling source3.cpp"));
QVERIFY(m_qbsStdout.contains("compiling lib.cpp"));
QVERIFY(m_qbsStdout.contains("linking product 1.debug"));
QVERIFY(m_qbsStdout.contains("generated.txt"));
+ QVERIFY(m_qbsStdout.contains("Making output from input"));
QFile generatedFile(buildDir + QLatin1String("/generated.txt"));
QVERIFY(generatedFile.open(QIODevice::ReadOnly));
QCOMPARE(generatedFile.readAll(), QByteArray("contents 1"));
generatedFile.close();
// Incremental build with no changes.
- QCOMPARE(runQbs(), 0);
+ QCOMPARE(runQbs(params), 0);
QVERIFY(!m_qbsStdout.contains("compiling source1.cpp"));
QVERIFY(!m_qbsStdout.contains("compiling source2.cpp"));
QVERIFY(!m_qbsStdout.contains("compiling source3.cpp"));
QVERIFY(!m_qbsStdout.contains("compiling lib.cpp.cpp"));
QVERIFY(!m_qbsStdout.contains("linking"));
QVERIFY(!m_qbsStdout.contains("generated.txt"));
+ QVERIFY(!m_qbsStdout.contains("Making output from input"));
// Incremental build with no changes, but updated project file timestamp.
waitForNewTimestamp();
QVERIFY(projectFile.open(QIODevice::ReadWrite | QIODevice::Append));
projectFile.write("\n");
projectFile.close();
- QCOMPARE(runQbs(), 0);
+ QCOMPARE(runQbs(params), 0);
QVERIFY(!m_qbsStdout.contains("compiling source1.cpp"));
QVERIFY(!m_qbsStdout.contains("compiling source2.cpp"));
QVERIFY(!m_qbsStdout.contains("compiling source3.cpp"));
QVERIFY(!m_qbsStdout.contains("compiling lib.cpp"));
QVERIFY(!m_qbsStdout.contains("linking"));
QVERIFY(!m_qbsStdout.contains("generated.txt"));
+ QVERIFY(!m_qbsStdout.contains("Making output from input"));
// Incremental build, input property changed for first product
waitForNewTimestamp();
@@ -1099,13 +1103,14 @@ void TestBlackbox::propertyChanges()
projectFile.resize(0);
projectFile.write(contents);
projectFile.close();
- QCOMPARE(runQbs(), 0);
+ QCOMPARE(runQbs(params), 0);
QVERIFY(m_qbsStdout.contains("compiling source1.cpp"));
QVERIFY(m_qbsStdout.contains("linking product 1.debug"));
QVERIFY(!m_qbsStdout.contains("linking product 2"));
QVERIFY(!m_qbsStdout.contains("linking product 3"));
QVERIFY(!m_qbsStdout.contains("linking library"));
QVERIFY(!m_qbsStdout.contains("generated.txt"));
+ QVERIFY(!m_qbsStdout.contains("Making output from input"));
// Incremental build, input property changed via project for second product.
waitForNewTimestamp();
@@ -1115,26 +1120,29 @@ void TestBlackbox::propertyChanges()
projectFile.resize(0);
projectFile.write(contents);
projectFile.close();
- QCOMPARE(runQbs(), 0);
+ QCOMPARE(runQbs(params), 0);
QVERIFY(!m_qbsStdout.contains("linking product 1"));
QVERIFY(m_qbsStdout.contains("compiling source2.cpp"));
QVERIFY(!m_qbsStdout.contains("linking product 3"));
QVERIFY(!m_qbsStdout.contains("generated.txt"));
+ QVERIFY(!m_qbsStdout.contains("Making output from input"));
// Incremental build, input property changed via command line for second product.
- QCOMPARE(runQbs(QbsRunParameters(QLatin1String("project.projectDefines:blubb002"))), 0);
+ params.arguments << "project.projectDefines:blubb002";
+ QCOMPARE(runQbs(params), 0);
QVERIFY(!m_qbsStdout.contains("linking product 1"));
QVERIFY(m_qbsStdout.contains("compiling source2.cpp"));
QVERIFY(!m_qbsStdout.contains("linking product 3"));
QVERIFY(!m_qbsStdout.contains("generated.txt"));
- QCOMPARE(runQbs(), 0);
+ params.arguments.removeLast();
+ QCOMPARE(runQbs(params), 0);
QVERIFY(!m_qbsStdout.contains("linking product 1"));
QVERIFY(m_qbsStdout.contains("compiling source2.cpp"));
QVERIFY(!m_qbsStdout.contains("linking product 3"));
QVERIFY(!m_qbsStdout.contains("generated.txt"));
+ QVERIFY(!m_qbsStdout.contains("Making output from input"));
// Incremental build, input property changed via environment for third product.
- QbsRunParameters params;
params.environment.insert("QBS_BLACKBOX_DEFINE", "newvalue");
QCOMPARE(runQbs(params), 0);
QVERIFY(!m_qbsStdout.contains("linking product 1"));
@@ -1147,21 +1155,25 @@ void TestBlackbox::propertyChanges()
QVERIFY(!m_qbsStdout.contains("linking product 2"));
QVERIFY(m_qbsStdout.contains("compiling source3.cpp"));
QVERIFY(!m_qbsStdout.contains("generated.txt"));
+ QVERIFY(!m_qbsStdout.contains("Making output from input"));
// Incremental build, module property changed via command line.
- QCOMPARE(runQbs(QbsRunParameters(QLatin1String("qbs.enableDebugCode:false"))), 0);
+ params.arguments << "qbs.enableDebugCode:false";
+ QCOMPARE(runQbs(params), 0);
QVERIFY(m_qbsStdout.contains("compiling source1.cpp"));
QVERIFY(m_qbsStdout.contains("linking product 1.release"));
QVERIFY(m_qbsStdout.contains("compiling source2.cpp"));
QVERIFY(m_qbsStdout.contains("compiling source3.cpp"));
QVERIFY(m_qbsStdout.contains("compiling lib.cpp"));
QVERIFY(!m_qbsStdout.contains("generated.txt"));
- QCOMPARE(runQbs(), 0);
+ params.arguments.removeLast();
+ QCOMPARE(runQbs(params), 0);
QVERIFY(m_qbsStdout.contains("compiling source1.cpp"));
QVERIFY(m_qbsStdout.contains("linking product 1.debug"));
QVERIFY(m_qbsStdout.contains("compiling source2.cpp"));
QVERIFY(m_qbsStdout.contains("compiling source3.cpp"));
QVERIFY(!m_qbsStdout.contains("generated.txt"));
+ QVERIFY(!m_qbsStdout.contains("Making output from input"));
// Incremental build, non-essential dependency removed.
waitForNewTimestamp();
@@ -1171,12 +1183,13 @@ void TestBlackbox::propertyChanges()
projectFile.resize(0);
projectFile.write(contents);
projectFile.close();
- QCOMPARE(runQbs(), 0);
+ QCOMPARE(runQbs(params), 0);
QVERIFY(!m_qbsStdout.contains("linking product 1"));
QVERIFY(m_qbsStdout.contains("linking product 2"));
QVERIFY(!m_qbsStdout.contains("linking product 3"));
QVERIFY(!m_qbsStdout.contains("linking library"));
QVERIFY(!m_qbsStdout.contains("generated.txt"));
+ QVERIFY(!m_qbsStdout.contains("Making output from input"));
// Incremental build, prepare script of a transformer changed.
waitForNewTimestamp();
@@ -1186,15 +1199,49 @@ void TestBlackbox::propertyChanges()
projectFile.resize(0);
projectFile.write(contents);
projectFile.close();
- QCOMPARE(runQbs(), 0);
+ QCOMPARE(runQbs(params), 0);
QVERIFY(!m_qbsStdout.contains("compiling source1.cpp"));
QVERIFY(!m_qbsStdout.contains("compiling source2.cpp"));
QVERIFY(!m_qbsStdout.contains("compiling source3.cpp"));
QVERIFY(!m_qbsStdout.contains("compiling lib.cpp"));
QVERIFY(m_qbsStdout.contains("generated.txt"));
+ QVERIFY(!m_qbsStdout.contains("Making output from input"));
QVERIFY(generatedFile.open(QIODevice::ReadOnly));
QCOMPARE(generatedFile.readAll(), QByteArray("contents 2"));
generatedFile.close();
+
+ // Incremental build, prepare script of a rule in a module changed.
+ waitForNewTimestamp();
+ QFile moduleFile("modules/TestModule/module.qbs");
+ QVERIFY(moduleFile.open(QIODevice::ReadWrite));
+ contents = moduleFile.readAll();
+ contents.replace("// print('Change in source code')", "print('Change in source code')");
+ moduleFile.resize(0);
+ moduleFile.write(contents);
+ moduleFile.close();
+ QCOMPARE(runQbs(params), 0);
+ QVERIFY(!m_qbsStdout.contains("compiling source1.cpp"));
+ QVERIFY(!m_qbsStdout.contains("compiling source2.cpp"));
+ QVERIFY(!m_qbsStdout.contains("compiling source3.cpp"));
+ QVERIFY(!m_qbsStdout.contains("compiling lib.cpp"));
+ QVERIFY(!m_qbsStdout.contains("generated.txt"));
+ QVERIFY(m_qbsStdout.contains("Making output from input"));
+
+ // Incremental build, irrelevant file tag of a rule in a module changed.
+ waitForNewTimestamp();
+ QVERIFY(moduleFile.open(QIODevice::ReadWrite));
+ contents = moduleFile.readAll();
+ contents.replace("inputs: ['test-input']", "inputs: ['test-input', 'hupe']");
+ moduleFile.resize(0);
+ moduleFile.write(contents);
+ moduleFile.close();
+ QCOMPARE(runQbs(params), 0);
+ QVERIFY(!m_qbsStdout.contains("compiling source1.cpp"));
+ QVERIFY(!m_qbsStdout.contains("compiling source2.cpp"));
+ QVERIFY(!m_qbsStdout.contains("compiling source3.cpp"));
+ QVERIFY(!m_qbsStdout.contains("compiling lib.cpp"));
+ QVERIFY(!m_qbsStdout.contains("generated.txt"));
+ QVERIFY(!m_qbsStdout.contains("Making output from input"));
}
void TestBlackbox::disabledProduct()
@@ -1480,7 +1527,7 @@ void TestBlackbox::testAssembly()
{
SettingsPtr settings = qbsSettings();
Profile profile(buildProfileName, settings.data());
- bool haveGcc = profile.value("qbs.toolchain").toString().contains("gcc");
+ bool haveGcc = profile.value("qbs.toolchain").toStringList().contains("gcc");
QDir::setCurrent(testDataDir + "/assembly");
QVERIFY(runQbs() == 0);
QCOMPARE((bool)m_qbsStdout.contains("compiling testa.s"), haveGcc);