aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Kandeler <christian.kandeler@digia.com>2012-11-29 16:25:17 +0100
committerJoerg Bornemann <joerg.bornemann@digia.com>2012-12-03 11:07:09 +0100
commit29150c3efdf0afee63317486760bc7b7a30cac3d (patch)
treeff41c26d328ac625ed0b56edb09c69af52fb2fdf
parentbb75c2724f4e09327b342f5372719d286526f271 (diff)
Move engine-related functionality out of BuildGraph.
Change-Id: I5da16ea99bce3e6f737f37770fb0fe3e2e5c0214 Reviewed-by: Joerg Bornemann <joerg.bornemann@digia.com>
-rw-r--r--src/lib/api/internaljobs.cpp19
-rw-r--r--src/lib/buildgraph/automoc.cpp7
-rw-r--r--src/lib/buildgraph/automoc.h4
-rw-r--r--src/lib/buildgraph/buildgraph.cpp197
-rw-r--r--src/lib/buildgraph/buildgraph.h78
-rw-r--r--src/lib/buildgraph/buildgraph.pri6
-rw-r--r--src/lib/buildgraph/executor.cpp29
-rw-r--r--src/lib/buildgraph/executor.h5
-rw-r--r--src/lib/buildgraph/rulesevaluationcontext.cpp116
-rw-r--r--src/lib/buildgraph/rulesevaluationcontext.h81
10 files changed, 320 insertions, 222 deletions
diff --git a/src/lib/api/internaljobs.cpp b/src/lib/api/internaljobs.cpp
index 67ff0deee..19543cc8f 100644
--- a/src/lib/api/internaljobs.cpp
+++ b/src/lib/api/internaljobs.cpp
@@ -31,9 +31,9 @@
#include <buildgraph/artifactcleaner.h>
#include <buildgraph/buildgraph.h>
#include <buildgraph/executor.h>
+#include <buildgraph/rulesevaluationcontext.h>
#include <language/language.h>
#include <language/loader.h>
-#include <language/scriptengine.h>
#include <logging/logger.h>
#include <logging/translator.h>
#include <tools/error.h>
@@ -143,25 +143,23 @@ void InternalSetupProjectJob::doResolve()
void InternalSetupProjectJob::execute()
{
- ScriptEngine scriptEngine;
- QScopedPointer<BuildGraph> buildGraph(new BuildGraph);
- buildGraph->setEngine(&scriptEngine);
- buildGraph->setProgressObserver(observer());
+ QScopedPointer<RulesEvaluationContext> evalContext(new RulesEvaluationContext);
+ evalContext->setObserver(observer());
const QStringList searchPaths = Settings().searchPaths();
const BuildProjectLoader::LoadResult loadResult = BuildProjectLoader().load(m_projectFilePath,
- buildGraph.data(), m_buildRoot, m_buildConfig, searchPaths);
+ evalContext.data(), m_buildRoot, m_buildConfig, searchPaths);
ResolvedProjectPtr rProject;
if (!loadResult.discardLoadedProject)
m_buildProject = loadResult.loadedProject;
if (m_buildProject) {
- buildGraph.take();
+ evalContext.take();
rProject = m_buildProject->resolvedProject();
} else {
if (loadResult.changedResolvedProject) {
rProject = loadResult.changedResolvedProject;
} else {
- Loader loader(&scriptEngine);
+ Loader loader(evalContext->engine());
loader.setSearchPaths(searchPaths);
loader.setProgressObserver(observer());
rProject = loader.loadProject(m_projectFilePath, m_buildRoot, m_buildConfig);
@@ -188,10 +186,10 @@ void InternalSetupProjectJob::execute()
return;
TimedActivityLogger resolveLogger(QLatin1String("Resolving build project"));
- m_buildProject = BuildProjectResolver().resolveProject(rProject, buildGraph.data(), observer());
+ m_buildProject = BuildProjectResolver().resolveProject(rProject, evalContext.data());
if (loadResult.loadedProject)
m_buildProject->rescueDependencies(loadResult.loadedProject);
- buildGraph.take();
+ evalContext.take();
}
@@ -237,7 +235,6 @@ void InternalBuildJob::start()
{
m_executor = new Executor(this);
connect(m_executor, SIGNAL(finished()), SLOT(handleFinished()));
- m_executor->setEngine(new ScriptEngine(this));
m_executor->setBuildOptions(buildOptions());
m_executor->setProgressObserver(observer());
m_executor->build(products());
diff --git a/src/lib/buildgraph/automoc.cpp b/src/lib/buildgraph/automoc.cpp
index f6a9fffc8..070b75e17 100644
--- a/src/lib/buildgraph/automoc.cpp
+++ b/src/lib/buildgraph/automoc.cpp
@@ -51,8 +51,7 @@ void AutoMoc::setScanResultCache(ScanResultCache *scanResultCache)
m_scanResultCache = scanResultCache;
}
-void AutoMoc::apply(const BuildProductPtr &product, ScriptEngine *engine,
- ProgressObserver *observer)
+void AutoMoc::apply(const BuildProductPtr &product)
{
if (scanners().isEmpty())
throw Error("C++ scanner cannot be loaded.");
@@ -131,7 +130,7 @@ void AutoMoc::apply(const BuildProductPtr &product, ScriptEngine *engine,
artifactsPerFileTag[QLatin1String("c++_pch")] += pchFile;
if (!artifactsPerFileTag.isEmpty()) {
qbsInfo() << DontPrintLogLevel << "Applying moc rules for '" << product->rProduct->name << "'.";
- product->applyRules(artifactsPerFileTag, engine, observer);
+ product->applyRules(artifactsPerFileTag);
}
if (pluginHeaderFile && pluginMetaDataFile) {
// Make every artifact that is dependent of the header file also
@@ -140,7 +139,7 @@ void AutoMoc::apply(const BuildProductPtr &product, ScriptEngine *engine,
BuildGraph::loggedConnect(outputOfHeader, pluginMetaDataFile);
}
- product->project->updateNodesThatMustGetNewTransformer(engine, observer);
+ product->project->updateNodesThatMustGetNewTransformer();
}
QString AutoMoc::generateMocFileName(Artifact *artifact, FileType fileType)
diff --git a/src/lib/buildgraph/automoc.h b/src/lib/buildgraph/automoc.h
index 18c0089bc..89bcd7537 100644
--- a/src/lib/buildgraph/automoc.h
+++ b/src/lib/buildgraph/automoc.h
@@ -36,9 +36,7 @@ struct ScannerPlugin;
namespace qbs {
namespace Internal {
-class ProgressObserver;
class ScanResultCache;
-class ScriptEngine;
/**
* Scans cpp and hpp files for the Q_OBJECT / Q_GADGET macro and
@@ -54,7 +52,7 @@ public:
AutoMoc();
void setScanResultCache(ScanResultCache *scanResultCache);
- void apply(const BuildProductPtr &product, ScriptEngine *engine, ProgressObserver *observer);
+ void apply(const BuildProductPtr &product);
private:
enum FileType
diff --git a/src/lib/buildgraph/buildgraph.cpp b/src/lib/buildgraph/buildgraph.cpp
index 4f4db8498..4e79acd0f 100644
--- a/src/lib/buildgraph/buildgraph.cpp
+++ b/src/lib/buildgraph/buildgraph.cpp
@@ -33,6 +33,7 @@
#include "cycledetector.h"
#include "command.h"
#include "rulegraph.h"
+#include "rulesevaluationcontext.h"
#include "transformer.h"
#include <language/language.h>
@@ -173,37 +174,17 @@ void BuildProduct::insertArtifact(Artifact *artifact)
qbsTrace("[BG] insert artifact '%s'", qPrintable(artifact->filePath()));
}
-void BuildProduct::applyRules(ArtifactsPerFileTagMap &artifactsPerFileTag, ScriptEngine *engine,
- ProgressObserver *observer)
+void BuildProduct::applyRules(ArtifactsPerFileTagMap &artifactsPerFileTag)
{
- BuildGraph::EngineInitializer engineInitializer(project->buildGraph());
- RulesApplicator rulesApplier(this, artifactsPerFileTag, engine, observer);
+ RulesEvaluationContext::Scope s(project->evaluationContext());
+ RulesApplicator rulesApplier(this, artifactsPerFileTag);
rulesApplier.applyAllRules();
}
-BuildGraph::BuildGraph()
- : m_progressObserver(0)
- , m_engine(0)
- , m_initEngineCalls(0)
-{
-}
-
-BuildGraph::~BuildGraph()
-{
-}
-
-void BuildGraph::setEngine(ScriptEngine *engine)
-{
- m_engine = engine;
- m_prepareScriptScope = m_engine->newObject();
- ProcessCommand::setupForJavaScript(m_prepareScriptScope);
- JavaScriptCommand::setupForJavaScript(m_prepareScriptScope);
-}
-
void BuildGraph::setupScriptEngineForProduct(ScriptEngine *engine,
const ResolvedProductConstPtr &product,
- RuleConstPtr rule,
+ const RuleConstPtr &rule,
QScriptValue targetObject)
{
const ResolvedProject *lastSetupProject = reinterpret_cast<ResolvedProject *>(engine->property("lastSetupProject").toULongLong());
@@ -241,11 +222,6 @@ void BuildGraph::setupScriptEngineForProduct(ScriptEngine *engine,
engine->import(rule->jsImports, targetObject, targetObject);
}
-void BuildGraph::setProgressObserver(ProgressObserver *observer)
-{
- m_progressObserver = observer;
-}
-
bool BuildGraph::findPath(Artifact *u, Artifact *v, QList<Artifact*> &path)
{
if (u == v) {
@@ -329,32 +305,6 @@ void BuildGraph::disconnect(Artifact *u, Artifact *v)
v->parents.remove(u);
}
-void BuildGraph::initEngine()
-{
- if (m_initEngineCalls++ > 0)
- return;
-
- m_engine->setProperty("lastSetupProject", QVariant());
- m_engine->setProperty("lastSetupProduct", QVariant());
-
- m_engine->clearImportsCache();
- m_engine->pushContext();
- m_scope = m_engine->newObject();
- m_scope.setPrototype(m_prepareScriptScope);
- m_engine->currentContext()->pushScope(m_scope);
-}
-
-void BuildGraph::cleanupEngine()
-{
- Q_ASSERT(m_initEngineCalls > 0);
- if (--m_initEngineCalls > 0)
- return;
-
- m_scope = QScriptValue();
- m_engine->currentContext()->popScope();
- m_engine->popContext();
-}
-
void BuildGraph::removeGeneratedArtifactFromDisk(Artifact *artifact)
{
if (artifact->artifactType != Artifact::Generated)
@@ -473,15 +423,13 @@ void BuildProduct::store(PersistentPool &pool) const
pool.storeContainer(dependencies);
}
-BuildProject::BuildProject(BuildGraph *bg)
- : m_buildGraph(bg)
- , m_dirty(false)
+BuildProject::BuildProject() : m_evalContext(0), m_dirty(false)
{
}
BuildProject::~BuildProject()
{
- delete m_buildGraph;
+ delete m_evalContext;
qDeleteAll(m_dependencyArtifacts);
}
@@ -529,6 +477,12 @@ QString BuildProject::buildGraphFilePath() const
return deriveBuildGraphFilePath(resolvedProject()->buildDirectory, resolvedProject()->id());
}
+void BuildProject::setEvaluationContext(RulesEvaluationContext *evalContext)
+{
+ delete m_evalContext;
+ m_evalContext = evalContext;
+}
+
void BuildProject::load(PersistentPool &pool)
{
TimedActivityLogger logger(QLatin1String("Loading project from disk."));
@@ -587,11 +541,6 @@ void freeCFileTags(char **cFileTags, int numFileTags)
delete[] cFileTags;
}
-BuildGraph * BuildProject::buildGraph() const
-{
- return m_buildGraph;
-}
-
ResolvedProjectPtr BuildProject::resolvedProject() const
{
return m_resolvedProject;
@@ -717,17 +666,15 @@ void BuildProject::removeArtifact(Artifact *artifact)
markDirty();
}
-void BuildProject::updateNodesThatMustGetNewTransformer(ScriptEngine *engine,
- ProgressObserver *observer)
+void BuildProject::updateNodesThatMustGetNewTransformer()
{
- BuildGraph::EngineInitializer engineInitializer(buildGraph());
+ RulesEvaluationContext::Scope s(evaluationContext());
foreach (Artifact *artifact, m_artifactsThatMustGetNewTransformers)
- updateNodeThatMustGetNewTransformer(artifact, engine, observer);
+ updateNodeThatMustGetNewTransformer(artifact);
m_artifactsThatMustGetNewTransformers.clear();
}
-void BuildProject::updateNodeThatMustGetNewTransformer(Artifact *artifact, ScriptEngine *engine,
- ProgressObserver *observer)
+void BuildProject::updateNodeThatMustGetNewTransformer(Artifact *artifact)
{
Q_ASSERT(artifact->transformer);
@@ -745,7 +692,7 @@ void BuildProject::updateNodeThatMustGetNewTransformer(Artifact *artifact, Scrip
foreach (const QString &fileTag, input->fileTags)
artifactsPerFileTag[fileTag] += input;
}
- RulesApplicator rulesApplier(artifact->product, artifactsPerFileTag, engine, observer);
+ RulesApplicator rulesApplier(artifact->product, artifactsPerFileTag);
rulesApplier.applyRule(rule);
}
@@ -761,23 +708,9 @@ QString fileName(Artifact *n)
return str;
}
-BuildGraph::EngineInitializer::EngineInitializer(BuildGraph *bg)
- : buildGraph(bg)
-{
- buildGraph->initEngine();
-}
-
-BuildGraph::EngineInitializer::~EngineInitializer()
-{
- buildGraph->cleanupEngine();
-}
-
-RulesApplicator::RulesApplicator(BuildProduct *product, ArtifactsPerFileTagMap &artifactsPerFileTag,
- ScriptEngine *engine, ProgressObserver *observer)
+RulesApplicator::RulesApplicator(BuildProduct *product, ArtifactsPerFileTagMap &artifactsPerFileTag)
: m_buildProduct(product)
, m_artifactsPerFileTag(artifactsPerFileTag)
- , m_engine(engine)
- , m_observer(observer)
{
}
@@ -790,8 +723,8 @@ void RulesApplicator::applyAllRules()
void RulesApplicator::applyRule(const RuleConstPtr &rule)
{
m_rule = rule;
- BuildGraph::setupScriptEngineForProduct(m_engine, m_buildProduct->rProduct, m_rule, scope());
- Q_ASSERT_X(scope().property("product").strictlyEquals(m_engine->evaluate("product")),
+ BuildGraph::setupScriptEngineForProduct(engine(), m_buildProduct->rProduct, m_rule, scope());
+ Q_ASSERT_X(scope().property("product").strictlyEquals(engine()->evaluate("product")),
"BG", "Product object is not in current scope.");
ArtifactList inputArtifacts;
@@ -813,8 +746,7 @@ void RulesApplicator::applyRule(const RuleConstPtr &rule)
void RulesApplicator::doApply(const ArtifactList &inputArtifacts)
{
- if (m_observer && m_observer->canceled())
- throw Error(Tr::tr("Build canceled."));
+ evalContext()->checkForCancelation();
if (qbsLogLevel(LoggerDebug))
qbsDebug() << "[BG] apply rule " << m_rule->toString() << " "
@@ -870,7 +802,7 @@ void RulesApplicator::doApply(const ArtifactList &inputArtifacts)
m_buildProduct->project->removeFromArtifactsThatMustGetNewTransformers(outputArtifact);
}
- m_transformer->setupInputs(m_engine, scope());
+ m_transformer->setupInputs(engine(), scope());
// change the transformer outputs according to the bindings in Artifact
QScriptValue scriptValue;
@@ -883,13 +815,13 @@ void RulesApplicator::doApply(const ArtifactList &inputArtifacts)
Artifact *outputArtifact = ruleArtifactArtifactMap.at(i).second;
outputArtifact->properties = outputArtifact->properties->clone();
- scope().setProperty("fileName", m_engine->toScriptValue(outputArtifact->filePath()));
- scope().setProperty("fileTags", toScriptValue(m_engine, outputArtifact->fileTags));
+ scope().setProperty("fileName", engine()->toScriptValue(outputArtifact->filePath()));
+ scope().setProperty("fileTags", toScriptValue(engine(), outputArtifact->fileTags));
QVariantMap artifactModulesCfg = outputArtifact->properties->value().value("modules").toMap();
for (int i=0; i < ra->bindings.count(); ++i) {
const RuleArtifact::Binding &binding = ra->bindings.at(i);
- scriptValue = m_engine->evaluate(binding.code);
+ scriptValue = engine()->evaluate(binding.code);
if (scriptValue.isError()) {
QString msg = QLatin1String("evaluating rule binding '%1': %2");
throw Error(msg.arg(binding.name.join(QLatin1String(".")), scriptValue.toString()), binding.location);
@@ -901,8 +833,8 @@ void RulesApplicator::doApply(const ArtifactList &inputArtifacts)
outputArtifact->properties->setValue(outputArtifactConfig);
}
- m_transformer->setupOutputs(m_engine, scope());
- m_transformer->createCommands(m_rule->script, m_engine);
+ m_transformer->setupOutputs(engine(), scope());
+ m_transformer->createCommands(m_rule->script, engine());
if (m_transformer->commands.isEmpty())
throw Error(QString("There's a rule without commands: %1.").arg(m_rule->toString()), m_rule->script->location);
}
@@ -922,11 +854,11 @@ void RulesApplicator::setupScriptEngineForArtifact(Artifact *artifact)
basedir = FileInfo::path(buildDir.relativeFilePath(artifact->filePath()));
}
- QScriptValue modulesScriptValue = artifact->properties->toScriptValue(m_engine);
+ QScriptValue modulesScriptValue = artifact->properties->toScriptValue(engine());
modulesScriptValue = modulesScriptValue.property("modules");
// expose per file properties we want to use in an Artifact within a Rule
- QScriptValue scriptValue = m_engine->newObject();
+ QScriptValue scriptValue = engine()->newObject();
scriptValue.setProperty("fileName", inFileName);
scriptValue.setProperty("baseName", inBaseName);
scriptValue.setProperty("completeBaseName", inCompleteBaseName);
@@ -934,15 +866,15 @@ void RulesApplicator::setupScriptEngineForArtifact(Artifact *artifact)
scriptValue.setProperty("modules", modulesScriptValue);
scope().setProperty("input", scriptValue);
- Q_ASSERT_X(scriptValue.strictlyEquals(m_engine->evaluate("input")),
+ Q_ASSERT_X(scriptValue.strictlyEquals(engine()->evaluate("input")),
"BG", "The input object is not in current scope.");
}
Artifact *RulesApplicator::createOutputArtifact(const RuleArtifactConstPtr &ruleArtifact,
const ArtifactList &inputArtifacts)
{
- QScriptValue scriptValue = m_engine->evaluate(ruleArtifact->fileName);
- if (scriptValue.isError() || m_engine->hasUncaughtException())
+ QScriptValue scriptValue = engine()->evaluate(ruleArtifact->fileName);
+ if (scriptValue.isError() || engine()->hasUncaughtException())
throw Error("Error in Rule.Artifact fileName: " + scriptValue.toString());
QString outputPath = scriptValue.toString();
outputPath.replace("..", "dotdot"); // don't let the output artifact "escape" its build dir
@@ -1020,25 +952,33 @@ QString RulesApplicator::resolveOutPath(const QString &path) const
return result;
}
+RulesEvaluationContext *RulesApplicator::evalContext() const
+{
+ return m_buildProduct->project->evaluationContext();
+}
+
+ScriptEngine *RulesApplicator::engine() const
+{
+ return evalContext()->engine();
+}
+
QScriptValue RulesApplicator::scope() const
{
- return m_engine->currentContext()->scopeChain().first();
+ return evalContext()->scope();
}
BuildProjectPtr BuildProjectResolver::resolveProject(const ResolvedProjectPtr &resolvedProject,
- BuildGraph *buildgraph, ProgressObserver *observer)
+ RulesEvaluationContext *evalContext)
{
m_productCache.clear();
- m_observer = observer;
- m_project = BuildProjectPtr(new BuildProject(buildgraph));
+ m_project = BuildProjectPtr(new BuildProject);
+ m_project->setEvaluationContext(evalContext);
m_project->setResolvedProject(resolvedProject);
- if (m_observer)
- m_observer->initialize(Tr::tr("Resolving project"), resolvedProject->products.count());
+ evalContext->initializeObserver(Tr::tr("Resolving project"), resolvedProject->products.count());
foreach (ResolvedProductPtr rProduct, resolvedProject->products) {
resolveProduct(rProduct);
- if (m_observer)
- m_observer->incrementProgressValue();
+ evalContext->incrementProgressValue();
}
CycleDetector().visitProject(m_project);
return m_project;
@@ -1050,8 +990,7 @@ BuildProductPtr BuildProjectResolver::resolveProduct(const ResolvedProductPtr &r
if (product)
return product;
- if (m_observer && m_observer->canceled())
- throw Error(Tr::tr("Build canceled."));
+ evalContext()->checkForCancelation();
product = BuildProduct::create();
m_productCache.insert(rProduct, product);
@@ -1114,7 +1053,7 @@ BuildProductPtr BuildProjectResolver::resolveProduct(const ResolvedProductPtr &r
transformer->outputs += outputArtifact;
product->targetArtifacts += outputArtifact;
foreach (Artifact *inputArtifact, inputArtifacts)
- buildGraph()->safeConnect(outputArtifact, inputArtifact);
+ BuildGraph::safeConnect(outputArtifact, inputArtifact);
foreach (const QString &fileTag, outputArtifact->fileTags)
artifactsPerFileTag[fileTag].insert(outputArtifact);
@@ -1125,16 +1064,16 @@ BuildProductPtr BuildProjectResolver::resolveProduct(const ResolvedProductPtr &r
}
transformer->rule = rule;
- BuildGraph::EngineInitializer initializer(buildGraph());
- buildGraph()->setupScriptEngineForProduct(engine(), rProduct, transformer->rule, scope());
+ RulesEvaluationContext::Scope s(evalContext());
+ BuildGraph::setupScriptEngineForProduct(engine(), rProduct, transformer->rule, scope());
transformer->setupInputs(engine(), scope());
transformer->setupOutputs(engine(), scope());
- transformer->createCommands(rtrafo->transform, buildGraph()->engine());
+ transformer->createCommands(rtrafo->transform, engine());
if (transformer->commands.isEmpty())
throw Error(QString("There's a transformer without commands."), rtrafo->transform->location);
}
- product->applyRules(artifactsPerFileTag, buildGraph()->engine(), m_observer);
+ product->applyRules(artifactsPerFileTag);
QSet<Artifact *> productArtifactCandidates;
for (int i = 0; i < product->rProduct->fileTags.count(); ++i)
@@ -1152,18 +1091,27 @@ BuildProductPtr BuildProjectResolver::resolveProduct(const ResolvedProductPtr &r
return product;
}
+RulesEvaluationContext *BuildProjectResolver::evalContext() const
+{
+ return m_project->evaluationContext();
+}
+
+ScriptEngine *BuildProjectResolver::engine() const
+{
+ return evalContext()->engine();
+}
+
QScriptValue BuildProjectResolver::scope() const
{
- return engine()->currentContext()->scopeChain().first();
+ return evalContext()->scope();
}
BuildProjectLoader::LoadResult BuildProjectLoader::load(const QString &projectFilePath,
- BuildGraph *bg, const QString &buildRoot, const QVariantMap &cfg,
+ RulesEvaluationContext *evalContext, const QString &buildRoot, const QVariantMap &cfg,
const QStringList &loaderSearchPaths)
{
m_result = LoadResult();
- m_engine = bg->engine();
- m_observer = bg->observer();
+ m_evalContext = evalContext;
const QString projectId = ResolvedProject::deriveId(cfg);
const QString buildDir = ResolvedProject::deriveBuildDirectory(buildRoot, projectId);
@@ -1178,7 +1126,8 @@ BuildProjectLoader::LoadResult BuildProjectLoader::load(const QString &projectFi
return m_result;
}
- const BuildProjectPtr project = BuildProjectPtr(new BuildProject(bg));
+ const BuildProjectPtr project = BuildProjectPtr(new BuildProject);
+ project->setEvaluationContext(evalContext);
TimedActivityLogger loadLogger(QLatin1String("Loading build graph"), QLatin1String("[BG] "));
project->load(pool);
foreach (const BuildProductPtr &bp, project->buildProducts())
@@ -1219,7 +1168,7 @@ BuildProjectLoader::LoadResult BuildProjectLoader::load(const QString &projectFi
}
if (projectFileChanged || referencedProductRemoved || !changedProducts.isEmpty()) {
- Loader ldr(bg->engine());
+ Loader ldr(evalContext->engine());
ldr.setSearchPaths(loaderSearchPaths);
const ResolvedProjectPtr changedProject
= ldr.loadProject(project->resolvedProject()->location.fileName, buildRoot, cfg);
@@ -1349,13 +1298,13 @@ void BuildProjectLoader::onProductChanged(const BuildProductPtr &product,
foreach (Artifact *artifact, addedArtifacts)
foreach (const QString &ft, artifact->fileTags)
artifactsPerFileTag[ft] += artifact;
- product->applyRules(artifactsPerFileTag, m_engine, m_observer);
+ product->applyRules(artifactsPerFileTag);
// parents of removed artifacts must update their transformers
foreach (Artifact *removedArtifact, artifactsToRemove)
foreach (Artifact *parent, removedArtifact->parents)
product->project->addToArtifactsThatMustGetNewTransformers(parent);
- product->project->updateNodesThatMustGetNewTransformer(m_engine, m_observer);
+ product->project->updateNodesThatMustGetNewTransformer();
// delete all removed artifacts physically from the disk
foreach (Artifact *artifact, artifactsToRemove) {
diff --git a/src/lib/buildgraph/buildgraph.h b/src/lib/buildgraph/buildgraph.h
index 7547a095a..25dd664d5 100644
--- a/src/lib/buildgraph/buildgraph.h
+++ b/src/lib/buildgraph/buildgraph.h
@@ -47,9 +47,9 @@
#include <QVector>
namespace qbs {
-
namespace Internal {
class ProgressObserver;
+class RulesEvaluationContext;
class ScriptEngine;
class Transformer;
@@ -68,8 +68,7 @@ public:
Artifact *lookupArtifact(const QString &filePath) const;
Artifact *createArtifact(const SourceArtifactConstPtr &sourceArtifact);
void insertArtifact(Artifact *n);
- void applyRules(ArtifactsPerFileTagMap &artifactsPerFileTag, ScriptEngine *engine,
- ProgressObserver *observer);
+ void applyRules(ArtifactsPerFileTagMap &artifactsPerFileTag);
WeakPointer<BuildProject> project;
ResolvedProductPtr rProduct;
@@ -96,14 +95,16 @@ class BuildProject : public PersistentObject
friend class BuildProjectLoader;
friend class BuildProjectResolver;
public:
- BuildProject(BuildGraph *bg);
+ BuildProject();
~BuildProject();
void store() const;
static QString deriveBuildGraphFilePath(const QString &buildDir, const QString projectId);
QString buildGraphFilePath() const;
- BuildGraph *buildGraph() const;
+ void setEvaluationContext(RulesEvaluationContext *evalContext);
+ RulesEvaluationContext *evaluationContext() const { return m_evalContext; }
+
ResolvedProjectPtr resolvedProject() const;
QSet<BuildProductPtr> buildProducts() const;
bool dirty() const;
@@ -115,7 +116,7 @@ public:
void insertFileDependency(Artifact *artifact);
void rescueDependencies(const BuildProjectPtr &other);
void removeArtifact(Artifact *artifact);
- void updateNodesThatMustGetNewTransformer(ScriptEngine *engine, ProgressObserver *observer);
+ void updateNodesThatMustGetNewTransformer();
void removeFromArtifactsThatMustGetNewTransformers(Artifact *a) {
m_artifactsThatMustGetNewTransformers -= a;
}
@@ -128,11 +129,10 @@ private:
void store(PersistentPool &pool) const;
void addBuildProduct(const BuildProductPtr &product);
void setResolvedProject(const ResolvedProjectPtr &resolvedProject);
- void updateNodeThatMustGetNewTransformer(Artifact *artifact, ScriptEngine *engine,
- ProgressObserver *observer);
+ void updateNodeThatMustGetNewTransformer(Artifact *artifact);
private:
- BuildGraph *m_buildGraph;
+ RulesEvaluationContext *m_evalContext;
ResolvedProjectPtr m_resolvedProject;
QSet<BuildProductPtr> m_buildProducts;
ArtifactList m_dependencyArtifacts;
@@ -154,54 +154,24 @@ private:
class BuildGraph
{
public:
- class EngineInitializer
- {
- public:
- EngineInitializer(BuildGraph *bg);
- ~EngineInitializer();
-
- private:
- BuildGraph *buildGraph;
- };
-
- BuildGraph();
- ~BuildGraph();
-
- void setEngine(ScriptEngine *engine);
- ScriptEngine *engine() { return m_engine; }
-
- void setProgressObserver(ProgressObserver *observer);
- ProgressObserver *observer() const { return m_progressObserver; }
-
static bool findPath(Artifact *u, Artifact *v, QList<Artifact*> &path);
static void connect(Artifact *p, Artifact *c);
static void loggedConnect(Artifact *u, Artifact *v);
static bool safeConnect(Artifact *u, Artifact *v);
static void removeGeneratedArtifactFromDisk(Artifact *artifact);
-
- static void setupScriptEngineForProduct(ScriptEngine *scriptEngine,
- const ResolvedProductConstPtr &product,
- RuleConstPtr rule, QScriptValue targetObject);
static void disconnect(Artifact *u, Artifact *v);
+ static void setupScriptEngineForProduct(ScriptEngine *engine,
+ const ResolvedProductConstPtr &product, const RuleConstPtr &rule,
+ QScriptValue targetObject);
private:
- void initEngine();
- void cleanupEngine();
-
- ProgressObserver *m_progressObserver;
- ScriptEngine *m_engine;
- unsigned int m_initEngineCalls;
- QScriptValue m_scope;
- QScriptValue m_prepareScriptScope;
-
- friend class EngineInitializer;
+ BuildGraph();
};
class RulesApplicator
{
public:
- RulesApplicator(BuildProduct *product, ArtifactsPerFileTagMap &artifactsPerFileTag,
- ScriptEngine *engine, ProgressObserver *observer);
+ RulesApplicator(BuildProduct *product, ArtifactsPerFileTagMap &artifactsPerFileTag);
void applyAllRules();
void applyRule(const RuleConstPtr &rule);
@@ -211,13 +181,12 @@ private:
Artifact *createOutputArtifact(const RuleArtifactConstPtr &ruleArtifact,
const ArtifactList &inputArtifacts);
QString resolveOutPath(const QString &path) const;
-
+ RulesEvaluationContext *evalContext() const;
+ ScriptEngine *engine() const;
QScriptValue scope() const;
BuildProduct * const m_buildProduct;
ArtifactsPerFileTagMap &m_artifactsPerFileTag;
- ScriptEngine * const m_engine;
- ProgressObserver * const m_observer;
RuleConstPtr m_rule;
TransformerPtr m_transformer;
@@ -227,17 +196,16 @@ class BuildProjectResolver
{
public:
BuildProjectPtr resolveProject(const ResolvedProjectPtr &resolvedProject,
- BuildGraph *buildgraph, ProgressObserver *observer = 0);
+ RulesEvaluationContext *evalContext);
private:
BuildProductPtr resolveProduct(const ResolvedProductPtr &rProduct);
- BuildGraph *buildGraph() const { return m_project->buildGraph(); }
- ScriptEngine *engine() const { return buildGraph()->engine(); }
+ RulesEvaluationContext *evalContext() const;
+ ScriptEngine *engine() const;
QScriptValue scope() const;
BuildProjectPtr m_project;
- ProgressObserver *m_observer;
QHash<ResolvedProductPtr, BuildProductPtr> m_productCache;
};
@@ -253,8 +221,9 @@ public:
bool discardLoadedProject;
};
- LoadResult load(const QString &projectFilePath, BuildGraph *bg, const QString &buildRoot,
- const QVariantMap &cfg, const QStringList &loaderSearchPaths);
+ LoadResult load(const QString &projectFilePath, RulesEvaluationContext *evalContext,
+ const QString &buildRoot, const QVariantMap &cfg,
+ const QStringList &loaderSearchPaths);
private:
void onProductRemoved(const BuildProductPtr &product);
@@ -263,8 +232,7 @@ private:
void removeArtifactAndExclusiveDependents(Artifact *artifact,
QList<Artifact*> *removedArtifacts = 0);
- ScriptEngine *m_engine;
- ProgressObserver *m_observer;
+ RulesEvaluationContext *m_evalContext;
LoadResult m_result;
};
diff --git a/src/lib/buildgraph/buildgraph.pri b/src/lib/buildgraph/buildgraph.pri
index 2290df847..45d34ffec 100644
--- a/src/lib/buildgraph/buildgraph.pri
+++ b/src/lib/buildgraph/buildgraph.pri
@@ -15,7 +15,8 @@ SOURCES += \
$$PWD/inputartifactscanner.cpp \
$$PWD/artifactvisitor.cpp \
$$PWD/artifactcleaner.cpp \
- $$PWD/cycledetector.cpp
+ $$PWD/cycledetector.cpp \
+ $$PWD/rulesevaluationcontext.cpp
HEADERS += \
$$PWD/automoc.h\
@@ -35,4 +36,5 @@ HEADERS += \
$$PWD/artifactvisitor.h \
$$PWD/artifactcleaner.h \
$$PWD/cycledetector.h \
- $$PWD/forward_decls.h
+ $$PWD/forward_decls.h \
+ $$PWD/rulesevaluationcontext.h
diff --git a/src/lib/buildgraph/executor.cpp b/src/lib/buildgraph/executor.cpp
index 9d055c85f..df63aa111 100644
--- a/src/lib/buildgraph/executor.cpp
+++ b/src/lib/buildgraph/executor.cpp
@@ -34,6 +34,7 @@
#include "cycledetector.h"
#include "executorjob.h"
#include "inputartifactscanner.h"
+#include "rulesevaluationcontext.h"
#include <buildgraph/transformer.h>
#include <language/language.h>
@@ -87,13 +88,15 @@ private:
Executor::Executor(QObject *parent)
: QObject(parent)
- , m_engine(0)
+ , m_evalContext(new RulesEvaluationContext)
, m_progressObserver(0)
, m_state(ExecutorIdle)
{
m_inputArtifactScanContext = new InputArtifactScannerContext(&m_scanResultCache);
m_autoMoc = new AutoMoc;
m_autoMoc->setScanResultCache(&m_scanResultCache);
+ foreach (ExecutorJob *job, findChildren<ExecutorJob *>())
+ job->setMainThreadScriptEngine(m_evalContext->engine());
}
Executor::~Executor()
@@ -133,7 +136,6 @@ void Executor::build(const QList<BuildProductPtr> &productsToBuild)
void Executor::doBuild(const QList<BuildProductPtr> &productsToBuild)
{
Q_ASSERT(m_buildOptions.maxJobCount > 0);
- Q_ASSERT(m_engine);
Q_ASSERT(m_state == ExecutorIdle);
m_leaves.clear();
m_productsToBuild = productsToBuild;
@@ -143,10 +145,8 @@ void Executor::doBuild(const QList<BuildProductPtr> &productsToBuild)
QSet<BuildProject *> projects;
foreach (const BuildProductConstPtr &buildProduct, productsToBuild)
projects << buildProduct->project;
- foreach (BuildProject * const project, projects) {
- project->buildGraph()->setEngine(m_engine);
- project->buildGraph()->setProgressObserver(m_progressObserver);
- }
+ foreach (BuildProject * const project, projects)
+ project->setEvaluationContext(m_evalContext);
initializeArtifactsState();
setState(ExecutorRunning);
@@ -170,7 +170,7 @@ void Executor::doBuild(const QList<BuildProductPtr> &productsToBuild)
// prepare products
const QProcessEnvironment systemEnvironment = QProcessEnvironment::systemEnvironment();
foreach (BuildProductPtr product, m_productsToBuild)
- product->rProduct->setupBuildEnvironment(m_engine, systemEnvironment);
+ product->rProduct->setupBuildEnvironment(m_evalContext->engine(), systemEnvironment);
// find the root nodes
m_roots.clear();
@@ -196,16 +196,6 @@ void Executor::doBuild(const QList<BuildProductPtr> &productsToBuild)
}
}
-void Executor::setEngine(ScriptEngine *engine)
-{
- if (m_engine == engine)
- return;
-
- m_engine = engine;
- foreach (ExecutorJob *job, findChildren<ExecutorJob *>())
- job->setMainThreadScriptEngine(engine);
-}
-
void Executor::setBuildOptions(const BuildOptions &buildOptions)
{
m_buildOptions = buildOptions;
@@ -577,8 +567,7 @@ void Executor::addExecutorJobs(int jobNumber)
{
for (int i = 1; i <= jobNumber; i++) {
ExecutorJob *job = new ExecutorJob(this);
- if (m_engine)
- job->setMainThreadScriptEngine(m_engine);
+ job->setMainThreadScriptEngine(m_evalContext->engine());
job->setObjectName(QString(QLatin1String("J%1")).arg(i));
m_availableJobs.append(job);
connect(job, SIGNAL(error(QString)), this, SLOT(onProcessError(QString)));
@@ -606,7 +595,7 @@ void Executor::runAutoMoc()
foreach (const ResolvedModuleConstPtr &m, product->rProduct->modules) {
if (m->name == "qt/core") {
autoMocApplied = true;
- m_autoMoc->apply(product, m_engine, m_progressObserver);
+ m_autoMoc->apply(product);
break;
}
}
diff --git a/src/lib/buildgraph/executor.h b/src/lib/buildgraph/executor.h
index 918045308..7ddb66b9e 100644
--- a/src/lib/buildgraph/executor.h
+++ b/src/lib/buildgraph/executor.h
@@ -46,8 +46,8 @@ class AutoMoc;
class ExecutorJob;
class InputArtifactScannerContext;
class ProgressObserver;
+class RulesEvaluationContext;
class ScanResultCache;
-class ScriptEngine;
class Executor : public QObject
{
@@ -58,7 +58,6 @@ public:
void build(const QList<BuildProductPtr> &productsToBuild);
- void setEngine(ScriptEngine *engine);
void setBuildOptions(const BuildOptions &buildOptions);
void setProgressObserver(ProgressObserver *observer) { m_progressObserver = observer; }
@@ -96,7 +95,7 @@ private:
void cancelJobs();
void setupProgressObserver(bool mocWillRun);
- ScriptEngine *m_engine;
+ RulesEvaluationContext *m_evalContext;
BuildOptions m_buildOptions;
ProgressObserver *m_progressObserver;
QList<ExecutorJob*> m_availableJobs;
diff --git a/src/lib/buildgraph/rulesevaluationcontext.cpp b/src/lib/buildgraph/rulesevaluationcontext.cpp
new file mode 100644
index 000000000..9c5db3643
--- /dev/null
+++ b/src/lib/buildgraph/rulesevaluationcontext.cpp
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+#include "rulesevaluationcontext.h"
+
+#include "artifact.h"
+#include "buildgraph.h"
+#include "command.h"
+#include "transformer.h"
+#include <language/language.h>
+#include <language/scriptengine.h>
+#include <logging/translator.h>
+#include <tools/error.h>
+#include <tools/fileinfo.h>
+#include <tools/progressobserver.h>
+
+#include <QVariant>
+
+namespace qbs {
+namespace Internal {
+
+RulesEvaluationContext::RulesEvaluationContext()
+ : m_engine(new ScriptEngine), m_observer(0), m_initScopeCalls(0)
+{
+ m_prepareScriptScope = m_engine->newObject();
+ ProcessCommand::setupForJavaScript(m_prepareScriptScope);
+ JavaScriptCommand::setupForJavaScript(m_prepareScriptScope);
+}
+
+RulesEvaluationContext::~RulesEvaluationContext()
+{
+ delete m_engine;
+}
+
+void RulesEvaluationContext::initializeObserver(const QString &description, int maximumProgress)
+{
+ if (m_observer)
+ m_observer->initialize(description, maximumProgress);
+}
+
+void RulesEvaluationContext::incrementProgressValue()
+{
+ if (m_observer)
+ m_observer->incrementProgressValue();
+}
+
+void RulesEvaluationContext::checkForCancelation()
+{
+ if (m_observer && m_observer->canceled())
+ throw Error(Tr::tr("Build canceled."));
+}
+
+void RulesEvaluationContext::initScope()
+{
+ if (m_initScopeCalls++ > 0)
+ return;
+
+ m_engine->setProperty("lastSetupProject", QVariant());
+ m_engine->setProperty("lastSetupProduct", QVariant());
+
+ m_engine->clearImportsCache();
+ m_engine->pushContext();
+ m_scope = m_engine->newObject();
+ m_scope.setPrototype(m_prepareScriptScope);
+ m_engine->currentContext()->pushScope(m_scope);
+}
+
+void RulesEvaluationContext::cleanupScope()
+{
+ Q_ASSERT(m_initScopeCalls > 0);
+ if (--m_initScopeCalls > 0)
+ return;
+
+ m_scope = QScriptValue();
+ m_engine->currentContext()->popScope();
+ m_engine->popContext();
+}
+
+RulesEvaluationContext::Scope::Scope(RulesEvaluationContext *evalContext)
+ : m_evalContext(evalContext)
+{
+ evalContext->initScope();
+}
+
+RulesEvaluationContext::Scope::~Scope()
+{
+ m_evalContext->cleanupScope();
+}
+
+} // namespace Internal
+} // namespace qbs
diff --git a/src/lib/buildgraph/rulesevaluationcontext.h b/src/lib/buildgraph/rulesevaluationcontext.h
new file mode 100644
index 000000000..2395cc34f
--- /dev/null
+++ b/src/lib/buildgraph/rulesevaluationcontext.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+#ifndef QBS_RULESEVALUATIONCONTEXT_H
+#define QBS_RULESEVALUATIONCONTEXT_H
+
+#include <language/forward_decls.h>
+
+#include <QScriptValue>
+
+namespace qbs {
+namespace Internal {
+class ProgressObserver;
+class ScriptEngine;
+
+class RulesEvaluationContext
+{
+public:
+ RulesEvaluationContext();
+ ~RulesEvaluationContext();
+
+ class Scope
+ {
+ public:
+ Scope(RulesEvaluationContext *evalContext);
+ ~Scope();
+
+ private:
+ RulesEvaluationContext * const m_evalContext;
+ };
+
+ ScriptEngine *engine() const { return m_engine; }
+ QScriptValue scope() const { return m_scope; }
+
+ void setObserver(ProgressObserver *observer) { m_observer = observer; }
+ void initializeObserver(const QString &description, int maximumProgress);
+ void incrementProgressValue();
+ void checkForCancelation();
+
+private:
+ friend class Scope;
+
+ void initScope();
+ void cleanupScope();
+
+ ScriptEngine * const m_engine;
+ ProgressObserver *m_observer;
+ unsigned int m_initScopeCalls;
+ QScriptValue m_scope;
+ QScriptValue m_prepareScriptScope;
+};
+
+} // namespace Internal
+} // namespace qbs
+
+#endif // QBS_RULESEVALUATIONCONTEXT_H