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 ********* |
---|