BuildCommon.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. var fs = require('fs-extra');
  2. var os = require('os');
  3. var path = require("path");
  4. var glob = require('glob');
  5. var Tslint = require("tslint");
  6. var fso = require('fs');
  7. var spawnSync = require('child_process').spawnSync;
  8. var host = require("./Host");
  9. var config = require('./BuildConfig');
  10. var atomicRoot = config.atomicRoot;
  11. var jsDocFolder = config.artifactsRoot + "Build/JSDoc/";
  12. var cppDocFolder = config.artifactsRoot + "Build/CPPDocs/";
  13. var csharpDocFolder = config.artifactsRoot + "Build/CSharpDocs/";
  14. namespace('build', function() {
  15. // Linting task
  16. task('lint_typescript', {
  17. async: true
  18. }, function(fileMask, failOnError) {
  19. console.log("TSLINT: Linting files in " + fileMask);
  20. var lintConfig = JSON.parse(fs.readFileSync("./Script/tslint.json"));
  21. var tslintConfig = {
  22. configuration: lintConfig,
  23. formatter: "prose"
  24. };
  25. // lint
  26. // Since TSLint does not yet support recursively searching for files, then we need to
  27. // create a command per file. The main issue with this is that it will abort on the first error instead
  28. // of listing out all lint errors
  29. glob(fileMask, function(err, results) {
  30. var lintErrors = [];
  31. results.forEach(function(filename) {
  32. var contents = fs.readFileSync(filename, "utf8");
  33. var ll = new Tslint(filename, contents, tslintConfig);
  34. var result = ll.lint();
  35. if (result.failureCount > 0) {
  36. lintErrors.push(result.output);
  37. }
  38. });
  39. if (lintErrors.length > 0) {
  40. console.warn("TSLINT: WARNING - Lint errors detected");
  41. console.warn(lintErrors.join(''));
  42. if (failOnError) {
  43. fail("TSLint errors detected");
  44. }
  45. }
  46. complete();
  47. });
  48. });
  49. // precreate script bindgs so they can be picked up by CMake
  50. task('precreateScriptBindings', {
  51. async: true
  52. }, function(clean) {
  53. if (clean === undefined) {
  54. clean = true;
  55. }
  56. console.log("Precreating script bindings");
  57. if (clean) {
  58. common.cleanCreateDir(common.getGenScriptRootDir())
  59. }
  60. common.createGenScriptFiles();
  61. complete();
  62. });
  63. function fileExists(filePath)
  64. {
  65. try
  66. {
  67. return fs.statSync(filePath).isFile();
  68. }
  69. catch (err)
  70. {
  71. return false;
  72. }
  73. }
  74. task('genAtomicNET', {
  75. async:true
  76. }, function(platform, configuration) {
  77. if (configuration != "Debug" && configuration != "Release")
  78. configuration = "Release";
  79. // Compile AtomicNET assemblies
  80. var cmds = [];
  81. cmds.push(host.atomicTool + " net compile " + atomicRoot + "Script/AtomicNET/AtomicNETProject.json -platform " + platform + " -config " + configuration);
  82. jake.exec(cmds, function() {
  83. complete();
  84. }, {
  85. printStdout: true
  86. });
  87. })
  88. task('genscripts', {
  89. async: true
  90. }, function(force) {
  91. // default to true
  92. if (force != "true" && force != "false") {
  93. force = "true";
  94. }
  95. var anyZero = false;
  96. if (force != "true") {
  97. var filenames = common.getGenScriptFilenames();
  98. for (var i in filenames) {
  99. if (!fileExists(filenames[i]))
  100. {
  101. console.log("genscripts: file missing, regenerating script bindings: " + filenames[i]);
  102. anyZero = true;
  103. break;
  104. }
  105. var stats = fs.statSync(filenames[i]);
  106. if (stats["size"] == 0) {
  107. console.log("genscripts: file zero size, regenerating script bindings: " + filenames[i]);
  108. anyZero = true;
  109. break;
  110. }
  111. }
  112. if (!anyZero)
  113. return;
  114. }
  115. process.chdir(atomicRoot);
  116. var modules = host.getScriptModules();
  117. var bindCmd = host.atomicTool + " bind \"" + atomicRoot + "\" ";
  118. var node = host.node;
  119. var tsc = "./Build/node_modules/typescript/lib/tsc";
  120. var tslint = "./Build/node_modules/tslint/lib/tslint-cli";
  121. var dtsGenerator = "./Build/node_modules/dts-generator/bin/dts-generator";
  122. var cmds = [];
  123. for (var pkgName in modules) {
  124. cmds.push(bindCmd + "Script/Packages/" + pkgName + "/");
  125. }
  126. if (node) {
  127. // compile
  128. cmds.push(node + " " + tsc + " -p ./Script");
  129. cmds.push(node + " " + tsc + " -p ./Script/AtomicWebViewEditor");
  130. // generate combined atomic.d.ts
  131. cmds.push(node + " " + dtsGenerator + " --name Atomic --project ./Script/TypeScript --out ./Script/TypeScript/dist/Atomic.d.ts");
  132. var lintTask = jake.Task['build:lint_typescript'];
  133. lintTask.addListener('complete', function () {
  134. console.log("\n\nLint: Typescript linting complete.\n\n");
  135. jake.exec(cmds, { printStdout : true, printStderr: true }, function() {
  136. // copy some external dependencies into the editor modules directory
  137. var editorModulesDir = "./Artifacts/Build/Resources/EditorData/AtomicEditor/EditorScripts/AtomicEditor/modules";
  138. var webeditorModulesDir = "./Data/AtomicEditor/CodeEditor/source/editorCore/modules";
  139. var nodeModulesDir = "./Build/node_modules";
  140. fs.mkdirsSync(editorModulesDir);
  141. // TypeScript
  142. fs.copySync(nodeModulesDir + "/typescript/lib/typescript.js", webeditorModulesDir + "/typescript.js")
  143. // copy lib.core.d.ts into the tool data directory
  144. fs.mkdirsSync("./Artifacts/Build/Resources/EditorData/AtomicEditor/EditorScripts/AtomicEditor/TypeScriptSupport");
  145. fs.copySync("./Build/node_modules/typescript/lib/lib.es5.d.ts","./Data/AtomicEditor/TypeScriptSupport/lib.es5.d.ts");
  146. // copy the combined Atomic.d.ts to the tool data directory
  147. fs.copySync("./Script/TypeScript/dist/Atomic.d.ts","./Data/AtomicEditor/TypeScriptSupport/Atomic.d.ts")
  148. complete();
  149. }, {
  150. printStdout: true
  151. });
  152. });
  153. lintTask.invoke("{./Script/AtomicEditor/**/*.ts,./Script/AtomicWebViewEditor/**/*.ts}", false);
  154. } else {
  155. throw new Error("Node not configured for this platform: " + os.platform());
  156. }
  157. });
  158. task('gendocs', {
  159. async: true
  160. }, function() {
  161. console.log( "Generating Docs..." );
  162. fs.copySync(atomicRoot + "Build/Docs/Readme.md", jsDocFolder + "Readme.md");
  163. fs.copySync(atomicRoot + "Build/Docs/atomic-theme", jsDocFolder + "atomic-theme");
  164. var typeDoc;
  165. if (os.platform() == "win32") {
  166. // uses system node for typedoc, which should have as require npm
  167. typeDoc = "node_modules\\.bin\\typedoc.cmd";
  168. }
  169. else
  170. typeDoc = host.node + " ./node_modules/.bin/typedoc";
  171. // tsdoc is having problems when name has spaces on Windows and Linux, tried quoting/escaping
  172. // what should happen here is instead of command line use a json config file (or maybe new version of tsdoc fixes this)
  173. var name = "Atomic-Game-Engine";
  174. cmds = [
  175. "cd " + jsDocFolder + " && echo {} > package.json", // newer versions of npm require package.json to be in the folder or else it searches up the heirarchy
  176. "cd " + jsDocFolder + " && npm install typedoc",
  177. "cd " + jsDocFolder + " && " + typeDoc + " --out out " + config.atomicRoot +
  178. "Script/TypeScript/dist/Atomic.d.ts --module commonjs --includeDeclarations --mode file --theme atomic-theme --name " +
  179. name + " --readme ./Readme.md"
  180. ];
  181. jake.exec(cmds, function() {
  182. common.cleanCreateDir( config.toolDataFolder + "Docs");
  183. fs.copySync(jsDocFolder + "out", config.toolDataFolder + "Docs/JSDocs");
  184. complete();
  185. console.log( "completed installing API documentation" );
  186. }, {
  187. printStdout: true
  188. });
  189. });
  190. task('gendoxygen', {
  191. async: true
  192. }, function() {
  193. console.log( "Generating C++ API Documentation..." );
  194. var cppDoc;
  195. if (os.platform() == "win32") {
  196. cppDoc = "doxygen"; // I dont know what to do here...
  197. }
  198. else {
  199. // use doxygen on path
  200. cppDoc = "doxygen";
  201. }
  202. cmds = [
  203. "cd " + atomicRoot + "Source && " + cppDoc + " " + atomicRoot + "Build/Docs/CPlusPlus/Doxyfile"
  204. ];
  205. jake.exec(cmds, function() {
  206. common.cleanCreateDir( config.toolDataFolder + "Docs/CPPDocs"); // clear destination
  207. fs.copySync(cppDocFolder, config.toolDataFolder + "Docs/CPPDocs"); // copy into release same place as JSDocs
  208. complete();
  209. console.log( "completed installing CPP API documentation" );
  210. }, {
  211. printStdout: true
  212. });
  213. });
  214. task('genmdoc', {
  215. async: true
  216. }, function() {
  217. console.log( "Generating C# API Documentation..." );
  218. // mdoc must be on path
  219. var mdoc = "mdoc";
  220. // clear destination
  221. common.cleanCreateDir( csharpDocFolder );
  222. cmds = [
  223. "cd " + csharpDocFolder + " && " + mdoc + " update -o docgen -i ../../AtomicNET/Release/Desktop/AtomicNET.xml ../../AtomicNET/Release/Desktop/AtomicNET.dll",
  224. "cd " + csharpDocFolder + " && " + mdoc + " export-html -o html docgen --template=../../../Build/Docs/CSharp/atomictemplate.xlst"
  225. ];
  226. jake.exec(cmds, function() {
  227. // clear destination
  228. common.cleanCreateDir( config.toolDataFolder + "Docs/CSharpDocs");
  229. // copy into release same place as JSDocs
  230. fs.copySync(csharpDocFolder, config.toolDataFolder + "Docs/CSharpDocs");
  231. complete();
  232. console.log( "completed installing C# API documentation" );
  233. }, {
  234. printStdout: true
  235. });
  236. });
  237. task('genexamples', {
  238. async: true
  239. }, function() {
  240. console.log( "Generating Examples..." );
  241. // TODO: support pulling examples from a specific branch/commit/etc
  242. var exampleSrc = atomicRoot + "Submodules/AtomicExamples/";
  243. var exampleDst = config.toolDataFolder + "AtomicExamples/";
  244. common.testRemoveDir( exampleDst);
  245. fs.copySync(exampleSrc, exampleDst);
  246. // remove the .git file/folder and save some space
  247. fs.removeSync( exampleDst + ".git" );
  248. complete();
  249. });
  250. }); // end of build namespace