diff options
author | Joerg Bornemann <joerg.bornemann@digia.com> | 2014-07-18 15:46:21 +0200 |
---|---|---|
committer | Joerg Bornemann <joerg.bornemann@digia.com> | 2014-07-22 12:26:07 +0200 |
commit | 38a47ae98b37ec3b2062763f04a083e1592905f5 (patch) | |
tree | 8c19e8615c04b5822d7bc630e5aac95838f78e67 | |
parent | 2d94c00ba8ffd902ffc25254a19d982ea6b0896e (diff) |
make it possible to set module properties on artifacts in outputArtifacts
Example:
outputArtifacts: {
return [{
fileTags: "blubb",
filePath: "x",
cpp: {
includePaths: "mydir"
defines: ["BLA", "BLUBB"]
}
}]
}
Task-number: QBS-646
Change-Id: I3defa656e1a5b10fe56e4bbba7c354612144552c
Reviewed-by: Christian Kandeler <christian.kandeler@digia.com>
4 files changed, 88 insertions, 1 deletions
diff --git a/src/lib/corelib/buildgraph/rulesapplicator.cpp b/src/lib/corelib/buildgraph/rulesapplicator.cpp index 6d1e31a3d..f28b98e29 100644 --- a/src/lib/corelib/buildgraph/rulesapplicator.cpp +++ b/src/lib/corelib/buildgraph/rulesapplicator.cpp @@ -38,6 +38,7 @@ #include "transformer.h" #include <jsextensions/moduleproperties.h> #include <language/artifactproperties.h> +#include <language/builtindeclarations.h> #include <language/language.h> #include <language/preparescriptobserver.h> #include <language/scriptengine.h> @@ -47,6 +48,7 @@ #include <tools/qbsassert.h> #include <QDir> +#include <QScriptValueIterator> namespace qbs { namespace Internal { @@ -378,6 +380,76 @@ QList<Artifact *> RulesApplicator::runOutputArtifactsScript(const ArtifactSet &i return lst; } +class ArtifactBindingsExtractor +{ + typedef QPair<QStringList, QVariant> NameValuePair; + QList<NameValuePair> m_propertyValues; + + static QSet<QString> getArtifactItemPropertyNames() + { + QSet<QString> s; + foreach (const PropertyDeclaration &pd, + BuiltinDeclarations().declarationsForType( + QLatin1String("Artifact")).properties()) { + s.insert(pd.name()); + } + s.insert(QLatin1String("explicitlyDependsOn")); + return s; + } + + void extractPropertyValues(const QScriptValue &obj, QStringList fullName = QStringList()) + { + QScriptValueIterator svit(obj); + while (svit.hasNext()) { + svit.next(); + const QString name = svit.name(); + if (fullName.isEmpty()) { + // Ignore property names that are part of the Artifact item. + static const QSet<QString> artifactItemPropertyNames + = getArtifactItemPropertyNames(); + if (artifactItemPropertyNames.contains(name)) + continue; + } + + const QScriptValue value = svit.value(); + fullName.append(name); + if (value.isObject() && !value.isArray() && !value.isError() && !value.isRegExp()) + extractPropertyValues(value, fullName); + else + m_propertyValues.append(NameValuePair(fullName, value.toVariant())); + fullName.removeLast(); + } + } +public: + ArtifactBindingsExtractor() + { + } + + void apply(Artifact *outputArtifact, const QScriptValue &obj) + { + extractPropertyValues(obj); + if (m_propertyValues.isEmpty()) + return; + + outputArtifact->properties = outputArtifact->properties->clone(); + QVariantMap artifactModulesCfg = outputArtifact->properties->value() + .value(QLatin1String("modules")).toMap(); + foreach (const NameValuePair &nvp, m_propertyValues) { + const QStringList &nameParts = nvp.first; + const QVariant &value = nvp.second; + if (!artifactModulesCfg.contains(nameParts.first())) { + throw ErrorInfo(Tr::tr("Can't set module property %1 on artifact %2.") + .arg(nameParts.join(QLatin1Char('.')), + outputArtifact->filePath())); + } + setConfigProperty(artifactModulesCfg, nameParts, value); + } + QVariantMap outputArtifactConfig = outputArtifact->properties->value(); + outputArtifactConfig.insert(QLatin1String("modules"), artifactModulesCfg); + outputArtifact->properties->setValue(outputArtifactConfig); + } +}; + Artifact *RulesApplicator::createOutputArtifactFromScriptValue(const QScriptValue &obj, const ArtifactSet &inputArtifacts) { @@ -396,6 +468,7 @@ Artifact *RulesApplicator::createOutputArtifactFromScriptValue(const QScriptValu loggedConnect(output, dependency, m_logger); } } + ArtifactBindingsExtractor().apply(output, obj); return output; } diff --git a/tests/auto/blackbox/testdata/dynamicRuleOutputs/after/numbers.l b/tests/auto/blackbox/testdata/dynamicRuleOutputs/after/numbers.l index b29f8798f..5c06e1258 100644 --- a/tests/auto/blackbox/testdata/dynamicRuleOutputs/after/numbers.l +++ b/tests/auto/blackbox/testdata/dynamicRuleOutputs/after/numbers.l @@ -40,6 +40,10 @@ %option noyywrap %{ +#ifndef CRUCIAL_DEFINE +# error CRUCIAL_DEFINE is missing! +#endif + /* need this for the call to atof() below */ #include <math.h> %} diff --git a/tests/auto/blackbox/testdata/dynamicRuleOutputs/before/genlexer.qbs b/tests/auto/blackbox/testdata/dynamicRuleOutputs/before/genlexer.qbs index 2c145682a..9fe553cb3 100644 --- a/tests/auto/blackbox/testdata/dynamicRuleOutputs/before/genlexer.qbs +++ b/tests/auto/blackbox/testdata/dynamicRuleOutputs/before/genlexer.qbs @@ -65,7 +65,10 @@ Project { var headerFileName = options["header-file"]; var result = [{ filePath: "GeneratedFiles/" + sourceFileName, - fileTags: ["c"] + fileTags: ["c"], + cpp: { + defines: ["CRUCIAL_DEFINE"] + } }]; if (headerFileName) { result.push({ @@ -95,6 +98,9 @@ Project { fhdr.write("// a rather empty header file\n"); fhdr.close(); } + fsrc.write("\n#ifndef CRUCIAL_DEFINE\n"); + fsrc.write("# error CRUCIAL_DEFINE is missing!\n"); + fsrc.write("#endif\n\n"); fsrc.write("int main() { return 0; }\n"); fsrc.close(); }; diff --git a/tests/auto/blackbox/testdata/dynamicRuleOutputs/before/numbers.l b/tests/auto/blackbox/testdata/dynamicRuleOutputs/before/numbers.l index 19f503562..fbc134ee7 100644 --- a/tests/auto/blackbox/testdata/dynamicRuleOutputs/before/numbers.l +++ b/tests/auto/blackbox/testdata/dynamicRuleOutputs/before/numbers.l @@ -41,6 +41,10 @@ %option outfile="numberscanner.c" header-file="numberscanner.h" %{ +#ifndef CRUCIAL_DEFINE +# error CRUCIAL_DEFINE is missing! +#endif + /* need this for the call to atof() below */ #include <math.h> %} |