Translate the Arch enum to an arch directory name. This is necessary for Linux builds...
[mirror_edk2.git] / Tools / Source / GenBuild / org / tianocore / build / GenBuildTask.java
CommitLineData
878ddf1f 1/** @file\r
2 This file is ANT task GenBuild. \r
3 \r
4 The file is used to parse a specified Module, and generate its build time \r
5 ANT script build.xml, then call the the ANT script to build the module.\r
6 \r
7Copyright (c) 2006, Intel Corporation\r
8All rights reserved. This program and the accompanying materials\r
9are licensed and made available under the terms and conditions of the BSD License\r
10which accompanies this distribution. The full text of the license may be found at\r
11http://opensource.org/licenses/bsd-license.php\r
12\r
13THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
14WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
15**/\r
16package org.tianocore.build;\r
17\r
18import java.io.File;\r
19import java.util.HashMap;\r
20import java.util.HashSet;\r
21import java.util.Iterator;\r
22import java.util.LinkedHashSet;\r
23import java.util.List;\r
24import java.util.Map;\r
25import java.util.Set;\r
26import java.util.Vector;\r
27import java.util.regex.Matcher;\r
28import java.util.regex.Pattern;\r
29\r
30import javax.xml.parsers.DocumentBuilder;\r
31import javax.xml.parsers.DocumentBuilderFactory;\r
32import javax.xml.transform.OutputKeys;\r
33import javax.xml.transform.Result;\r
34import javax.xml.transform.Source;\r
35import javax.xml.transform.Transformer;\r
36import javax.xml.transform.TransformerFactory;\r
37import javax.xml.transform.dom.DOMSource;\r
38import javax.xml.transform.stream.StreamResult;\r
39\r
40import org.apache.tools.ant.BuildException;\r
41import org.apache.tools.ant.Project;\r
42import org.apache.tools.ant.Task;\r
43import org.apache.tools.ant.taskdefs.Ant;\r
44import org.apache.xmlbeans.XmlObject;\r
45import org.w3c.dom.Comment;\r
46import org.w3c.dom.Document;\r
47import org.w3c.dom.Element;\r
48import org.w3c.dom.Node;\r
49\r
50import org.tianocore.build.autogen.AutoGen;\r
51import org.tianocore.build.autogen.CommonDefinition;\r
52import org.tianocore.build.fpd.FpdParserTask;\r
53import org.tianocore.build.global.GlobalData;\r
54import org.tianocore.build.global.OutputManager;\r
55import org.tianocore.build.global.SurfaceAreaQuery;\r
56import org.tianocore.build.toolchain.ToolChainFactory;\r
57import org.tianocore.FilenameDocument;\r
58import org.tianocore.MsaHeaderDocument;\r
59import org.tianocore.MsaLibHeaderDocument;\r
60\r
61/**\r
62 <p>\r
63 <code>GenBuildTask</code> is an ANT task that can be used in ANT build\r
64 system. The main function of this task is to parse module's surface area,\r
65 then generate the corresponding <em>BaseName_build.xml</em> (the real ANT\r
66 build script) and call this to build the module.\r
67 </p>\r
68 \r
69 <p>\r
70 The usage is (take module <em>HelloWorld</em> for example):\r
71 </p>\r
72 \r
73 <pre>\r
74 &lt;GenBuild baseName=&quot;HelloWorld&quot; \r
75 mbdFilename=&quot;${MODULE_DIR}/HelloWorld.mbd&quot; \r
76 msaFilename=&quot;${MODULE_DIR}/HelloWorld.msa&quot;/&gt;\r
77 </pre>\r
78 \r
79 <p>\r
80 This task calls <code>AutoGen</code> to generate <em>AutoGen.c</em> and\r
81 <em>AutoGen.h</em>. The task also parses the development environment\r
82 configuration files, such as collecting package information, setting compiler\r
83 flags and so on.\r
84 </p>\r
85 \r
86 \r
87 @since GenBuild 1.0\r
88**/\r
89public class GenBuildTask extends Task {\r
90\r
91 ///\r
92 /// Module surface area file.\r
93 ///\r
94 File msaFilename;\r
95\r
96 ///\r
97 /// Module build description file.\r
98 ///\r
99 File mbdFilename;\r
100\r
101 ///\r
102 /// Module surface area information after overrided.\r
103 ///\r
104 public Map<String, XmlObject> map = new HashMap<String, XmlObject>();\r
105\r
106 ///\r
107 /// Module's base name.\r
108 ///\r
109 private String baseName;\r
110\r
111 ///\r
112 /// Current build Arch, such as IA32, X64, IPF and so on.\r
113 ///\r
114 private String arch;\r
115\r
116 ///\r
117 /// Module's GUID (Globally Unique Identifier).\r
118 ///\r
119 private String guid;\r
120\r
121 ///\r
122 /// Module's component type, such as SEC, LIBRARY, BS_DRIVER and so on.\r
123 ///\r
124 private String componentType;\r
125\r
126 ///\r
127 /// This value is used in build time. Override module's component type. When\r
128 /// search FFS (Sections information) in common file, buildtype instead of\r
129 /// component type.\r
130 ///\r
131 private String buildType;\r
132\r
133 ///\r
134 /// List all required includes for current build module.\r
135 ///\r
136 public Set<String> includes = new LinkedHashSet<String>();\r
137\r
138 ///\r
139 /// List all libraries for current build module.\r
140 ///\r
141 public Set<String> libraries = new LinkedHashSet<String>();\r
142\r
143 ///\r
144 /// List all source files for current build module.\r
145 ///\r
146 public Set<String> sourceFiles = new LinkedHashSet<String>();\r
147\r
148 ///\r
149 /// Flag to identify what surface area files are specified. Current value is\r
150 /// <em>NO_SA</em>, <em>ONLY_MSA</em>, <em>ONLY_LIBMSA</em>,\r
151 /// <em>MSA_AND_MBD</em> or <em>LIBMSA_AND_LIBMBD</em>.\r
152 /// \r
153 /// @see org.tianocore.build.global.GlobaData\r
154 ///\r
155 private int flag = GlobalData.NO_SA;\r
156\r
157 ///\r
158 /// The information at the header of <em>build.xml</em>.\r
159 ///\r
160 private String info = "====================================================================\n"\r
161 + "DO NOT EDIT \n"\r
162 + "File auto-generated by build utility\n"\r
163 + "\n"\r
164 + "Abstract:\n"\r
165 + "Auto-generated ANT build file for building of EFI Modules/Platforms\n"\r
166 + "=====================================================================";\r
167\r
168 /**\r
169 Public construct method. It is necessary for ANT task.\r
170 **/\r
171 public GenBuildTask() {\r
172 }\r
173\r
174 /**\r
175 ANT task's entry point, will be called after init(). The main steps is described\r
176 as following: \r
177 <ul>\r
178 <li> Judge current build mode (MODULE | PACKAGE | PLATFORM). This step will execute\r
179 only once in whole build process; </li>\r
180 <li> Initialize global information (Framework DB, SPD files and all MSA files \r
181 listed in SPD). This step will execute only once in whole build process; </li>\r
182 <li> Restore some important ANT property. If current build is single module \r
183 build, here will set many default values; </li>\r
184 <li> Get the current module's overridded surface area information from \r
185 global data; </li> \r
186 <li> Set up the output directories, including BIN_DIR, DEST_DIR_OUTPUT and\r
187 DEST_DIR_DEBUG; </li>\r
188 <li> Get module dependent library instances and include pathes; </li>\r
189 <li> Judge whether current module is built. If yes, skip it; </li>\r
190 <li> Call AutoGen and PCD to generate AutoGen.c & AutoGen.h </li>\r
191 <li> Set up the compile flags; </li>\r
192 <li> Generate BaseName_build.xml; </li>\r
193 <li> Call to BaseName_build.xml, and build the current module. </li>\r
194 </ul>\r
195 \r
196 <p>Build is dependent on BuildMacro.xml which define many macro. </p> \r
197 \r
198 @throws BuildException\r
199 From module build, exception from module surface area invalid.\r
200 **/\r
201 public void execute() throws BuildException {\r
202 System.out.println("Module [" + baseName + "] start.");\r
203 OutputManager.update(getProject());\r
204 GlobalData.initInfo("Tools" + File.separatorChar + "Conf" + File.separatorChar + "FrameworkDatabase.db",\r
205 getProject().getProperty("WORKSPACE_DIR"));\r
206 recallFixedProperties();\r
207 arch = getProject().getProperty("ARCH");\r
208 arch = arch.toUpperCase();\r
209 map = GlobalData.getDoc(baseName);\r
210 //\r
211 // Initialize SurfaceAreaQuery\r
212 //\r
213 SurfaceAreaQuery.setDoc(map);\r
214 //\r
215 // Setup Output Management\r
216 //\r
217 String[] outdir = SurfaceAreaQuery.getOutputDirectory();\r
218 OutputManager.update(getProject(), outdir[1], outdir[0]);\r
219\r
220 updateIncludesAndLibraries();\r
221\r
222 if (GlobalData.isModuleBuilt(baseName, arch)) {\r
223 return;\r
224 } else {\r
225 GlobalData.registerBuiltModule(baseName, arch);\r
226 }\r
227 //\r
228 // Call AutoGen\r
229 //\r
230 AutoGen autogen = new AutoGen(getProject().getProperty("DEST_DIR_DEBUG"), baseName, arch);\r
231 autogen.genAutogen();\r
232 //\r
233 // Update parameters\r
234 //\r
235 updateParameters();\r
236 //\r
237 // Update flags like CC_FLAGS, LIB_FLAGS etc.\r
238 //\r
239 flagsSetup();\r
61746a87 240 GlobalData.addLibrary(baseName, arch, getProject().getProperty("BIN_DIR") + File.separatorChar + baseName + ".lib");\r
241 GlobalData.addModuleLibrary(baseName, arch, libraries);\r
878ddf1f 242 //\r
243 // If ComponentType is USER_DEFINED,\r
244 // then call the exist BaseName_build.xml directly.\r
245 //\r
246 if (buildType.equalsIgnoreCase("CUSTOM_BUILD")) {\r
247 System.out.println("Call user-defined " + baseName + "_build.xml");\r
248 Ant ant = new Ant();\r
249 ant.setProject(getProject());\r
250 ant.setAntfile(getProject().getProperty("MODULE_DIR") + File.separatorChar + baseName + "_build.xml");\r
251 ant.setInheritAll(true);\r
252 ant.init();\r
253 ant.execute();\r
254 return;\r
255 }\r
256 //\r
257 // Generate ${BASE_NAME}_build.xml file\r
258 //\r
259 System.out.println("Generate " + baseName + "_build.xml");\r
260 genBuildFile();\r
261 System.out.println("Call the " + baseName + "_build.xml");\r
262 Ant ant = new Ant();\r
263 ant.setProject(getProject());\r
264 ant.setAntfile(getProject().getProperty("DEST_DIR_OUTPUT") + File.separatorChar + baseName + "_build.xml");\r
265 ant.setInheritAll(true);\r
266 ant.init();\r
267 ant.execute();\r
268 }\r
269\r
c43c6719 270 /**\r
271 Return the name of the directory that corresponds to the architecture.\r
272 This is a translation from the XML Schema tag to a directory that\r
273 corresponds to our directory name coding convention.\r
274 \r
275 **/\r
276 private String archDir(String arch) {\r
277 return arch.replaceFirst("X64", "x64")\r
278 .replaceFirst("IPF", "Ipf")\r
279 .replaceFirst("IA32", "Ia32")\r
280 .replaceFirst("ARM", "Arm")\r
281 .replaceFirst("EBC", "Ebc");\r
282 }\r
283\r
878ddf1f 284 /**\r
285 Get the dependent library instances and include package name from \r
286 surface area, and initialize module include pathes. \r
287 \r
288 **/\r
289 private void updateIncludesAndLibraries() {\r
290 List<String> rawIncludes = SurfaceAreaQuery.getIncludePackageName(arch);\r
291 if (rawIncludes != null) {\r
292 Iterator iter = rawIncludes.iterator();\r
293 while (iter.hasNext()) {\r
294 String packageName = (String) iter.next();\r
295 includes.add("${WORKSPACE_DIR}" + File.separatorChar + GlobalData.getPackagePath(packageName)\r
296 + File.separatorChar + "Include");\r
297 includes.add("${WORKSPACE_DIR}" + File.separatorChar + GlobalData.getPackagePath(packageName)\r
c43c6719 298 + File.separatorChar + "Include" + File.separatorChar + archDir(arch));\r
878ddf1f 299 }\r
300 }\r
301 includes.add("${DEST_DIR_DEBUG}");\r
302 List<String> rawLibraries = SurfaceAreaQuery.getLibraryInstance(this.arch, CommonDefinition.AlwaysConsumed);\r
303 if (rawLibraries != null) {\r
304 Iterator iter = rawLibraries.iterator();\r
305 while (iter.hasNext()) {\r
306 libraries.add((String) iter.next());\r
307 }\r
308 }\r
309 normalize();\r
310 }\r
311\r
312 /**\r
313 Normalize all dependent library instance and include pathes' format. \r
314 \r
315 **/\r
316 private void normalize() {\r
317 String[] includesArray = includes.toArray(new String[includes.size()]);\r
318 includes.clear();\r
319 for (int i = 0; i < includesArray.length; i++) {\r
320 includes.add((new File(includesArray[i])).getPath());\r
321 }\r
322 String[] librariesArray = libraries.toArray(new String[libraries.size()]);\r
323 libraries.clear();\r
324 for (int i = 0; i < librariesArray.length; i++) {\r
325 libraries.add((new File(librariesArray[i])).getPath());\r
326 }\r
327 }\r
328\r
329 /**\r
330 Restore some important ANT property. If current build is single module \r
331 build, here will set many default values.\r
332 \r
333 <p> If current build is single module build, then the default <code>ARCH</code>\r
334 is <code>IA32</code>. Also set up the properties <code>PACKAGE</code>, \r
335 <code>PACKAGE_DIR</code>, <code>TARGET</code> and <code>MODULE_DIR</code></p>\r
336 \r
337 <p> Note that for package build, package name is stored in <code>PLATFORM</code>\r
338 and package directory is stored in <code>PLATFORM_DIR</code>. </p> \r
339 \r
340 @see org.tianocore.build.global.OutputManager\r
341 **/\r
342 private void recallFixedProperties() {\r
343 //\r
344 // If build is for module build\r
345 //\r
346 if (getProject().getProperty("PACKAGE_DIR") == null) {\r
347 ToolChainFactory toolChainFactory = new ToolChainFactory(getProject());\r
348 toolChainFactory.setupToolChain();\r
349 //\r
350 // PACKAGE PACKAGE_DIR ARCH (Default) COMMON_FILE BUILD_MACRO\r
351 //\r
352 if (getProject().getProperty("ARCH") == null) {\r
353 getProject().setProperty("ARCH", "IA32");\r
354 }\r
355 String packageName = GlobalData.getPackageNameForModule(baseName);\r
356 getProject().setProperty("PACKAGE", packageName);\r
357 \r
358 String packageDir = GlobalData.getPackagePath(packageName);\r
359 getProject().setProperty("PACKAGE_DIR",\r
360 getProject().getProperty("WORKSPACE_DIR") + File.separatorChar + packageDir);\r
361 \r
362 getProject().setProperty("TARGET", toolChainFactory.getCurrentTarget());\r
363 \r
364 getProject().setProperty("MODULE_DIR",\r
365 getProject().replaceProperties(getProject().getProperty("MODULE_DIR")));\r
366 }\r
367 if (OutputManager.PLATFORM != null) {\r
368 getProject().setProperty("PLATFORM", OutputManager.PLATFORM);\r
369 }\r
370 if (OutputManager.PLATFORM_DIR != null) {\r
371 getProject().setProperty("PLATFORM_DIR", OutputManager.PLATFORM_DIR);\r
372 }\r
373 }\r
374\r
375 /**\r
376 The whole BaseName_build.xml is composed of seven part. \r
377 <ul>\r
378 <li> ANT properties; </li>\r
379 <li> Dependent module (dependent library instances in most case); </li>\r
380 <li> Source files; </li>\r
381 <li> Sections if module is not library; </li>\r
382 <li> Output (different for library module and driver module); </li>\r
383 <li> Clean; </li>\r
384 <li> Clean all. </li>\r
385 </ul>\r
386 \r
387 @throws BuildException\r
388 Error throws during BaseName_build.xml generating. \r
389 **/\r
390 private void genBuildFile() throws BuildException {\r
391 FfsProcess fp = new FfsProcess();\r
392 DocumentBuilderFactory domfac = DocumentBuilderFactory.newInstance();\r
393 try {\r
394 DocumentBuilder dombuilder = domfac.newDocumentBuilder();\r
395 Document document = dombuilder.newDocument();\r
396 Comment rootComment = document.createComment(info);\r
397 //\r
398 // create root element and its attributes\r
399 //\r
400 Element root = document.createElement("project");\r
401 //\r
402 // root.setAttribute("name", base_name);\r
403 //\r
404 root.setAttribute("default", "main");\r
405 root.setAttribute("basedir", ".");\r
406 //\r
407 // element for External ANT tasks\r
408 //\r
409 root.appendChild(document.createComment("Apply external ANT tasks"));\r
410 Element ele = document.createElement("taskdef");\r
411 ele.setAttribute("resource", "frameworktasks.tasks");\r
412 root.appendChild(ele);\r
413 ele = document.createElement("taskdef");\r
414 ele.setAttribute("resource", "cpptasks.tasks");\r
415 root.appendChild(ele);\r
416 ele = document.createElement("typedef");\r
417 ele.setAttribute("resource", "cpptasks.types");\r
418 root.appendChild(ele);\r
419 ele = document.createElement("taskdef");\r
420 ele.setAttribute("resource", "net/sf/antcontrib/antlib.xml");\r
421 root.appendChild(ele);\r
422 //\r
423 // elements for Properties\r
424 //\r
425 root.appendChild(document.createComment("All Properties"));\r
426 ele = document.createElement("property");\r
427 ele.setAttribute("name", "BASE_NAME");\r
428 ele.setAttribute("value", baseName);\r
429 root.appendChild(ele);\r
430 //\r
431 // Generate the default target,\r
432 // which depends on init, sections and output target\r
433 //\r
434 root.appendChild(document.createComment("Default target"));\r
435 ele = document.createElement("target");\r
436 ele.setAttribute("name", "main");\r
437 ele.setAttribute("depends", "libraries, sourcefiles, sections, output");\r
438 root.appendChild(ele);\r
439 //\r
440 // compile all source files\r
441 //\r
442 root.appendChild(document.createComment("Compile all dependency Library instances."));\r
443 ele = document.createElement("target");\r
444 ele.setAttribute("name", "libraries");\r
445 //\r
446 // Parse all sourfiles but files specified in sections\r
447 //\r
448 applyLibraryInstance(document, ele);\r
449 root.appendChild(ele);\r
450 //\r
451 // compile all source files\r
452 //\r
453 root.appendChild(document.createComment("sourcefiles target"));\r
454 ele = document.createElement("target");\r
455 ele.setAttribute("name", "sourcefiles");\r
456 //\r
457 // Parse all sourfiles but files specified in sections\r
458 //\r
459 applyCompileElement(document, ele);\r
460 root.appendChild(ele);\r
461 //\r
462 // generate the init target\r
463 // main purpose is create all nessary pathes\r
464 // generate the sections target\r
465 //\r
466 root.appendChild(document.createComment("sections target"));\r
467 ele = document.createElement("target");\r
468 ele.setAttribute("name", "sections");\r
469 applySectionsElement(document, ele, fp);\r
470 root.appendChild(ele);\r
471 //\r
472 // generate the output target\r
473 //\r
474 root.appendChild(document.createComment("output target"));\r
475 ele = document.createElement("target");\r
476 ele.setAttribute("name", "output");\r
477 applyOutputElement(document, ele, fp);\r
478 root.appendChild(ele);\r
479 //\r
480 // generate the clean target\r
481 //\r
482 root.appendChild(document.createComment("clean target"));\r
483 ele = document.createElement("target");\r
484 ele.setAttribute("name", "clean");\r
485 applyCleanElement(document, ele);\r
486 root.appendChild(ele);\r
487 //\r
488 // generate the Clean All target\r
489 //\r
490 root.appendChild(document.createComment("Clean All target"));\r
491 ele = document.createElement("target");\r
492 ele.setAttribute("name", "cleanall");\r
493 applyDeepcleanElement(document, ele);\r
494 root.appendChild(ele);\r
495 //\r
496 // add the root element to the document\r
497 //\r
498 document.appendChild(rootComment);\r
499 document.appendChild(root);\r
500 //\r
501 // Prepare the DOM document for writing\r
502 //\r
503 Source source = new DOMSource(document);\r
504 //\r
505 // Prepare the output file\r
506 //\r
507 File file = new File(getProject().getProperty("DEST_DIR_OUTPUT") + File.separatorChar + baseName\r
508 + "_build.xml");\r
509 //\r
510 // generate all directory path\r
511 //\r
512 (new File(file.getParent())).mkdirs();\r
513 Result result = new StreamResult(file);\r
514 //\r
515 // Write the DOM document to the file\r
516 //\r
517 Transformer xformer = TransformerFactory.newInstance().newTransformer();\r
518 xformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");\r
519 xformer.setOutputProperty(OutputKeys.INDENT, "yes");\r
520 xformer.transform(source, result);\r
521 } catch (Exception ex) {\r
522 throw new BuildException("Module [" + baseName + "] generating build file failed.\n" + ex.getMessage());\r
523 }\r
524 }\r
525\r
526 /**\r
527 Generate the clean elements for BaseName_build.xml. \r
528 \r
529 @param document current BaseName_build.xml XML document\r
530 @param root Root element for current\r
531 **/\r
532 private void applyCleanElement(Document document, Node root) {\r
533 String[] libinstances = libraries.toArray(new String[libraries.size()]);\r
534 for (int i = 0; i < libinstances.length; i++) {\r
535 File file = new File(GlobalData.getModulePath(libinstances[i]) + File.separatorChar + "build.xml");\r
536\r
537 Element ifEle = document.createElement("if");\r
538 Element availableEle = document.createElement("available");\r
539 availableEle.setAttribute("file", file.getPath());\r
540 ifEle.appendChild(availableEle);\r
541 Element elseEle = document.createElement("then");\r
542\r
543 Element ele = document.createElement("ant");\r
544 ele.setAttribute("antfile", file.getPath());\r
545 ele.setAttribute("inheritAll", "false");\r
546 ele.setAttribute("target", libinstances[i] + "_clean");\r
547 //\r
548 // Workspace_DIR\r
549 //\r
550 Element property = document.createElement("property");\r
551 property.setAttribute("name", "WORKSPACE_DIR");\r
552 property.setAttribute("value", "${WORKSPACE_DIR}");\r
553 ele.appendChild(property);\r
554 //\r
555 // Package Dir\r
556 //\r
557 property = document.createElement("property");\r
558 property.setAttribute("name", "PACKAGE_DIR");\r
559 property.setAttribute("value", "${WORKSPACE_DIR}" + File.separatorChar\r
560 + GlobalData.getPackagePathForModule(libinstances[i]));\r
561 ele.appendChild(property);\r
562 //\r
563 // ARCH\r
564 //\r
565 property = document.createElement("property");\r
566 property.setAttribute("name", "ARCH");\r
567 property.setAttribute("value", "${ARCH}");\r
568 ele.appendChild(property);\r
569 //\r
570 // TARGET\r
571 //\r
572 property = document.createElement("property");\r
573 property.setAttribute("name", "TARGET");\r
574 property.setAttribute("value", "${TARGET}");\r
575 ele.appendChild(property);\r
576 //\r
577 // PACKAGE\r
578 //\r
579 property = document.createElement("property");\r
580 property.setAttribute("name", "PACKAGE");\r
581 property.setAttribute("value", GlobalData.getPackageNameForModule(libinstances[i]));\r
582 ele.appendChild(property);\r
583\r
584 elseEle.appendChild(ele);\r
585 ifEle.appendChild(elseEle);\r
586 root.appendChild(ifEle);\r
587 }\r
588 }\r
589\r
590 /**\r
591 Generate the cleanall elements for BaseName_build.xml. \r
592 \r
593 @param document current BaseName_build.xml XML document\r
594 @param root Root element for current\r
595 **/\r
596 private void applyDeepcleanElement(Document document, Node root) {\r
597 String[] libinstances = libraries.toArray(new String[libraries.size()]);\r
598 for (int i = 0; i < libinstances.length; i++) {\r
599 File file = new File(GlobalData.getModulePath(libinstances[i]) + File.separatorChar + "build.xml");\r
600\r
601 Element ifEle = document.createElement("if");\r
602 Element availableEle = document.createElement("available");\r
603 availableEle.setAttribute("file", file.getPath());\r
604 ifEle.appendChild(availableEle);\r
605 Element elseEle = document.createElement("then");\r
606\r
607 Element ele = document.createElement("ant");\r
608 ele.setAttribute("antfile", file.getPath());\r
609 ele.setAttribute("inheritAll", "false");\r
610 ele.setAttribute("target", libinstances[i] + "_cleanall");\r
611 //\r
612 // Workspace_DIR\r
613 //\r
614 Element property = document.createElement("property");\r
615 property.setAttribute("name", "WORKSPACE_DIR");\r
616 property.setAttribute("value", "${WORKSPACE_DIR}");\r
617 ele.appendChild(property);\r
618 //\r
619 // Package Dir\r
620 //\r
621 property = document.createElement("property");\r
622 property.setAttribute("name", "PACKAGE_DIR");\r
623 property.setAttribute("value", "${WORKSPACE_DIR}" + File.separatorChar\r
624 + GlobalData.getPackagePathForModule(libinstances[i]));\r
625 ele.appendChild(property);\r
626 //\r
627 // ARCH\r
628 //\r
629 property = document.createElement("property");\r
630 property.setAttribute("name", "ARCH");\r
631 property.setAttribute("value", "${ARCH}");\r
632 ele.appendChild(property);\r
633 //\r
634 // TARGET\r
635 //\r
636 property = document.createElement("property");\r
637 property.setAttribute("name", "TARGET");\r
638 property.setAttribute("value", "${TARGET}");\r
639 ele.appendChild(property);\r
640 //\r
641 // PACKAGE\r
642 //\r
643 property = document.createElement("property");\r
644 property.setAttribute("name", "PACKAGE");\r
645 property.setAttribute("value", GlobalData.getPackageNameForModule(libinstances[i]));\r
646 ele.appendChild(property);\r
647\r
648 elseEle.appendChild(ele);\r
649 ifEle.appendChild(elseEle);\r
650 root.appendChild(ifEle);\r
651 }\r
652 }\r
653\r
654 /**\r
655 Generate the dependent library instances elements for BaseName_build.xml. \r
656 \r
657 @param document current BaseName_build.xml XML document\r
658 @param root Root element for current\r
659 **/\r
660 private void applyLibraryInstance(Document document, Node root) {\r
661 String[] libinstances = libraries.toArray(new String[libraries.size()]);\r
662 for (int i = 0; i < libinstances.length; i++) {\r
663 Element ele = document.createElement("ant");\r
664 File file = new File(GlobalData.getModulePath(libinstances[i]) + File.separatorChar + "build.xml");\r
665 ele.setAttribute("antfile", file.getPath());\r
666 ele.setAttribute("inheritAll", "false");\r
667 ele.setAttribute("target", libinstances[i]);\r
668 //\r
669 // Workspace_DIR\r
670 //\r
671 Element property = document.createElement("property");\r
672 property.setAttribute("name", "WORKSPACE_DIR");\r
673 property.setAttribute("value", "${WORKSPACE_DIR}");\r
674 ele.appendChild(property);\r
675 //\r
676 // Package Dir\r
677 //\r
678 property = document.createElement("property");\r
679 property.setAttribute("name", "PACKAGE_DIR");\r
680 property.setAttribute("value", "${WORKSPACE_DIR}" + File.separatorChar\r
681 + GlobalData.getPackagePathForModule(libinstances[i]));\r
682 ele.appendChild(property);\r
683 //\r
684 // ARCH\r
685 //\r
686 property = document.createElement("property");\r
687 property.setAttribute("name", "ARCH");\r
688 property.setAttribute("value", "${ARCH}");\r
689 ele.appendChild(property);\r
690 //\r
691 // TARGET\r
692 //\r
693 property = document.createElement("property");\r
694 property.setAttribute("name", "TARGET");\r
695 property.setAttribute("value", "${TARGET}");\r
696 ele.appendChild(property);\r
697 //\r
698 // PACKAGE\r
699 //\r
700 property = document.createElement("property");\r
701 property.setAttribute("name", "PACKAGE");\r
702 property.setAttribute("value", GlobalData.getPackageNameForModule(libinstances[i]));\r
703 ele.appendChild(property);\r
704 root.appendChild(ele);\r
705 }\r
706 Element expand = document.createElement("Expand");\r
707 root.appendChild(expand);\r
708 }\r
709 \r
710 /**\r
711 Generate the build source files elements for BaseName_build.xml. \r
712 \r
713 @param document current BaseName_build.xml XML document\r
714 @param root Root element for current\r
715 **/\r
716 private void applyCompileElement(Document document, Node root) {\r
717 FileProcess fileProcess = new FileProcess();\r
718 fileProcess.init(getProject(), includes, sourceFiles, document);\r
719 Node[] files = this.getSourceFiles();\r
720 //\r
721 // Parse all unicode files\r
722 //\r
723 for (int i = 0; i < files.length; i++) {\r
724 String filetype = getFiletype(files[i]);\r
725 if (filetype != null) {\r
726 fileProcess.parseFile(getFilename(files[i]), filetype, root, true);\r
727 } else {\r
728 fileProcess.parseFile(getFilename(files[i]), root, true);\r
729 }\r
730 }\r
731 if (fileProcess.isUnicodeExist()) {\r
732 Element ele = document.createElement("Build_Unicode_Database");\r
733 ele.setAttribute("FILEPATH", ".");\r
734 ele.setAttribute("FILENAME", "${BASE_NAME}");\r
735 root.appendChild(ele);\r
736 }\r
737\r
738 //\r
739 // Parse AutoGen.c & AutoGen.h\r
740 //\r
741 if (!baseName.equalsIgnoreCase("Shell")) {\r
742 fileProcess.parseFile(getProject().getProperty("DEST_DIR_DEBUG") + File.separatorChar + "AutoGen.c", root,\r
743 false);\r
744 }\r
745 //\r
746 // Parse all source files\r
747 //\r
748 for (int i = 0; i < files.length; i++) {\r
749 String filetype = getFiletype(files[i]);\r
750 if (filetype != null) {\r
751 fileProcess.parseFile(getFilename(files[i]), filetype, root, false);\r
752 } else {\r
753 fileProcess.parseFile(getFilename(files[i]), root, false);\r
754 }\r
755 }\r
756 //\r
757 // root.appendChild(parallelEle);\r
758 //\r
759 Iterator iter = sourceFiles.iterator();\r
760 String str = "";\r
761 while (iter.hasNext()) {\r
762 str += " " + (String) iter.next();\r
763 }\r
764 getProject().setProperty("SOURCE_FILES", str);\r
765 }\r
766\r
767 /**\r
768 Generate the section elements for BaseName_build.xml. Library module will\r
769 skip this process. \r
770 \r
771 @param document current BaseName_build.xml XML document\r
772 @param root Root element for current\r
773 **/\r
774 private void applySectionsElement(Document document, Node root, FfsProcess fp) {\r
775 if (fp.initSections(buildType, getProject())) {\r
776 String targetFilename = guid + "-" + baseName + FpdParserTask.getSuffix(componentType);\r
777 String[] list = fp.getGenSectionElements(document, baseName, guid, targetFilename);\r
778\r
779 for (int i = 0; i < list.length; i++) {\r
780 Element ele = document.createElement(list[i]);\r
781 ele.setAttribute("FILEPATH", ".");\r
782 ele.setAttribute("FILENAME", "${BASE_NAME}");\r
783 root.appendChild(ele);\r
784 }\r
785 }\r
786 }\r
787\r
788 /**\r
789 Generate the output elements for BaseName_build.xml. If module is library,\r
790 call the <em>LIB</em> command, else call the <em>GenFfs</em> command. \r
791 \r
792 @param document current BaseName_build.xml XML document\r
793 @param root Root element for current\r
794 **/\r
795 private void applyOutputElement(Document document, Node root, FfsProcess fp) {\r
796 if (flag == GlobalData.ONLY_LIBMSA || flag == GlobalData.LIBMSA_AND_LIBMBD) {\r
797 //\r
798 // call Lib command\r
799 //\r
800 Element cc = document.createElement("Build_Library");\r
801 cc.setAttribute("FILENAME", baseName);\r
802 root.appendChild(cc);\r
803 }\r
804 //\r
805 // if it is a module but library\r
806 //\r
807 else {\r
808 if (fp.getFfsNode() != null) {\r
809 root.appendChild(fp.getFfsNode());\r
810 }\r
811 }\r
812 }\r
813\r
814 /**\r
815 Get file name from node. If some wrong, return string with zero length. \r
816 \r
817 @param node Filename node of MSA/MBD or specified in each Section\r
818 @return File name\r
819 **/\r
820 private String getFilename(Node node) {\r
821 String path = null;\r
822 String filename = "${MODULE_DIR}" + File.separatorChar;\r
823 String str = "";\r
824 try {\r
825 FilenameDocument file = (FilenameDocument) XmlObject.Factory.parse(node);\r
826 str = file.getFilename().getStringValue().trim();\r
827 path = file.getFilename().getPath();\r
828 } catch (Exception e) {\r
829 str = "";\r
830 }\r
831 if (path != null) {\r
832 filename += path + File.separatorChar + str;\r
833 } else {\r
834 filename += str;\r
835 }\r
836 return getProject().replaceProperties(filename);\r
837 }\r
838\r
839 /**\r
840 Get file type from node. If some wrong or not specified, return \r
841 <code>null</code>. \r
842 \r
843 @param node Filename node of MSA/MBD or specified in each Section\r
844 @return File type\r
845 **/\r
846 private String getFiletype(Node node) {\r
847 String str = null;\r
848 try {\r
849 FilenameDocument file = (FilenameDocument) XmlObject.Factory.parse(node);\r
850 str = file.getFilename().getFileType();\r
851 } catch (Exception e) {\r
852 str = null;\r
853 }\r
854 return str;\r
855 }\r
856\r
857 /**\r
858 Return all source files but AutoGen.c.\r
859 \r
860 @return source files Node array\r
861 **/\r
862 public Node[] getSourceFiles() {\r
863 XmlObject[] files = SurfaceAreaQuery.getSourceFiles(arch);\r
864 if (files == null) {\r
865 return new Node[0];\r
866 }\r
867 Vector<Node> vector = new Vector<Node>();\r
868 for (int i = 0; i < files.length; i++) {\r
869 vector.addElement(files[i].getDomNode());\r
870 }\r
871 //\r
872 // To be consider sourcefiles from Sections\r
873 //\r
874 return vector.toArray(new Node[vector.size()]);\r
875 }\r
876\r
877 /**\r
878 Get current module's base name. \r
879 \r
880 @return base name\r
881 **/\r
882 public String getBaseName() {\r
883 return baseName;\r
884 }\r
885\r
886 /**\r
887 Set MBD surface area file. For ANT use.\r
888 \r
889 @param mbdFilename Surface Area file\r
890 **/\r
891 public void setMbdFilename(File mbdFilename) {\r
892 this.mbdFilename = mbdFilename;\r
893 }\r
894\r
895 /**\r
896 Set MSA surface area file. For ANT use.\r
897 \r
898 @param msaFilename Surface Area file\r
899 **/\r
900 public void setMsaFilename(File msaFilename) {\r
901 this.msaFilename = msaFilename;\r
902 }\r
903\r
904 /**\r
905 Compile flags setup. \r
906 \r
907 <p> Take command <code>CC</code> and arch <code>IA32</code> for example, \r
908 Those flags are from <code>ToolChainFactory</code>: </p>\r
909 <ul>\r
910 <li> IA32_CC </li>\r
911 <li> IA32_CC_STD_FLAGS </li>\r
912 <li> IA32_CC_GLOBAL_FLAGS </li>\r
913 <li> IA32_CC_GLOBAL_ADD_FLAGS </li>\r
914 <li> IA32_CC_GLOBAL_SUB_FLAGS </li>\r
915 </ul>\r
916 Those flags can user-define: \r
917 <ul>\r
918 <li> IA32_CC_PROJ_FLAGS </li>\r
919 <li> IA32_CC_PROJ_ADD_FLAGS </li>\r
920 <li> IA32_CC_PROJ_SUB_FLAGS </li>\r
921 <li> CC_PROJ_FLAGS </li>\r
922 <li> CC_PROJ_ADD_FLAGS </li>\r
923 <li> CC_PROJ_SUB_FLAGS </li>\r
924 <li> CC_FLAGS </li>\r
925 <li> IA32_CC_FLAGS </li>\r
926 </ul>\r
927 \r
928 <p> The final flags is composed of STD, GLOBAL and PROJ. If CC_FLAGS or\r
929 IA32_CC_FLAGS is specified, STD, GLOBAL and PROJ will not affect. </p>\r
930 \r
931 Note that the <code>ToolChainFactory</code> executes only once \r
932 during whole build process. \r
933 **/\r
934 private void flagsSetup() {\r
935 Project project = getProject();\r
936 //\r
937 // If ToolChain has been set up before, do nothing.\r
938 //\r
939 ToolChainFactory toolChainFactory = new ToolChainFactory(project);\r
940 toolChainFactory.setupToolChain();\r
941\r
942 String[] cmd = ToolChainFactory.commandType;\r
943 Set<String> addSet = new HashSet<String>(40);\r
944 Set<String> subSet = new HashSet<String>(40);\r
945 for (int i = 0; i < cmd.length; i++) {\r
946 String str = ToolChainFactory.getValue(arch + "_" + cmd[i]);\r
947 //\r
948 // Command line path+command name\r
949 //\r
950 if (str != null) {\r
951 project.setProperty(cmd[i], str);\r
952 }\r
953 //\r
954 // ARCH_CMD_STD_FLAGS\r
955 //\r
956 str = ToolChainFactory.getValue(arch + "_" + cmd[i] + "_STD_FLAGS");\r
957 if (str != null) {\r
958 putFlagsToSet(addSet, str);\r
959 project.setProperty(cmd[i] + "_STD_FLAGS", str);\r
960 }\r
961 //\r
962 // ARCH_CMD_GLOBAL_FLAGS\r
963 //\r
964 str = ToolChainFactory.getValue(arch + "_" + cmd[i] + "_GLOBAL_FLAGS");\r
965 if (str != null) {\r
966 putFlagsToSet(addSet, str);\r
967 }\r
968 //\r
969 // ARCH_CMD_GLOBAL_ADD_FLAGS\r
970 //\r
971 str = ToolChainFactory.getValue(arch + "_" + cmd[i] + "_GLOBAL_ADD_FLAGS");\r
972 if (str != null) {\r
973 putFlagsToSet(addSet, str);\r
974 }\r
975 //\r
976 // ARCH_CMD_GLOBAL_SUB_FLAGS\r
977 //\r
978 str = ToolChainFactory.getValue(arch + "_" + cmd[i] + "_GLOBAL_SUB_FLAGS");\r
979 if (str != null) {\r
980 putFlagsToSet(subSet, str);\r
981 }\r
982 //\r
983 // ARCH_CMD_PROJ_FLAGS\r
984 //\r
985 str = project.getProperty(arch + "_" + cmd[i] + "_PROJ_FLAGS");\r
986 if (str != null) {\r
987 putFlagsToSet(addSet, str);\r
988 }\r
989 //\r
990 // ARCH_CMD_PROG_FLAGS\r
991 //\r
992 str = project.getProperty(arch + "_" + cmd[i] + "_PROJ_ADD_FLAGS");\r
993 if (str != null) {\r
994 putFlagsToSet(addSet, str);\r
995 }\r
996 //\r
997 // ARCH_CMD_PROG_FLAGS\r
998 //\r
999 str = project.getProperty(arch + "_" + cmd[i] + "_PROJ_SUB_FLAGS");\r
1000 if (str != null) {\r
1001 putFlagsToSet(subSet, str);\r
1002 }\r
1003 //\r
1004 // CMD_PROJ_FLAGS\r
1005 //\r
1006 str = project.getProperty(cmd[i] + "_PROJ_FLAGS");\r
1007 if (str != null) {\r
1008 putFlagsToSet(addSet, str);\r
1009 }\r
1010 //\r
1011 // CMD_PROG_FLAGS\r
1012 //\r
1013 str = project.getProperty(cmd[i] + "_PROJ_ADD_FLAGS");\r
1014 if (str != null) {\r
1015 putFlagsToSet(addSet, str);\r
1016 }\r
1017 //\r
1018 // CMD_PROG_FLAGS\r
1019 //\r
1020 str = project.getProperty(cmd[i] + "_PROJ_SUB_FLAGS");\r
1021 if (str != null) {\r
1022 putFlagsToSet(subSet, str);\r
1023 }\r
1024 //\r
1025 // If IA32_CC_FLAGS or IA32_LIB_FLAGS .. has defined in BuildOptions\r
1026 //\r
1027 if ((str = project.getProperty(arch + "_" + cmd[i] + "_FLAGS")) != null) {\r
1028 project.setProperty(cmd[i] + "_FLAGS", getRawFlags(addSet, subSet));\r
1029 addSet.clear();\r
1030 subSet.clear();\r
1031 putFlagsToSet(addSet, project.replaceProperties(str));\r
1032 project.setProperty(cmd[i] + "_FLAGS", project.replaceProperties(getFlags(addSet, subSet)));\r
1033 addSet.clear();\r
1034 subSet.clear();\r
1035 }\r
1036 //\r
1037 // If CC_FLAGS or LIB_FLAGS .. has defined in BuildOptions\r
1038 //\r
1039 else if ((str = project.getProperty(cmd[i] + "_FLAGS")) != null) {\r
1040 project.setProperty(cmd[i] + "_FLAGS", getRawFlags(addSet, subSet));\r
1041 addSet.clear();\r
1042 subSet.clear();\r
1043 putFlagsToSet(addSet, project.replaceProperties(str));\r
1044 project.setProperty(cmd[i] + "_FLAGS", project.replaceProperties(getFlags(addSet, subSet)));\r
1045 addSet.clear();\r
1046 subSet.clear();\r
1047 } else {\r
1048 project.setProperty(cmd[i] + "_FLAGS", getFlags(addSet, subSet));\r
1049 addSet.clear();\r
1050 subSet.clear();\r
1051 }\r
1052 }\r
1053 project.setProperty("C_FLAGS", project.getProperty("CC_FLAGS"));\r
1054 }\r
1055\r
1056 /**\r
1057 Initialize some properties will be used in current module build, including\r
1058 user-defined option from <em>Option</em> of <em>BuildOptions</em> in \r
1059 surface area. \r
1060 **/\r
1061 private void updateParameters() {\r
1062 getProject().setProperty("OBJECTS", "");\r
1063 getProject().setProperty("SDB_FILES", "");\r
1064 getProject().setProperty("BASE_NAME", baseName);\r
1065 if (map.get("MsaHeader") != null) {\r
1066 flag = GlobalData.MSA_AND_MBD;\r
1067 MsaHeaderDocument.MsaHeader header = ((MsaHeaderDocument) map.get("MsaHeader")).getMsaHeader();\r
1068 guid = header.getGuid().getStringValue();\r
1069 componentType = header.getComponentType().toString();\r
1070 } \r
1071 \r
1072 else if (map.get("MsaLibHeader") != null) {\r
1073 flag = GlobalData.LIBMSA_AND_LIBMBD;\r
1074 MsaLibHeaderDocument.MsaLibHeader header = ((MsaLibHeaderDocument) map.get("MsaLibHeader"))\r
1075 .getMsaLibHeader();\r
1076 guid = header.getGuid().getStringValue();\r
1077 componentType = header.getComponentType().toString();\r
1078 }\r
1079 \r
1080 if (componentType != null) {\r
1081 getProject().setProperty("COMPONENT_TYPE", componentType);\r
1082 }\r
1083 \r
1084 if (guid != null) {\r
1085 getProject().setProperty("FILE_GUID", guid);\r
1086 }\r
1087 //\r
1088 // Get all options and set to properties\r
1089 //\r
1090 String[][] options = SurfaceAreaQuery.getOptions(arch);\r
1091 for (int i = 0; i < options.length; i++) {\r
1092 if (options[i][0] != null && options[i][1] != null) {\r
1093 getProject().setProperty(options[i][0], getProject().replaceProperties(options[i][1]));\r
1094 }\r
1095 }\r
1096\r
1097 buildType = getProject().getProperty("BUILD_TYPE");\r
1098 if (buildType == null) {\r
1099 buildType = componentType;\r
1100 }\r
1101\r
1102 }\r
1103\r
1104 /**\r
1105 Separate the string and instore in set.\r
1106 \r
1107 <p> String is separated by Java Regulation Expression \r
1108 "[^\\\\]?(\".*?[^\\\\]\")[ \t,]+". </p>\r
1109 \r
1110 <p>For example: </p>\r
1111 \r
1112 <pre>\r
1113 "/nologo", "/W3", "/WX"\r
1114 "/C", "/DSTRING_DEFINES_FILE=\"BdsStrDefs.h\""\r
1115 </pre>\r
1116 \r
1117 @param set store the separated string\r
1118 @param str string to separate\r
1119 **/\r
1120 private void putFlagsToSet(Set<String> set, String str) {\r
1121 Pattern myPattern = Pattern.compile("[^\\\\]?(\".*?[^\\\\]\")[ \t,]+");\r
1122 Matcher matcher = myPattern.matcher(str + " ");\r
1123 while (matcher.find()) {\r
1124 String item = str.substring(matcher.start(1), matcher.end(1));\r
1125 if (!set.contains(item)) {\r
1126 set.add(item);\r
1127 }\r
1128 }\r
1129 }\r
1130 \r
1131 /**\r
1132 Generate the final flags string will be used by compile command. \r
1133 \r
1134 @param add the add flags set\r
1135 @param sub the sub flags set\r
1136 @return final flags after add set substract sub set\r
1137 **/\r
1138 private String getFlags(Set<String> add, Set<String> sub) {\r
1139 String result = "";\r
1140 add.removeAll(sub);\r
1141 Iterator iter = add.iterator();\r
1142 while (iter.hasNext()) {\r
1143 String str = getProject().replaceProperties((String) iter.next());\r
1144 result += str.substring(1, str.length() - 1) + " ";\r
1145 }\r
1146 return result;\r
1147 }\r
1148\r
1149 /**\r
1150 Generate the flags string with original format. The format is defined by \r
1151 Java Regulation Expression "[^\\\\]?(\".*?[^\\\\]\")[ \t,]+". </p>\r
1152 \r
1153 <p>For example: </p>\r
1154 \r
1155 <pre>\r
1156 "/nologo", "/W3", "/WX"\r
1157 "/C", "/DSTRING_DEFINES_FILE=\"BdsStrDefs.h\""\r
1158 </pre>\r
1159 \r
1160 @param add the add flags set\r
1161 @param sub the sub flags set\r
1162 @return flags with original format\r
1163 **/\r
1164 private String getRawFlags(Set<String> add, Set<String> sub) {\r
1165 String result = "";\r
1166 add.removeAll(sub);\r
1167 Iterator iter = add.iterator();\r
1168 while (iter.hasNext()) {\r
1169 String str = getProject().replaceProperties((String) iter.next());\r
1170 result += "\"" + str.substring(1, str.length() - 1) + "\", ";\r
1171 }\r
1172 return result;\r
1173 }\r
1174\r
1175 /**\r
1176 Set base name. For ANT use.\r
1177 \r
1178 @param baseName Base name\r
1179 **/\r
1180 public void setBaseName(String baseName) {\r
1181 this.baseName = baseName;\r
1182 }\r
1183\r
1184}\r