1e5c7744b557811323045b0813d6a6ac69af12de
[mirror_edk2.git] / Tools / Java / Source / GenBuild / org / tianocore / build / fpd / PlatformBuildFileGenerator.java
1 /** @file
2
3 Copyright (c) 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11 **/
12 package org.tianocore.build.fpd;
13
14 import java.io.File;
15 import java.util.HashMap;
16 import java.util.Iterator;
17 import java.util.Map;
18 import java.util.Set;
19
20 import javax.xml.parsers.DocumentBuilder;
21 import javax.xml.parsers.DocumentBuilderFactory;
22 import javax.xml.transform.OutputKeys;
23 import javax.xml.transform.Result;
24 import javax.xml.transform.Source;
25 import javax.xml.transform.Transformer;
26 import javax.xml.transform.TransformerFactory;
27 import javax.xml.transform.dom.DOMSource;
28 import javax.xml.transform.stream.StreamResult;
29
30 import org.apache.tools.ant.BuildException;
31 import org.apache.tools.ant.Project;
32 import org.tianocore.build.global.GlobalData;
33 import org.tianocore.build.global.SurfaceAreaQuery;
34 import org.tianocore.build.id.FpdModuleIdentification;
35 import org.tianocore.build.id.ModuleIdentification;
36 import org.w3c.dom.Comment;
37 import org.w3c.dom.Document;
38 import org.w3c.dom.Element;
39 import org.w3c.dom.NamedNodeMap;
40 import org.w3c.dom.Node;
41 import org.w3c.dom.NodeList;
42
43 /**
44 class PlatformBuildFileGenerator is used to generate ${PLATFORM}_build.xml file.
45
46 @since GenBuild 1.0
47 **/
48 public class PlatformBuildFileGenerator {
49
50 ///
51 /// Mapping from modules identification to out put file name
52 ///
53 private Map<FpdModuleIdentification, String> outfiles;
54
55 ///
56 /// Mapping from FV name to its modules
57 ///
58 private Map<String, Set<FpdModuleIdentification>> fvs = new HashMap<String, Set<FpdModuleIdentification>>();
59
60
61 private boolean isUnified = true;
62
63 private SurfaceAreaQuery saq = null;
64
65 private File platformBuildFile = null;
66
67 private Map<String, String> aprioriType = null;
68
69 private Project project;
70
71 private String info = "DO NOT EDIT \n"
72 + "This file is auto-generated by the build utility\n"
73 + "\n"
74 + "Abstract:\n"
75 + "Auto-generated ANT build file for building EFI Modules and Platforms\n";
76
77 public PlatformBuildFileGenerator(Project project, Map<FpdModuleIdentification, String> outfiles, Map<String, Set<FpdModuleIdentification>> fvs, boolean isUnified, SurfaceAreaQuery saq, String platformBuildFile, Map<String, String> aprioriType){
78 this.project = project;
79 this.outfiles = outfiles;
80 this.isUnified = isUnified;
81 this.fvs = fvs;
82 this.saq = saq;
83 this.platformBuildFile = new File(platformBuildFile);
84 this.aprioriType = aprioriType;
85 }
86
87 /**
88 Generate build.out.xml file.
89
90 @throws BuildException
91 build.out.xml XML document create error
92 **/
93 public void genBuildFile() throws BuildException {
94 DocumentBuilderFactory domfac = DocumentBuilderFactory.newInstance();
95 try {
96 DocumentBuilder dombuilder = domfac.newDocumentBuilder();
97 Document document = dombuilder.newDocument();
98 Comment rootComment = document.createComment(info);
99 //
100 // create root element and its attributes
101 //
102 Element root = document.createElement("project");
103 root.setAttribute("name", project.getProperty("PLATFORM"));
104 root.setAttribute("default", "all");
105 root.setAttribute("basedir", ".");
106
107 //
108 // element for External ANT tasks
109 //
110 root.appendChild(document.createComment("Apply external ANT tasks"));
111 Element ele = document.createElement("taskdef");
112 ele.setAttribute("resource", "GenBuild.tasks");
113 root.appendChild(ele);
114
115 ele = document.createElement("taskdef");
116 ele.setAttribute("resource", "frameworktasks.tasks");
117 root.appendChild(ele);
118
119 ele = document.createElement("taskdef");
120 ele.setAttribute("resource", "net/sf/antcontrib/antlib.xml");
121 root.appendChild(ele);
122
123 ele = document.createElement("property");
124 ele.setAttribute("environment", "env");
125 root.appendChild(ele);
126
127 //
128 // Default Target
129 //
130 root.appendChild(document.createComment("Default target"));
131 ele = document.createElement("target");
132 ele.setAttribute("name", "all");
133 ele.setAttribute("depends", "prebuild, modules, fvs, postbuild");
134 root.appendChild(ele);
135
136 //
137 // Modules and Fvs Target
138 //
139 applyModules(document, root);
140
141 applyFvs(document, root);
142
143 //
144 // Clean Target
145 //
146 applyClean(document, root);
147
148 //
149 // Deep Clean Target
150 //
151 applyCleanall(document, root);
152
153 //
154 // User Extension pre build
155 //
156 applyUserExtensionsPreBuild(document, root);
157
158 //
159 // User Extension Post build
160 //
161 applyUserExtensionsPostBuild(document, root);
162
163 document.appendChild(rootComment);
164 document.appendChild(root);
165 //
166 // Prepare the DOM document for writing
167 //
168 Source source = new DOMSource(document);
169 //
170 // generate all directory path
171 //
172 (new File(platformBuildFile.getParent())).mkdirs();
173 Result result = new StreamResult(platformBuildFile);
174 //
175 // Write the DOM document to the file
176 //
177 Transformer xformer = TransformerFactory.newInstance().newTransformer();
178 xformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
179 xformer.setOutputProperty(OutputKeys.INDENT, "yes");
180 xformer.transform(source, result);
181 } catch (Exception ex) {
182 throw new BuildException("Generating platform build file [" + platformBuildFile.getPath() + "_build.xml] failed. \n" + ex.getMessage());
183 }
184 }
185
186 /**
187 1. Get All valid Fv Image Names in sequence
188 2. For each FV, get modules by sequences
189 3. Get other modules
190
191 @param document XML document
192 @param root Node
193 **/
194 private void applyModules(Document document, Node root) {
195 root.appendChild(document.createComment("Modules target"));
196 Element ele = document.createElement("target");
197 ele.setAttribute("name", "modules");
198
199 //
200 // Try to build apriori if necessary
201 //
202 //
203 // For every Target and ToolChain
204 //
205 String[] targetList = GlobalData.getToolChainInfo().getTargets();
206 for (int i = 0; i < targetList.length; i++){
207 String[] toolchainList = GlobalData.getToolChainInfo().getTagnames();
208 for(int j = 0; j < toolchainList.length; j++){
209 //
210 // Prepare FV_DIR
211 //
212 String ffsCommonDir = project.getProperty("BUILD_DIR") + File.separatorChar
213 + targetList[i] + "_"
214 + toolchainList[j];
215 File fvDir = new File(ffsCommonDir + File.separatorChar + "FV");
216 Element fvEle = document.createElement("var");
217 fvEle.setAttribute("name", "FV_DIR");
218 fvEle.setAttribute("value", fvDir.getPath().replaceAll("(\\\\)", "/"));
219 ele.appendChild(fvEle);
220
221 Iterator<String> aprIter = aprioriType.keySet().iterator();
222 while (aprIter.hasNext()) {
223 String fvName = aprIter.next();
224 Element moduleEle = document.createElement("Build_Apriori");
225 moduleEle.setAttribute("FILENAME", fvName);
226 moduleEle.setAttribute("GUID", aprioriType.get(fvName));
227 ele.appendChild(moduleEle);
228 }
229 }
230 }
231
232 //
233 // Get all valid FV name
234 //
235 String[] validFv = saq.getFpdValidImageNames();
236
237 //
238 // For each valid FV, get all modules in sequence
239 //
240 for (int i = 0; i < validFv.length; i++) {
241 if (fvs.containsKey(validFv[i])) {
242 Set<FpdModuleIdentification> set = fvs.get(validFv[i]);
243 Iterator<FpdModuleIdentification> iter = set.iterator();
244 while (iter.hasNext()) {
245 FpdModuleIdentification fpdModuleId = iter.next();
246 applySingleModule(document, ele, fpdModuleId);
247 }
248 }
249 }
250
251 //
252 // Get all other modules
253 //
254 Iterator<String> fvsNameIter = fvs.keySet().iterator();
255
256 while (fvsNameIter.hasNext()) {
257 String fvName = fvsNameIter.next();
258 if (!isContain(validFv, fvName)) {
259 Set<FpdModuleIdentification> set = fvs.get(fvName);
260 Iterator iter = set.iterator();
261 while (iter.hasNext()) {
262 FpdModuleIdentification fpdModuleId = (FpdModuleIdentification) iter.next();
263 applySingleModule(document, ele, fpdModuleId);
264 }
265 }
266 }
267
268 root.appendChild(ele);
269 }
270
271 private void applySingleModule(Document document, Node root, FpdModuleIdentification fpdModuleId) {
272 ModuleIdentification moduleId = fpdModuleId.getModule();
273 Element moduleEle = document.createElement("GenBuild");
274 moduleEle.setAttribute("type", "build");
275 //
276 // Inherit Properties.
277 //{"ARCH", "PACKAGE", "PACKAGE_GUID", "PACKAGE_VERSION", "MODULE_DIR"}
278 //
279
280 //
281 // ARCH
282 //
283 Element property = document.createElement("property");
284 property.setAttribute("name", "ARCH");
285 property.setAttribute("value", fpdModuleId.getArch());
286 moduleEle.appendChild(property);
287
288 //
289 // MODULE_GUID
290 //
291 property = document.createElement("property");
292 property.setAttribute("name", "MODULE_GUID");
293 property.setAttribute("value", moduleId.getGuid());
294 moduleEle.appendChild(property);
295
296 //
297 // MODULE_VERSION
298 //
299 property = document.createElement("property");
300 property.setAttribute("name", "MODULE_VERSION");
301 property.setAttribute("value", moduleId.getVersion());
302 moduleEle.appendChild(property);
303
304 //
305 // PACKAGE_GUID
306 //
307 property = document.createElement("property");
308 property.setAttribute("name", "PACKAGE_GUID");
309 property.setAttribute("value", moduleId.getPackage().getGuid());
310 moduleEle.appendChild(property);
311
312 //
313 // PACKAGE_VERSION
314 //
315 property = document.createElement("property");
316 property.setAttribute("name", "PACKAGE_VERSION");
317 property.setAttribute("value", moduleId.getPackage().getVersion());
318 moduleEle.appendChild(property);
319
320 root.appendChild(moduleEle);
321 }
322
323 private boolean isContain(String[] list, String item) {
324 for (int i = 0; i < list.length; i++) {
325 if (list[i].equalsIgnoreCase(item)) {
326 return true;
327 }
328 }
329 return false;
330 }
331
332 private void applyFvs(Document document, Node root) {
333 //
334 // FVS Target
335 //
336 root.appendChild(document.createComment("FVs target"));
337 Element ele = document.createElement("target");
338 ele.setAttribute("name", "fvs");
339
340 //
341 // For every Target and ToolChain
342 //
343 String[] targetList = GlobalData.getToolChainInfo().getTargets();
344 for (int i = 0; i < targetList.length; i++){
345 String[] toolchainList = GlobalData.getToolChainInfo().getTagnames();
346 for(int j = 0; j < toolchainList.length; j++){
347 String fvOutputDir = project.getProperty("BUILD_DIR") + File.separatorChar
348 + targetList[i] + "_"
349 + toolchainList[j] + File.separatorChar + "FV";
350 String[] validFv = saq.getFpdValidImageNames();
351 for (int k = 0; k < validFv.length; k++) {
352 String inputFile = fvOutputDir + "" + File.separatorChar + validFv[k].toUpperCase() + ".inf";
353 Element fvEle = document.createElement("genfvimage");
354 fvEle.setAttribute("infFile", inputFile);
355 fvEle.setAttribute("outputDir", fvOutputDir);
356 ele.appendChild(fvEle);
357 }
358 }
359 }
360 root.appendChild(ele);
361 }
362
363 private void applyClean(Document document, Node root) {
364 //
365 // Clean Target
366 //
367 root.appendChild(document.createComment("Clean target"));
368 Element ele = document.createElement("target");
369 ele.setAttribute("name", "clean");
370
371 if (isUnified) {
372 Element cleanEle = document.createElement("delete");
373 cleanEle.setAttribute("includeemptydirs", "true");
374 Element filesetEle = document.createElement("fileset");
375 filesetEle.setAttribute("dir", project.getProperty("BUILD_DIR"));
376 filesetEle.setAttribute("includes", "**\\OUTPUT\\**");
377 cleanEle.appendChild(filesetEle);
378 ele.appendChild(cleanEle);
379 } else {
380 Set set = outfiles.keySet();
381 Iterator iter = set.iterator();
382 while (iter.hasNext()) {
383 FpdModuleIdentification fpdModuleId = (FpdModuleIdentification) iter.next();
384 ModuleIdentification moduleId = fpdModuleId.getModule();
385
386 Element ifEle = document.createElement("if");
387 Element availableEle = document.createElement("available");
388 availableEle.setAttribute("file", moduleId.getMsaFile().getParent() + File.separatorChar
389 + "build.xml");
390 ifEle.appendChild(availableEle);
391 Element elseEle = document.createElement("then");
392
393 Element moduleEle = document.createElement("ant");
394 moduleEle.setAttribute("antfile", moduleId.getMsaFile().getParent() + File.separatorChar
395 + "build.xml");
396 moduleEle.setAttribute("target", "clean");
397 //
398 // Inherit Properties.
399 //{"ARCH", "PACKAGE", "PACKAGE_GUID", "PACKAGE_VERSION", "MODULE_DIR"}
400 //
401
402 //
403 // ARCH
404 //
405 Element property = document.createElement("property");
406 property.setAttribute("name", "ARCH");
407 property.setAttribute("value", fpdModuleId.getArch());
408 moduleEle.appendChild(property);
409
410 //
411 // PACKAGE
412 //
413 property = document.createElement("property");
414 property.setAttribute("name", "PACKAGE");
415 property.setAttribute("value", moduleId.getPackage().getName());
416 moduleEle.appendChild(property);
417
418 //
419 // PACKAGE_GUID
420 //
421 property = document.createElement("property");
422 property.setAttribute("name", "PACKAGE_GUID");
423 property.setAttribute("value", moduleId.getPackage().getGuid());
424 moduleEle.appendChild(property);
425
426 //
427 // PACKAGE_VERSION
428 //
429 property = document.createElement("property");
430 property.setAttribute("name", "PACKAGE_VERSION");
431 property.setAttribute("value", moduleId.getPackage().getVersion());
432 moduleEle.appendChild(property);
433
434 //
435 // MODULE_DIR
436 //
437 property = document.createElement("property");
438 property.setAttribute("name", "MODULE_DIR");
439 property.setAttribute("value", moduleId.getMsaFile().getParent());
440 moduleEle.appendChild(property);
441 elseEle.appendChild(moduleEle);
442 ifEle.appendChild(elseEle);
443 ele.appendChild(ifEle);
444 }
445 }
446 root.appendChild(ele);
447 }
448
449 private void applyCleanall(Document document, Node root) {
450 //
451 // Deep Clean Target
452 //
453 root.appendChild(document.createComment("Target: cleanall"));
454 Element ele = document.createElement("target");
455 ele.setAttribute("name", "cleanall");
456
457 if (isUnified) {
458 String[] targetList = GlobalData.getToolChainInfo().getTargets();
459 for (int i = 0; i < targetList.length; ++i) {
460 String[] toolchainList = GlobalData.getToolChainInfo().getTagnames();
461 for(int j = 0; j < toolchainList.length; j++) {
462 Element cleanAllEle = document.createElement("delete");
463 cleanAllEle.setAttribute("dir", project.getProperty("BUILD_DIR") + File.separatorChar + targetList[i] + "_" + toolchainList[j]);
464 ele.appendChild(cleanAllEle);
465 }
466 }
467 } else {
468 Set set = outfiles.keySet();
469 Iterator iter = set.iterator();
470 while (iter.hasNext()) {
471 FpdModuleIdentification fpdModuleId = (FpdModuleIdentification) iter.next();
472 ModuleIdentification moduleId = fpdModuleId.getModule();
473
474 Element ifEle = document.createElement("if");
475 Element availableEle = document.createElement("available");
476 availableEle.setAttribute("file", moduleId.getMsaFile().getParent() + File.separatorChar
477 + "build.xml");
478 ifEle.appendChild(availableEle);
479 Element elseEle = document.createElement("then");
480
481 Element moduleEle = document.createElement("ant");
482 moduleEle.setAttribute("antfile", moduleId.getMsaFile().getParent() + File.separatorChar
483 + "build.xml");
484 moduleEle.setAttribute("target", "cleanall");
485 //
486 // Inherit Properties.
487 //{"ARCH", "PACKAGE", "PACKAGE_GUID", "PACKAGE_VERSION", "MODULE_DIR"}
488 //
489
490 //
491 // ARCH
492 //
493 Element property = document.createElement("property");
494 property.setAttribute("name", "ARCH");
495 property.setAttribute("value", fpdModuleId.getArch());
496 moduleEle.appendChild(property);
497
498 //
499 // PACKAGE
500 //
501 property = document.createElement("property");
502 property.setAttribute("name", "PACKAGE");
503 property.setAttribute("value", moduleId.getPackage().getName());
504 moduleEle.appendChild(property);
505
506 //
507 // PACKAGE_GUID
508 //
509 property = document.createElement("property");
510 property.setAttribute("name", "PACKAGE_GUID");
511 property.setAttribute("value", moduleId.getPackage().getGuid());
512 moduleEle.appendChild(property);
513
514 //
515 // PACKAGE_VERSION
516 //
517 property = document.createElement("property");
518 property.setAttribute("name", "PACKAGE_VERSION");
519 property.setAttribute("value", moduleId.getPackage().getVersion());
520 moduleEle.appendChild(property);
521
522 //
523 // MODULE_DIR
524 //
525 property = document.createElement("property");
526 property.setAttribute("name", "MODULE_DIR");
527 property.setAttribute("value", moduleId.getMsaFile().getParent());
528 moduleEle.appendChild(property);
529 elseEle.appendChild(moduleEle);
530 ifEle.appendChild(elseEle);
531 ele.appendChild(ifEle);
532 }
533 }
534 root.appendChild(ele);
535 }
536
537 private void applyUserExtensionsPreBuild(Document document, Node root) {
538 //
539 // User Extensions
540 //
541 root.appendChild(document.createComment("Pre-Build Processing"));
542 Element ele = document.createElement("target");
543 ele.setAttribute("name", "prebuild");
544
545 Node node = saq.getFpdUserExtensionPreBuild();
546 if (node != null) {
547 //
548 // For every Target and ToolChain
549 //
550 String[] targetList = GlobalData.getToolChainInfo().getTargets();
551 for (int i = 0; i < targetList.length; i++){
552 String[] toolchainList = GlobalData.getToolChainInfo().getTagnames();
553 for(int j = 0; j < toolchainList.length; j++){
554 //
555 // Prepare FV_DIR
556 //
557 String ffsCommonDir = project.getProperty("BUILD_DIR") + File.separatorChar
558 + targetList[i] + "_"
559 + toolchainList[j];
560 File fvDir = new File(ffsCommonDir + File.separatorChar + "FV");
561 Element fvEle = document.createElement("var");
562 fvEle.setAttribute("name", "FV_DIR");
563 fvEle.setAttribute("value", fvDir.getPath().replaceAll("(\\\\)", "/"));
564 ele.appendChild(fvEle);
565
566 Element targetDirEle = document.createElement("var");
567 targetDirEle.setAttribute("name", "TARGET_DIR");
568 targetDirEle.setAttribute("value", ffsCommonDir.replaceAll("(\\\\)", "/"));
569 ele.appendChild(targetDirEle);
570
571 NodeList childNodes = node.getChildNodes();
572 for (int k = 0; k < childNodes.getLength(); k++) {
573 Node childItem = childNodes.item(k);
574 if (childItem.getNodeType() == Node.ELEMENT_NODE) {
575 ele.appendChild(recursiveNode(childItem, document));
576 }
577 }
578 }
579 }
580 }
581
582 root.appendChild(ele);
583 }
584
585 private void applyUserExtensionsPostBuild(Document document, Node root) {
586 //
587 // User Extensions
588 //
589 root.appendChild(document.createComment("Post-Build Processing"));
590 Element ele = document.createElement("target");
591 ele.setAttribute("name", "postbuild");
592
593 Node node = saq.getFpdUserExtensionPostBuild();
594 if (node != null) {
595 //
596 // For every Target and ToolChain
597 //
598 String[] targetList = GlobalData.getToolChainInfo().getTargets();
599 for (int i = 0; i < targetList.length; i++){
600 String[] toolchainList = GlobalData.getToolChainInfo().getTagnames();
601 for(int j = 0; j < toolchainList.length; j++){
602 //
603 // Prepare FV_DIR
604 //
605 String ffsCommonDir = project.getProperty("BUILD_DIR") + File.separatorChar
606 + targetList[i] + "_"
607 + toolchainList[j];
608 File fvDir = new File(ffsCommonDir + File.separatorChar + "FV");
609 Element fvEle = document.createElement("var");
610 fvEle.setAttribute("name", "FV_DIR");
611 fvEle.setAttribute("value", fvDir.getPath().replaceAll("(\\\\)", "/"));
612 ele.appendChild(fvEle);
613
614 Element targetDirEle = document.createElement("var");
615 targetDirEle.setAttribute("name", "TARGET_DIR");
616 targetDirEle.setAttribute("value", ffsCommonDir.replaceAll("(\\\\)", "/"));
617 ele.appendChild(targetDirEle);
618
619 NodeList childNodes = node.getChildNodes();
620 for (int k = 0; k < childNodes.getLength(); k++) {
621 Node childItem = childNodes.item(k);
622 if (childItem.getNodeType() == Node.ELEMENT_NODE) {
623 ele.appendChild(recursiveNode(childItem, document));
624 }
625 }
626
627 }
628 }
629 }
630
631 root.appendChild(ele);
632 }
633
634 private Element recursiveNode(Node node, Document document) {
635 Element root = document.createElement(node.getNodeName());
636 NamedNodeMap attr = node.getAttributes();
637 for (int i = 0; i < attr.getLength(); i++) {
638 Node attrItem = attr.item(i);
639 root.setAttribute(attrItem.getNodeName(), attrItem.getNodeValue());
640 }
641 NodeList childNodes = node.getChildNodes();
642 for (int i = 0; i < childNodes.getLength(); i++) {
643 Node childItem = childNodes.item(i);
644 if (childItem.getNodeType() == Node.ELEMENT_NODE) {
645 root.appendChild(recursiveNode(childItem, document));
646 }
647 else if (childItem.getNodeType() == Node.TEXT_NODE){
648 if (!childItem.getNodeValue().trim().equalsIgnoreCase("")) {
649 root.setTextContent(childItem.getNodeValue());
650 }
651 }
652 }
653 return root;
654 }
655 }