TypeScript/Jakefile
2014-07-12 15:32:26 -07:00

513 lines
17 KiB
JavaScript

// This file contains the build logic for the public repo
var fs = require("fs");
var path = require("path");
// Variables
var compilerDirectory = "src/compiler/";
var servicesDirectory = "src/services/";
var harnessDirectory = "src/harness/";
var runnersDirectory = "tests/runners/";
var libraryDirectory = "typings/";
var builtDirectory = "built/";
var builtLocalDirectory = "built/local/";
var builtTestDirectory = "built/localtest/";
var LKGDirectory = "bin/";
var copyright = "CopyrightNotice.txt";
var thirdParty = "ThirdPartyNoticeText.txt";
var compilerSources = [
"ast.ts",
"astHelpers.ts",
"astWalker.ts",
"base64.ts",
"bloomFilter.ts",
"declarationEmitter.ts",
"diagnostics.ts",
"document.ts",
"emitter.ts",
"enumerator.ts",
"flags.ts",
"hashTable.ts",
"identifierWalker.ts",
"pathUtils.ts",
"precompile.ts",
"process.ts",
"references.ts",
"referenceResolution.ts",
"referenceResolver.ts",
"settings.ts",
"sourceMapping.ts",
"syntaxTreeToAstVisitor.ts",
"types.ts",
"core/arrayUtilities.ts",
"core/bitVector.ts",
"core/bitMatrix.ts",
"core/constants.ts",
"core/debug.ts",
"core/diagnosticCore.ts",
"core/diagnosticCategory.ts",
"core/diagnosticInfo.ts",
"core/environment.ts",
"core/errors.ts",
"core/hash.ts",
"core/hashTable.ts",
"core/integerUtilities.ts",
"core/lineAndCharacter.ts",
"core/lineMap.ts",
"core/linePosition.ts",
"core/mathPrototype.ts",
"core/references.ts",
"core/require.ts",
"core/stringTable.ts",
"core/stringUtilities.ts",
"core/timer.ts",
"resources/diagnosticCode.generated.ts",
"resources/diagnosticInformationMap.generated.ts",
"resources/references.ts",
"syntax/characterInfo.ts",
"syntax/constants.ts",
"syntax/depthLimitedWalker.ts",
"syntax/formattingOptions.ts",
"syntax/indentation.ts",
"syntax/languageVersion.ts",
"syntax/parseOptions.ts",
"syntax/parser.ts",
"syntax/positionedElement.ts",
"syntax/positionTrackingWalker.ts",
"syntax/references.ts",
"syntax/scanner.ts",
"syntax/scannerUtilities.generated.ts",
"syntax/separatedSyntaxList.ts",
"syntax/slidingWindow.ts",
"syntax/strings.ts",
"syntax/syntax.ts",
"syntax/syntaxDedenter.ts",
"syntax/syntaxElement.ts",
"syntax/syntaxFactory.generated.ts",
"syntax/syntaxFacts.ts",
"syntax/syntaxFacts2.ts",
"syntax/syntaxIndenter.ts",
"syntax/syntaxInformationMap.ts",
"syntax/syntaxIndenter.ts",
"syntax/syntaxKind.ts",
"syntax/syntaxList.ts",
"syntax/syntaxNode.ts",
"syntax/syntaxNodeInvariantsChecker.ts",
"syntax/syntaxNodeOrToken.ts",
"syntax/syntaxNodes.generated.ts",
"syntax/syntaxRewriter.generated.ts",
"syntax/syntaxToken.generated.ts",
"syntax/syntaxToken.ts",
"syntax/syntaxTokenReplacer.ts",
"syntax/syntaxTree.ts",
"syntax/syntaxTrivia.ts",
"syntax/syntaxTriviaList.ts",
"syntax/syntaxUtilities.ts",
"syntax/syntaxVisitor.generated.ts",
"syntax/syntaxWalker.generated.ts",
"syntax/unicode.ts",
"text/characterCodes.ts",
"text/lineMap.ts",
"text/references.ts",
"text/scriptSnapshot.ts",
"text/text.ts",
"text/textChangeRange.ts",
"text/textFactory.ts",
"text/textLine.ts",
"text/textSpan.ts",
"text/textUtilities.ts",
"typecheck/pullDeclCollection.ts",
"typecheck/pullDecls.ts",
"typecheck/pullFlags.ts",
"typecheck/pullHelpers.ts",
"typecheck/pullInstantiationHelpers.ts",
"typecheck/pullSemanticInfo.ts",
"typecheck/pullSymbolBinder.ts",
"typecheck/pullSymbols.ts",
"typecheck/pullTypeResolution.ts",
"typecheck/pullTypeResolutionContext.ts",
"typecheck/pullTypeEnclosingTypeWalker.ts",
"typecheck/pullTypeInstantiation.ts",
"typescript.ts"
].map(function (f) {
return path.join(compilerDirectory, f);
});
var tscSources = [
"io.ts",
"optionsParser.ts",
"tsc.ts"
].map(function (f) {
return path.join(compilerDirectory, f);
});
var servicesSources = [
"braceMatcher.ts",
"breakpoints.ts",
"classifier.ts",
"compilerState.ts",
"completionHelpers.ts",
"completionSession.ts",
"coreServices.ts",
"getScriptLexicalStructureWalker.ts",
"diagnosticServices.ts",
"es5compat.ts",
"findReferenceHelpers.ts",
"indenter.ts",
"keywordCompletions.ts",
"languageService.ts",
"outliningElementsCollector.ts",
"pullLanguageService.ts",
"shims.ts",
"signatureInfoHelpers.ts",
"formatting/formatter.ts",
"formatting/formatting.ts",
"formatting/formattingContext.ts",
"formatting/formattingManager.ts",
"formatting/formattingRequestKind.ts",
"formatting/indentationNodeContext.ts",
"formatting/indentationNodeContextPool.ts",
"formatting/indentationTrackingWalker.ts",
"formatting/multipleTokenIndenter.ts",
"formatting/rule.ts",
"formatting/ruleAction.ts",
"formatting/ruleDescriptor.ts",
"formatting/ruleFlag.ts",
"formatting/ruleOperation.ts",
"formatting/ruleOperationContext.ts",
"formatting/rules.ts",
"formatting/rulesMap.ts",
"formatting/rulesProvider.ts",
"formatting/singleTokenIndenter.ts",
"formatting/snapshotPoint.ts",
"formatting/textEditInfo.ts",
"formatting/textSnapshot.ts",
"formatting/textSnapshotLine.ts",
"formatting/tokenRange.ts",
"formatting/tokenSpan.ts",
"typescriptServices.ts"
].map(function (f) {
return path.join(servicesDirectory, f);
});
var harnessSources = [
path.join(compilerDirectory, "io.ts"),
path.join(compilerDirectory, "optionsParser.ts"),
path.join(harnessDirectory, "exec.ts"),
path.join(harnessDirectory, "diff.ts"),
path.join(harnessDirectory, "harness.ts"),
path.join(harnessDirectory, "baselining.ts"),
path.join(harnessDirectory, "fourslash.ts"),
path.join(harnessDirectory, "runner.ts"),
path.join(runnersDirectory, "runnerBase.ts"),
path.join(runnersDirectory, "compiler/compilerRunner.ts"),
path.join(runnersDirectory, "compiler/typeWriter.ts"),
path.join(runnersDirectory, "fourslash/fourslashRunner.ts"),
path.join(runnersDirectory, "projects/projectsRunner.ts"),
path.join(runnersDirectory, "unittest/unittestRunner.ts"),
path.join(runnersDirectory, "rwc/rwcRunner.ts"),
path.join(runnersDirectory, "../cases/unittests/samples/samples.ts"),
path.join(runnersDirectory, "../cases/unittests/compiler/callSignatureTests.ts"),
path.join(runnersDirectory, "../cases/unittests/compiler/classOverloads.ts"),
path.join(runnersDirectory, "../cases/unittests/compiler/constructSignatureTests.ts"),
path.join(runnersDirectory, "../cases/unittests/compiler/declarationTests.ts"),
path.join(runnersDirectory, "../cases/unittests/compiler/functionSignaturesTests.ts"),
path.join(runnersDirectory, "../cases/unittests/compiler/identifiers.ts"),
path.join(runnersDirectory, "../cases/unittests/compiler/moduleAlias.ts"),
path.join(runnersDirectory, "../cases/unittests/compiler/pathing.ts"),
path.join(runnersDirectory, "../cases/unittests/compiler/propertySignatureTests.ts"),
];
var libraryFiles = [
"lib.d.ts",
"jquery.d.ts",
"winjs.d.ts",
"winrt.d.ts"
];
var librarySources = libraryFiles.map(function (f) {
return path.join(libraryDirectory, f);
});
var libraryTargets = libraryFiles.map(function (f) {
return path.join(builtLocalDirectory, f);
});
// Prepends the contents of prefixFile to destinationFile
function prependFile(prefixFile, destinationFile) {
if (!fs.existsSync(prefixFile)) {
fail(prefixFile + " does not exist!");
}
if (!fs.existsSync(destinationFile)) {
fail(destinationFile + " failed to be created!");
}
var temp = "temptemp";
jake.cpR(prefixFile, temp);
fs.appendFileSync(temp, fs.readFileSync(destinationFile));
fs.renameSync(temp, destinationFile);
}
var useDebugMode = false;
/* Compiles a file from a list of sources
* @param outFile: the target file name
* @param sources: an array of the names of the source files
* @param prereqs: prerequisite tasks to compiling the file
* @param prefixes: a list of files to prepend to the target file
* @param useBuiltCompiler: true to use the built compiler, false to use the LKG
*/
function compileFile(outFile, sources, prereqs, prefixes, useBuiltCompiler) {
file(outFile, prereqs, function() {
var dir = useBuiltCompiler ? builtLocalDirectory : LKGDirectory;
var cmd = (process.env.host || process.env.TYPESCRIPT_HOST || "node") + " " + dir + "tsc.js -removeComments -propagateEnumConstants -declaration -noImplicitAny --module commonjs " + sources.join(" ") + " -out " + outFile;
if (useDebugMode) {
cmd = cmd + " -sourcemap -mapRoot file:///" + path.resolve(path.dirname(outFile));
}
console.log(cmd + "\n");
var ex = jake.createExec([cmd]);
// Add listeners for output and error
ex.addListener("stdout", function(output) {
process.stdout.write(output);
});
ex.addListener("stderr", function(error) {
process.stderr.write(error);
});
ex.addListener("cmdEnd", function() {
if (!useDebugMode && prefixes && fs.existsSync(outFile)) {
for (var i in prefixes) {
prependFile(prefixes[i], outFile);
}
}
complete();
});
ex.addListener("error", function() {
fs.unlinkSync(outFile);
console.log("Compilation of " + outFile + " unsuccessful");
});
ex.run();
}, {async: true});
}
// Prerequisite task for built directory and library typings
directory(builtLocalDirectory);
for (var i in libraryTargets) {
(function (i) {
file(libraryTargets[i], [builtLocalDirectory, librarySources[i]], function() {
jake.cpR(librarySources[i], builtLocalDirectory);
});
})(i);
}
var typescriptFile = path.join(builtLocalDirectory, "typescript.js");
compileFile(typescriptFile, compilerSources, [builtLocalDirectory, copyright].concat(compilerSources), [copyright]);
var tscFile = path.join(builtLocalDirectory, "tsc.js");
compileFile(tscFile, compilerSources.concat(tscSources), [builtLocalDirectory, copyright].concat(compilerSources).concat(tscSources), [copyright]);
var serviceFile = path.join(builtLocalDirectory, "typescriptServices.js");
compileFile(serviceFile, compilerSources.concat(servicesSources), [builtLocalDirectory, thirdParty, copyright].concat(compilerSources).concat(servicesSources), [thirdParty, copyright]);
// Local target to build the compiler and services
desc("Builds the full compiler and services");
task("local", libraryTargets.concat([typescriptFile, tscFile, serviceFile]));
// Local target to build the compiler and services
desc("Emit debug mode files with sourcemaps");
task("setDebugMode", function() {
useDebugMode = true;
});
// Local target to build the compiler and services
desc("Builds the full compiler and services in debug mode");
task("local-debug", ["setDebugMode", "local"]);
// Set the default task to "local"
task("default", ["local"]);
// Cleans the built directory
desc("Cleans the compiler output, declare files, and tests");
task("clean", function() {
jake.rmRf(builtDirectory);
});
// Makes a new LKG. This target does not build anything, but errors if not all the outputs are present in the built/local directory
desc("Makes a new LKG out of the built js files");
task("LKG", libraryTargets, function() {
var expectedFiles = [typescriptFile, tscFile, serviceFile];
var missingFiles = expectedFiles.filter(function (f) {
return !fs.existsSync(f);
});
if (missingFiles.length > 0) {
fail("Cannot replace the LKG unless all built targets are present in directory " + builtLocalDirectory +
". The following files are missing:\n" + missingFiles.join("\n"));
}
// Copy all the targets into the LKG directory
jake.mkdirP(LKGDirectory);
for (var i in librarySources) {
jake.cpR(libraryTargets[i], LKGDirectory);
}
for (i in expectedFiles) {
jake.cpR(expectedFiles[i], LKGDirectory);
}
//var resourceDirectories = fs.readdirSync(builtLocalResourcesDirectory).map(function(p) { return path.join(builtLocalResourcesDirectory, p); });
//resourceDirectories.map(function(d) {
// jake.cpR(d, LKGResourcesDirectory);
//});
});
// Test directory
directory(builtTestDirectory);
// Task to build the tests infrastructure using the built compiler
var run = path.join(builtTestDirectory, "run.js");
var json2 = path.join(harnessDirectory, "external/json2.js")
compileFile(run, harnessSources, [builtTestDirectory, tscFile].concat(libraryTargets).concat(harnessSources), [json2], true);
// Webharness
var frontEndPath = "tests/cases/webharness/frontEnd.ts";
var perfCompilerPath = "tests/cases/webharness/perfCompiler.js";
compileFile(perfCompilerPath, [frontEndPath], [tscFile], [], true);
// Webhost
var webhostPath = "tests/cases/webhost/webtsc.ts";
var webhostJsPath = "tests/cases/webhost/webtsc.js";
desc("Builds the web host");
compileFile(webhostJsPath, [webhostPath], [tscFile, webhostPath], [], true);
desc("Builds the tsc web host");
task("webhost", [webhostJsPath], function() {
jake.cpR(path.join(libraryDirectory, "lib.d.ts"), "tests/cases/webhost");
});
// Fidelity Tests
var fidelityTestsOutFile = "tests/Fidelity/program.js";
var fidelityTestsInFile1 = "tests/Fidelity/Program.ts";
var fidelityTestsInFile2 = "tests/Fidelity/incremental/IncrementalParserTests.ts";
compileFile(fidelityTestsOutFile, [fidelityTestsInFile1], [tscFile, fidelityTestsInFile2].concat(compilerSources.concat(servicesSources)), [], true);
desc("Builds the web harness front end");
task("test-harness", [perfCompilerPath]);
var localBaseline = "tests/baselines/local/";
var refBaseline = "tests/baselines/reference/";
var localRwcBaseline = "tests/baselines/rwc/local/";
var refRwcBaseline = "tests/baselines/rwc/reference/";
desc("Builds the test infrastructure using the built compiler");
task("tests", [run, serviceFile, fidelityTestsOutFile, perfCompilerPath].concat(libraryTargets), function() {
// Copy the language service over to the test directory
jake.cpR(serviceFile, builtTestDirectory);
jake.cpR(path.join(libraryDirectory, "lib.d.ts"), builtTestDirectory);
jake.cpR(path.join(libraryDirectory, "lib.d.ts"), "tests/cases/webhost");
});
desc("Runs the tests using the built run.js file. Syntax is jake runtests. Optional parameters 'host=' and 'tests='.");
task("runtests", ["local", "tests", builtTestDirectory], function() {
// Clean the local baselines directory
if (fs.existsSync(localBaseline)) {
jake.rmRf(localBaseline);
}
// Clean the local Rwc baselines directory
if (fs.existsSync(localRwcBaseline)) {
jake.rmRf(localRwcBaseline);
}
jake.mkdirP(localBaseline);
host = process.env.host || process.env.TYPESCRIPT_HOST || "node";
tests = process.env.test || process.env.tests;
tests = tests ? tests.split(',').join(' ') : ([].slice.call(arguments).join(' ') || "");
var cmd = host + " " + run + " " + tests;
console.log(cmd);
var ex = jake.createExec([cmd]);
// Add listeners for output and error
ex.addListener("stdout", function(output) {
process.stdout.write(output);
});
ex.addListener("stderr", function(error) {
process.stderr.write(error);
});
ex.addListener("cmdEnd", function() {
complete();
});
ex.run();
}, {async: true});
desc("Builds the test sources and automation in debug mode");
task("tests-debug", ["setDebugMode", "tests"]);
// Makes the test results the new baseline
desc("Makes the most recent test results the new baseline, overwriting the old baseline");
task("baseline-accept", function(hardOrSoft) {
if (!hardOrSoft || hardOrSoft == "hard") {
jake.rmRf(refBaseline);
fs.renameSync(localBaseline, refBaseline);
}
else if (hardOrSoft == "soft") {
var files = jake.readdirR(localBaseline);
for (var i in files) {
jake.cpR(files[i], refBaseline);
}
jake.rmRf(path.join(refBaseline, "local"));
}
});
desc("Makes the most recent rwc test results the new baseline, overwriting the old baseline");
task("baseline-accept-rwc", function() {
jake.rmRf(refRwcBaseline);
fs.renameSync(localRwcBaseline, refRwcBaseline);
});
// Syntax Generator
var syntaxGeneratorOutFile = compilerDirectory + "syntax/SyntaxGenerator.js";
var syntaxGeneratorInFile = compilerDirectory + "syntax/SyntaxGenerator.ts";
file(compilerDirectory + "syntax/syntaxKind.ts");
file(compilerDirectory + "syntax/syntaxFacts.ts");
compileFile(syntaxGeneratorOutFile, [syntaxGeneratorInFile], [syntaxGeneratorInFile, compilerDirectory + "syntax/syntaxKind.ts", compilerDirectory + "syntax/syntaxFacts.ts"], [], /*useBuiltCompiler:*/ false);
desc("Builds and runs the syntax generator");
task("run-syntax-generator", [syntaxGeneratorOutFile], function() {
host = process.env.host || process.env.TYPESCRIPT_HOST || "node";
var cmd = host + " " + syntaxGeneratorOutFile;
console.log(cmd);
var ex = jake.createExec([cmd]);
// Add listeners for output and error
ex.addListener("stdout", function(output) {
process.stdout.write(output);
});
ex.addListener("stderr", function(error) {
process.stderr.write(error);
});
ex.addListener("cmdEnd", function() {
complete();
});
ex.run();
}, {async: true});
desc("Builds and runs the Fidelity tests");
task("run-fidelity-tests", [fidelityTestsOutFile], function() {
host = process.env.host || process.env.TYPESCRIPT_HOST || "node";
var cmd = host + " " + fidelityTestsOutFile;
console.log(cmd);
var ex = jake.createExec([cmd]);
// Add listeners for output and error
ex.addListener("stdout", function(output) {
process.stdout.write(output);
});
ex.addListener("stderr", function(error) {
process.stderr.write(error);
});
ex.addListener("cmdEnd", function() {
complete();
});
ex.run();
}, {async: true});