diff options
| author | Joerg Bornemann <joerg.bornemann@digia.com> | 2013-08-02 13:57:26 +0200 |
|---|---|---|
| committer | Joerg Bornemann <joerg.bornemann@digia.com> | 2013-11-27 11:49:01 +0100 |
| commit | 006824f89c4f298f19c45f4f4585b4452cd2d2b9 (patch) | |
| tree | 0007c73137e7d167cefa4e5611a01803e69fa5fd /src/lib/language | |
| parent | dbb39fc1fce3686a5161d68e89e96086fc664556 (diff) | |
| download | qbs-006824f89c4f298f19c45f4f4585b4452cd2d2b9.tar.gz | |
introduce class BuildGraphNodedynablaster
To support different types of nodes in the build graph, we introduce
the base class BuildGraphNode. Artifact now derives from BuildGraphNode.
A - yet unused - RuleNode class is introduced that represents a rule in
the build graph.
Change-Id: Ie1ad5e7a9e65bfd5f99d3e824737516053de0f94
***new artifacts hash in ProductBuildData
Change-Id: I50521ec64f734bfb3662759076fa5e7912ac084e
***automoc fixup
Change-Id: Ie2bb228ae38d63deccc600d67d283bc3beda9fec
slightly nicer rule debug output
Change-Id: I60ddef73cd7f0a67055f2d56e6dbe7fa45ddd450
create RuleNode objects and add them to roots
Change-Id: I51a0f89b98cda524d34888ab758d7bd397d82f00
***execute rule nodes on build
Change-Id: I291c32868cd982e37393d6bc8d696f2b63fbff50
***ArtifactSet::fromNodeSet
Change-Id: I7586bcfbe43406c22b1ee1a1fd826beaa247164f
***update after rebase
Change-Id: I5f73afc80b746b11eeb83aeadf29c2358accbab8
***phonytarget
Change-Id: I587b7e072e54b866e8d5ea37c874e6a8baa550e0
update after rebase
Change-Id: I6017c0cbe9244fea04d513f53e3a2a85092bf962
skip nodes early
We must skip Building and Built nodes.
m_leaves can contain duplicates now.
Change-Id: If275106a47c403a455103f4deeb20049548007f5
debug message
Change-Id: I90e238eef72a8a02fb0a9f2c77715f5f15c1442d
disable phony thingy
Change-Id: I7bb60b850b96b65ab738c11e96c3a84cbe58d2f7
connect each output of a rule to the rule itself
Change-Id: I159d76c4b63094058cc9a07ccc2d0b67c7ce06e6
TagScanner
Change-Id: I4741e48cd674c0ca830ee1b4d05b59a8c542694f
TagScanner deps
Change-Id: If3e43a7ac25616cd151229684a085ac8ee787645
update after rebase
Change-Id: I58d49a5ed1049a17733fc2154588f12c1cda53e6
only root tag scanners in product
Change-Id: Ia94732a5632156a5ec3c5518c9596cd4cefac105
run TagScanners
Change-Id: I869a183f2da23a43957a6df45dc5a1b30b10af92
TagScannerRunner
Change-Id: Id3c5fac73e6fb84e56d6ab1d48a959f3677f7a67
crash fix
Change-Id: Ie3c26dbed41ab4615915a08913c495868c3a8910
more TagScanRunner
Change-Id: I80b79f101c0f4d802fb4f6515c0848e369fed066
handle removal of filetags
Change-Id: Icdd8d05c2e26953f7b12d968aa5dfcc23928b9ba
Qt4 build fix
Change-Id: Ie5fcb64e36ddc5004003183bea7243536bc8ab15
do not waste space with type information
Change-Id: I7b9354e6fceead228ba335723b9addeb701bef56
update nodes that must get new transformers
Change-Id: I06cd7ffe606ae643393350c5959ef6475343929f
update after rebase
Change-Id: If080e664972f2950c12fd800a3e4b521e65dca3a
only run tag scanners on changed sources
And do not call RulesApplicator in bgloader.
Change-Id: I5140c91c79a842dab933ad7b328100bdec13cb10
Conflicts:
src/lib/buildgraph/buildgraphloader.cpp
sketch of moc tagscanners impl
Change-Id: I7736c2da1b1742bc3556ef660c163e6c32cbd4c9
Conflicts:
share/qbs/modules/Qt/core/core.qbs
MocTagScanner
Change-Id: I87199e8f355b8b20cf2387f4d4190a20bddae0db
fix lib.qbs
Change-Id: Ibcb5bc290d3839b04828f8c9b155577634bcc9e4
moctagscanner split
Change-Id: Iace5d48483c02b5d33d9ccd54ac07162bfc09d27
Diffstat (limited to 'src/lib/language')
| -rw-r--r-- | src/lib/language/builtindeclarations.cpp | 17 | ||||
| -rw-r--r-- | src/lib/language/builtindeclarations.h | 1 | ||||
| -rw-r--r-- | src/lib/language/forward_decls.h | 4 | ||||
| -rw-r--r-- | src/lib/language/language.cpp | 73 | ||||
| -rw-r--r-- | src/lib/language/language.h | 47 | ||||
| -rw-r--r-- | src/lib/language/projectresolver.cpp | 54 | ||||
| -rw-r--r-- | src/lib/language/projectresolver.h | 4 |
7 files changed, 190 insertions, 10 deletions
diff --git a/src/lib/language/builtindeclarations.cpp b/src/lib/language/builtindeclarations.cpp index ebc876b60..7eb961d41 100644 --- a/src/lib/language/builtindeclarations.cpp +++ b/src/lib/language/builtindeclarations.cpp @@ -50,6 +50,7 @@ BuiltinDeclarations::BuiltinDeclarations() addPropertyOptionsItem(); addRuleItem(); addSubprojectItem(); + addTagScannerItem(); addTransformerItem(); } @@ -341,6 +342,22 @@ void BuiltinDeclarations::addSubprojectItem() m_builtins[QLatin1String("SubProject")] = properties; } +void BuiltinDeclarations::addTagScannerItem() +{ + QList<PropertyDeclaration> properties; + properties += PropertyDeclaration(QLatin1String("name"), + PropertyDeclaration::String); + properties += PropertyDeclaration(QLatin1String("dependencies"), + PropertyDeclaration::StringList); + properties += PropertyDeclaration(QLatin1String("inputTags"), + PropertyDeclaration::StringList); + properties += PropertyDeclaration(QLatin1String("outputTags"), + PropertyDeclaration::StringList); + properties += PropertyDeclaration(QLatin1String("scan"), + PropertyDeclaration::Verbatim); + m_builtins[QLatin1String("TagScanner")] = properties; +} + void BuiltinDeclarations::addTransformerItem() { QList<PropertyDeclaration> properties; diff --git a/src/lib/language/builtindeclarations.h b/src/lib/language/builtindeclarations.h index 4cbd352a7..b10c3eae9 100644 --- a/src/lib/language/builtindeclarations.h +++ b/src/lib/language/builtindeclarations.h @@ -64,6 +64,7 @@ private: void addPropertyOptionsItem(); void addRuleItem(); void addSubprojectItem(); + void addTagScannerItem(); void addTransformerItem(); QString m_languageVersion; diff --git a/src/lib/language/forward_decls.h b/src/lib/language/forward_decls.h index 5087258fc..d8d0d3d4f 100644 --- a/src/lib/language/forward_decls.h +++ b/src/lib/language/forward_decls.h @@ -66,6 +66,10 @@ class FileTagger; typedef QSharedPointer<FileTagger> FileTaggerPtr; typedef QSharedPointer<const FileTagger> FileTaggerConstPtr; +class TagScanner; +typedef QSharedPointer<TagScanner> TagScannerPtr; +typedef QSharedPointer<const TagScanner> TagScannerConstPtr; + class ResolvedProduct; typedef QSharedPointer<ResolvedProduct> ResolvedProductPtr; typedef QSharedPointer<const ResolvedProduct> ResolvedProductConstPtr; diff --git a/src/lib/language/language.cpp b/src/lib/language/language.cpp index 0530a78a6..f856a052b 100644 --- a/src/lib/language/language.cpp +++ b/src/lib/language/language.cpp @@ -104,6 +104,32 @@ void FileTagger::store(PersistentPool &pool) const } /*! + * \class TagScanner + * \brief The \c TagScanner class represents an entity that scans and tags source artifacts. + */ +void TagScanner::load(PersistentPool &pool) +{ + m_name = pool.idLoadString(); + pool.stream() + >> m_location + >> m_inputTags + >> m_outputTags; + m_scanScript = pool.idLoadS<ScriptFunction>(); + pool.loadContainerS(m_dependencies); +} + +void TagScanner::store(PersistentPool &pool) const +{ + pool.storeString(m_name); + pool.stream() + << m_location + << m_inputTags + << m_outputTags; + pool.store(m_scanScript); + pool.storeContainer(m_dependencies); +} + +/*! * \class SourceArtifact * \brief The \c SourceArtifact class represents a source file. * Everything except the file path is inherited from the surrounding \c ResolvedGroup. @@ -352,8 +378,9 @@ static bool modulesAreEqual(const ResolvedModuleConstPtr &m1, const ResolvedModu QString Rule::toString() const { - return QLatin1Char('[') + inputs.toStringList().join(QLatin1String(",")) + QLatin1String(" -> ") - + outputFileTags().toStringList().join(QLatin1String(",")) + QLatin1Char(']'); + return QLatin1Char('[') + outputFileTags().toStringList().join(QLatin1String(",")) + + QLatin1String("][") + + inputs.toStringList().join(QLatin1String(",")) + QLatin1Char(']'); } FileTags Rule::outputFileTags() const @@ -401,6 +428,14 @@ ResolvedProduct::~ResolvedProduct() { } +void ResolvedProduct::accept(BuildGraphVisitor *visitor) const +{ + if (!buildData) + return; + foreach (Artifact *artifact, buildData->targetArtifacts) + artifact->accept(visitor); +} + /*! * \brief Returns all files of all groups as source artifacts. * This includes the expanded list of wildcards. @@ -455,6 +490,7 @@ void ResolvedProduct::load(PersistentPool &pool) pool.loadContainerS(rules); pool.loadContainerS(dependencies); pool.loadContainerS(fileTaggers); + pool.loadContainerS(tagScanners); pool.loadContainerS(modules); pool.loadContainerS(transformers); pool.loadContainerS(groups); @@ -478,6 +514,7 @@ void ResolvedProduct::store(PersistentPool &pool) const pool.storeContainer(rules); pool.storeContainer(dependencies); pool.storeContainer(fileTaggers); + pool.storeContainer(tagScanners); pool.storeContainer(modules); pool.storeContainer(transformers); pool.storeContainer(groups); @@ -678,13 +715,13 @@ TopLevelProject *ResolvedProduct::topLevelProject() const static QStringList findGeneratedFiles(const Artifact *base, const FileTags &tags) { QStringList result; - foreach (const Artifact *parent, base->parents) { + foreach (const Artifact *parent, base->parentArtifacts()) { if (tags.isEmpty() || parent->fileTags.matches(tags)) result << parent->filePath(); } if (result.isEmpty() || tags.isEmpty()) - foreach (const Artifact *parent, base->parents) + foreach (const Artifact *parent, base->parentArtifacts()) result << findGeneratedFiles(parent, tags); return result; @@ -696,7 +733,7 @@ QStringList ResolvedProduct::generatedFiles(const QString &baseFile, const FileT if (!data) return QStringList(); - foreach (const Artifact *art, data->artifacts) { + foreach (const Artifact *art, ArtifactSet::fromNodeSet(data->nodes)) { if (art->filePath() == baseFile) return findGeneratedFiles(art, tags); } @@ -707,6 +744,12 @@ ResolvedProject::ResolvedProject() : enabled(true), m_topLevelProject(0) { } +void ResolvedProject::accept(BuildGraphVisitor *visitor) const +{ + foreach (const ResolvedProductPtr &product, products) + product->accept(visitor); +} + TopLevelProject *ResolvedProject::topLevelProject() { if (m_topLevelProject) @@ -755,8 +798,13 @@ void ResolvedProject::load(PersistentPool &pool) for (; --count >= 0;) { ResolvedProductPtr rProduct = pool.idLoadS<ResolvedProduct>(); if (rProduct->buildData) { - foreach (Artifact * const a, rProduct->buildData->artifacts) - a->product = rProduct; + foreach (BuildGraphNode * const node, rProduct->buildData->nodes) { + node->product = rProduct; + + // restore parent links + foreach (BuildGraphNode *child, node->children) + child->parents.insert(node); + } } products.append(rProduct); } @@ -810,6 +858,13 @@ QString TopLevelProject::deriveBuildDirectory(const QString &buildRoot, const QS return buildRoot + QLatin1Char('/') + id; } +void TopLevelProject::accept(BuildGraphVisitor *visitor) const +{ + ResolvedProject::accept(visitor); + foreach (const ResolvedProjectPtr &subProject, subProjects) + subProject->accept(visitor); +} + void TopLevelProject::setBuildConfiguration(const QVariantMap &config) { m_buildConfiguration = config; @@ -1040,7 +1095,7 @@ bool operator==(const SourceArtifact &sa1, const SourceArtifact &sa2) && sa1.properties->value() == sa2.properties->value(); } -bool sourceArtifactListsAreEqual(const QList<SourceArtifactPtr> &l1, +bool sourceArtifactSetsAreEqual(const QList<SourceArtifactPtr> &l1, const QList<SourceArtifactPtr> &l2) { return listsAreEqual(l1, l2); @@ -1050,7 +1105,7 @@ bool operator==(const ResolvedTransformer &t1, const ResolvedTransformer &t2) { return modulesAreEqual(t1.module, t2.module) && t1.inputs.toSet() == t2.inputs.toSet() - && sourceArtifactListsAreEqual(t1.outputs, t2.outputs) + && sourceArtifactSetsAreEqual(t1.outputs, t2.outputs) && *t1.transform == *t2.transform; } diff --git a/src/lib/language/language.h b/src/lib/language/language.h index 183a79e44..0af4cb621 100644 --- a/src/lib/language/language.h +++ b/src/lib/language/language.h @@ -61,6 +61,7 @@ QT_END_NAMESPACE namespace qbs { namespace Internal { class BuildGraphLoader; +class BuildGraphVisitor; class FileTagger : public PersistentObject { @@ -86,6 +87,45 @@ private: FileTags m_fileTags; }; +class TagScanner : public PersistentObject +{ +public: + static TagScannerPtr create() { return TagScannerPtr(new TagScanner); } + + void init(const CodeLocation &location, const QString &name, const FileTags &inTags, + const FileTags &outTags, const ScriptFunctionConstPtr &scanScript) + { + m_location = location; + m_name = name; + m_inputTags = inTags; + m_outputTags = outTags; + m_scanScript = scanScript; + } + + const CodeLocation &location() const { return m_location; } + const QString &name() const { return m_name; } + const FileTags &inputTags() const { return m_inputTags; } + const FileTags &outputTags() const { return m_outputTags; } + const ScriptFunctionConstPtr &scanScript() const { return m_scanScript; } + + void setDependencies(const QList<TagScannerConstPtr> &deps) { m_dependencies = deps; } + const QList<TagScannerConstPtr> &dependencies() const { return m_dependencies; } + +private: + TagScanner() + {} + + void load(PersistentPool &pool); + void store(PersistentPool &pool) const; + + CodeLocation m_location; + QString m_name; + FileTags m_inputTags; + FileTags m_outputTags; + ScriptFunctionConstPtr m_scanScript; + QList<TagScannerConstPtr> m_dependencies; +}; + class RuleArtifact : public PersistentObject { public: @@ -142,7 +182,7 @@ inline bool operator!=(const SourceArtifact &sa1, const SourceArtifact &sa2) { return !(sa1 == sa2); } -bool sourceArtifactListsAreEqual(const QList<SourceArtifactPtr> &l1, +bool sourceArtifactSetsAreEqual(const QList<SourceArtifactPtr> &l1, const QList<SourceArtifactPtr> &l2); class SourceWildCards : public PersistentObject @@ -354,6 +394,7 @@ public: QSet<RulePtr> rules; QSet<ResolvedProductPtr> dependencies; QList<FileTaggerConstPtr> fileTaggers; + QList<TagScannerConstPtr> tagScanners; QList<ResolvedModuleConstPtr> modules; QList<ResolvedTransformerConstPtr> transformers; QList<GroupPtr> groups; @@ -364,6 +405,7 @@ public: mutable QProcessEnvironment runEnvironment; // must not be saved QHash<QString, QString> executablePathCache; + void accept(BuildGraphVisitor *visitor) const; QList<SourceArtifactPtr> allFiles() const; QList<SourceArtifactPtr> allEnabledFiles() const; FileTags fileTagsForFileName(const QString &fileName) const; @@ -394,6 +436,8 @@ public: QList<ResolvedProjectPtr> subProjects; WeakPointer<ResolvedProject> parentProject; + virtual void accept(BuildGraphVisitor *visitor) const; + void setProjectProperties(const QVariantMap &config) { m_projectProperties = config; } const QVariantMap &projectProperties() const { return m_projectProperties; } @@ -432,6 +476,7 @@ public: QSet<QString> buildSystemFiles; + void accept(BuildGraphVisitor *visitor) const; void setBuildConfiguration(const QVariantMap &config); const QVariantMap &buildConfiguration() const { return m_buildConfiguration; } QString id() const { return m_id; } diff --git a/src/lib/language/projectresolver.cpp b/src/lib/language/projectresolver.cpp index 7de84608c..5763d7c5e 100644 --- a/src/lib/language/projectresolver.cpp +++ b/src/lib/language/projectresolver.cpp @@ -343,6 +343,8 @@ void ProjectResolver::resolveProduct(Item *item, ProjectContext *projectContext) foreach (const Item::Module &module, item->modules()) resolveModule(module.name, module.item, projectContext); + resolveTagScannerDependencies(); + m_productContext = 0; if (m_progressObserver) m_progressObserver->incrementProgressValue(); @@ -376,6 +378,7 @@ void ProjectResolver::resolveModule(const QStringList &moduleName, Item *item, mapping["PropertyOptions"] = &ProjectResolver::ignoreItem; mapping["Depends"] = &ProjectResolver::ignoreItem; mapping["Probe"] = &ProjectResolver::ignoreItem; + mapping["TagScanner"] = &ProjectResolver::resolveTagScanner; foreach (Item *child, item->children()) callItemFunction(mapping, child, projectContext); @@ -685,6 +688,57 @@ void ProjectResolver::resolveFileTagger(Item *item, ProjectContext *projectConte fileTaggers += FileTagger::create(patterns, fileTags); } +void ProjectResolver::resolveTagScanner(Item *item, ProjectResolver::ProjectContext *projectContext) +{ + Q_UNUSED(projectContext); + checkCancelation(); + const QString name = m_evaluator->stringValue(item, QLatin1String("name")); + if (name.isEmpty()) + throw ErrorInfo(Tr::tr("TagScanner items must have a name."), item->location()); + ProductContext::TagScannerHash::mapped_type &cached = m_productContext->tagScanners[name]; + TagScannerPtr &tagScanner = cached.first; + if (tagScanner) { + throw ErrorInfo(Tr::tr("TagScanner '%1' conflicts with TagScanner at %2.").arg(name, + tagScanner->location().toString()), item->location()); + } + + cached.second = m_evaluator->stringListValue(item, QLatin1String("dependencies")); + tagScanner = TagScanner::create(); + tagScanner->init( + item->location(), + name, + m_evaluator->fileTagsValue(item, QLatin1String("inputTags")), + m_evaluator->fileTagsValue(item, QLatin1String("outputTags")), + scriptFunctionValue(item, QLatin1String("scan"))); +} + +void ProjectResolver::resolveTagScannerDependencies() +{ + QSet<TagScannerConstPtr> rootTagScanners; + ProductContext::TagScannerHash::const_iterator it = m_productContext->tagScanners.constBegin(); + for (; it != m_productContext->tagScanners.constEnd(); ++it) + rootTagScanners += it.value().first; + + it = m_productContext->tagScanners.constBegin(); + for (; it != m_productContext->tagScanners.constEnd(); ++it) { + const TagScannerPtr &tagScanner = it.value().first; + QList<TagScannerConstPtr> dependencies; + foreach (const QString &dependencyName, it.value().second) { + const TagScannerPtr &dependency + = m_productContext->tagScanners.value(dependencyName).first; + if (!dependency) + throw ErrorInfo( + Tr::tr("Unsatisfied TagScanner dependency '%1'.").arg(dependencyName), + tagScanner->location()); + dependencies += dependency; + rootTagScanners.remove(dependency); + } + tagScanner->setDependencies(dependencies.toSet().toList()); + } + + m_productContext->product->tagScanners = rootTagScanners.toList(); +} + void ProjectResolver::resolveTransformer(Item *item, ProjectContext *projectContext) { checkCancelation(); diff --git a/src/lib/language/projectresolver.h b/src/lib/language/projectresolver.h index b23f19341..10d5e7fd6 100644 --- a/src/lib/language/projectresolver.h +++ b/src/lib/language/projectresolver.h @@ -78,6 +78,8 @@ private: { ResolvedProductPtr product; Item *item; + typedef QHash<QString, QPair<TagScannerPtr, QStringList> > TagScannerHash; + TagScannerHash tagScanners; }; struct ModuleContext @@ -103,6 +105,8 @@ private: const QStringList &namePrefix, StringListSet *seenBindings); void resolveFileTagger(Item *item, ProjectContext *projectContext); + void resolveTagScanner(Item *item, ProjectContext *projectContext); + void resolveTagScannerDependencies(); void resolveTransformer(Item *item, ProjectContext *projectContext); void resolveExport(Item *item, ProjectContext *projectContext); void resolveProductDependencies(ProjectContext *projectContext); |
