aboutsummaryrefslogtreecommitdiffstats
path: root/share
diff options
context:
space:
mode:
authorJake Petroules <jake.petroules@petroules.com>2014-04-01 11:52:08 -0400
committerJoerg Bornemann <joerg.bornemann@digia.com>2014-04-25 17:52:56 +0200
commit1dab72cfbf45ec6a47697d92fcad9f1b77a3e205 (patch)
tree39067ed2190262d25b92a6d0294c0cf2e2e43957 /share
parent7b81ad2adb32fe5d5b233bbc2bda8948224d778a (diff)
Add support for building and running TypeScript apps through Node.js.
Change-Id: I13f4d1e7d994cc5c52a0a0d80e1db1de0c710376 Reviewed-by: Joerg Bornemann <joerg.bornemann@digia.com>
Diffstat (limited to 'share')
-rw-r--r--share/qbs/modules/typescript/TypeScriptModule.qbs267
1 files changed, 267 insertions, 0 deletions
diff --git a/share/qbs/modules/typescript/TypeScriptModule.qbs b/share/qbs/modules/typescript/TypeScriptModule.qbs
new file mode 100644
index 000000000..531e5c30b
--- /dev/null
+++ b/share/qbs/modules/typescript/TypeScriptModule.qbs
@@ -0,0 +1,267 @@
+import qbs
+import qbs.File
+import qbs.FileInfo
+import qbs.ModUtils
+import qbs.Process
+
+Module {
+ Depends { name: "nodejs" }
+
+ additionalProductTypes: ["compiled_typescript"]
+
+ property path toolchainInstallPath
+ property string version: {
+ var p = new Process();
+ p.exec(compilerPath, ["--version"]);
+ var match = p.readStdOut().match(/^Version ([0-9]+(\.[0-9]+){1,3})\n$/);
+ if (match !== null)
+ return match[1];
+ }
+
+ property var versionParts: version ? version.split('.').map(function(item) { return parseInt(item, 10); }) : []
+ property int versionMajor: versionParts[0]
+ property int versionMinor: versionParts[1]
+ property int versionPatch: versionParts[2]
+ property int versionBuild: versionParts[3]
+
+ property string compilerName: "tsc"
+ property string compilerPath: FileInfo.joinPaths(toolchainInstallPath, compilerName)
+
+ property string warningLevel: "normal"
+ PropertyOptions {
+ name: "warningLevel"
+ description: "pedantic to warn on expressions and declarations with an implied 'any' type"
+ allowedValues: ["normal", "pedantic"]
+ }
+
+ property string targetVersion
+ PropertyOptions {
+ name: "targetVersion"
+ description: "ECMAScript target version"
+ allowedValues: ["ES3", "ES5"]
+ }
+
+ property string moduleLoader
+ PropertyOptions {
+ name: "moduleLoader"
+ allowedValues: ["commonjs", "amd"]
+ }
+
+ property bool stripComments: !qbs.debugInformation
+ PropertyOptions {
+ name: "stripComments"
+ description: "whether to remove comments from the generated output"
+ }
+
+ property bool generateDeclarations: false
+ PropertyOptions {
+ name: "generateDeclarations"
+ description: "whether to generate corresponding .d.ts files during compilation"
+ }
+
+ // In release mode, nodejs can/should default-enable minification and obfuscation,
+ // making the source maps useless, so these default settings work out fine
+ property bool generateSourceMaps: qbs.debugInformation
+ PropertyOptions {
+ name: "generateSourceMaps"
+ description: "whether to generate corresponding .map files during compilation"
+ }
+
+ property stringList compilerFlags
+ PropertyOptions {
+ name: "compilerFlags"
+ description: "additional flags for the TypeScript compiler"
+ }
+
+ property bool singleFile: false
+ PropertyOptions {
+ name: "singleFile"
+ description: "whether to compile all source files to a single output file"
+ }
+
+ validate: {
+ var validator = new ModUtils.PropertyValidator("typescript");
+ validator.setRequiredProperty("version", version);
+ validator.setRequiredProperty("versionMajor", versionMajor);
+ validator.setRequiredProperty("versionMinor", versionMinor);
+ validator.setRequiredProperty("versionPatch", versionPatch);
+ validator.setRequiredProperty("versionBuild", versionBuild);
+ validator.addVersionValidator("version", version, 4, 4);
+ validator.addRangeValidator("versionMajor", versionMajor, 1);
+ validator.addRangeValidator("versionMinor", versionMinor, 0);
+ validator.addRangeValidator("versionPatch", versionPatch, 0);
+ validator.addRangeValidator("versionBuild", versionBuild, 0);
+ validator.validate();
+ }
+
+ setupBuildEnvironment: {
+ if (toolchainInstallPath) {
+ var v = new ModUtils.EnvironmentVariable("PATH", qbs.pathListSeparator, qbs.hostOS.contains("windows"));
+ v.prepend(toolchainInstallPath);
+ v.set();
+ }
+ }
+
+ // TypeScript declaration files
+ FileTagger {
+ patterns: ["*.d.ts"]
+ fileTags: ["typescript_declaration"]
+ }
+
+ // TypeScript source files
+ FileTagger {
+ patterns: ["*.ts"]
+ fileTags: ["typescript"]
+ }
+
+ Rule {
+ id: typescriptCompiler
+ multiplex: true
+ inputs: ["typescript"]
+ usings: ["typescript_declaration"]
+
+ outputArtifacts: {
+ var artifacts = [];
+
+ if (product.moduleProperty("typescript", "singleFile")) {
+ var jsTags = ["js", "compiled_typescript"];
+
+ // We could check
+ // if (product.moduleProperty("nodejs", "applicationFile") === inputs.typescript[i].filePath)
+ // but since we're compiling to a single file there's no need to state it explicitly
+ jsTags.push("application_js");
+
+ var filePath = FileInfo.joinPaths(product.destinationDirectory, product.targetName);
+
+ artifacts.push({fileTags: jsTags,
+ filePath: FileInfo.joinPaths(".obj", product.targetName, "typescript", filePath + ".js")});
+ artifacts.push({condition: product.moduleProperty("typescript", "generateDeclarations"), // ### QBS-412
+ fileTags: ["typescript_declaration"],
+ filePath: filePath + ".d.ts"});
+ artifacts.push({condition: product.moduleProperty("typescript", "generateSourceMaps"), // ### QBS-412
+ fileTags: ["source_map"],
+ filePath: filePath + ".js.map"});
+ } else {
+ for (var i = 0; i < inputs.typescript.length; ++i) {
+ var jsTags = ["js", "compiled_typescript"];
+ if (product.moduleProperty("nodejs", "applicationFile") === inputs.typescript[i].filePath)
+ jsTags.push("application_js");
+
+ var filePath = FileInfo.joinPaths(product.destinationDirectory, FileInfo.baseName(inputs.typescript[i].filePath));
+
+ artifacts.push({fileTags: jsTags,
+ filePath: FileInfo.joinPaths(".obj", product.targetName, "typescript", filePath + ".js")});
+ artifacts.push({condition: product.moduleProperty("typescript", "generateDeclarations"), // ### QBS-412
+ fileTags: ["typescript_declaration"],
+ filePath: filePath + ".d.ts"});
+ artifacts.push({condition: product.moduleProperty("typescript", "generateSourceMaps"), // ### QBS-412
+ fileTags: ["source_map"],
+ filePath: filePath + ".js.map"});
+ }
+ }
+
+ return artifacts;
+ }
+
+ outputFileTags: {
+ var fileTags = ["js", "compiled_typescript"];
+ if (product.moduleProperty("nodejs", "applicationFile"))
+ fileTags.push("application_js");
+ if (product.moduleProperty("typescript", "generateDeclarations"))
+ fileTags.push("typescript_declaration");
+ if (product.moduleProperty("typescript", "generateSourceMaps"))
+ fileTags.push("source_map");
+ return fileTags;
+ }
+
+ prepare: {
+ var i;
+ var args = [];
+
+ var primaryOutput = outputs.compiled_typescript[0];
+ var outDir = FileInfo.joinPaths(product.buildDirectory, product.destinationDirectory);
+
+ if (ModUtils.moduleProperty(product, "warningLevel") === "pedantic") {
+ args.push("--noImplicitAny");
+ }
+
+ var targetVersion = ModUtils.moduleProperty(product, "targetVersion");
+ if (targetVersion) {
+ args.push("--target");
+ args.push(targetVersion);
+ }
+
+ var moduleLoader = ModUtils.moduleProperty(product, "moduleLoader");
+ if (moduleLoader) {
+ if (ModUtils.moduleProperty(product, "singleFile")) {
+ throw("typescript.singleFile cannot be true when typescript.moduleLoader is set");
+ }
+
+ args.push("--module");
+ args.push(moduleLoader);
+ }
+
+ if (ModUtils.moduleProperty(product, "stripComments")) {
+ args.push("--removeComments");
+ }
+
+ if (ModUtils.moduleProperty(product, "generateDeclarations")) {
+ args.push("--declaration");
+ }
+
+ if (ModUtils.moduleProperty(product, "generateSourceMaps")) {
+ args.push("--sourcemap");
+ }
+
+ // User-supplied flags
+ var flags = ModUtils.moduleProperty(product, "compilerFlags");
+ for (i in flags) {
+ args.push(flags[i]);
+ }
+
+ args.push("--outDir");
+ args.push(outDir);
+
+ if (ModUtils.moduleProperty(product, "singleFile")) {
+ args.push("--out");
+ args.push(primaryOutput.filePath);
+ }
+
+ if (inputs.typescript_declaration) {
+ for (i = 0; i < inputs.typescript_declaration.length; ++i) {
+ args.push(inputs.typescript_declaration[i].filePath);
+ }
+ }
+
+ for (i = 0; i < inputs.typescript.length; ++i) {
+ args.push(inputs.typescript[i].filePath);
+ }
+
+ var cmd, cmds = [];
+
+ cmd = new Command(ModUtils.moduleProperty(product, "compilerPath"), args);
+ cmd.description = "compiling " + (ModUtils.moduleProperty(product, "singleFile")
+ ? FileInfo.fileName(primaryOutput.filePath)
+ : inputs.typescript.map(function(obj) { return FileInfo.fileName(obj.filePath) }).join(", "));
+ cmd.highlight = "compiler";
+ cmd.workingDirectory = outDir;
+ cmds.push(cmd);
+
+ // Move all the compiled TypeScript files to the proper intermediate directory
+ cmd = new JavaScriptCommand();
+ cmd.silent = true;
+ cmd.outDir = outDir;
+ cmd.sourceCode = function() {
+ for (i = 0; i < outputs.compiled_typescript.length; ++i) {
+ var fp = outputs.compiled_typescript[i].filePath;
+ var originalFilePath = FileInfo.joinPaths(outDir, FileInfo.fileName(fp));
+ File.copy(originalFilePath, fp);
+ File.remove(originalFilePath);
+ }
+ };
+ cmds.push(cmd);
+
+ return cmds;
+ }
+ }
+}