diff options
Diffstat (limited to 'src/lib/buildgraph/buildgraph.h')
-rw-r--r-- | src/lib/buildgraph/buildgraph.h | 216 |
1 files changed, 216 insertions, 0 deletions
diff --git a/src/lib/buildgraph/buildgraph.h b/src/lib/buildgraph/buildgraph.h new file mode 100644 index 000000000..3c9992748 --- /dev/null +++ b/src/lib/buildgraph/buildgraph.h @@ -0,0 +1,216 @@ +/************************************************************************** +** +** This file is part of the Qt Build Suite +** +** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (info@qt.nokia.com) +** +** +** GNU Lesser General Public License Usage +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. +** Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +**************************************************************************/ + +#ifndef BUILDGRAPH_H +#define BUILDGRAPH_H + +#include "artifactlist.h" + +#include <language/language.h> +#include <tools/error.h> +#include <tools/persistence.h> + +#include <QtCore/QCoreApplication> +#include <QtCore/QSet> +#include <QtCore/QSharedPointer> +#include <QtCore/QStringList> + +#include <QtCore/QDir> +#include <QtCore/QVector> +#include <QtCore/QVariant> +#include <QtScript/QScriptEngine> +#include <QtCore/QFutureInterface> + +namespace qbs { + +class Artifact; +class Transformer; +class BuildProject; + +class BuildProduct : public PersistentObject +{ +public: + typedef QSharedPointer<BuildProduct> Ptr; + + BuildProduct(); + ~BuildProduct(); + + const QList<Rule::Ptr> &topSortedRules() const; + + BuildProject *project; + ResolvedProduct::Ptr rProduct; + QSet<Artifact *> targetArtifacts; + QList<BuildProduct *> usings; + QHash<QString, Artifact *> artifacts; + +private: + void load(PersistentPool &pool, PersistentObjectData &data); + void store(PersistentPool &pool, PersistentObjectData &data) const; + +private: + mutable QList<Rule::Ptr> m_topSortedRules; +}; + +class BuildGraph; + +class BuildProject : public PersistentObject +{ + friend class BuildGraph; +public: + typedef QSharedPointer<BuildProject> Ptr; + + BuildProject(BuildGraph *bg); + ~BuildProject(); + + static BuildProject::Ptr load(BuildGraph *bg, const FileTime &minTimeStamp, Configuration::Ptr cfg, const QStringList &loaderSearchPaths); + void store(); + + BuildGraph *buildGraph() const; + ResolvedProject::Ptr resolvedProject() const; + QSet<BuildProduct::Ptr> buildProducts() const; + QHash<QString, Artifact *> &dependencyArtifacts(); + bool dirty() const; + Artifact *findArtifact(const QString &filePath) const; + +private: + static QString storedProjectFilePath(BuildGraph *bg, const QString &configId); + static QStringList storedProjectFiles(BuildGraph *bg); + void load(PersistentPool &pool, PersistentObjectData &data); + void store(PersistentPool &pool, PersistentObjectData &data) const; + void markDirty(); + void addBuildProduct(const BuildProduct::Ptr &product); + void setResolvedProject(const ResolvedProject::Ptr & resolvedProject); + +private: + BuildGraph *m_buildGraph; + ResolvedProject::Ptr m_resolvedProject; + QSet<BuildProduct::Ptr> m_buildProducts; + QHash<QString, Artifact *> m_dependencyArtifacts; + bool m_dirty; +}; + +class BuildGraphListener; + +/** + * N artifact, T transformer, parent -> child + * parent depends on child, child is a dependency of parent, + * parent is a dependent of child. + * + * N a.out -> N main.o -> N main.cpp + * + * Every artifact can point to a transformer which contains the commands. + * Multiple artifacts can point to the same transformer. + */ +class BuildGraph +{ + Q_DECLARE_TR_FUNCTIONS(BuildGraph) +public: + BuildGraph(); + ~BuildGraph(); + + BuildProject::Ptr resolveProject(ResolvedProject::Ptr, QFutureInterface<bool> &futureInterface); + BuildProduct::Ptr resolveProduct(BuildProject *, ResolvedProduct::Ptr, QFutureInterface<bool> &futureInterface); + + void dump(BuildProduct::Ptr) const; + void applyRules(BuildProduct *product, QMap<QString, QSet<Artifact *> > &artifactsPerFileTag); + static void detectCycle(BuildProject *project); + static void detectCycle(Artifact *a); + + void setOutputDirectoryRoot(const QString &buildDirectoryRoot) { m_outputDirectoryRoot = buildDirectoryRoot; } + const QString &outputDirectoryRoot() const { return m_outputDirectoryRoot; } + QString buildDirectoryRoot() const; + QString resolveOutPath(const QString &path, BuildProduct *) const; + + void connect(Artifact *p, Artifact *c); + void loggedConnect(Artifact *u, Artifact *v); + bool safeConnect(Artifact *u, Artifact *v); + void insert(BuildProduct::Ptr target, Artifact *n) const; + void insert(BuildProduct *target, Artifact *n) const; + void remove(Artifact *artifact) const; + void removeArtifactAndExclusiveDependents(Artifact *artifact, QList<Artifact*> *removedArtifacts = 0); + + void createOutputArtifact(BuildProduct *product, + const Rule::Ptr &rule, const RuleArtifact::Ptr &ruleArtifact, + const QSet<Artifact *> &inputArtifacts, + QList<QPair<RuleArtifact *, Artifact *> > *ruleArtifactArtifactMap, + QList<Artifact *> *outputArtifacts, + QSharedPointer<Transformer> &transformer); + + void onProductChanged(BuildProduct::Ptr product, ResolvedProduct::Ptr changedProduct); + void updateNodesThatMustGetNewTransformer(); + + static void setupScriptEngineForProduct(QScriptEngine *scriptEngine, ResolvedProduct::Ptr product, Rule::Ptr rule, BuildGraph *bg = 0); + +private: + Artifact *createArtifact(BuildProduct::Ptr product, SourceArtifact::Ptr sourceArtifact); + void applyRule(BuildProduct *product, QMap<QString, QSet<Artifact *> > &artifactsPerFileTag, Rule::Ptr rule); + void applyRule(BuildProduct *product, QMap<QString, QSet<Artifact *> > &artifactsPerFileTag, Rule::Ptr rule, const QSet<Artifact *> &inputArtifacts); + void createTransformerCommands(RuleScript::Ptr script, Transformer *transformer); + static void disconnect(Artifact *u, Artifact *v); + QSet<Artifact *> disconnect(Artifact *n) const; + void setupScriptEngineForArtifact(BuildProduct *product, Artifact *artifact); + void updateNodeThatMustGetNewTransformer(Artifact *artifact); + static void detectCycle(Artifact *v, QSet<Artifact *> &done, QSet<Artifact *> ¤tBranch); + +private: + QString m_outputDirectoryRoot; /// The directory where the 'build' and 'targets' subdirectories end up. + QScriptEngine m_scriptEngine; + QHash<ResolvedProduct::Ptr, BuildProduct::Ptr> m_productCache; + QHash<QString, QScriptValue> m_jsImportCache; + QHash<QString, QScriptProgram> m_scriptProgramCache; + mutable QSet<Artifact *> m_artifactsThatMustGetNewTransformers; +}; + +// debugging helper +QString fileName(Artifact *n); + +// debugging helper +template <typename T> +static QStringList toStringList(const T &artifactContainer) +{ + QStringList l; + foreach (Artifact *n, artifactContainer) + l.append(fileName(n)); + return l; +} + +char **createCFileTags(const QSet<QString> &fileTags); +void freeCFileTags(char **cFileTags, int numFileTags); + +} // namespace qbs + +#endif // BUILDGRAPH_H |