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