aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJake Petroules <jake.petroules@qt.io>2017-09-19 00:41:19 -0700
committerJake Petroules <jake.petroules@qt.io>2017-09-20 00:39:43 +0000
commit923854e45bb29f3adb045c73ed0841730d838867 (patch)
tree152bbcf73eefd008f9329019b3fba2e5b205ed1e
parent848ce26d155ac4fe79399c93bf455cae816bdc47 (diff)
Add a PropertyListVariableExpander class
This allows us to control exactly what warning message is displayed when the expandPlistEnvironmentVariables function encounters an unknown variable replacement, as opposed to whether or not a hardcoded message is shown. We use this new functionality in the Info.plist processor in order to give a much clearer message what went wrong and where the user might look to correct it. Change-Id: I967ea87c837f9aa2b67bad292e392b356fee8bed Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
-rw-r--r--share/qbs/imports/qbs/DarwinTools/darwin-tools.js161
-rw-r--r--share/qbs/modules/bundle/BundleModule.qbs17
2 files changed, 105 insertions, 73 deletions
diff --git a/share/qbs/imports/qbs/DarwinTools/darwin-tools.js b/share/qbs/imports/qbs/DarwinTools/darwin-tools.js
index b0f0bdc52..95e8dab25 100644
--- a/share/qbs/imports/qbs/DarwinTools/darwin-tools.js
+++ b/share/qbs/imports/qbs/DarwinTools/darwin-tools.js
@@ -139,87 +139,104 @@ function _resourceFileProperties(path) {
return [ undefined, '.' ];
}
-/**
- * Recursively perform variable replacements in an environment dictionary.
- *
- * JSON.stringify(expandPlistEnvironmentVariables({a:"$(x)3$$(y)",b:{t:"%$(y) $(k)"}},
- * {x:"X",y:"Y"}, true))
- * Warning undefined variable k in variable expansion
- * => {"a":"X3$Y","b":{"t":"%Y $(k)"}}
- */
-function expandPlistEnvironmentVariables(obj, env, warn) {
- // Possible syntaxes for wrapping an environment variable name
- var syntaxes = [
- {"open": "${", "close": "}"},
- {"open": "$(", "close": ")"},
- {"open": "@", "close": "@"}
- ];
-
+var PropertyListVariableExpander = (function () {
+ function PropertyListVariableExpander() {
+ }
/**
- * Finds the first index of a replacement starting with one of the supported syntaxes
- * This is needed so we don't do recursive substitutions
+ * Recursively perform variable replacements in an environment dictionary.
*/
- function indexOfReplacementStart(syntaxes, str, offset) {
- var syntax;
- var idx = str.length;
- for (var i in syntaxes) {
- var j = str.indexOf(syntaxes[i].open, offset);
- if (j !== -1 && j < idx) {
- syntax = syntaxes[i];
- idx = j;
+ PropertyListVariableExpander.prototype.expand = function (obj, env) {
+ var $this = this;
+
+ // Possible syntaxes for wrapping an environment variable name
+ var syntaxes = [
+ {"open": "${", "close": "}"},
+ {"open": "$(", "close": ")"},
+ {"open": "@", "close": "@"}
+ ];
+
+ /**
+ * Finds the first index of a replacement starting with one of the supported syntaxes
+ * This is needed so we don't do recursive substitutions
+ */
+ function indexOfReplacementStart(syntaxes, str, offset) {
+ var syntax;
+ var idx = str.length;
+ for (var i in syntaxes) {
+ var j = str.indexOf(syntaxes[i].open, offset);
+ if (j !== -1 && j < idx) {
+ syntax = syntaxes[i];
+ idx = j;
+ }
}
+ return { "syntax": syntax, "index": idx === str.length ? -1 : idx };
}
- return { "syntax": syntax, "index": idx === str.length ? -1 : idx };
- }
- function expandRecursive(obj, env, checked) {
- checked.push(obj);
- for (var key in obj) {
- var value = obj[key];
- var type = typeof(value);
- if (type === "object") {
- if (checked.indexOf(value) !== -1)
+ function expandRecursive(obj, env, checked) {
+ checked.push(obj);
+ for (var key in obj) {
+ var value = obj[key];
+ var type = typeof(value);
+ if (type === "object") {
+ if (checked.indexOf(value) !== -1)
+ continue;
+ expandRecursive(value, env, checked);
+ }
+ if (type !== "string")
continue;
- expandRecursive(value, env, checked);
- }
- if (type !== "string")
- continue;
- var repl = indexOfReplacementStart(syntaxes, value);
- var i = repl.index;
- var changes = false;
- while (i !== -1) {
- var j = value.indexOf(repl.syntax.close, i + repl.syntax.open.length);
- if (j === -1)
- break;
- var varParts = value.slice(i + repl.syntax.open.length, j).split(':');
- var varName = varParts[0];
- var varFormatter = varParts[1];
- var varValue = env[varName];
- if (undefined === varValue) {
- // skip replacement
- if (warn)
- console.warn("undefined variable " + varName + " in variable expansion");
- i = j + repl.syntax.close.length;
- } else {
- changes = true;
- varValue = String(varValue);
- if (varFormatter !== undefined)
- varFormatter = varFormatter.toLowerCase();
- if (varFormatter === "rfc1034identifier")
- varValue = Utilities.rfc1034Identifier(varValue);
- value = value.slice(0, i) + varValue + value.slice(j + repl.syntax.close.length);
- // avoid recursive substitutions to avoid potentially infinite loops
- i += varValue.length;
+ var repl = indexOfReplacementStart(syntaxes, value);
+ var i = repl.index;
+ var changes = false;
+ while (i !== -1) {
+ var j = value.indexOf(repl.syntax.close, i + repl.syntax.open.length);
+ if (j === -1)
+ break;
+ var varParts = value.slice(i + repl.syntax.open.length, j).split(':');
+ var varName = varParts[0];
+ var varFormatter = varParts[1];
+ var varValue = env[varName];
+ if (undefined === varValue) {
+ // skip replacement
+ if ($this.undefinedVariableFunction)
+ $this.undefinedVariableFunction(key, varName);
+ i = j + repl.syntax.close.length;
+ } else {
+ changes = true;
+ varValue = String(varValue);
+ if (varFormatter !== undefined)
+ varFormatter = varFormatter.toLowerCase();
+ if (varFormatter === "rfc1034identifier")
+ varValue = Utilities.rfc1034Identifier(varValue);
+ value = value.slice(0, i) + varValue + value.slice(j + repl.syntax.close.length);
+ // avoid recursive substitutions to avoid potentially infinite loops
+ i += varValue.length;
+ }
+ repl = indexOfReplacementStart(syntaxes, value, i);
+ i = repl.index;
}
- repl = indexOfReplacementStart(syntaxes, value, i);
- i = repl.index;
+ if (changes)
+ obj[key] = value;
}
- if (changes)
- obj[key] = value;
}
- }
- expandRecursive(obj, env, []);
- return obj;
+ expandRecursive(obj, env, []);
+ return obj;
+ };
+ return PropertyListVariableExpander;
+}());
+
+/**
+ * JSON.stringify(expandPlistEnvironmentVariables({a:"$(x)3$$(y)",b:{t:"%$(y) $(k)"}},
+ * {x:"X",y:"Y"}, true))
+ * Warning undefined variable k in variable expansion
+ * => {"a":"X3$Y","b":{"t":"%Y $(k)"}}
+ */
+function expandPlistEnvironmentVariables(obj, env, warn) {
+ var expander = new PropertyListVariableExpander();
+ expander.undefinedVariableFunction = function (key, varName) {
+ if (warn)
+ console.warn("undefined variable " + varName + " in variable expansion");
+ };
+ return expander.expand(obj, env);
}
/**
diff --git a/share/qbs/modules/bundle/BundleModule.qbs b/share/qbs/modules/bundle/BundleModule.qbs
index e9f9128e2..b7f38559c 100644
--- a/share/qbs/modules/bundle/BundleModule.qbs
+++ b/share/qbs/modules/bundle/BundleModule.qbs
@@ -395,7 +395,22 @@ Module {
for (key in qmakeEnv)
env[key] = qmakeEnv[key];
- DarwinTools.expandPlistEnvironmentVariables(aggregatePlist, env, true);
+ var expander = new DarwinTools.PropertyListVariableExpander();
+ expander.undefinedVariableFunction = function (key, varName) {
+ var msg = "Info.plist variable expansion encountered undefined variable '"
+ + varName + "' when expanding value for key '" + key
+ + "', defined in one of the following files:\n\t";
+ var allFilePaths = [];
+ for (i in infoPlistFiles)
+ allFilePaths.push(infoPlistFiles[i].filePath);
+ if (platformInfoPlist)
+ allFilePaths.push(platformInfoPlist);
+ msg += allFilePaths.join("\n\t") + "\n";
+ msg += "or in the bundle.infoPlist property of product '"
+ + product.name + "'";
+ console.warn(msg);
+ };
+ aggregatePlist = expander.expand(aggregatePlist, env);
// Add keys from partial Info.plists from asset catalogs, XIBs, and storyboards
for (i in partialInfoPlistFiles) {