Fix a minor issue.
[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 = "";
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 + ", userextensions");
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
162 //
163 applyUserExtensions(document, root);
164
165 document.appendChild(rootComment);
166 document.appendChild(root);
167 //
168 // Prepare the DOM document for writing
169 //
170 Source source = new DOMSource(document);
171 //
172 // Prepare the output file
173 //
174 File file = new File(project.getProperty("PLATFORM_DIR") + File.separatorChar + platformName + "_build.xml");
175 //
176 // generate all directory path
177 //
178 (new File(file.getParent())).mkdirs();
179 Result result = new StreamResult(file);
180 //
181 // Write the DOM document to the file
182 //
183 Transformer xformer = TransformerFactory.newInstance().newTransformer();
184 xformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
185 xformer.setOutputProperty(OutputKeys.INDENT, "yes");
186 xformer.transform(source, result);
187 } catch (Exception ex) {
188 ex.printStackTrace();
189 throw new BuildException("Generate " + platformName + "_build.xml failed. \n" + ex.getMessage());
190 }
191 }
192
193 private void applyModules(Document document, Node root, String num) {
194 root.appendChild(document.createComment("Modules target"));
195 Element ele = document.createElement("target");
196 ele.setAttribute("name", "modules" + num);
197
198 Set<String> fvNameSet = sequences.get(num);
199
200 Iterator fvNameIter = fvNameSet.iterator();
201 while (fvNameIter.hasNext()) {
202 String fvName = (String)fvNameIter.next();
203 Set<FpdModuleIdentification> set = fvs.get(fvName);
204 Iterator iter = set.iterator();
205 while (iter.hasNext()) {
206 FpdModuleIdentification fpdModuleId = (FpdModuleIdentification) iter.next();
207 ModuleIdentification moduleId = fpdModuleId.getModule();
208 Element moduleEle = document.createElement("GenBuild");
209 moduleEle.setAttribute("type", "build");
210 //
211 // Inherit Properties.
212 //{"ARCH", "PACKAGE", "PACKAGE_GUID", "PACKAGE_VERSION", "MODULE_DIR"}
213 //
214
215 //
216 // ARCH
217 //
218 Element property = document.createElement("property");
219 property.setAttribute("name", "ARCH");
220 property.setAttribute("value", fpdModuleId.getArch());
221 moduleEle.appendChild(property);
222
223 //
224 // MODULE_GUID
225 //
226 property = document.createElement("property");
227 property.setAttribute("name", "MODULE_GUID");
228 property.setAttribute("value", moduleId.getGuid());
229 moduleEle.appendChild(property);
230
231 //
232 // MODULE_VERSION
233 //
234 property = document.createElement("property");
235 property.setAttribute("name", "MODULE_VERSION");
236 property.setAttribute("value", moduleId.getVersion());
237 moduleEle.appendChild(property);
238
239 //
240 // PACKAGE_GUID
241 //
242 property = document.createElement("property");
243 property.setAttribute("name", "PACKAGE_GUID");
244 property.setAttribute("value", moduleId.getPackage().getGuid());
245 moduleEle.appendChild(property);
246
247 //
248 // PACKAGE_VERSION
249 //
250 property = document.createElement("property");
251 property.setAttribute("name", "PACKAGE_VERSION");
252 property.setAttribute("value", moduleId.getPackage().getVersion());
253 moduleEle.appendChild(property);
254
255 ele.appendChild(moduleEle);
256 }
257 }
258 root.appendChild(ele);
259 }
260
261 private void applyFvs(Document document, Node root, String num) {
262 Set<String> fvNameSet = sequences.get(num);
263 //
264 // FVS Target
265 //
266 root.appendChild(document.createComment("FVs target"));
267 Element ele = document.createElement("target");
268 ele.setAttribute("name", "fvs" + num);
269
270 //
271 // For every Target and ToolChain
272 //
273 String[] targetList = GlobalData.getToolChainInfo().getTargets();
274 for (int i = 0; i < targetList.length; i++){
275 String[] toolchainList = GlobalData.getToolChainInfo().getTagnames();
276 for(int j = 0; j < toolchainList.length; j++){
277 String fvOutputDir = project.getProperty("BUILD_DIR") + File.separatorChar
278 + targetList[i] + File.separatorChar
279 + toolchainList[i] + File.separatorChar + "FV";
280 String[] validFv = SurfaceAreaQuery.getFpdValidImageNames();
281 for (int k = 0; k < validFv.length; k++) {
282 if (fvNameSet.contains(validFv[k]) || ! isListInSequence(validFv[k])) {
283 String inputFile = fvOutputDir + "" + File.separatorChar + validFv[k].toUpperCase() + ".inf";
284 Element fvEle = document.createElement("genfvimage");
285 fvEle.setAttribute("infFile", inputFile);
286 fvEle.setAttribute("outputDir", fvOutputDir);
287 ele.appendChild(fvEle);
288 }
289 }
290 }
291 }
292 root.appendChild(ele);
293 }
294
295 private void applyClean(Document document, Node root) {
296 //
297 // Clean Target
298 //
299 root.appendChild(document.createComment("Clean target"));
300 Element ele = document.createElement("target");
301 ele.setAttribute("name", "clean");
302
303 if (isUnified) {
304 Element cleanEle = document.createElement("delete");
305 cleanEle.setAttribute("includeemptydirs", "true");
306 Element filesetEle = document.createElement("fileset");
307 filesetEle.setAttribute("dir", project.getProperty("BUILD_DIR"));
308 filesetEle.setAttribute("includes", "**\\OUTPUT\\**");
309 cleanEle.appendChild(filesetEle);
310 ele.appendChild(cleanEle);
311 } else {
312 Set set = outfiles.keySet();
313 Iterator iter = set.iterator();
314 while (iter.hasNext()) {
315 FpdModuleIdentification fpdModuleId = (FpdModuleIdentification) iter.next();
316 ModuleIdentification moduleId = fpdModuleId.getModule();
317
318 Element ifEle = document.createElement("if");
319 Element availableEle = document.createElement("available");
320 availableEle.setAttribute("file", moduleId.getMsaFile().getParent() + File.separatorChar
321 + "build.xml");
322 ifEle.appendChild(availableEle);
323 Element elseEle = document.createElement("then");
324
325 Element moduleEle = document.createElement("ant");
326 moduleEle.setAttribute("antfile", moduleId.getMsaFile().getParent() + File.separatorChar
327 + "build.xml");
328 moduleEle.setAttribute("target", "clean");
329 //
330 // Inherit Properties.
331 //{"ARCH", "PACKAGE", "PACKAGE_GUID", "PACKAGE_VERSION", "MODULE_DIR"}
332 //
333
334 //
335 // ARCH
336 //
337 Element property = document.createElement("property");
338 property.setAttribute("name", "ARCH");
339 property.setAttribute("value", fpdModuleId.getArch());
340 moduleEle.appendChild(property);
341
342 //
343 // PACKAGE
344 //
345 property = document.createElement("property");
346 property.setAttribute("name", "PACKAGE");
347 property.setAttribute("value", moduleId.getPackage().getName());
348 moduleEle.appendChild(property);
349
350 //
351 // PACKAGE_GUID
352 //
353 property = document.createElement("property");
354 property.setAttribute("name", "PACKAGE_GUID");
355 property.setAttribute("value", moduleId.getPackage().getGuid());
356 moduleEle.appendChild(property);
357
358 //
359 // PACKAGE_VERSION
360 //
361 property = document.createElement("property");
362 property.setAttribute("name", "PACKAGE_VERSION");
363 property.setAttribute("value", moduleId.getPackage().getVersion());
364 moduleEle.appendChild(property);
365
366 //
367 // MODULE_DIR
368 //
369 property = document.createElement("property");
370 property.setAttribute("name", "MODULE_DIR");
371 property.setAttribute("value", moduleId.getMsaFile().getParent());
372 moduleEle.appendChild(property);
373 elseEle.appendChild(moduleEle);
374 ifEle.appendChild(elseEle);
375 ele.appendChild(ifEle);
376 }
377 }
378 root.appendChild(ele);
379 }
380
381 private void applyCleanall(Document document, Node root) {
382 //
383 // Deep Clean Target
384 //
385 root.appendChild(document.createComment("Clean All target"));
386 Element ele = document.createElement("target");
387 ele.setAttribute("name", "cleanall");
388
389 if (isUnified) {
390 String[] targetList = GlobalData.getToolChainInfo().getTargets();
391 for (int i = 0; i < targetList.length; ++i) {
392 Element cleanAllEle = document.createElement("delete");
393 cleanAllEle.setAttribute("dir", project.getProperty("BUILD_DIR") + File.separatorChar + targetList[i]);
394 ele.appendChild(cleanAllEle);
395 }
396 } else {
397 Set set = outfiles.keySet();
398 Iterator iter = set.iterator();
399 while (iter.hasNext()) {
400 FpdModuleIdentification fpdModuleId = (FpdModuleIdentification) iter.next();
401 ModuleIdentification moduleId = fpdModuleId.getModule();
402
403 Element ifEle = document.createElement("if");
404 Element availableEle = document.createElement("available");
405 availableEle.setAttribute("file", moduleId.getMsaFile().getParent() + File.separatorChar
406 + "build.xml");
407 ifEle.appendChild(availableEle);
408 Element elseEle = document.createElement("then");
409
410 Element moduleEle = document.createElement("ant");
411 moduleEle.setAttribute("antfile", moduleId.getMsaFile().getParent() + File.separatorChar
412 + "build.xml");
413 moduleEle.setAttribute("target", "cleanall");
414 //
415 // Inherit Properties.
416 //{"ARCH", "PACKAGE", "PACKAGE_GUID", "PACKAGE_VERSION", "MODULE_DIR"}
417 //
418
419 //
420 // ARCH
421 //
422 Element property = document.createElement("property");
423 property.setAttribute("name", "ARCH");
424 property.setAttribute("value", fpdModuleId.getArch());
425 moduleEle.appendChild(property);
426
427 //
428 // PACKAGE
429 //
430 property = document.createElement("property");
431 property.setAttribute("name", "PACKAGE");
432 property.setAttribute("value", moduleId.getPackage().getName());
433 moduleEle.appendChild(property);
434
435 //
436 // PACKAGE_GUID
437 //
438 property = document.createElement("property");
439 property.setAttribute("name", "PACKAGE_GUID");
440 property.setAttribute("value", moduleId.getPackage().getGuid());
441 moduleEle.appendChild(property);
442
443 //
444 // PACKAGE_VERSION
445 //
446 property = document.createElement("property");
447 property.setAttribute("name", "PACKAGE_VERSION");
448 property.setAttribute("value", moduleId.getPackage().getVersion());
449 moduleEle.appendChild(property);
450
451 //
452 // MODULE_DIR
453 //
454 property = document.createElement("property");
455 property.setAttribute("name", "MODULE_DIR");
456 property.setAttribute("value", moduleId.getMsaFile().getParent());
457 moduleEle.appendChild(property);
458 elseEle.appendChild(moduleEle);
459 ifEle.appendChild(elseEle);
460 ele.appendChild(ifEle);
461 }
462 }
463 root.appendChild(ele);
464 }
465
466 private void applyUserExtensions(Document document, Node root) {
467 //
468 // User Extensions
469 //
470 root.appendChild(document.createComment("User Extensions"));
471 Element ele = document.createElement("target");
472 ele.setAttribute("name", "userextensions");
473
474 Node node = SurfaceAreaQuery.getFpdUserExtension();
475 if (node != null) {
476 //
477 // For every Target and ToolChain
478 //
479 String[] targetList = GlobalData.getToolChainInfo().getTargets();
480 for (int i = 0; i < targetList.length; i++){
481 String[] toolchainList = GlobalData.getToolChainInfo().getTagnames();
482 for(int j = 0; j < toolchainList.length; j++){
483 //
484 // Prepare FV_DIR
485 //
486 String ffsCommonDir = project.getProperty("BUILD_DIR") + File.separatorChar
487 + targetList[i] + File.separatorChar
488 + toolchainList[j];
489 File fvDir = new File(ffsCommonDir + File.separatorChar + "FV");
490 Element fvEle = document.createElement("var");
491 fvEle.setAttribute("name", "FV_DIR");
492 fvEle.setAttribute("value", fvDir.getPath().replaceAll("(\\\\)", "/"));
493 ele.appendChild(fvEle);
494
495 NodeList childNodes = node.getChildNodes();
496 for (int k = 0; k < childNodes.getLength(); k++) {
497 Node childItem = childNodes.item(k);
498 if (childItem.getNodeType() == Node.ELEMENT_NODE) {
499 ele.appendChild(recursiveNode(childItem, document));
500 }
501 }
502
503 }
504 }
505 }
506
507 root.appendChild(ele);
508 }
509
510 private Element recursiveNode(Node node, Document document) {
511 Element root = document.createElement(node.getNodeName());
512 NamedNodeMap attr = node.getAttributes();
513 for (int i = 0; i < attr.getLength(); i++) {
514 Node attrItem = attr.item(i);
515 root.setAttribute(attrItem.getNodeName(), attrItem.getNodeValue());
516 }
517 NodeList childNodes = node.getChildNodes();
518 for (int i = 0; i < childNodes.getLength(); i++) {
519 Node childItem = childNodes.item(i);
520 if (childItem.getNodeType() == Node.ELEMENT_NODE) {
521 root.appendChild(recursiveNode(childItem, document));
522 }
523 else if (childItem.getNodeType() == Node.TEXT_NODE){
524 if ( ! childItem.getNodeValue().trim().equalsIgnoreCase("")) {
525 root.setTextContent(childItem.getNodeValue());
526 }
527 }
528 }
529 return root;
530 }
531
532 private boolean isListInSequence(String fvName) {
533 Set<String> numbers = sequences.keySet();
534 Iterator<String> iter = numbers.iterator();
535 while (iter.hasNext()) {
536 Set<String> fvNameSet = sequences.get(iter.next());
537 if (fvNameSet.contains(fvName)) {
538 return true;
539 }
540 }
541 return false;
542 }
543 }