diff options
| author | Joerg Bornemann <joerg.bornemann@digia.com> | 2013-03-30 12:31:05 +0100 |
|---|---|---|
| committer | Joerg Bornemann <joerg.bornemann@digia.com> | 2013-04-03 15:18:32 +0200 |
| commit | 9f71bd40503001cb593ec113d16f9212263d4723 (patch) | |
| tree | 34bd763e314a02f8c07cb717c537853e76b41f50 | |
| parent | a44efdd72349a5d2fcb1bb77cf729a84e712f74e (diff) | |
| download | qbs-9f71bd40503001cb593ec113d16f9212263d4723.tar.gz | |
introduce product.dependencies property
It is now possible to access the dependencies of a product or module.
Entry point for the tree of dependencies is product.dependencies which
returns a list of objects that represent products/modules the product
depends on.
Blackbox test added.
Change-Id: I0c2728da479e8cc45ca3994d7e4a9e7a41802aa1
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@digia.com>
Reviewed-by: Christian Kandeler <christian.kandeler@digia.com>
| -rw-r--r-- | src/lib/buildgraph/buildgraph.cpp | 123 | ||||
| -rw-r--r-- | tests/auto/blackbox/testdata/dependenciesProperty/dependenciesProperty.qbs | 37 | ||||
| -rw-r--r-- | tests/auto/blackbox/testdata/dependenciesProperty/product2.cpp | 1 | ||||
| -rw-r--r-- | tests/auto/blackbox/tst_blackbox.cpp | 47 | ||||
| -rw-r--r-- | tests/auto/blackbox/tst_blackbox.h | 1 |
5 files changed, 200 insertions, 9 deletions
diff --git a/src/lib/buildgraph/buildgraph.cpp b/src/lib/buildgraph/buildgraph.cpp index 3ec381e0e..81e01cc51 100644 --- a/src/lib/buildgraph/buildgraph.cpp +++ b/src/lib/buildgraph/buildgraph.cpp @@ -44,6 +44,119 @@ namespace qbs { namespace Internal { +static void setupProductScriptValue(ScriptEngine *engine, QScriptValue &productScriptValue, + const ResolvedProductConstPtr &product, + ScriptPropertyObserver *observer); + +class DependenciesFunction +{ +public: + DependenciesFunction(ScriptEngine *engine) + : m_engine(engine) + { + } + + void init(QScriptValue &productScriptValue, const ResolvedProductConstPtr &product) + { + QScriptValue depfunc = m_engine->newFunction(&js_productDependencies); + setProduct(depfunc, product.data()); + QScriptValue descriptor = m_engine->newObject(); + descriptor.setProperty(QLatin1String("get"), depfunc); + descriptor.setProperty(QLatin1String("set"), m_engine->evaluate("(function(){})")); + descriptor.setProperty(QLatin1String("enumerable"), true); + m_engine->defineProperty(productScriptValue, QLatin1String("dependencies"), descriptor); + } + +private: + static QScriptValue js_productDependencies(QScriptContext *context, QScriptEngine *engine) + { + QScriptValue callee = context->callee(); + const ResolvedProduct * const product = getProduct(callee); + QScriptValue result = engine->newArray(); + quint32 idx = 0; + foreach (const ResolvedProductPtr &dependency, product->dependencies) { + QScriptValue obj = engine->newObject(); + setupProductScriptValue(static_cast<ScriptEngine *>(engine), obj, dependency, 0); + result.setProperty(idx++, obj); + } + foreach (const ResolvedModuleConstPtr &dependency, product->modules) { + QScriptValue obj = engine->newObject(); + setupModuleScriptValue(static_cast<ScriptEngine *>(engine), obj, + product->properties->value(), dependency->name); + result.setProperty(idx++, obj); + } + return result; + } + + static QScriptValue js_moduleDependencies(QScriptContext *context, QScriptEngine *engine) + { + QScriptValue callee = context->callee(); + const QVariantMap modulesMap = callee.data().toVariant().toMap(); + QScriptValue result = engine->newArray(); + quint32 idx = 0; + for (QVariantMap::const_iterator it = modulesMap.begin(); it != modulesMap.end(); ++it) { + QScriptValue obj = engine->newObject(); + obj.setProperty(QLatin1String("name"), it.key()); + setupModuleScriptValue(static_cast<ScriptEngine *>(engine), obj, it.value().toMap(), + it.key()); + result.setProperty(idx++, obj); + } + return result; + } + + static void setupModuleScriptValue(ScriptEngine *engine, QScriptValue &moduleScriptValue, + const QVariantMap &propertyMap, + const QString &moduleName) + { + const QVariantMap propMap + = propertyMap.value(QLatin1String("modules")).toMap().value(moduleName).toMap(); + for (QVariantMap::ConstIterator it = propMap.constBegin(); it != propMap.constEnd(); ++it) { + const QVariant &value = it.value(); + if (value.isValid() && !value.canConvert<QVariantMap>()) + moduleScriptValue.setProperty(it.key(), engine->toScriptValue(value)); + } + QScriptValue depfunc = engine->newFunction(&js_moduleDependencies); + depfunc.setData(engine->toScriptValue(propMap.value(QLatin1String("modules")))); + QScriptValue descriptor = engine->newObject(); + descriptor.setProperty(QLatin1String("get"), depfunc); + descriptor.setProperty(QLatin1String("set"), engine->evaluate("(function(){})")); + descriptor.setProperty(QLatin1String("enumerable"), true); + engine->defineProperty(moduleScriptValue, QLatin1String("dependencies"), descriptor); + moduleScriptValue.setProperty(QLatin1String("dependencies"), depfunc); + moduleScriptValue.setProperty(QLatin1String("type"), QLatin1String("module")); + } + + static void setProduct(QScriptValue scriptValue, const ResolvedProduct *product) + { + QVariant v; + v.setValue<quintptr>(reinterpret_cast<quintptr>(product)); + scriptValue.setData(scriptValue.engine()->newVariant(v)); + } + + static const ResolvedProduct *getProduct(const QScriptValue &scriptValue) + { + const quintptr ptr = scriptValue.data().toVariant().value<quintptr>(); + return reinterpret_cast<const ResolvedProduct *>(ptr); + } + + ScriptEngine *m_engine; +}; + +static void setupProductScriptValue(ScriptEngine *engine, QScriptValue &productScriptValue, + const ResolvedProductConstPtr &product, + ScriptPropertyObserver *observer) +{ + ModuleProperties::init(productScriptValue, product); + DependenciesFunction(engine).init(productScriptValue, product); + const QVariantMap &propMap = product->properties->value(); + for (QVariantMap::ConstIterator it = propMap.constBegin(); it != propMap.constEnd(); ++it) { + const QVariant &value = it.value(); + if (value.isValid() && !value.canConvert<QVariantMap>()) + engine->setObservedProperty(productScriptValue, it.key(), + engine->toScriptValue(value), observer); + } +} + void setupScriptEngineForProduct(ScriptEngine *engine, const ResolvedProductConstPtr &product, const RuleConstPtr &rule, QScriptValue targetObject, ScriptPropertyObserver *observer) @@ -81,15 +194,7 @@ void setupScriptEngineForProduct(ScriptEngine *engine, const ResolvedProductCons engine->setProperty("_qbs_procenv", v); } productScriptValue = engine->newObject(); - ModuleProperties::init(productScriptValue, product); - const QVariantMap &propMap = product->properties->value(); - for (QVariantMap::ConstIterator it = propMap.constBegin(); it != propMap.constEnd(); ++it) { - const QVariant &value = it.value(); - if (value.isValid() && !value.canConvert<QVariantMap>()) - engine->setObservedProperty(productScriptValue, it.key(), - engine->toScriptValue(value), observer); - } - + setupProductScriptValue(engine, productScriptValue, product, observer); targetObject.setProperty("product", productScriptValue); } else { productScriptValue = targetObject.property("product"); diff --git a/tests/auto/blackbox/testdata/dependenciesProperty/dependenciesProperty.qbs b/tests/auto/blackbox/testdata/dependenciesProperty/dependenciesProperty.qbs new file mode 100644 index 000000000..96058f107 --- /dev/null +++ b/tests/auto/blackbox/testdata/dependenciesProperty/dependenciesProperty.qbs @@ -0,0 +1,37 @@ +import qbs 1.0 +import qbs.fileinfo as FileInfo + +Project { + Product { + type: "deps" + name: "product1" + Depends { name: "product2" } + Transformer { + Artifact { + fileTags: ["deps"] + fileName: product.name + '.deps' + } + prepare: { + var cmd = new JavaScriptCommand(); + cmd.description = 'generate ' + FileInfo.fileName(output.fileName); + cmd.highlight = 'codegen'; + cmd.content = JSON.stringify(product.dependencies); + cmd.sourceCode = function() { + file = new TextFile(output.fileName, TextFile.WriteOnly); + file.truncate(); + file.write(content); + file.close(); + } + return cmd; + } + } + } + Product { + type: "application" + name: "product2" + property string narf: "zort" + Depends { name: "cpp" } + cpp.defines: ["SMURF"] + files: ["product2.cpp"] + } +} diff --git a/tests/auto/blackbox/testdata/dependenciesProperty/product2.cpp b/tests/auto/blackbox/testdata/dependenciesProperty/product2.cpp new file mode 100644 index 000000000..76e819701 --- /dev/null +++ b/tests/auto/blackbox/testdata/dependenciesProperty/product2.cpp @@ -0,0 +1 @@ +int main() { return 0; } diff --git a/tests/auto/blackbox/tst_blackbox.cpp b/tests/auto/blackbox/tst_blackbox.cpp index 937421f3e..2540cdfd6 100644 --- a/tests/auto/blackbox/tst_blackbox.cpp +++ b/tests/auto/blackbox/tst_blackbox.cpp @@ -35,6 +35,8 @@ #include <QLocale> #include <QTemporaryFile> +#include <QScriptEngine> +#include <QScriptValue> #if QT_VERSION >= 0x050000 #define SKIP_TEST(message) QSKIP(message) @@ -245,6 +247,51 @@ void TestBlackbox::build_project_dry_run() QVERIFY2(buildDirContents.isEmpty(), qPrintable(buildDirContents.join(" "))); } +void TestBlackbox::dependenciesProperty() +{ + QDir::setCurrent(testDataDir + QLatin1String("/dependenciesProperty")); + QCOMPARE(runQbs(), 0); + QFile depsFile(buildDir + QLatin1String("/product1.deps")); + QVERIFY(depsFile.open(QFile::ReadOnly)); + QString deps = QString::fromLatin1(depsFile.readAll()); + QVERIFY(!deps.isEmpty()); + QScriptEngine scriptEngine; + QScriptValue scriptValue = scriptEngine.evaluate(deps); + QScriptValue product2; + QScriptValue qbs; + int c = scriptValue.property(QLatin1String("length")).toInt32(); + QCOMPARE(c, 2); + for (int i = 0; i < c; ++i) { + QScriptValue dep = scriptValue.property(i); + QString name = dep.property(QLatin1String("name")).toVariant().toString(); + if (name == QLatin1String("product2")) + product2 = dep; + else if (name == QLatin1String("qbs")) + qbs = dep; + } + QVERIFY(qbs.isObject()); + QVERIFY(product2.isObject()); + QCOMPARE(product2.property(QLatin1String("type")).toString(), QLatin1String("application")); + QCOMPARE(product2.property(QLatin1String("narf")).toString(), QLatin1String("zort")); + QScriptValue product2_deps = product2.property(QLatin1String("dependencies")); + QVERIFY(product2_deps.isObject()); + c = product2_deps.property(QLatin1String("length")).toInt32(); + QCOMPARE(c, 2); + QScriptValue product2_qbs; + QScriptValue product2_cpp; + for (int i = 0; i < c; ++i) { + QScriptValue dep = product2_deps.property(i); + QString name = dep.property(QLatin1String("name")).toVariant().toString(); + if (name == QLatin1String("cpp")) + product2_cpp = dep; + else if (name == QLatin1String("qbs")) + product2_qbs = dep; + } + QVERIFY(product2_qbs.isObject()); + QVERIFY(product2_cpp.isObject()); + QCOMPARE(product2_cpp.property("defines").toString(), QLatin1String("SMURF")); +} + void TestBlackbox::resolve_project_data() { return build_project_data(); diff --git a/tests/auto/blackbox/tst_blackbox.h b/tests/auto/blackbox/tst_blackbox.h index d1d32e05e..c67aad5ab 100644 --- a/tests/auto/blackbox/tst_blackbox.h +++ b/tests/auto/blackbox/tst_blackbox.h @@ -65,6 +65,7 @@ private slots: void build_project(); void build_project_dry_run_data(); void build_project_dry_run(); + void dependenciesProperty(); void resolve_project_data(); void resolve_project(); void resolve_project_dry_run_data(); |
