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