[483] | 1 | //Main build script for Dojo |
---|
| 2 | var buildTimerStart = (new Date()).getTime(); |
---|
| 3 | buildScriptsPath = typeof buildScriptsPath == "undefined" ? "./" : buildScriptsPath; |
---|
| 4 | load(buildScriptsPath + "jslib/logger.js"); |
---|
| 5 | load(buildScriptsPath + "jslib/fileUtil.js"); |
---|
| 6 | load(buildScriptsPath + "jslib/buildUtil.js"); |
---|
| 7 | load(buildScriptsPath + "jslib/buildUtilXd.js"); |
---|
| 8 | load(buildScriptsPath + "jslib/i18nUtil.js"); |
---|
| 9 | |
---|
| 10 | //NOTE: See buildUtil.DojoBuildOptions for the list of build options. |
---|
| 11 | |
---|
| 12 | //***************************************************************************** |
---|
| 13 | //Convert arguments to keyword arguments. |
---|
| 14 | var kwArgs = buildUtil.makeBuildOptions(arguments); |
---|
| 15 | |
---|
| 16 | //Remove the default namespaces that are created by Rhino, but only |
---|
| 17 | //if asked to -- it has bad consequences if the build system is used |
---|
| 18 | //with other rhino-based server-side code. |
---|
| 19 | if(kwArgs.removeDefaultNameSpaces){ |
---|
| 20 | delete com; |
---|
| 21 | delete net; |
---|
| 22 | delete org; |
---|
| 23 | } |
---|
| 24 | |
---|
| 25 | //Set logging level. |
---|
| 26 | logger.level = kwArgs["log"]; |
---|
| 27 | |
---|
| 28 | //Execute the requested build actions |
---|
| 29 | var action = kwArgs.action; |
---|
| 30 | for(var i = 0; i < action.length; i ++){ |
---|
| 31 | logger.logPrefix = action[i] + ": "; |
---|
| 32 | this[action[i]](); |
---|
| 33 | logger.logPrefix = ""; |
---|
| 34 | } |
---|
| 35 | |
---|
| 36 | var buildTime = ((new Date().getTime() - buildTimerStart) / 1000); |
---|
| 37 | logger.info("Build time: " + buildTime + " seconds"); |
---|
| 38 | //***************************************************************************** |
---|
| 39 | |
---|
| 40 | //********* Start help ************ |
---|
| 41 | function help(){ |
---|
| 42 | var buildOptionText = ""; |
---|
| 43 | for(var param in buildUtil.DojoBuildOptions){ |
---|
| 44 | buildOptionText += param + "=" + buildUtil.DojoBuildOptions[param].defaultValue + "\n" |
---|
| 45 | + buildUtil.DojoBuildOptions[param].helpText + "\n\n"; |
---|
| 46 | } |
---|
| 47 | |
---|
| 48 | var helpText = "To run the build, you must have Java 1.4.2 or later installed.\n" |
---|
| 49 | + "To run a build run the following command from this directory:\n\n" |
---|
| 50 | + "> java -classpath ../shrinksafe/js.jar:../shrinksafe/shrinksafe.jar " |
---|
| 51 | + "org.mozilla.javascript.tools.shell.Main build.js [name=value...]\n\n" |
---|
| 52 | + "Here is an example of a typical release build:\n\n" |
---|
| 53 | + "> java -classpath ../shrinksafe/js.jar:../shrinksafe/shrinksafe.jar " |
---|
| 54 | + "org.mozilla.javascript.tools.shell.Main build.js profile=base action=release\n\n" |
---|
| 55 | + "If you get a 'java.lang.OutOfMemoryError: Java heap space' error, try increasing the " |
---|
| 56 | + "memory Java can use for the command:\n\n" |
---|
| 57 | + "> java -Xms256m -Xmx256m -classpath ../shrinksafe/js.jar:../shrinksafe/shrinksafe.jar " |
---|
| 58 | + "org.mozilla.javascript.tools.shell.Main build.js profile=base action=release\n\n" |
---|
| 59 | + "Change the 256 number to the number of megabytes you want to give Java.\n\n" |
---|
| 60 | + "The possible name=value build options are shown below with the defaults as their values:\n\n" |
---|
| 61 | + buildOptionText; |
---|
| 62 | |
---|
| 63 | print(helpText); |
---|
| 64 | } |
---|
| 65 | //********* End help ********* |
---|
| 66 | |
---|
| 67 | //********* Start clean ************ |
---|
| 68 | function clean(){ |
---|
| 69 | logger.info("Deleting: " + kwArgs.releaseDir); |
---|
| 70 | fileUtil.deleteFile(kwArgs.releaseDir); |
---|
| 71 | } |
---|
| 72 | //********* End clean ********* |
---|
| 73 | |
---|
| 74 | //********* Start release ********* |
---|
| 75 | function release(){ |
---|
| 76 | logger.info("Using profile: " + kwArgs.profileFile); |
---|
| 77 | logger.info("Using version number: " + kwArgs.version + " for the release."); |
---|
| 78 | |
---|
| 79 | if(!kwArgs.buildLayers){ |
---|
| 80 | clean(); |
---|
| 81 | } |
---|
| 82 | |
---|
| 83 | var dependencies = kwArgs.profileProperties.dependencies; |
---|
| 84 | var prefixes = dependencies.prefixes; |
---|
| 85 | var lineSeparator = fileUtil.getLineSeparator(); |
---|
| 86 | var copyrightText = fileUtil.readFile(buildScriptsPath + "copyright.txt"); |
---|
| 87 | var buildNoticeText = fileUtil.readFile(buildScriptsPath + "build_notice.txt"); |
---|
| 88 | |
---|
| 89 | //Find the dojo prefix path. Need it to process other module prefixes. |
---|
| 90 | var dojoPrefixPath = buildUtil.getDojoPrefixPath(prefixes); |
---|
| 91 | |
---|
| 92 | //Convert targeted build layers to an array. |
---|
| 93 | var buildLayers = null; |
---|
| 94 | if(kwArgs.buildLayers){ |
---|
| 95 | //Make sure to copy over any "source" files for the layers be targeted by |
---|
| 96 | //buildLayers. Otherwise dependencies will not be calculated correctly. |
---|
| 97 | buildLayers = kwArgs.buildLayers.split(","); |
---|
| 98 | } |
---|
| 99 | |
---|
| 100 | //Get the list of module directories we need to process. |
---|
| 101 | //They will be in the dependencies.prefixes array. |
---|
| 102 | //Copy each prefix dir to the releases and |
---|
| 103 | //operate on that copy instead of modifying the source. |
---|
| 104 | for(var i = 0; i < prefixes.length; i++){ |
---|
| 105 | var prefixName = prefixes[i][0]; |
---|
| 106 | var prefixPath = prefixes[i][1]; |
---|
| 107 | |
---|
| 108 | var finalPrefixPath = prefixPath; |
---|
| 109 | if(finalPrefixPath.indexOf(".") == 0 && prefixName != "dojo"){ |
---|
| 110 | finalPrefixPath = dojoPrefixPath + "/" + prefixPath; |
---|
| 111 | } |
---|
| 112 | _copyToRelease(prefixName, finalPrefixPath, kwArgs, buildLayers); |
---|
| 113 | |
---|
| 114 | if(kwArgs.symbol){ |
---|
| 115 | var releasePath = kwArgs.releaseDir + "/" + prefixName.replace(/\./g, "/"); |
---|
| 116 | buildUtil.insertSymbols(releasePath, kwArgs); |
---|
| 117 | } |
---|
| 118 | } |
---|
| 119 | |
---|
| 120 | //Fix all the prefix paths to be in the release directory. |
---|
| 121 | //Do this after the copy step above. If it is done as part |
---|
| 122 | //of that loop, then dojo path gets set first usually, and any prefixes |
---|
| 123 | //after it are wrong. |
---|
| 124 | for(i = 0; i < prefixes.length; i++){ |
---|
| 125 | prefixes[i][1] = kwArgs.releaseDir + "/" + prefixes[i][0].replace(/\./g, "/"); |
---|
| 126 | } |
---|
| 127 | |
---|
| 128 | //Make sure dojo is clear before trying to map dependencies. |
---|
| 129 | if(typeof dojo != "undefined"){ |
---|
| 130 | dojo = undefined; |
---|
| 131 | } |
---|
| 132 | |
---|
| 133 | logger.trace("Building dojo.js and layer files"); |
---|
| 134 | var result = buildUtil.makeDojoJs(buildUtil.loadDependencyList(kwArgs.profileProperties, kwArgs, buildScriptsPath), kwArgs.version, kwArgs); |
---|
| 135 | |
---|
| 136 | //Save the build layers. The first layer is dojo.js. |
---|
| 137 | var defaultLegalText = copyrightText + buildNoticeText; |
---|
| 138 | var dojoReleaseDir = kwArgs.releaseDir + "/dojo/"; |
---|
| 139 | var layerIgnoreString = ""; |
---|
| 140 | var nlsIgnoreString = ""; |
---|
| 141 | |
---|
| 142 | //Add an ending comma to the list to make matches easier. |
---|
| 143 | //Also make sure we normalize to unix path separators. |
---|
| 144 | if(kwArgs.buildLayers){ |
---|
| 145 | kwArgs.buildLayers += ","; |
---|
| 146 | kwArgs.buildLayers = kwArgs.buildLayers.replace(/\\/g, "/"); |
---|
| 147 | } |
---|
| 148 | for(i = 0; i < result.length; i++){ |
---|
| 149 | var currentLayer = result[i]; |
---|
| 150 | var layerName = currentLayer.layerName; |
---|
| 151 | var layerLegalText = (currentLayer.copyrightFile ? fileUtil.readFile(currentLayer.copyrightFile) : defaultLegalText); |
---|
| 152 | var fileName = dojoReleaseDir + currentLayer.layerName; |
---|
| 153 | var fileContents = currentLayer.contents; |
---|
| 154 | |
---|
| 155 | //Build up string of files to ignore for the directory optimization step |
---|
| 156 | var ignoreName = layerName.replace(/\.\.\//g, ""); |
---|
| 157 | var nameSegment = ignoreName.replace(/\.js$/, ""); |
---|
| 158 | layerIgnoreString += (layerIgnoreString ? "|" : "") + buildUtil.regExpEscape(ignoreName) + "$"; |
---|
| 159 | layerIgnoreString += "|" + buildUtil.regExpEscape(ignoreName + ".uncompressed.js") + "$"; |
---|
| 160 | |
---|
| 161 | if(nameSegment.indexOf("/") != -1){ |
---|
| 162 | nameSegment = nameSegment.substring(nameSegment.lastIndexOf("/") + 1, nameSegment.length); |
---|
| 163 | } |
---|
| 164 | nlsIgnoreString += (nlsIgnoreString ? "|" : "") + buildUtil.regExpEscape(nameSegment); |
---|
| 165 | |
---|
| 166 | //If only want to build certain layers, skip ones that do not match. |
---|
| 167 | if(kwArgs.buildLayers && kwArgs.buildLayers.indexOf(layerName + ",") == -1){ |
---|
| 168 | continue; |
---|
| 169 | } |
---|
| 170 | |
---|
| 171 | //Burn in djConfig for dojo.js/xd.js if requested. |
---|
| 172 | if(kwArgs.scopeDjConfig && (layerName.match(/dojo\.xd\.js$/) || layerName.match(/dojo\.js$/))){ |
---|
| 173 | fileContents = buildUtil.setScopeDjConfig(fileContents, kwArgs.scopeDjConfig); |
---|
| 174 | } |
---|
| 175 | |
---|
| 176 | //Burn in scope names for dojo.js/xd.js if requested. |
---|
| 177 | if(kwArgs.scopeMap && (layerName.match(/dojo\.xd\.js$/) || layerName.match(/dojo\.js$/))){ |
---|
| 178 | fileContents = buildUtil.setScopeNames(fileContents, kwArgs.scopeMap); |
---|
| 179 | } |
---|
| 180 | |
---|
| 181 | //Burn in xd path for dojo if requested, and only do this in dojo.xd.js. |
---|
| 182 | if(layerName == "dojo.xd.js" && kwArgs.xdDojoPath){ |
---|
| 183 | fileContents = buildUtilXd.setXdDojoConfig(fileContents, kwArgs.xdDojoPath); |
---|
| 184 | } |
---|
| 185 | |
---|
| 186 | //Flatten resources |
---|
| 187 | fileContents = i18nUtil.flattenLayerFileBundles(fileName, fileContents, kwArgs); |
---|
| 188 | |
---|
| 189 | //Save uncompressed file. |
---|
| 190 | var uncompressedFileName = fileName + ".uncompressed.js"; |
---|
| 191 | var uncompressedContents = layerLegalText + fileContents; |
---|
| 192 | if(layerName.match(/\.xd\.js$/) && !layerName.match(/dojo(\.xd)?\.js/)){ |
---|
| 193 | uncompressedContents = buildUtilXd.makeXdContents(uncompressedContents, prefixes, kwArgs); |
---|
| 194 | } |
---|
| 195 | fileUtil.saveUtf8File(uncompressedFileName, uncompressedContents); |
---|
| 196 | |
---|
| 197 | //Intern strings if desired. Do this before compression, since, in the xd case, |
---|
| 198 | //"dojo" gets converted to a shortened name. |
---|
| 199 | if(kwArgs.internStrings){ |
---|
| 200 | logger.info("Interning strings for file: " + fileName); |
---|
| 201 | prefixes = dependencies["prefixes"] || []; |
---|
| 202 | var skiplist = dependencies["internSkipList"] || []; |
---|
| 203 | buildUtil.internTemplateStringsInFile(uncompressedFileName, dojoReleaseDir, prefixes, skiplist); |
---|
| 204 | |
---|
| 205 | //Load the file contents after string interning, to pick up interned strings. |
---|
| 206 | fileContents = fileUtil.readFile(uncompressedFileName); |
---|
| 207 | }else{ |
---|
| 208 | fileContents = uncompressedContents; |
---|
| 209 | } |
---|
| 210 | |
---|
| 211 | //Save compressed file. |
---|
| 212 | logger.trace("Optimizing (" + kwArgs.layerOptimize + ") file: " + fileName); |
---|
| 213 | var compressedContents = buildUtil.optimizeJs(fileName, fileContents, layerLegalText, kwArgs.layerOptimize, kwArgs.stripConsole); |
---|
| 214 | fileUtil.saveUtf8File(fileName, compressedContents); |
---|
| 215 | } |
---|
| 216 | |
---|
| 217 | //Save the dependency lists to build.txt |
---|
| 218 | var buildText = "Files baked into this build:" + lineSeparator; |
---|
| 219 | for(i = 0; i < result.length; i++){ |
---|
| 220 | buildText += lineSeparator + result[i].layerName + ":" + lineSeparator; |
---|
| 221 | buildText += result[i].depList.join(lineSeparator) + lineSeparator; |
---|
| 222 | } |
---|
| 223 | fileUtil.saveFile(kwArgs.releaseDir + "/dojo/build.txt", buildText); |
---|
| 224 | logger.info(buildText); |
---|
| 225 | |
---|
| 226 | //Run string interning, xd file building, etc.. on the prefix dirs in the |
---|
| 227 | //release area. |
---|
| 228 | var layerIgnoreRegExp = new RegExp("(" + layerIgnoreString + ")"); |
---|
| 229 | var nlsIgnoreRegExp = new RegExp("\\/nls\\/(" + nlsIgnoreString + ")_"); |
---|
| 230 | |
---|
| 231 | for(i = 0; i < prefixes.length; i++){ |
---|
| 232 | copyrightText = null; |
---|
| 233 | if(prefixes[i][2]){ |
---|
| 234 | copyrightText = fileUtil.readFile(prefixes[i][2]); |
---|
| 235 | } |
---|
| 236 | |
---|
| 237 | //Optimize the release dirs, but only if we are not building just a layer. |
---|
| 238 | if(!kwArgs.buildLayers){ |
---|
| 239 | _optimizeReleaseDirs(prefixes[i][0], prefixes[i][1], copyrightText, kwArgs, layerIgnoreRegExp, nlsIgnoreRegExp); |
---|
| 240 | } |
---|
| 241 | } |
---|
| 242 | |
---|
| 243 | //Copy over DOH if tests where copied. |
---|
| 244 | if(kwArgs.copyTests && !kwArgs.mini){ |
---|
| 245 | fileUtil.copyDir("../doh", kwArgs.releaseDir + "/util/doh", /./); |
---|
| 246 | } |
---|
| 247 | |
---|
| 248 | //Remove any files no longer needed. |
---|
| 249 | if(kwArgs.mini && kwArgs.internStrings){ |
---|
| 250 | fileUtil.deleteFile(kwArgs.releaseDir + "/dijit/templates"); |
---|
| 251 | fileUtil.deleteFile(kwArgs.releaseDir + "/dijit/form/templates"); |
---|
| 252 | fileUtil.deleteFile(kwArgs.releaseDir + "/dijit/layout/templates"); |
---|
| 253 | } |
---|
| 254 | |
---|
| 255 | logger.info("Build is in directory: " + kwArgs.releaseDir); |
---|
| 256 | } |
---|
| 257 | //********* End release ********* |
---|
| 258 | |
---|
| 259 | //********* Start _copyToRelease ********* |
---|
| 260 | function _copyToRelease(/*String*/prefixName, /*String*/prefixPath, /*Object*/kwArgs, /*Array?*/buildLayers){ |
---|
| 261 | // summary: |
---|
| 262 | // copies modules and supporting files from the prefix path to the release |
---|
| 263 | // directory. Also adds code guards to module resources. |
---|
| 264 | var prefixSlashName = prefixName.replace(/\./g, "/"); |
---|
| 265 | var releasePath = kwArgs.releaseDir + "/" + prefixSlashName; |
---|
| 266 | var copyRegExps = { |
---|
| 267 | include: /./ |
---|
| 268 | }; |
---|
| 269 | |
---|
| 270 | //Use the copyRegExps to filter out tests if requested. |
---|
| 271 | if(!kwArgs.copyTests){ |
---|
| 272 | copyRegExps.exclude = /\/tests\//; |
---|
| 273 | } |
---|
| 274 | |
---|
| 275 | if(kwArgs.mini){ |
---|
| 276 | copyRegExps.exclude = /\/tests\/|\/demos\/|tests\.js|dijit\/bench|dijit\/themes\/themeTest|(\.php$)/; |
---|
| 277 | } |
---|
| 278 | |
---|
| 279 | logger.info("Copying: " + prefixPath + " to: " + releasePath); |
---|
| 280 | var copiedFiles = fileUtil.copyDir(prefixPath, releasePath, copyRegExps, true); |
---|
| 281 | |
---|
| 282 | //If want a different selector engine, adjust that now. |
---|
| 283 | //Copy the new selector js over the dojo._base.query file |
---|
| 284 | if(prefixName == "dojo" && kwArgs.query == "sizzle"){ |
---|
| 285 | fileUtil.copyFile(releasePath + "/_base/query-sizzle.js", releasePath + "/_base/query.js"); |
---|
| 286 | } |
---|
| 287 | |
---|
| 288 | if(!copiedFiles){ |
---|
| 289 | logger.info(" ********** Not Copied: " + prefixPath ); |
---|
| 290 | } |
---|
| 291 | |
---|
| 292 | //Make sure to copy over any "source" files for the layers be targeted by |
---|
| 293 | //buildLayers. Otherwise dependencies will not be calculated correctly. |
---|
| 294 | if(buildLayers){ |
---|
| 295 | for(i = 0; i < buildLayers.length; i++){ |
---|
| 296 | var relativeLayerPath = buildLayers[i].replace(/\.\.\//g, ""); |
---|
| 297 | |
---|
| 298 | //See if relativeLayerPath has teh prefix slash name in it. |
---|
| 299 | //This means the layer is probably in this prefix dir (but no guarantee) |
---|
| 300 | //This is a bit hacky. |
---|
| 301 | if(relativeLayerPath.indexOf(prefixSlashName) == 0){ |
---|
| 302 | |
---|
| 303 | //Remove the prefix part from the dir and add the prefix path to get a |
---|
| 304 | //full path. |
---|
| 305 | var layerPathSuffix = relativeLayerPath.replace(prefixSlashName, ""); |
---|
| 306 | relativeLayerPath = prefixPath + layerPathSuffix; |
---|
| 307 | |
---|
| 308 | //If that source path exists, it means we need to copy over the source |
---|
| 309 | //layer file. |
---|
| 310 | if((new java.io.File(relativeLayerPath)).exists()){ |
---|
| 311 | //Need to copy over from the source area. |
---|
| 312 | var destPath = releasePath + layerPathSuffix; |
---|
| 313 | fileUtil.copyFile(relativeLayerPath, destPath); |
---|
| 314 | } |
---|
| 315 | } |
---|
| 316 | } |
---|
| 317 | } |
---|
| 318 | |
---|
| 319 | //Put in code guards for each resource, to protect against redefinition of |
---|
| 320 | //code in the layered build cases. Also inject base require calls if there is |
---|
| 321 | //a layer with the customBase attribute. Do this here before the layers are built. |
---|
| 322 | if(copiedFiles){ |
---|
| 323 | var needBaseRequires = false; |
---|
| 324 | var layers = kwArgs.profileProperties.dependencies.layers; |
---|
| 325 | if(layers){ |
---|
| 326 | for(var i = 0; i < layers.length; i++){ |
---|
| 327 | if((needBaseRequires = layers[i].customBase)){ |
---|
| 328 | break; |
---|
| 329 | } |
---|
| 330 | } |
---|
| 331 | } |
---|
| 332 | |
---|
| 333 | if(kwArgs.addGuards){ |
---|
| 334 | buildUtil.addGuardsAndBaseRequires(copiedFiles, needBaseRequires); |
---|
| 335 | } |
---|
| 336 | } |
---|
| 337 | } |
---|
| 338 | //********* End _copyToRelease ********* |
---|
| 339 | |
---|
| 340 | //********* Start _optimizeReleaseDirs ********* |
---|
| 341 | function _optimizeReleaseDirs( |
---|
| 342 | /*String*/prefixName, |
---|
| 343 | /*String*/prefixPath, |
---|
| 344 | /*String*/copyrightText, |
---|
| 345 | /*Object*/kwArgs, |
---|
| 346 | /*RegExp*/layerIgnoreRegExp, |
---|
| 347 | /*RegExp*/nlsIgnoreRegExp){ |
---|
| 348 | // summary: |
---|
| 349 | // runs intern strings, i18n bundle flattening and xdomain file generation |
---|
| 350 | // on the files in a release directory, if those options are enabled. |
---|
| 351 | var releasePath = kwArgs.releaseDir + "/" + prefixName.replace(/\./g, "/"); |
---|
| 352 | var prefixes = kwArgs.profileProperties.dependencies.prefixes; |
---|
| 353 | |
---|
| 354 | //Intern strings if desired. |
---|
| 355 | if(kwArgs.internStrings){ |
---|
| 356 | logger.info("Interning strings for: " + releasePath); |
---|
| 357 | buildUtil.internTemplateStrings(kwArgs.profileProperties.dependencies, releasePath, layerIgnoreRegExp); |
---|
| 358 | } |
---|
| 359 | |
---|
| 360 | //Process build conditionals in non-layer module files. |
---|
| 361 | buildUtil.processConditionalsForDir(releasePath, layerIgnoreRegExp, kwArgs); |
---|
| 362 | |
---|
| 363 | //Flatten bundles inside the directory |
---|
| 364 | i18nUtil.flattenDirBundles(prefixName, prefixPath, kwArgs, nlsIgnoreRegExp); |
---|
| 365 | |
---|
| 366 | if(kwArgs.loader == "xdomain"){ |
---|
| 367 | buildUtilXd.xdgen(prefixName, prefixPath, prefixes, layerIgnoreRegExp, kwArgs); |
---|
| 368 | } |
---|
| 369 | |
---|
| 370 | buildUtil.optimizeJsDir(releasePath, layerIgnoreRegExp, copyrightText, kwArgs.optimize, kwArgs.stripConsole); |
---|
| 371 | |
---|
| 372 | if(kwArgs.cssOptimize){ |
---|
| 373 | buildUtil.optimizeCss(releasePath, kwArgs.cssOptimize, kwArgs.cssImportIgnore); |
---|
| 374 | } |
---|
| 375 | } |
---|
| 376 | //********* End _optimizeReleaseDirs ********* |
---|