2265d6ba05cbf2135505727ab0ff75a92b7f62e1
[mirror_edk2.git] / Tools / Java / Source / GenBuild / org / tianocore / build / GenBuildTask.java
1 /** @file
2 This file is ANT task GenBuild.
3
4 The file is used to parse a specified Module, and generate its build time
5 ANT script build.xml, then call the the ANT script to build the module.
6
7 Copyright (c) 2006, Intel Corporation
8 All rights reserved. This program and the accompanying materials
9 are licensed and made available under the terms and conditions of the BSD License
10 which accompanies this distribution. The full text of the license may be found at
11 http://opensource.org/licenses/bsd-license.php
12
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 **/
16 package org.tianocore.build;
17
18 import java.io.File;
19 import java.util.Hashtable;
20 import java.util.Iterator;
21 import java.util.LinkedHashSet;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.Set;
25 import java.util.Vector;
26
27 import org.apache.tools.ant.BuildException;
28 import org.apache.tools.ant.BuildListener;
29 import org.apache.tools.ant.Location;
30 import org.apache.tools.ant.Project;
31 import org.apache.tools.ant.taskdefs.Ant;
32 import org.apache.tools.ant.taskdefs.Property;
33 import org.apache.xmlbeans.XmlObject;
34 import org.tianocore.build.autogen.AutoGen;
35 import org.tianocore.build.exception.AutoGenException;
36 import org.tianocore.build.exception.GenBuildException;
37 import org.tianocore.build.exception.PcdAutogenException;
38 import org.tianocore.build.exception.PlatformPcdPreprocessBuildException;
39 import org.tianocore.build.fpd.FpdParserTask;
40 import org.tianocore.build.global.GlobalData;
41 import org.tianocore.build.global.OutputManager;
42 import org.tianocore.build.global.SurfaceAreaQuery;
43 import org.tianocore.build.id.FpdModuleIdentification;
44 import org.tianocore.build.id.ModuleIdentification;
45 import org.tianocore.build.id.PackageIdentification;
46 import org.tianocore.build.id.PlatformIdentification;
47 import org.tianocore.build.tools.ModuleItem;
48 import org.tianocore.common.definitions.ToolDefinitions;
49 import org.tianocore.common.exception.EdkException;
50 import org.tianocore.common.logger.EdkLog;
51
52 /**
53 <p>
54 <code>GenBuildTask</code> is an ANT task that can be used in ANT build
55 system.
56
57 <p>The main function of this task is to parse module's surface area (MSA),
58 then generate the corresponding <em>BaseName_build.xml</em> (the real ANT
59 build script) and call this to build the module. The whole process including:
60
61 <pre>
62 1. generate AutoGen.c and AutoGen.h;
63 2. build all dependent library instances;
64 3. build all source files inlcude AutoGen.c;
65 4. generate sections;
66 5. generate FFS file if it is driver module while LIB file if it is Library module.
67 </pre>
68
69
70 <p>
71 The usage is (take module <em>HelloWorld</em> for example):
72 </p>
73
74 <pre>
75 &lt;GenBuild
76 msaFile="${PACKAGE_DIR}/Application/HelloWorld/HelloWorld.msa"
77 type="cleanall" /&gt;
78 </pre>
79
80 <p>
81 This task calls <code>AutoGen</code> to generate <em>AutoGen.c</em> and
82 <em>AutoGen.h</em>.
83 </p>
84
85 <p>
86 This task will also set properties for current module, such as PACKAGE,
87 PACKAGE_GUID, PACKAGE_VERSION, PACKAGE_DIR, PACKAGE_RELATIVE_DIR
88 (relative to Workspace), MODULE or BASE_NAME, GUID, VERSION, MODULE_DIR,
89 MODULE_RELATIVE_DIR (relative to Package), CONFIG_DIR, BIN_DIR,
90 DEST_DIR_DEBUG, DEST_DIR_OUTPUT, TARGET, ARCH, TOOLCHAIN, TOOLCHAIN_FAMILY,
91 SUBSYSTEM, ENTRYPOINT, EBC_TOOL_LIB_PATH, all compiler command related
92 properties (CC, CC_FLAGS, CC_DPATH, CC_SPATH, CC_FAMILY, CC_EXT).
93 </p>
94
95 @since GenBuild 1.0
96 **/
97 public class GenBuildTask extends Ant {
98
99 ///
100 /// Module surface area file.
101 ///
102 File msaFile;
103
104 public ModuleIdentification parentId;
105
106 private String type = "all";
107
108 ///
109 /// Module's Identification.
110 ///
111 private ModuleIdentification moduleId;
112
113 private Vector<Property> properties = new Vector<Property>();
114
115 private boolean isSingleModuleBuild = false;
116
117 private SurfaceAreaQuery saq = null;
118
119 /**
120 Public construct method. It is necessary for ANT task.
121 **/
122 public GenBuildTask() {
123 }
124
125 /**
126
127 @throws BuildException
128 From module build, exception from module surface area invalid.
129 **/
130 public void execute() throws BuildException {
131 this.setTaskName("GenBuild");
132 try {
133 processGenBuild();
134 } catch (PcdAutogenException e) {
135 BuildException buildException = new BuildException(e.getMessage());
136 buildException.setStackTrace(e.getStackTrace());
137 throw buildException;
138 } catch (AutoGenException e) {
139 BuildException buildException = new BuildException(e.getMessage());
140 buildException.setStackTrace(e.getStackTrace());
141 throw buildException;
142 } catch (PlatformPcdPreprocessBuildException e) {
143 BuildException buildException = new BuildException(e.getMessage());
144 buildException.setStackTrace(e.getStackTrace());
145 throw buildException;
146 } catch (GenBuildException e) {
147 BuildException buildException = new BuildException(e.getMessage());
148 buildException.setStackTrace(e.getStackTrace());
149 throw buildException;
150 } catch (EdkException e) {
151 BuildException buildException = new BuildException(e.getMessage());
152 buildException.setStackTrace(e.getStackTrace());
153 throw buildException;
154 } catch (Exception e) {
155 BuildException buildException = new BuildException(e.getMessage());
156 buildException.setStackTrace(e.getStackTrace());
157 throw buildException;
158 }
159 }
160
161 private void processGenBuild() throws EdkException, BuildException, GenBuildException, AutoGenException, PcdAutogenException, PlatformPcdPreprocessBuildException {
162 if (!FrameworkBuildTask.multithread) {
163 cleanupProperties();
164 }
165
166 //
167 // Enable all specified properties
168 //
169 Iterator<Property> iter = properties.iterator();
170 while (iter.hasNext()) {
171 Property item = iter.next();
172 getProject().setProperty(item.getName(), item.getValue());
173 }
174
175 //
176 // GenBuild should specify either msaFile or moduleGuid & packageGuid
177 //
178 if (msaFile == null ) {
179 String moduleGuid = getProject().getProperty("MODULE_GUID");
180 String moduleVersion = getProject().getProperty("MODULE_VERSION");
181 String packageGuid = getProject().getProperty("PACKAGE_GUID");
182 String packageVersion = getProject().getProperty("PACKAGE_VERSION");
183 //
184 // If one of module Guid or package Guid is not specified, report error
185 //
186 if (moduleGuid == null || packageGuid == null) {
187 throw new BuildException("GenBuild parameter error.");
188 }
189
190 PackageIdentification packageId = new PackageIdentification(packageGuid, packageVersion);
191 GlobalData.refreshPackageIdentification(packageId);
192 moduleId = new ModuleIdentification(moduleGuid, moduleVersion);
193 moduleId.setPackage(packageId);
194 GlobalData.refreshModuleIdentification(moduleId);
195 Map<String, XmlObject> doc = GlobalData.getNativeMsa(moduleId);
196 saq = new SurfaceAreaQuery(doc);
197 } else {
198 Map<String, XmlObject> doc = GlobalData.getNativeMsa(msaFile);
199 saq = new SurfaceAreaQuery(doc);
200 moduleId = saq.getMsaHeader();
201 moduleId.setMsaFile(msaFile);
202 }
203
204 String[] producedLibraryClasses = saq.getLibraryClasses("ALWAYS_PRODUCED", null, null);
205 if (producedLibraryClasses.length == 0) {
206 moduleId.setLibrary(false);
207 } else {
208 moduleId.setLibrary(true);
209 }
210
211 //
212 // Judge whether it is single module build or not
213 //
214 if (isSingleModuleBuild) {
215 //
216 // Single Module build
217 //
218 prepareSingleModuleBuild();
219 }
220
221 //
222 // If single module : get arch from pass down, otherwise intersection MSA
223 // supported ARCHs and tools def
224 //
225 Set<String> archListSupByToolChain = new LinkedHashSet<String>();
226 String[] archs = GlobalData.getToolChainInfo().getArchs();
227
228 for (int i = 0; i < archs.length; i ++) {
229 archListSupByToolChain.add(archs[i]);
230 }
231
232 Set<String> archSet = new LinkedHashSet<String>();
233 String archString = getProject().getProperty("ARCH");
234 if (archString != null) {
235 String[] fpdArchList = archString.split(" ");
236
237 for (int i = 0; i < fpdArchList.length; i++) {
238 if (archListSupByToolChain.contains(fpdArchList[i])) {
239 archSet.add(fpdArchList[i]);
240 }
241 }
242 } else {
243 archSet = archListSupByToolChain;
244 }
245
246 String[] archList = archSet.toArray(new String[archSet.size()]);
247
248 //
249 // Judge if arch is all supported by current module. If not, throw Exception.
250 //
251 List moduleSupportedArchs = saq.getModuleSupportedArchs();
252 if (moduleSupportedArchs != null) {
253 for (int k = 0; k < archList.length; k++) {
254 if ( ! moduleSupportedArchs.contains(archList[k])) {
255 throw new BuildException("Specified architecture [" + archList[k] + "] is not supported by " + moduleId + ". The module " + moduleId + " only supports [" + moduleSupportedArchs + "] architectures.");
256 }
257 }
258 }
259
260 if (archList.length == 0) {
261 EdkLog.log(this, EdkLog.EDK_WARNING, "Warning: " + "[" + archString + "] is not supported for " + moduleId + " in this build!\n");
262 }
263
264 for (int k = 0; k < archList.length; k++) {
265
266 getProject().setProperty("ARCH", archList[k]);
267
268 FpdModuleIdentification fpdModuleId = new FpdModuleIdentification(moduleId, archList[k]);
269
270 //
271 // Whether the module is built before
272 //
273 if (moduleId.isLibrary() == false && GlobalData.hasFpdModuleSA(fpdModuleId) == false) {
274 EdkLog.log(this, EdkLog.EDK_WARNING, "Warning: " + moduleId + " for " + archList[k] + " was not found in current platform FPD file!\n");
275 continue;
276 } else if (GlobalData.isModuleBuilt(fpdModuleId)) {
277 break;
278 } else {
279 GlobalData.registerBuiltModule(fpdModuleId);
280 }
281
282 //
283 // For Every TOOLCHAIN, TARGET
284 //
285 String[] targetList = GlobalData.getToolChainInfo().getTargets();
286 for (int i = 0; i < targetList.length; i ++){
287 //
288 // Prepare for target related common properties
289 // TARGET
290 //
291 getProject().setProperty("TARGET", targetList[i]);
292 String[] toolchainList = GlobalData.getToolChainInfo().getTagnames();
293 for(int j = 0; j < toolchainList.length; j ++){
294 //
295 // check if any tool is defined for current target + toolchain + arch
296 // don't do anything if no tools found
297 //
298 if (GlobalData.isCommandSet(targetList[i], toolchainList[j], archList[k]) == false) {
299 EdkLog.log(this, EdkLog.EDK_WARNING, "Warning: No build issued. No tools found for [target=" + targetList[i] + " toolchain=" + toolchainList[j] + " arch=" + archList[k] + "]\n");
300 continue;
301 }
302
303 //
304 // Prepare for toolchain related common properties
305 // TOOLCHAIN
306 //
307 getProject().setProperty("TOOLCHAIN", toolchainList[j]);
308
309 EdkLog.log(this, "Build " + moduleId + " start >>>");
310 EdkLog.log(this, "Target: " + targetList[i] + " Tagname: " + toolchainList[j] + " Arch: " + archList[k]);
311 saq.push(GlobalData.getDoc(fpdModuleId));
312
313 //
314 // Prepare for all other common properties
315 // PACKAGE, PACKAGE_GUID, PACKAGE_VERSION, PACKAGE_DIR, PACKAGE_RELATIVE_DIR
316 // MODULE or BASE_NAME, GUID or FILE_GUID, VERSION, MODULE_TYPE
317 // MODULE_DIR, MODULE_RELATIVE_DIR
318 // SUBSYSTEM, ENTRYPOINT, EBC_TOOL_LIB_PATH
319 //
320 setModuleCommonProperties(archList[k]);
321
322 //
323 // OutputManage prepare for
324 // BIN_DIR, DEST_DIR_DEBUG, DEST_DIR_OUTPUT, BUILD_DIR, FV_DIR
325 //
326 OutputManager.getInstance().update(getProject());
327
328 if (type.equalsIgnoreCase("all") || type.equalsIgnoreCase("build")) {
329 applyBuild(targetList[i], toolchainList[j], fpdModuleId);
330 } else if (type.equalsIgnoreCase("clean")) {
331 applyClean(fpdModuleId);
332 } else if (type.equalsIgnoreCase("cleanall")) {
333 applyCleanall(fpdModuleId);
334 }
335 }
336 }
337 }
338 }
339
340 /**
341 This method is used to prepare Platform-related information.
342
343 <p>In Single Module Build mode, platform-related information is not ready.
344 The method read the system environment variable <code>ACTIVE_PLATFORM</code>
345 and search in the Framework Database. Note that platform name in the Framework
346 Database must be unique. </p>
347
348 **/
349 private void prepareSingleModuleBuild() throws EdkException {
350 //
351 // Find out the package which the module belongs to
352 //
353 PackageIdentification packageId = GlobalData.getPackageForModule(moduleId);
354 GlobalData.refreshPackageIdentification(packageId);
355 moduleId.setPackage(packageId);
356 GlobalData.refreshModuleIdentification(moduleId);
357
358 //
359 // Read ACTIVE_PLATFORM's FPD file
360 //
361 String filename = getProject().getProperty("PLATFORM_FILE");
362
363 if (filename == null){
364 throw new BuildException("Please set ACTIVE_PLATFORM in the file: Tools/Conf/target.txt if you want to build a single module!");
365 }
366
367 PlatformIdentification platformId = GlobalData.getPlatform(filename);
368
369 //
370 // Read FPD file (Call FpdParserTask's method)
371 //
372 FpdParserTask fpdParser = new FpdParserTask();
373 fpdParser.setProject(getProject());
374 fpdParser.parseFpdFile(platformId.getFpdFile());
375 getProject().setProperty("ARCH", fpdParser.getAllArchForModule(moduleId));
376 }
377
378 private void cleanupProperties() {
379 Project newProject = new Project();
380
381 Hashtable<String, String> passdownProperties = FrameworkBuildTask.originalProperties;
382 Iterator<String> iter = passdownProperties.keySet().iterator();
383 while (iter.hasNext()) {
384 String item = iter.next();
385 newProject.setProperty(item, passdownProperties.get(item));
386 }
387
388 newProject.setInputHandler(getProject().getInputHandler());
389
390 Iterator listenerIter = getProject().getBuildListeners().iterator();
391 while (listenerIter.hasNext()) {
392 newProject.addBuildListener((BuildListener) listenerIter.next());
393 }
394
395 getProject().initSubProject(newProject);
396
397 setProject(newProject);
398 }
399
400 /**
401 Set Module-Related information to properties.
402
403 @param arch current build ARCH
404 **/
405 private void setModuleCommonProperties(String arch) {
406 //
407 // Prepare for all other common properties
408 // PACKAGE, PACKAGE_GUID, PACKAGE_VERSION, PACKAGE_DIR, PACKAGE_RELATIVE_DIR
409 //
410 PackageIdentification packageId = moduleId.getPackage();
411 getProject().setProperty("PACKAGE", packageId.getName());
412 getProject().setProperty("PACKAGE_GUID", packageId.getGuid());
413 getProject().setProperty("PACKAGE_VERSION", packageId.getVersion());
414 getProject().setProperty("PACKAGE_DIR", packageId.getPackageDir().replaceAll("(\\\\)", "/"));
415 getProject().setProperty("PACKAGE_RELATIVE_DIR", packageId.getPackageRelativeDir().replaceAll("(\\\\)", "/"));
416
417 //
418 // MODULE or BASE_NAME, GUID or FILE_GUID, VERSION, MODULE_TYPE
419 // MODULE_DIR, MODULE_RELATIVE_DIR
420 //
421 getProject().setProperty("MODULE", moduleId.getName());
422 String baseName = saq.getModuleOutputFileBasename();
423 if (baseName == null) {
424 getProject().setProperty("BASE_NAME", moduleId.getName());
425 } else {
426 getProject().setProperty("BASE_NAME", baseName);
427 }
428 getProject().setProperty("GUID", moduleId.getGuid());
429 getProject().setProperty("FILE_GUID", moduleId.getGuid());
430 getProject().setProperty("VERSION", moduleId.getVersion());
431 getProject().setProperty("MODULE_TYPE", moduleId.getModuleType());
432 File msaFile = moduleId.getMsaFile();
433 String msaFileName = msaFile.getName();
434 getProject().setProperty("MODULE_DIR", msaFile.getParent().replaceAll("(\\\\)", "/"));
435 getProject().setProperty("MODULE_RELATIVE_DIR", moduleId.getModuleRelativePath().replaceAll("(\\\\)", "/")
436 + File.separatorChar + msaFileName.substring(0, msaFileName.lastIndexOf('.')));
437
438 //
439 // SUBSYSTEM
440 //
441 String[][] subsystemMap = { { "BASE", "EFI_BOOT_SERVICE_DRIVER"},
442 { "SEC", "EFI_BOOT_SERVICE_DRIVER" },
443 { "PEI_CORE", "EFI_BOOT_SERVICE_DRIVER" },
444 { "PEIM", "EFI_BOOT_SERVICE_DRIVER" },
445 { "DXE_CORE", "EFI_BOOT_SERVICE_DRIVER" },
446 { "DXE_DRIVER", "EFI_BOOT_SERVICE_DRIVER" },
447 { "DXE_RUNTIME_DRIVER", "EFI_RUNTIME_DRIVER" },
448 { "DXE_SAL_DRIVER", "EFI_BOOT_SERVICE_DRIVER" },
449 { "DXE_SMM_DRIVER", "EFI_BOOT_SERVICE_DRIVER" },
450 { "TOOL", "EFI_BOOT_SERVICE_DRIVER" },
451 { "UEFI_DRIVER", "EFI_BOOT_SERVICE_DRIVER" },
452 { "UEFI_APPLICATION", "EFI_APPLICATION" },
453 { "USER_DEFINED", "EFI_BOOT_SERVICE_DRIVER"} };
454
455 String subsystem = "EFI_BOOT_SERVICE_DRIVER";
456 for (int i = 0; i < subsystemMap.length; i++) {
457 if (moduleId.getModuleType().equalsIgnoreCase(subsystemMap[i][0])) {
458 subsystem = subsystemMap[i][1];
459 break ;
460 }
461 }
462 getProject().setProperty("SUBSYSTEM", subsystem);
463
464 //
465 // ENTRYPOINT
466 //
467 if (arch.equalsIgnoreCase("EBC")) {
468 getProject().setProperty("ENTRYPOINT", "EfiStart");
469 } else {
470 getProject().setProperty("ENTRYPOINT", "_ModuleEntryPoint");
471 }
472
473 getProject().setProperty("OBJECTS", "");
474 }
475
476 private void getCompilerFlags(String target, String toolchain, FpdModuleIdentification fpdModuleId) throws EdkException {
477 String[] cmd = GlobalData.getToolChainInfo().getCommands();
478 for ( int m = 0; m < cmd.length; m++) {
479 //
480 // Set cmd, like CC, DLINK
481 //
482 String[] key = new String[]{target, toolchain, fpdModuleId.getArch(), cmd[m], null};
483 key[4] = ToolDefinitions.TOOLS_DEF_ATTRIBUTE_PATH;
484 String cmdPath = GlobalData.getCommandSetting(key, fpdModuleId);
485 key[4] = ToolDefinitions.TOOLS_DEF_ATTRIBUTE_NAME;
486 String cmdName = GlobalData.getCommandSetting(key, fpdModuleId);
487 if (cmdName.length() == 0) {
488 EdkLog.log(this, EdkLog.EDK_VERBOSE, "Warning: " + cmd[m] + " hasn't been defined!");
489 getProject().setProperty(cmd[m], "");
490 continue;
491 }
492 File cmdFile = new File(cmdPath + File.separatorChar + cmdName);
493 getProject().setProperty(cmd[m], cmdFile.getPath().replaceAll("(\\\\)", "/"));
494
495 //
496 // set CC_FLAGS
497 //
498 key[4] = ToolDefinitions.TOOLS_DEF_ATTRIBUTE_FLAGS;
499 String cmdFlags = GlobalData.getCommandSetting(key, fpdModuleId);
500 if (cmdFlags != null)
501 {
502 getProject().setProperty(cmd[m] + "_FLAGS", cmdFlags);
503 }
504 else
505 {
506 getProject().setProperty(cmd[m] + "_FLAGS", "");
507 }
508
509 //
510 // Set CC_EXT
511 //
512 key[4] = ToolDefinitions.TOOLS_DEF_ATTRIBUTE_EXT;
513 String extName = GlobalData.getCommandSetting(key, fpdModuleId);
514 if ( extName != null && ! extName.equalsIgnoreCase("")) {
515 getProject().setProperty(cmd[m] + "_EXT", extName);
516 } else {
517 getProject().setProperty(cmd[m] + "_EXT", "");
518 }
519
520 //
521 // set CC_FAMILY
522 //
523 key[4] = ToolDefinitions.TOOLS_DEF_ATTRIBUTE_FAMILY;
524 String toolChainFamily = GlobalData.getCommandSetting(key, fpdModuleId);
525 if (toolChainFamily != null) {
526 getProject().setProperty(cmd[m] + "_FAMILY", toolChainFamily);
527 }
528
529 //
530 // set CC_SPATH
531 //
532 key[4] = ToolDefinitions.TOOLS_DEF_ATTRIBUTE_SPATH;
533 String spath = GlobalData.getCommandSetting(key, fpdModuleId);
534 if (spath != null) {
535 getProject().setProperty(cmd[m] + "_SPATH", spath.replaceAll("(\\\\)", "/"));
536 } else {
537 getProject().setProperty(cmd[m] + "_SPATH", "");
538 }
539
540 //
541 // set CC_DPATH
542 //
543 key[4] = ToolDefinitions.TOOLS_DEF_ATTRIBUTE_DPATH;
544 String dpath = GlobalData.getCommandSetting(key, fpdModuleId);
545 if (dpath != null) {
546 getProject().setProperty(cmd[m] + "_DPATH", dpath.replaceAll("(\\\\)", "/"));
547 } else {
548 getProject().setProperty(cmd[m] + "_DPATH", "");
549 }
550
551 //
552 // Set CC_LIBPATH
553 //
554 key[4] = ToolDefinitions.TOOLS_DEF_ATTRIBUTE_LIBPATH;
555 String libpath = GlobalData.getCommandSetting(key, fpdModuleId);
556 if (libpath != null) {
557 getProject().setProperty(cmd[m] + "_LIBPATH", libpath.replaceAll("(\\\\)", "/"));
558 } else {
559 getProject().setProperty(cmd[m] + "_LIBPATH", "");
560 }
561
562 //
563 // Set CC_INCLUDEPATH
564 //
565 key[4] = ToolDefinitions.TOOLS_DEF_ATTRIBUTE_INCLUDEPATH;
566 String includepath = GlobalData.getCommandSetting(key, fpdModuleId);
567 if (dpath != null) {
568 getProject().setProperty(cmd[m] + "_INCLUDEPATH", includepath.replaceAll("(\\\\)", "/"));
569 } else {
570 getProject().setProperty(cmd[m] + "_INCLUDEPATH", "");
571 }
572 }
573 }
574
575 public void setMsaFile(File msaFile) {
576 this.msaFile = msaFile;
577 }
578
579 /**
580 Method is for ANT to initialize MSA file.
581
582 @param msaFilename MSA file name
583 **/
584 public void setMsaFile(String msaFilename) {
585 String moduleDir = getProject().getProperty("MODULE_DIR");
586
587 //
588 // If is Single Module Build, then use the Base Dir defined in build.xml
589 //
590 if (moduleDir == null) {
591 moduleDir = getProject().getBaseDir().getPath();
592 }
593 msaFile = new File(moduleDir + File.separatorChar + msaFilename);
594 }
595
596 public void addConfiguredModuleItem(ModuleItem moduleItem) {
597 PackageIdentification packageId = new PackageIdentification(moduleItem.getPackageGuid(), moduleItem.getPackageVersion());
598 ModuleIdentification moduleId = new ModuleIdentification(moduleItem.getModuleGuid(), moduleItem.getModuleVersion());
599 moduleId.setPackage(packageId);
600 this.moduleId = moduleId;
601 }
602
603 /**
604 Add a property.
605
606 @param p property
607 **/
608 public void addProperty(Property p) {
609 properties.addElement(p);
610 }
611
612 public void setType(String type) {
613 this.type = type;
614 }
615
616 private void applyBuild(String buildTarget, String buildTagname, FpdModuleIdentification fpdModuleId) throws EdkException {
617 //
618 // Call AutoGen to generate AutoGen.c and AutoGen.h
619 //
620 AutoGen autogen = new AutoGen(getProject().getProperty("FV_DIR"), getProject().getProperty("DEST_DIR_DEBUG"), fpdModuleId.getModule(),fpdModuleId.getArch(), saq, parentId);
621 autogen.genAutogen();
622
623 //
624 // Get compiler flags
625 //
626 try {
627 getCompilerFlags(buildTarget, buildTagname, fpdModuleId);
628 }
629 catch (EdkException ee) {
630 throw new BuildException(ee.getMessage());
631 }
632
633 //
634 // Prepare LIBS
635 //
636 ModuleIdentification[] libinstances = saq.getLibraryInstance(fpdModuleId.getArch());
637 String propertyLibs = "";
638 for (int i = 0; i < libinstances.length; i++) {
639 propertyLibs += getProject().getProperty("BIN_DIR") + File.separatorChar + libinstances[i].getName() + ".lib" + " ";
640 }
641 getProject().setProperty("LIBS", propertyLibs.replaceAll("(\\\\)", "/"));
642
643 //
644 // Get all includepath and set to INCLUDE_PATHS
645 //
646 String[] includes = prepareIncludePaths(fpdModuleId);
647
648 //
649 // if it is CUSTOM_BUILD
650 // then call the exist BaseName_build.xml directly.
651 //
652 String buildFilename = "";
653 if ((buildFilename = GetCustomizedBuildFile(fpdModuleId.getArch())) != "") {
654 EdkLog.log(this, "Call user-defined " + buildFilename);
655
656 String antFilename = getProject().getProperty("MODULE_DIR") + File.separatorChar + buildFilename;
657 antCall(antFilename, null);
658
659 return ;
660 }
661
662 //
663 // Generate ${BASE_NAME}_build.xml
664 // TBD
665 //
666 String ffsKeyword = saq.getModuleFfsKeyword();
667 ModuleBuildFileGenerator fileGenerator = new ModuleBuildFileGenerator(getProject(), ffsKeyword, fpdModuleId, includes, saq);
668 buildFilename = getProject().getProperty("DEST_DIR_OUTPUT") + File.separatorChar + moduleId.getName() + "_build.xml";
669 fileGenerator.genBuildFile(buildFilename);
670
671 //
672 // Ant call ${BASE_NAME}_build.xml
673 //
674 String antFilename = getProject().getProperty("DEST_DIR_OUTPUT") + File.separatorChar + moduleId.getName() + "_build.xml";
675 antCall(antFilename, null);
676 }
677
678 private void applyClean(FpdModuleIdentification fpdModuleId){
679 //
680 // if it is CUSTOM_BUILD
681 // then call the exist BaseName_build.xml directly.
682 //
683 if (moduleId.getModuleType().equalsIgnoreCase("USER_DEFINED")) {
684 EdkLog.log(this, "Calling user-defined " + moduleId.getName() + "_build.xml");
685
686 String antFilename = getProject().getProperty("MODULE_DIR") + File.separatorChar + moduleId.getName() + "_build.xml";
687 antCall(antFilename, "clean");
688
689 return ;
690 }
691
692 String antFilename = getProject().getProperty("DEST_DIR_OUTPUT") + File.separatorChar + moduleId.getName() + "_build.xml";
693 antCall(antFilename, "clean");
694 }
695
696 private void applyCleanall(FpdModuleIdentification fpdModuleId){
697 //
698 // if it is CUSTOM_BUILD
699 // then call the exist BaseName_build.xml directly.
700 //
701 if (moduleId.getModuleType().equalsIgnoreCase("USER_DEFINED")) {
702 EdkLog.log(this, "Calling user-defined " + moduleId.getName() + "_build.xml");
703
704 String antFilename = getProject().getProperty("MODULE_DIR") + File.separatorChar + moduleId.getName() + "_build.xml";
705 antCall(antFilename, "cleanall");
706
707 return ;
708 }
709
710 String antFilename = getProject().getProperty("DEST_DIR_OUTPUT") + File.separatorChar + moduleId.getName() + "_build.xml";
711 antCall(antFilename, "cleanall");
712 }
713
714 private void antCall(String antFilename, String target) {
715 Ant ant = new Ant();
716 ant.setProject(getProject());
717 ant.setAntfile(antFilename);
718 if (target != null) {
719 ant.setTarget(target);
720 }
721 ant.setInheritAll(true);
722 ant.init();
723 ant.execute();
724 }
725
726 public void setSingleModuleBuild(boolean isSingleModuleBuild) {
727 this.isSingleModuleBuild = isSingleModuleBuild;
728 }
729
730 private String[] prepareIncludePaths(FpdModuleIdentification fpdModuleId) throws EdkException{
731 //
732 // Prepare the includes: PackageDependencies and Output debug direactory
733 //
734 Set<String> includes = new LinkedHashSet<String>();
735 String arch = fpdModuleId.getArch();
736
737 //
738 // WORKSPACE
739 //
740 includes.add("${WORKSPACE_DIR}" + File.separatorChar);
741
742 //
743 // Module iteself
744 //
745 includes.add("${MODULE_DIR}");
746 includes.add("${MODULE_DIR}" + File.separatorChar + archDir(arch));
747
748 //
749 // Packages in PackageDenpendencies
750 //
751 PackageIdentification[] packageDependencies = saq.getDependencePkg(fpdModuleId.getArch());
752 for (int i = 0; i < packageDependencies.length; i++) {
753 GlobalData.refreshPackageIdentification(packageDependencies[i]);
754 File packageFile = packageDependencies[i].getSpdFile();
755 includes.add(packageFile.getParent() + File.separatorChar + "Include");
756 includes.add(packageFile.getParent() + File.separatorChar + "Include" + File.separatorChar + archDir(arch));
757 }
758
759 //
760 // All Dependency Library Instance's PackageDependencies
761 //
762 ModuleIdentification[] libinstances = saq.getLibraryInstance(fpdModuleId.getArch());
763 for (int i = 0; i < libinstances.length; i++) {
764 saq.push(GlobalData.getDoc(libinstances[i], fpdModuleId.getArch()));
765 PackageIdentification[] libraryPackageDependencies = saq.getDependencePkg(fpdModuleId.getArch());
766 for (int j = 0; j < libraryPackageDependencies.length; j++) {
767 GlobalData.refreshPackageIdentification(libraryPackageDependencies[j]);
768 File packageFile = libraryPackageDependencies[j].getSpdFile();
769 includes.add(packageFile.getParent() + File.separatorChar + "Include");
770 includes.add(packageFile.getParent() + File.separatorChar + "Include" + File.separatorChar + archDir(arch));
771 }
772 saq.pop();
773 }
774
775
776 //
777 // The package which the module belongs to
778 // TBD
779 includes.add(fpdModuleId.getModule().getPackage().getPackageDir() + File.separatorChar + "Include");
780 includes.add(fpdModuleId.getModule().getPackage().getPackageDir() + File.separatorChar + "Include" + File.separatorChar + archDir(arch));
781
782 //
783 // Debug files output directory
784 //
785 includes.add("${DEST_DIR_DEBUG}");
786
787 //
788 // set to INCLUDE_PATHS property
789 //
790 Iterator<String> iter = includes.iterator();
791 StringBuffer includePaths = new StringBuffer();
792 while (iter.hasNext()) {
793 includePaths.append(iter.next());
794 includePaths.append("; ");
795 }
796 getProject().setProperty("INCLUDE_PATHS", getProject().replaceProperties(includePaths.toString()).replaceAll("(\\\\)", "/"));
797
798 return includes.toArray(new String[includes.size()]);
799 }
800
801 /**
802 Return the name of the directory that corresponds to the architecture.
803 This is a translation from the XML Schema tag to a directory that
804 corresponds to our directory name coding convention.
805
806 **/
807 private String archDir(String arch) {
808 return arch.replaceFirst("X64", "x64")
809 .replaceFirst("IPF", "Ipf")
810 .replaceFirst("IA32", "Ia32")
811 .replaceFirst("ARM", "Arm")
812 .replaceFirst("EBC", "Ebc");
813 }
814
815
816 public void setExternalProperties(Vector<Property> v) {
817 this.properties = v;
818 }
819
820 private String GetCustomizedBuildFile(String arch) {
821 String[][] files = saq.getSourceFiles(arch);
822 for (int i = 0; i < files.length; ++i) {
823 if (files[i][1].endsWith("build.xml")) {
824 return files[i][1];
825 }
826 }
827
828 return "";
829 }
830 }