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