]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/AutoGen/AutoGen.py
700b689a54fbda3f57c14a32498eecd4c4defd7f
[mirror_edk2.git] / BaseTools / Source / Python / AutoGen / AutoGen.py
1 ## @file
2 # Generate AutoGen.h, AutoGen.c and *.depex files
3 #
4 # Copyright (c) 2007 - 2011, Intel Corporation. All rights reserved.<BR>
5 # This program and the accompanying materials
6 # are licensed and made available under the terms and conditions of the BSD License
7 # which accompanies this distribution. The full text of the license may be found at
8 # http://opensource.org/licenses/bsd-license.php
9 #
10 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 #
13
14 ## Import Modules
15 #
16 import os
17 import re
18 import os.path as path
19 import copy
20
21 import GenC
22 import GenMake
23 import GenDepex
24 from StringIO import StringIO
25
26 from StrGather import *
27 from BuildEngine import BuildRule
28
29 from Common.BuildToolError import *
30 from Common.DataType import *
31 from Common.Misc import *
32 from Common.String import *
33 import Common.GlobalData as GlobalData
34 from GenFds.FdfParser import *
35 from CommonDataClass.CommonClass import SkuInfoClass
36 from Workspace.BuildClassObject import *
37 import Common.VpdInfoFile as VpdInfoFile
38
39 ## Regular expression for splitting Dependency Expression stirng into tokens
40 gDepexTokenPattern = re.compile("(\(|\)|\w+| \S+\.inf)")
41
42 ## Mapping Makefile type
43 gMakeTypeMap = {"MSFT":"nmake", "GCC":"gmake"}
44
45
46 ## Build rule configuration file
47 gBuildRuleFile = 'Conf/build_rule.txt'
48
49 ## default file name for AutoGen
50 gAutoGenCodeFileName = "AutoGen.c"
51 gAutoGenHeaderFileName = "AutoGen.h"
52 gAutoGenStringFileName = "%(module_name)sStrDefs.h"
53 gAutoGenStringFormFileName = "%(module_name)sStrDefs.hpk"
54 gAutoGenDepexFileName = "%(module_name)s.depex"
55
56 #
57 # Template string to generic AsBuilt INF
58 #
59 gAsBuiltInfHeaderString = TemplateString("""## @file
60 # ${module_name}
61 #
62 # DO NOT EDIT
63 # FILE auto-generated Binary INF
64 #
65 ##
66
67 [Defines]
68 INF_VERSION = 0x00010016
69 BASE_NAME = ${module_name}
70 FILE_GUID = ${module_guid}
71 MODULE_TYPE = ${module_module_type}
72 VERSION_STRING = ${module_version_string}${BEGIN}
73 UEFI_SPECIFICATION_VERSION = ${module_uefi_specification_version}${END}${BEGIN}
74 PI_SPECIFICATION_VERSION = ${module_pi_specification_version}${END}
75
76 [Packages]${BEGIN}
77 ${package_item}${END}
78
79 [Binaries.${module_arch}]${BEGIN}
80 ${binary_item}${END}
81
82 [PcdEx]${BEGIN}
83 ${pcd_item}${END}
84
85 ## @AsBuilt${BEGIN}
86 ## ${flags_item}${END}
87 """)
88
89 ## Base class for AutoGen
90 #
91 # This class just implements the cache mechanism of AutoGen objects.
92 #
93 class AutoGen(object):
94 # database to maintain the objects of xxxAutoGen
95 _CACHE_ = {} # (BuildTarget, ToolChain) : {ARCH : {platform file: AutoGen object}}}
96
97 ## Factory method
98 #
99 # @param Class class object of real AutoGen class
100 # (WorkspaceAutoGen, ModuleAutoGen or PlatformAutoGen)
101 # @param Workspace Workspace directory or WorkspaceAutoGen object
102 # @param MetaFile The path of meta file
103 # @param Target Build target
104 # @param Toolchain Tool chain name
105 # @param Arch Target arch
106 # @param *args The specific class related parameters
107 # @param **kwargs The specific class related dict parameters
108 #
109 def __new__(Class, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):
110 # check if the object has been created
111 Key = (Target, Toolchain)
112 if Key not in Class._CACHE_ or Arch not in Class._CACHE_[Key] \
113 or MetaFile not in Class._CACHE_[Key][Arch]:
114 AutoGenObject = super(AutoGen, Class).__new__(Class)
115 # call real constructor
116 if not AutoGenObject._Init(Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):
117 return None
118 if Key not in Class._CACHE_:
119 Class._CACHE_[Key] = {}
120 if Arch not in Class._CACHE_[Key]:
121 Class._CACHE_[Key][Arch] = {}
122 Class._CACHE_[Key][Arch][MetaFile] = AutoGenObject
123 else:
124 AutoGenObject = Class._CACHE_[Key][Arch][MetaFile]
125
126 return AutoGenObject
127
128 ## hash() operator
129 #
130 # The file path of platform file will be used to represent hash value of this object
131 #
132 # @retval int Hash value of the file path of platform file
133 #
134 def __hash__(self):
135 return hash(self.MetaFile)
136
137 ## str() operator
138 #
139 # The file path of platform file will be used to represent this object
140 #
141 # @retval string String of platform file path
142 #
143 def __str__(self):
144 return str(self.MetaFile)
145
146 ## "==" operator
147 def __eq__(self, Other):
148 return Other and self.MetaFile == Other
149
150 ## Workspace AutoGen class
151 #
152 # This class is used mainly to control the whole platform build for different
153 # architecture. This class will generate top level makefile.
154 #
155 class WorkspaceAutoGen(AutoGen):
156 ## Real constructor of WorkspaceAutoGen
157 #
158 # This method behaves the same as __init__ except that it needs explicit invoke
159 # (in super class's __new__ method)
160 #
161 # @param WorkspaceDir Root directory of workspace
162 # @param ActivePlatform Meta-file of active platform
163 # @param Target Build target
164 # @param Toolchain Tool chain name
165 # @param ArchList List of architecture of current build
166 # @param MetaFileDb Database containing meta-files
167 # @param BuildConfig Configuration of build
168 # @param ToolDefinition Tool chain definitions
169 # @param FlashDefinitionFile File of flash definition
170 # @param Fds FD list to be generated
171 # @param Fvs FV list to be generated
172 # @param Caps Capsule list to be generated
173 # @param SkuId SKU id from command line
174 #
175 def _Init(self, WorkspaceDir, ActivePlatform, Target, Toolchain, ArchList, MetaFileDb,
176 BuildConfig, ToolDefinition, FlashDefinitionFile='', Fds=None, Fvs=None, Caps=None, SkuId='', UniFlag=None):
177 if Fds is None:
178 Fds = []
179 if Fvs is None:
180 Fvs = []
181 if Caps is None:
182 Caps = []
183 self.BuildDatabase = MetaFileDb
184 self.MetaFile = ActivePlatform
185 self.WorkspaceDir = WorkspaceDir
186 self.Platform = self.BuildDatabase[self.MetaFile, 'COMMON', Target, Toolchain]
187 self.BuildTarget = Target
188 self.ToolChain = Toolchain
189 self.ArchList = ArchList
190 self.SkuId = SkuId
191 self.UniFlag = UniFlag
192
193 self.TargetTxt = BuildConfig
194 self.ToolDef = ToolDefinition
195 self.FdfFile = FlashDefinitionFile
196 self.FdTargetList = Fds
197 self.FvTargetList = Fvs
198 self.CapTargetList = Caps
199 self.AutoGenObjectList = []
200
201 # there's many relative directory operations, so ...
202 os.chdir(self.WorkspaceDir)
203
204 #
205 # Merge Arch
206 #
207 if not self.ArchList:
208 ArchList = set(self.Platform.SupArchList)
209 else:
210 ArchList = set(self.ArchList) & set(self.Platform.SupArchList)
211 if not ArchList:
212 EdkLogger.error("build", PARAMETER_INVALID,
213 ExtraData = "Invalid ARCH specified. [Valid ARCH: %s]" % (" ".join(self.Platform.SupArchList)))
214 elif self.ArchList and len(ArchList) != len(self.ArchList):
215 SkippedArchList = set(self.ArchList).symmetric_difference(set(self.Platform.SupArchList))
216 EdkLogger.verbose("\nArch [%s] is ignored because the platform supports [%s] only!"
217 % (" ".join(SkippedArchList), " ".join(self.Platform.SupArchList)))
218 self.ArchList = tuple(ArchList)
219
220 # Validate build target
221 if self.BuildTarget not in self.Platform.BuildTargets:
222 EdkLogger.error("build", PARAMETER_INVALID,
223 ExtraData="Build target [%s] is not supported by the platform. [Valid target: %s]"
224 % (self.BuildTarget, " ".join(self.Platform.BuildTargets)))
225
226 # Validate SKU ID
227 if not self.SkuId:
228 self.SkuId = 'DEFAULT'
229
230 if self.SkuId not in self.Platform.SkuIds:
231 EdkLogger.error("build", PARAMETER_INVALID,
232 ExtraData="SKU-ID [%s] is not supported by the platform. [Valid SKU-ID: %s]"
233 % (self.SkuId, " ".join(self.Platform.SkuIds.keys())))
234
235 # parse FDF file to get PCDs in it, if any
236 if not self.FdfFile:
237 self.FdfFile = self.Platform.FlashDefinition
238 EdkLogger.verbose("\nFLASH_DEFINITION = %s" % self.FdfFile)
239
240 if self.FdfFile:
241 #
242 # Mark now build in AutoGen Phase
243 #
244 GlobalData.gAutoGenPhase = True
245 Fdf = FdfParser(self.FdfFile.Path)
246 Fdf.ParseFile()
247 GlobalData.gAutoGenPhase = False
248 PcdSet = Fdf.Profile.PcdDict
249 ModuleList = Fdf.Profile.InfList
250 self.FdfProfile = Fdf.Profile
251 for fvname in self.FvTargetList:
252 if fvname.upper() not in self.FdfProfile.FvDict:
253 EdkLogger.error("build", OPTION_VALUE_INVALID,
254 "No such an FV in FDF file: %s" % fvname)
255 else:
256 PcdSet = {}
257 ModuleList = []
258 self.FdfProfile = None
259 if self.FdTargetList:
260 EdkLogger.info("No flash definition file found. FD [%s] will be ignored." % " ".join(self.FdTargetList))
261 self.FdTargetList = []
262 if self.FvTargetList:
263 EdkLogger.info("No flash definition file found. FV [%s] will be ignored." % " ".join(self.FvTargetList))
264 self.FvTargetList = []
265 if self.CapTargetList:
266 EdkLogger.info("No flash definition file found. Capsule [%s] will be ignored." % " ".join(self.CapTargetList))
267 self.CapTargetList = []
268
269 # apply SKU and inject PCDs from Flash Definition file
270 for Arch in self.ArchList:
271 Platform = self.BuildDatabase[self.MetaFile, Arch, Target, Toolchain]
272 Platform.SkuName = self.SkuId
273 for Name, Guid in PcdSet:
274 Platform.AddPcd(Name, Guid, PcdSet[Name, Guid])
275
276 Pa = PlatformAutoGen(self, self.MetaFile, Target, Toolchain, Arch)
277 #
278 # Explicitly collect platform's dynamic PCDs
279 #
280 Pa.CollectPlatformDynamicPcds()
281 self.AutoGenObjectList.append(Pa)
282
283 #
284 # Check PCDs token value conflict in each DEC file.
285 #
286 self._CheckAllPcdsTokenValueConflict()
287
288 #
289 # Check PCD type and definition between DSC and DEC
290 #
291 self._CheckPcdDefineAndType()
292
293 if self.FdfFile:
294 self._CheckDuplicateInFV(Fdf)
295
296 self._BuildDir = None
297 self._FvDir = None
298 self._MakeFileDir = None
299 self._BuildCommand = None
300
301 return True
302
303 ## _CheckDuplicateInFV() method
304 #
305 # Check whether there is duplicate modules/files exist in FV section.
306 # The check base on the file GUID;
307 #
308 def _CheckDuplicateInFV(self, Fdf):
309 for Fv in Fdf.Profile.FvDict:
310 _GuidDict = {}
311 for FfsFile in Fdf.Profile.FvDict[Fv].FfsList:
312 if FfsFile.InfFileName and FfsFile.NameGuid == None:
313 #
314 # Get INF file GUID
315 #
316 InfFoundFlag = False
317 for Pa in self.AutoGenObjectList:
318 for Module in Pa.ModuleAutoGenList:
319 if path.normpath(Module.MetaFile.File) == path.normpath(FfsFile.InfFileName):
320 InfFoundFlag = True
321 if not Module.Guid.upper() in _GuidDict.keys():
322 _GuidDict[Module.Guid.upper()] = FfsFile
323 else:
324 EdkLogger.error("build",
325 FORMAT_INVALID,
326 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s"%(FfsFile.CurrentLineNum,
327 FfsFile.CurrentLineContent,
328 _GuidDict[Module.Guid.upper()].CurrentLineNum,
329 _GuidDict[Module.Guid.upper()].CurrentLineContent,
330 Module.Guid.upper()),
331 ExtraData=self.FdfFile)
332 #
333 # Some INF files not have entity in DSC file.
334 #
335 if not InfFoundFlag:
336 if FfsFile.InfFileName.find('$') == -1:
337 InfPath = NormPath(FfsFile.InfFileName)
338 if not os.path.exists(InfPath):
339 EdkLogger.error('build', GENFDS_ERROR, "Non-existant Module %s !" % (FfsFile.InfFileName))
340
341 PathClassObj = PathClass(FfsFile.InfFileName, self.WorkspaceDir)
342 #
343 # Here we just need to get FILE_GUID from INF file, use 'COMMON' as ARCH attribute. and use
344 # BuildObject from one of AutoGenObjectList is enough.
345 #
346 InfObj = self.AutoGenObjectList[0].BuildDatabase.WorkspaceDb.BuildObject[PathClassObj, 'COMMON', self.BuildTarget, self.ToolChain]
347 if not InfObj.Guid.upper() in _GuidDict.keys():
348 _GuidDict[InfObj.Guid.upper()] = FfsFile
349 else:
350 EdkLogger.error("build",
351 FORMAT_INVALID,
352 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s"%(FfsFile.CurrentLineNum,
353 FfsFile.CurrentLineContent,
354 _GuidDict[InfObj.Guid.upper()].CurrentLineNum,
355 _GuidDict[InfObj.Guid.upper()].CurrentLineContent,
356 InfObj.Guid.upper()),
357 ExtraData=self.FdfFile)
358 InfFoundFlag = False
359
360 if FfsFile.NameGuid != None:
361 _CheckPCDAsGuidPattern = re.compile("^PCD\(.+\..+\)$")
362
363 #
364 # If the NameGuid reference a PCD name.
365 # The style must match: PCD(xxxx.yyy)
366 #
367 if _CheckPCDAsGuidPattern.match(FfsFile.NameGuid):
368 #
369 # Replace the PCD value.
370 #
371 _PcdName = FfsFile.NameGuid.lstrip("PCD(").rstrip(")")
372 PcdFoundFlag = False
373 for Pa in self.AutoGenObjectList:
374 if not PcdFoundFlag:
375 for PcdItem in Pa.AllPcdList:
376 if (PcdItem.TokenSpaceGuidCName + "." + PcdItem.TokenCName) == _PcdName:
377 #
378 # First convert from CFormatGuid to GUID string
379 #
380 _PcdGuidString = GuidStructureStringToGuidString(PcdItem.DefaultValue)
381
382 if not _PcdGuidString:
383 #
384 # Then try Byte array.
385 #
386 _PcdGuidString = GuidStructureByteArrayToGuidString(PcdItem.DefaultValue)
387
388 if not _PcdGuidString:
389 #
390 # Not Byte array or CFormat GUID, raise error.
391 #
392 EdkLogger.error("build",
393 FORMAT_INVALID,
394 "The format of PCD value is incorrect. PCD: %s , Value: %s\n"%(_PcdName, PcdItem.DefaultValue),
395 ExtraData=self.FdfFile)
396
397 if not _PcdGuidString.upper() in _GuidDict.keys():
398 _GuidDict[_PcdGuidString.upper()] = FfsFile
399 PcdFoundFlag = True
400 break
401 else:
402 EdkLogger.error("build",
403 FORMAT_INVALID,
404 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s"%(FfsFile.CurrentLineNum,
405 FfsFile.CurrentLineContent,
406 _GuidDict[_PcdGuidString.upper()].CurrentLineNum,
407 _GuidDict[_PcdGuidString.upper()].CurrentLineContent,
408 FfsFile.NameGuid.upper()),
409 ExtraData=self.FdfFile)
410
411 if not FfsFile.NameGuid.upper() in _GuidDict.keys():
412 _GuidDict[FfsFile.NameGuid.upper()] = FfsFile
413 else:
414 #
415 # Two raw file GUID conflict.
416 #
417 EdkLogger.error("build",
418 FORMAT_INVALID,
419 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s"%(FfsFile.CurrentLineNum,
420 FfsFile.CurrentLineContent,
421 _GuidDict[FfsFile.NameGuid.upper()].CurrentLineNum,
422 _GuidDict[FfsFile.NameGuid.upper()].CurrentLineContent,
423 FfsFile.NameGuid.upper()),
424 ExtraData=self.FdfFile)
425
426
427 def _CheckPcdDefineAndType(self):
428 PcdTypeList = [
429 "FixedAtBuild", "PatchableInModule", "FeatureFlag",
430 "Dynamic", #"DynamicHii", "DynamicVpd",
431 "DynamicEx", # "DynamicExHii", "DynamicExVpd"
432 ]
433
434 # This dict store PCDs which are not used by any modules with specified arches
435 UnusedPcd = sdict()
436 for Pa in self.AutoGenObjectList:
437 # Key of DSC's Pcds dictionary is PcdCName, TokenSpaceGuid
438 for Pcd in Pa.Platform.Pcds:
439 PcdType = Pa.Platform.Pcds[Pcd].Type
440
441 # If no PCD type, this PCD comes from FDF
442 if not PcdType:
443 continue
444
445 # Try to remove Hii and Vpd suffix
446 if PcdType.startswith("DynamicEx"):
447 PcdType = "DynamicEx"
448 elif PcdType.startswith("Dynamic"):
449 PcdType = "Dynamic"
450
451 for Package in Pa.PackageList:
452 # Key of DEC's Pcds dictionary is PcdCName, TokenSpaceGuid, PcdType
453 if (Pcd[0], Pcd[1], PcdType) in Package.Pcds:
454 break
455 for Type in PcdTypeList:
456 if (Pcd[0], Pcd[1], Type) in Package.Pcds:
457 EdkLogger.error(
458 'build',
459 FORMAT_INVALID,
460 "Type [%s] of PCD [%s.%s] in DSC file doesn't match the type [%s] defined in DEC file." \
461 % (Pa.Platform.Pcds[Pcd].Type, Pcd[1], Pcd[0], Type),
462 ExtraData=None
463 )
464 return
465 else:
466 UnusedPcd.setdefault(Pcd, []).append(Pa.Arch)
467
468 for Pcd in UnusedPcd:
469 EdkLogger.warn(
470 'build',
471 "The PCD was not specified by any INF module in the platform for the given architecture.\n"
472 "\tPCD: [%s.%s]\n\tPlatform: [%s]\n\tArch: %s"
473 % (Pcd[1], Pcd[0], os.path.basename(str(self.MetaFile)), str(UnusedPcd[Pcd])),
474 ExtraData=None
475 )
476
477 def __repr__(self):
478 return "%s [%s]" % (self.MetaFile, ", ".join(self.ArchList))
479
480 ## Return the directory to store FV files
481 def _GetFvDir(self):
482 if self._FvDir == None:
483 self._FvDir = path.join(self.BuildDir, 'FV')
484 return self._FvDir
485
486 ## Return the directory to store all intermediate and final files built
487 def _GetBuildDir(self):
488 return self.AutoGenObjectList[0].BuildDir
489
490 ## Return the build output directory platform specifies
491 def _GetOutputDir(self):
492 return self.Platform.OutputDirectory
493
494 ## Return platform name
495 def _GetName(self):
496 return self.Platform.PlatformName
497
498 ## Return meta-file GUID
499 def _GetGuid(self):
500 return self.Platform.Guid
501
502 ## Return platform version
503 def _GetVersion(self):
504 return self.Platform.Version
505
506 ## Return paths of tools
507 def _GetToolDefinition(self):
508 return self.AutoGenObjectList[0].ToolDefinition
509
510 ## Return directory of platform makefile
511 #
512 # @retval string Makefile directory
513 #
514 def _GetMakeFileDir(self):
515 if self._MakeFileDir == None:
516 self._MakeFileDir = self.BuildDir
517 return self._MakeFileDir
518
519 ## Return build command string
520 #
521 # @retval string Build command string
522 #
523 def _GetBuildCommand(self):
524 if self._BuildCommand == None:
525 # BuildCommand should be all the same. So just get one from platform AutoGen
526 self._BuildCommand = self.AutoGenObjectList[0].BuildCommand
527 return self._BuildCommand
528
529 ## Check the PCDs token value conflict in each DEC file.
530 #
531 # Will cause build break and raise error message while two PCDs conflict.
532 #
533 # @return None
534 #
535 def _CheckAllPcdsTokenValueConflict(self):
536 for Pa in self.AutoGenObjectList:
537 for Package in Pa.PackageList:
538 PcdList = Package.Pcds.values()
539 PcdList.sort(lambda x, y: cmp(x.TokenValue, y.TokenValue))
540 Count = 0
541 while (Count < len(PcdList) - 1) :
542 Item = PcdList[Count]
543 ItemNext = PcdList[Count + 1]
544 #
545 # Make sure in the same token space the TokenValue should be unique
546 #
547 if (Item.TokenValue == ItemNext.TokenValue):
548 SameTokenValuePcdList = []
549 SameTokenValuePcdList.append(Item)
550 SameTokenValuePcdList.append(ItemNext)
551 RemainPcdListLength = len(PcdList) - Count - 2
552 for ValueSameCount in range(RemainPcdListLength):
553 if PcdList[len(PcdList) - RemainPcdListLength + ValueSameCount].TokenValue == Item.TokenValue:
554 SameTokenValuePcdList.append(PcdList[len(PcdList) - RemainPcdListLength + ValueSameCount])
555 else:
556 break;
557 #
558 # Sort same token value PCD list with TokenGuid and TokenCName
559 #
560 SameTokenValuePcdList.sort(lambda x, y: cmp("%s.%s"%(x.TokenSpaceGuidCName, x.TokenCName), "%s.%s"%(y.TokenSpaceGuidCName, y.TokenCName)))
561 SameTokenValuePcdListCount = 0
562 while (SameTokenValuePcdListCount < len(SameTokenValuePcdList) - 1):
563 TemListItem = SameTokenValuePcdList[SameTokenValuePcdListCount]
564 TemListItemNext = SameTokenValuePcdList[SameTokenValuePcdListCount + 1]
565
566 if (TemListItem.TokenSpaceGuidCName == TemListItemNext.TokenSpaceGuidCName) and (TemListItem.TokenCName != TemListItemNext.TokenCName):
567 EdkLogger.error(
568 'build',
569 FORMAT_INVALID,
570 "The TokenValue [%s] of PCD [%s.%s] is conflict with: [%s.%s] in %s"\
571 % (TemListItem.TokenValue, TemListItem.TokenSpaceGuidCName, TemListItem.TokenCName, TemListItemNext.TokenSpaceGuidCName, TemListItemNext.TokenCName, Package),
572 ExtraData=None
573 )
574 SameTokenValuePcdListCount += 1
575 Count += SameTokenValuePcdListCount
576 Count += 1
577
578 PcdList = Package.Pcds.values()
579 PcdList.sort(lambda x, y: cmp("%s.%s"%(x.TokenSpaceGuidCName, x.TokenCName), "%s.%s"%(y.TokenSpaceGuidCName, y.TokenCName)))
580 Count = 0
581 while (Count < len(PcdList) - 1) :
582 Item = PcdList[Count]
583 ItemNext = PcdList[Count + 1]
584 #
585 # Check PCDs with same TokenSpaceGuidCName.TokenCName have same token value as well.
586 #
587 if (Item.TokenSpaceGuidCName == ItemNext.TokenSpaceGuidCName) and (Item.TokenCName == ItemNext.TokenCName) and (Item.TokenValue != ItemNext.TokenValue):
588 EdkLogger.error(
589 'build',
590 FORMAT_INVALID,
591 "The TokenValue [%s] of PCD [%s.%s] in %s defined in two places should be same as well."\
592 % (Item.TokenValue, Item.TokenSpaceGuidCName, Item.TokenCName, Package),
593 ExtraData=None
594 )
595 Count += 1
596
597
598 ## Create makefile for the platform and modules in it
599 #
600 # @param CreateDepsMakeFile Flag indicating if the makefile for
601 # modules will be created as well
602 #
603 def CreateMakeFile(self, CreateDepsMakeFile=False):
604 # create makefile for platform
605 Makefile = GenMake.TopLevelMakefile(self)
606 if Makefile.Generate():
607 EdkLogger.debug(EdkLogger.DEBUG_9, "Generated makefile for platform [%s] %s\n" %
608 (self.MetaFile, self.ArchList))
609 else:
610 EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of makefile for platform [%s] %s\n" %
611 (self.MetaFile, self.ArchList))
612
613 if CreateDepsMakeFile:
614 for Pa in self.AutoGenObjectList:
615 Pa.CreateMakeFile(CreateDepsMakeFile)
616
617 ## Create autogen code for platform and modules
618 #
619 # Since there's no autogen code for platform, this method will do nothing
620 # if CreateModuleCodeFile is set to False.
621 #
622 # @param CreateDepsCodeFile Flag indicating if creating module's
623 # autogen code file or not
624 #
625 def CreateCodeFile(self, CreateDepsCodeFile=False):
626 if not CreateDepsCodeFile:
627 return
628 for Pa in self.AutoGenObjectList:
629 Pa.CreateCodeFile(CreateDepsCodeFile)
630
631 ## Create AsBuilt INF file the platform
632 #
633 def CreateAsBuiltInf(self):
634 return
635
636 Name = property(_GetName)
637 Guid = property(_GetGuid)
638 Version = property(_GetVersion)
639 OutputDir = property(_GetOutputDir)
640
641 ToolDefinition = property(_GetToolDefinition) # toolcode : tool path
642
643 BuildDir = property(_GetBuildDir)
644 FvDir = property(_GetFvDir)
645 MakeFileDir = property(_GetMakeFileDir)
646 BuildCommand = property(_GetBuildCommand)
647
648 ## AutoGen class for platform
649 #
650 # PlatformAutoGen class will process the original information in platform
651 # file in order to generate makefile for platform.
652 #
653 class PlatformAutoGen(AutoGen):
654 #
655 # Used to store all PCDs for both PEI and DXE phase, in order to generate
656 # correct PCD database
657 #
658 _DynaPcdList_ = []
659 _NonDynaPcdList_ = []
660
661 #
662 # The priority list while override build option
663 #
664 PrioList = {"0x11111" : 16, # TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE (Highest)
665 "0x01111" : 15, # ******_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
666 "0x10111" : 14, # TARGET_*********_ARCH_COMMANDTYPE_ATTRIBUTE
667 "0x00111" : 13, # ******_*********_ARCH_COMMANDTYPE_ATTRIBUTE
668 "0x11011" : 12, # TARGET_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
669 "0x01011" : 11, # ******_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
670 "0x10011" : 10, # TARGET_*********_****_COMMANDTYPE_ATTRIBUTE
671 "0x00011" : 9, # ******_*********_****_COMMANDTYPE_ATTRIBUTE
672 "0x11101" : 8, # TARGET_TOOLCHAIN_ARCH_***********_ATTRIBUTE
673 "0x01101" : 7, # ******_TOOLCHAIN_ARCH_***********_ATTRIBUTE
674 "0x10101" : 6, # TARGET_*********_ARCH_***********_ATTRIBUTE
675 "0x00101" : 5, # ******_*********_ARCH_***********_ATTRIBUTE
676 "0x11001" : 4, # TARGET_TOOLCHAIN_****_***********_ATTRIBUTE
677 "0x01001" : 3, # ******_TOOLCHAIN_****_***********_ATTRIBUTE
678 "0x10001" : 2, # TARGET_*********_****_***********_ATTRIBUTE
679 "0x00001" : 1} # ******_*********_****_***********_ATTRIBUTE (Lowest)
680
681 ## The real constructor of PlatformAutoGen
682 #
683 # This method is not supposed to be called by users of PlatformAutoGen. It's
684 # only used by factory method __new__() to do real initialization work for an
685 # object of PlatformAutoGen
686 #
687 # @param Workspace WorkspaceAutoGen object
688 # @param PlatformFile Platform file (DSC file)
689 # @param Target Build target (DEBUG, RELEASE)
690 # @param Toolchain Name of tool chain
691 # @param Arch arch of the platform supports
692 #
693 def _Init(self, Workspace, PlatformFile, Target, Toolchain, Arch):
694 EdkLogger.debug(EdkLogger.DEBUG_9, "AutoGen platform [%s] [%s]" % (PlatformFile, Arch))
695 GlobalData.gProcessingFile = "%s [%s, %s, %s]" % (PlatformFile, Arch, Toolchain, Target)
696
697 self.MetaFile = PlatformFile
698 self.Workspace = Workspace
699 self.WorkspaceDir = Workspace.WorkspaceDir
700 self.ToolChain = Toolchain
701 self.BuildTarget = Target
702 self.Arch = Arch
703 self.SourceDir = PlatformFile.SubDir
704 self.SourceOverrideDir = None
705 self.FdTargetList = self.Workspace.FdTargetList
706 self.FvTargetList = self.Workspace.FvTargetList
707 self.AllPcdList = []
708
709 # flag indicating if the makefile/C-code file has been created or not
710 self.IsMakeFileCreated = False
711 self.IsCodeFileCreated = False
712
713 self._Platform = None
714 self._Name = None
715 self._Guid = None
716 self._Version = None
717
718 self._BuildRule = None
719 self._SourceDir = None
720 self._BuildDir = None
721 self._OutputDir = None
722 self._FvDir = None
723 self._MakeFileDir = None
724 self._FdfFile = None
725
726 self._PcdTokenNumber = None # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber
727 self._DynamicPcdList = None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
728 self._NonDynamicPcdList = None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
729
730 self._ToolDefinitions = None
731 self._ToolDefFile = None # toolcode : tool path
732 self._ToolChainFamily = None
733 self._BuildRuleFamily = None
734 self._BuildOption = None # toolcode : option
735 self._EdkBuildOption = None # edktoolcode : option
736 self._EdkIIBuildOption = None # edkiitoolcode : option
737 self._PackageList = None
738 self._ModuleAutoGenList = None
739 self._LibraryAutoGenList = None
740 self._BuildCommand = None
741
742 # get the original module/package/platform objects
743 self.BuildDatabase = Workspace.BuildDatabase
744 return True
745
746 def __repr__(self):
747 return "%s [%s]" % (self.MetaFile, self.Arch)
748
749 ## Create autogen code for platform and modules
750 #
751 # Since there's no autogen code for platform, this method will do nothing
752 # if CreateModuleCodeFile is set to False.
753 #
754 # @param CreateModuleCodeFile Flag indicating if creating module's
755 # autogen code file or not
756 #
757 def CreateCodeFile(self, CreateModuleCodeFile=False):
758 # only module has code to be greated, so do nothing if CreateModuleCodeFile is False
759 if self.IsCodeFileCreated or not CreateModuleCodeFile:
760 return
761
762 for Ma in self.ModuleAutoGenList:
763 Ma.CreateCodeFile(True)
764
765 # don't do this twice
766 self.IsCodeFileCreated = True
767
768 ## Create makefile for the platform and mdoules in it
769 #
770 # @param CreateModuleMakeFile Flag indicating if the makefile for
771 # modules will be created as well
772 #
773 def CreateMakeFile(self, CreateModuleMakeFile=False):
774 if CreateModuleMakeFile:
775 for ModuleFile in self.Platform.Modules:
776 Ma = ModuleAutoGen(self.Workspace, ModuleFile, self.BuildTarget,
777 self.ToolChain, self.Arch, self.MetaFile)
778 Ma.CreateMakeFile(True)
779 Ma.CreateAsBuiltInf()
780
781 # no need to create makefile for the platform more than once
782 if self.IsMakeFileCreated:
783 return
784
785 # create makefile for platform
786 Makefile = GenMake.PlatformMakefile(self)
787 if Makefile.Generate():
788 EdkLogger.debug(EdkLogger.DEBUG_9, "Generated makefile for platform [%s] [%s]\n" %
789 (self.MetaFile, self.Arch))
790 else:
791 EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of makefile for platform [%s] [%s]\n" %
792 (self.MetaFile, self.Arch))
793 self.IsMakeFileCreated = True
794
795 ## Collect dynamic PCDs
796 #
797 # Gather dynamic PCDs list from each module and their settings from platform
798 # This interface should be invoked explicitly when platform action is created.
799 #
800 def CollectPlatformDynamicPcds(self):
801 # for gathering error information
802 NoDatumTypePcdList = set()
803
804 self._GuidValue = {}
805 for F in self.Platform.Modules.keys():
806 M = ModuleAutoGen(self.Workspace, F, self.BuildTarget, self.ToolChain, self.Arch, self.MetaFile)
807 #GuidValue.update(M.Guids)
808
809 self.Platform.Modules[F].M = M
810
811 for PcdFromModule in M.ModulePcdList+M.LibraryPcdList:
812 # make sure that the "VOID*" kind of datum has MaxDatumSize set
813 if PcdFromModule.DatumType == "VOID*" and PcdFromModule.MaxDatumSize == None:
814 NoDatumTypePcdList.add("%s.%s [%s]" % (PcdFromModule.TokenSpaceGuidCName, PcdFromModule.TokenCName, F))
815
816 if PcdFromModule.Type in GenC.gDynamicPcd or PcdFromModule.Type in GenC.gDynamicExPcd:
817 #
818 # If a dynamic PCD used by a PEM module/PEI module & DXE module,
819 # it should be stored in Pcd PEI database, If a dynamic only
820 # used by DXE module, it should be stored in DXE PCD database.
821 # The default Phase is DXE
822 #
823 if M.ModuleType in ["PEIM", "PEI_CORE"]:
824 PcdFromModule.Phase = "PEI"
825 if PcdFromModule not in self._DynaPcdList_:
826 self._DynaPcdList_.append(PcdFromModule)
827 elif PcdFromModule.Phase == 'PEI':
828 # overwrite any the same PCD existing, if Phase is PEI
829 Index = self._DynaPcdList_.index(PcdFromModule)
830 self._DynaPcdList_[Index] = PcdFromModule
831 elif PcdFromModule not in self._NonDynaPcdList_:
832 self._NonDynaPcdList_.append(PcdFromModule)
833
834 # print out error information and break the build, if error found
835 if len(NoDatumTypePcdList) > 0:
836 NoDatumTypePcdListString = "\n\t\t".join(NoDatumTypePcdList)
837 EdkLogger.error("build", AUTOGEN_ERROR, "PCD setting error",
838 File=self.MetaFile,
839 ExtraData="\n\tPCD(s) without MaxDatumSize:\n\t\t%s\n"
840 % NoDatumTypePcdListString)
841 self._NonDynamicPcdList = self._NonDynaPcdList_
842 self._DynamicPcdList = self._DynaPcdList_
843 self.AllPcdList = self._NonDynamicPcdList + self._DynamicPcdList
844
845 #
846 # Sort dynamic PCD list to:
847 # 1) If PCD's datum type is VOID* and value is unicode string which starts with L, the PCD item should
848 # try to be put header of dynamicd List
849 # 2) If PCD is HII type, the PCD item should be put after unicode type PCD
850 #
851 # The reason of sorting is make sure the unicode string is in double-byte alignment in string table.
852 #
853 UnicodePcdArray = []
854 HiiPcdArray = []
855 OtherPcdArray = []
856 VpdPcdDict = {}
857 VpdFile = VpdInfoFile.VpdInfoFile()
858 NeedProcessVpdMapFile = False
859
860 if (self.Workspace.ArchList[-1] == self.Arch):
861 for Pcd in self._DynamicPcdList:
862 # just pick the a value to determine whether is unicode string type
863 Sku = Pcd.SkuInfoList[Pcd.SkuInfoList.keys()[0]]
864 Sku.VpdOffset = Sku.VpdOffset.strip()
865
866 PcdValue = Sku.DefaultValue
867 if Pcd.DatumType == 'VOID*' and PcdValue.startswith("L"):
868 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
869 UnicodePcdArray.append(Pcd)
870 elif len(Sku.VariableName) > 0:
871 # if found HII type PCD then insert to right of UnicodeIndex
872 HiiPcdArray.append(Pcd)
873 else:
874 OtherPcdArray.append(Pcd)
875 if Pcd.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD]:
876 VpdPcdDict[(Pcd.TokenCName, Pcd.TokenSpaceGuidCName)] = Pcd
877
878 PlatformPcds = self.Platform.Pcds.keys()
879 PlatformPcds.sort()
880 #
881 # Add VPD type PCD into VpdFile and determine whether the VPD PCD need to be fixed up.
882 #
883 for PcdKey in PlatformPcds:
884 Pcd = self.Platform.Pcds[PcdKey]
885 if Pcd.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD]:
886 Pcd = VpdPcdDict[PcdKey]
887 Sku = Pcd.SkuInfoList[Pcd.SkuInfoList.keys()[0]]
888 Sku.VpdOffset = Sku.VpdOffset.strip()
889 #
890 # Fix the optional data of VPD PCD.
891 #
892 if (Pcd.DatumType.strip() != "VOID*"):
893 if Sku.DefaultValue == '':
894 Pcd.SkuInfoList[Pcd.SkuInfoList.keys()[0]].DefaultValue = Pcd.MaxDatumSize
895 Pcd.MaxDatumSize = None
896 else:
897 EdkLogger.error("build", AUTOGEN_ERROR, "PCD setting error",
898 File=self.MetaFile,
899 ExtraData="\n\tPCD: %s.%s format incorrect in DSC: %s\n\t\t\n"
900 % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName, self.Platform.MetaFile.Path))
901
902 VpdFile.Add(Pcd, Sku.VpdOffset)
903 # if the offset of a VPD is *, then it need to be fixed up by third party tool.
904 if not NeedProcessVpdMapFile and Sku.VpdOffset == "*":
905 NeedProcessVpdMapFile = True
906 if self.Platform.VpdToolGuid == None or self.Platform.VpdToolGuid == '':
907 EdkLogger.error("Build", FILE_NOT_FOUND, \
908 "Fail to find third-party BPDG tool to process VPD PCDs. BPDG Guid tool need to be defined in tools_def.txt and VPD_TOOL_GUID need to be provided in DSC file.")
909
910
911 #
912 # Fix the PCDs define in VPD PCD section that never referenced by module.
913 # An example is PCD for signature usage.
914 #
915 for DscPcd in PlatformPcds:
916 DscPcdEntry = self.Platform.Pcds[DscPcd]
917 if DscPcdEntry.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD]:
918 if not (self.Platform.VpdToolGuid == None or self.Platform.VpdToolGuid == ''):
919 FoundFlag = False
920 for VpdPcd in VpdFile._VpdArray.keys():
921 # This PCD has been referenced by module
922 if (VpdPcd.TokenSpaceGuidCName == DscPcdEntry.TokenSpaceGuidCName) and \
923 (VpdPcd.TokenCName == DscPcdEntry.TokenCName):
924 FoundFlag = True
925
926 # Not found, it should be signature
927 if not FoundFlag :
928 # just pick the a value to determine whether is unicode string type
929 Sku = DscPcdEntry.SkuInfoList[DscPcdEntry.SkuInfoList.keys()[0]]
930 Sku.VpdOffset = Sku.VpdOffset.strip()
931
932 # Need to iterate DEC pcd information to get the value & datumtype
933 for eachDec in self.PackageList:
934 for DecPcd in eachDec.Pcds:
935 DecPcdEntry = eachDec.Pcds[DecPcd]
936 if (DecPcdEntry.TokenSpaceGuidCName == DscPcdEntry.TokenSpaceGuidCName) and \
937 (DecPcdEntry.TokenCName == DscPcdEntry.TokenCName):
938 # Print warning message to let the developer make a determine.
939 EdkLogger.warn("build", "Unreferenced vpd pcd used!",
940 File=self.MetaFile, \
941 ExtraData = "PCD: %s.%s used in the DSC file %s is unreferenced." \
942 %(DscPcdEntry.TokenSpaceGuidCName, DscPcdEntry.TokenCName, self.Platform.MetaFile.Path))
943
944 DscPcdEntry.DatumType = DecPcdEntry.DatumType
945 DscPcdEntry.DefaultValue = DecPcdEntry.DefaultValue
946 # Only fix the value while no value provided in DSC file.
947 if (Sku.DefaultValue == "" or Sku.DefaultValue==None):
948 DscPcdEntry.SkuInfoList[DscPcdEntry.SkuInfoList.keys()[0]].DefaultValue = DecPcdEntry.DefaultValue
949
950
951 VpdFile.Add(DscPcdEntry, Sku.VpdOffset)
952 # if the offset of a VPD is *, then it need to be fixed up by third party tool.
953 if not NeedProcessVpdMapFile and Sku.VpdOffset == "*":
954 NeedProcessVpdMapFile = True
955
956
957 if (self.Platform.FlashDefinition == None or self.Platform.FlashDefinition == '') and \
958 VpdFile.GetCount() != 0:
959 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE,
960 "Fail to get FLASH_DEFINITION definition in DSC file %s which is required when DSC contains VPD PCD." % str(self.Platform.MetaFile))
961
962 if VpdFile.GetCount() != 0:
963 WorkspaceDb = self.BuildDatabase.WorkspaceDb
964 DscTimeStamp = WorkspaceDb.GetTimeStamp(WorkspaceDb.GetFileId(str(self.Platform.MetaFile)))
965 FvPath = os.path.join(self.BuildDir, "FV")
966 if not os.path.exists(FvPath):
967 try:
968 os.makedirs(FvPath)
969 except:
970 EdkLogger.error("build", FILE_WRITE_FAILURE, "Fail to create FV folder under %s" % self.BuildDir)
971
972
973 VpdFilePath = os.path.join(FvPath, "%s.txt" % self.Platform.VpdToolGuid)
974
975
976 if not os.path.exists(VpdFilePath) or os.path.getmtime(VpdFilePath) < DscTimeStamp:
977 VpdFile.Write(VpdFilePath)
978
979 # retrieve BPDG tool's path from tool_def.txt according to VPD_TOOL_GUID defined in DSC file.
980 BPDGToolName = None
981 for ToolDef in self.ToolDefinition.values():
982 if ToolDef.has_key("GUID") and ToolDef["GUID"] == self.Platform.VpdToolGuid:
983 if not ToolDef.has_key("PATH"):
984 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE, "PATH attribute was not provided for BPDG guid tool %s in tools_def.txt" % self.Platform.VpdToolGuid)
985 BPDGToolName = ToolDef["PATH"]
986 break
987 # Call third party GUID BPDG tool.
988 if BPDGToolName != None:
989 VpdInfoFile.CallExtenalBPDGTool(BPDGToolName, VpdFilePath)
990 else:
991 EdkLogger.error("Build", FILE_NOT_FOUND, "Fail to find third-party BPDG tool to process VPD PCDs. BPDG Guid tool need to be defined in tools_def.txt and VPD_TOOL_GUID need to be provided in DSC file.")
992
993 # Process VPD map file generated by third party BPDG tool
994 if NeedProcessVpdMapFile:
995 VpdMapFilePath = os.path.join(self.BuildDir, "FV", "%s.map" % self.Platform.VpdToolGuid)
996 if os.path.exists(VpdMapFilePath):
997 VpdFile.Read(VpdMapFilePath)
998
999 # Fixup "*" offset
1000 for Pcd in self._DynamicPcdList:
1001 # just pick the a value to determine whether is unicode string type
1002 Sku = Pcd.SkuInfoList[Pcd.SkuInfoList.keys()[0]]
1003 if Sku.VpdOffset == "*":
1004 Sku.VpdOffset = VpdFile.GetOffset(Pcd)[0]
1005 else:
1006 EdkLogger.error("build", FILE_READ_FAILURE, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath)
1007
1008 # Delete the DynamicPcdList At the last time enter into this function
1009 del self._DynamicPcdList[:]
1010 self._DynamicPcdList.extend(UnicodePcdArray)
1011 self._DynamicPcdList.extend(HiiPcdArray)
1012 self._DynamicPcdList.extend(OtherPcdArray)
1013
1014
1015 ## Return the platform build data object
1016 def _GetPlatform(self):
1017 if self._Platform == None:
1018 self._Platform = self.BuildDatabase[self.MetaFile, self.Arch, self.BuildTarget, self.ToolChain]
1019 return self._Platform
1020
1021 ## Return platform name
1022 def _GetName(self):
1023 return self.Platform.PlatformName
1024
1025 ## Return the meta file GUID
1026 def _GetGuid(self):
1027 return self.Platform.Guid
1028
1029 ## Return the platform version
1030 def _GetVersion(self):
1031 return self.Platform.Version
1032
1033 ## Return the FDF file name
1034 def _GetFdfFile(self):
1035 if self._FdfFile == None:
1036 if self.Workspace.FdfFile != "":
1037 self._FdfFile= path.join(self.WorkspaceDir, self.Workspace.FdfFile)
1038 else:
1039 self._FdfFile = ''
1040 return self._FdfFile
1041
1042 ## Return the build output directory platform specifies
1043 def _GetOutputDir(self):
1044 return self.Platform.OutputDirectory
1045
1046 ## Return the directory to store all intermediate and final files built
1047 def _GetBuildDir(self):
1048 if self._BuildDir == None:
1049 if os.path.isabs(self.OutputDir):
1050 self._BuildDir = path.join(
1051 path.abspath(self.OutputDir),
1052 self.BuildTarget + "_" + self.ToolChain,
1053 )
1054 else:
1055 self._BuildDir = path.join(
1056 self.WorkspaceDir,
1057 self.OutputDir,
1058 self.BuildTarget + "_" + self.ToolChain,
1059 )
1060 return self._BuildDir
1061
1062 ## Return directory of platform makefile
1063 #
1064 # @retval string Makefile directory
1065 #
1066 def _GetMakeFileDir(self):
1067 if self._MakeFileDir == None:
1068 self._MakeFileDir = path.join(self.BuildDir, self.Arch)
1069 return self._MakeFileDir
1070
1071 ## Return build command string
1072 #
1073 # @retval string Build command string
1074 #
1075 def _GetBuildCommand(self):
1076 if self._BuildCommand == None:
1077 self._BuildCommand = []
1078 if "MAKE" in self.ToolDefinition and "PATH" in self.ToolDefinition["MAKE"]:
1079 self._BuildCommand += SplitOption(self.ToolDefinition["MAKE"]["PATH"])
1080 if "FLAGS" in self.ToolDefinition["MAKE"]:
1081 NewOption = self.ToolDefinition["MAKE"]["FLAGS"].strip()
1082 if NewOption != '':
1083 self._BuildCommand += SplitOption(NewOption)
1084 return self._BuildCommand
1085
1086 ## Get tool chain definition
1087 #
1088 # Get each tool defition for given tool chain from tools_def.txt and platform
1089 #
1090 def _GetToolDefinition(self):
1091 if self._ToolDefinitions == None:
1092 ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDictionary
1093 if TAB_TOD_DEFINES_COMMAND_TYPE not in self.Workspace.ToolDef.ToolsDefTxtDatabase:
1094 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "No tools found in configuration",
1095 ExtraData="[%s]" % self.MetaFile)
1096 self._ToolDefinitions = {}
1097 DllPathList = set()
1098 for Def in ToolDefinition:
1099 Target, Tag, Arch, Tool, Attr = Def.split("_")
1100 if Target != self.BuildTarget or Tag != self.ToolChain or Arch != self.Arch:
1101 continue
1102
1103 Value = ToolDefinition[Def]
1104 # don't record the DLL
1105 if Attr == "DLL":
1106 DllPathList.add(Value)
1107 continue
1108
1109 if Tool not in self._ToolDefinitions:
1110 self._ToolDefinitions[Tool] = {}
1111 self._ToolDefinitions[Tool][Attr] = Value
1112
1113 ToolsDef = ''
1114 MakePath = ''
1115 if GlobalData.gOptions.SilentMode and "MAKE" in self._ToolDefinitions:
1116 if "FLAGS" not in self._ToolDefinitions["MAKE"]:
1117 self._ToolDefinitions["MAKE"]["FLAGS"] = ""
1118 self._ToolDefinitions["MAKE"]["FLAGS"] += " -s"
1119 MakeFlags = ''
1120 for Tool in self._ToolDefinitions:
1121 for Attr in self._ToolDefinitions[Tool]:
1122 Value = self._ToolDefinitions[Tool][Attr]
1123 if Tool in self.BuildOption and Attr in self.BuildOption[Tool]:
1124 # check if override is indicated
1125 if self.BuildOption[Tool][Attr].startswith('='):
1126 Value = self.BuildOption[Tool][Attr][1:]
1127 else:
1128 Value += " " + self.BuildOption[Tool][Attr]
1129
1130 if Attr == "PATH":
1131 # Don't put MAKE definition in the file
1132 if Tool == "MAKE":
1133 MakePath = Value
1134 else:
1135 ToolsDef += "%s = %s\n" % (Tool, Value)
1136 elif Attr != "DLL":
1137 # Don't put MAKE definition in the file
1138 if Tool == "MAKE":
1139 if Attr == "FLAGS":
1140 MakeFlags = Value
1141 else:
1142 ToolsDef += "%s_%s = %s\n" % (Tool, Attr, Value)
1143 ToolsDef += "\n"
1144
1145 SaveFileOnChange(self.ToolDefinitionFile, ToolsDef)
1146 for DllPath in DllPathList:
1147 os.environ["PATH"] = DllPath + os.pathsep + os.environ["PATH"]
1148 os.environ["MAKE_FLAGS"] = MakeFlags
1149
1150 return self._ToolDefinitions
1151
1152 ## Return the paths of tools
1153 def _GetToolDefFile(self):
1154 if self._ToolDefFile == None:
1155 self._ToolDefFile = os.path.join(self.MakeFileDir, "TOOLS_DEF." + self.Arch)
1156 return self._ToolDefFile
1157
1158 ## Retrieve the toolchain family of given toolchain tag. Default to 'MSFT'.
1159 def _GetToolChainFamily(self):
1160 if self._ToolChainFamily == None:
1161 ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDatabase
1162 if TAB_TOD_DEFINES_FAMILY not in ToolDefinition \
1163 or self.ToolChain not in ToolDefinition[TAB_TOD_DEFINES_FAMILY] \
1164 or not ToolDefinition[TAB_TOD_DEFINES_FAMILY][self.ToolChain]:
1165 EdkLogger.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
1166 % self.ToolChain)
1167 self._ToolChainFamily = "MSFT"
1168 else:
1169 self._ToolChainFamily = ToolDefinition[TAB_TOD_DEFINES_FAMILY][self.ToolChain]
1170 return self._ToolChainFamily
1171
1172 def _GetBuildRuleFamily(self):
1173 if self._BuildRuleFamily == None:
1174 ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDatabase
1175 if TAB_TOD_DEFINES_BUILDRULEFAMILY not in ToolDefinition \
1176 or self.ToolChain not in ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY] \
1177 or not ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY][self.ToolChain]:
1178 EdkLogger.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
1179 % self.ToolChain)
1180 self._BuildRuleFamily = "MSFT"
1181 else:
1182 self._BuildRuleFamily = ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY][self.ToolChain]
1183 return self._BuildRuleFamily
1184
1185 ## Return the build options specific for all modules in this platform
1186 def _GetBuildOptions(self):
1187 if self._BuildOption == None:
1188 self._BuildOption = self._ExpandBuildOption(self.Platform.BuildOptions)
1189 return self._BuildOption
1190
1191 ## Return the build options specific for EDK modules in this platform
1192 def _GetEdkBuildOptions(self):
1193 if self._EdkBuildOption == None:
1194 self._EdkBuildOption = self._ExpandBuildOption(self.Platform.BuildOptions, EDK_NAME)
1195 return self._EdkBuildOption
1196
1197 ## Return the build options specific for EDKII modules in this platform
1198 def _GetEdkIIBuildOptions(self):
1199 if self._EdkIIBuildOption == None:
1200 self._EdkIIBuildOption = self._ExpandBuildOption(self.Platform.BuildOptions, EDKII_NAME)
1201 return self._EdkIIBuildOption
1202
1203 ## Parse build_rule.txt in $(WORKSPACE)/Conf/build_rule.txt
1204 #
1205 # @retval BuildRule object
1206 #
1207 def _GetBuildRule(self):
1208 if self._BuildRule == None:
1209 BuildRuleFile = None
1210 if TAB_TAT_DEFINES_BUILD_RULE_CONF in self.Workspace.TargetTxt.TargetTxtDictionary:
1211 BuildRuleFile = self.Workspace.TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_BUILD_RULE_CONF]
1212 if BuildRuleFile in [None, '']:
1213 BuildRuleFile = gBuildRuleFile
1214 self._BuildRule = BuildRule(BuildRuleFile)
1215 return self._BuildRule
1216
1217 ## Summarize the packages used by modules in this platform
1218 def _GetPackageList(self):
1219 if self._PackageList == None:
1220 self._PackageList = set()
1221 for La in self.LibraryAutoGenList:
1222 self._PackageList.update(La.DependentPackageList)
1223 for Ma in self.ModuleAutoGenList:
1224 self._PackageList.update(Ma.DependentPackageList)
1225 self._PackageList = list(self._PackageList)
1226 return self._PackageList
1227
1228 ## Get list of non-dynamic PCDs
1229 def _GetNonDynamicPcdList(self):
1230 if self._NonDynamicPcdList == None:
1231 self.CollectPlatformDynamicPcds()
1232 return self._NonDynamicPcdList
1233
1234 ## Get list of dynamic PCDs
1235 def _GetDynamicPcdList(self):
1236 if self._DynamicPcdList == None:
1237 self.CollectPlatformDynamicPcds()
1238 return self._DynamicPcdList
1239
1240 ## Generate Token Number for all PCD
1241 def _GetPcdTokenNumbers(self):
1242 if self._PcdTokenNumber == None:
1243 self._PcdTokenNumber = sdict()
1244 TokenNumber = 1
1245 for Pcd in self.DynamicPcdList:
1246 if Pcd.Phase == "PEI":
1247 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))
1248 self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
1249 TokenNumber += 1
1250
1251 for Pcd in self.DynamicPcdList:
1252 if Pcd.Phase == "DXE":
1253 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))
1254 self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
1255 TokenNumber += 1
1256
1257 for Pcd in self.NonDynamicPcdList:
1258 self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
1259 TokenNumber += 1
1260 return self._PcdTokenNumber
1261
1262 ## Summarize ModuleAutoGen objects of all modules/libraries to be built for this platform
1263 def _GetAutoGenObjectList(self):
1264 self._ModuleAutoGenList = []
1265 self._LibraryAutoGenList = []
1266 for ModuleFile in self.Platform.Modules:
1267 Ma = ModuleAutoGen(
1268 self.Workspace,
1269 ModuleFile,
1270 self.BuildTarget,
1271 self.ToolChain,
1272 self.Arch,
1273 self.MetaFile
1274 )
1275 if Ma not in self._ModuleAutoGenList:
1276 self._ModuleAutoGenList.append(Ma)
1277 for La in Ma.LibraryAutoGenList:
1278 if La not in self._LibraryAutoGenList:
1279 self._LibraryAutoGenList.append(La)
1280
1281 ## Summarize ModuleAutoGen objects of all modules to be built for this platform
1282 def _GetModuleAutoGenList(self):
1283 if self._ModuleAutoGenList == None:
1284 self._GetAutoGenObjectList()
1285 return self._ModuleAutoGenList
1286
1287 ## Summarize ModuleAutoGen objects of all libraries to be built for this platform
1288 def _GetLibraryAutoGenList(self):
1289 if self._LibraryAutoGenList == None:
1290 self._GetAutoGenObjectList()
1291 return self._LibraryAutoGenList
1292
1293 ## Test if a module is supported by the platform
1294 #
1295 # An error will be raised directly if the module or its arch is not supported
1296 # by the platform or current configuration
1297 #
1298 def ValidModule(self, Module):
1299 return Module in self.Platform.Modules or Module in self.Platform.LibraryInstances
1300
1301 ## Resolve the library classes in a module to library instances
1302 #
1303 # This method will not only resolve library classes but also sort the library
1304 # instances according to the dependency-ship.
1305 #
1306 # @param Module The module from which the library classes will be resolved
1307 #
1308 # @retval library_list List of library instances sorted
1309 #
1310 def ApplyLibraryInstance(self, Module):
1311 ModuleType = Module.ModuleType
1312
1313 # for overridding library instances with module specific setting
1314 PlatformModule = self.Platform.Modules[str(Module)]
1315
1316 # add forced library instances (specified under LibraryClasses sections)
1317 #
1318 # If a module has a MODULE_TYPE of USER_DEFINED,
1319 # do not link in NULL library class instances from the global [LibraryClasses.*] sections.
1320 #
1321 if Module.ModuleType != SUP_MODULE_USER_DEFINED:
1322 for LibraryClass in self.Platform.LibraryClasses.GetKeys():
1323 if LibraryClass.startswith("NULL") and self.Platform.LibraryClasses[LibraryClass, Module.ModuleType]:
1324 Module.LibraryClasses[LibraryClass] = self.Platform.LibraryClasses[LibraryClass, Module.ModuleType]
1325
1326 # add forced library instances (specified in module overrides)
1327 for LibraryClass in PlatformModule.LibraryClasses:
1328 if LibraryClass.startswith("NULL"):
1329 Module.LibraryClasses[LibraryClass] = PlatformModule.LibraryClasses[LibraryClass]
1330
1331 # EdkII module
1332 LibraryConsumerList = [Module]
1333 Constructor = []
1334 ConsumedByList = sdict()
1335 LibraryInstance = sdict()
1336
1337 EdkLogger.verbose("")
1338 EdkLogger.verbose("Library instances of module [%s] [%s]:" % (str(Module), self.Arch))
1339 while len(LibraryConsumerList) > 0:
1340 M = LibraryConsumerList.pop()
1341 for LibraryClassName in M.LibraryClasses:
1342 if LibraryClassName not in LibraryInstance:
1343 # override library instance for this module
1344 if LibraryClassName in PlatformModule.LibraryClasses:
1345 LibraryPath = PlatformModule.LibraryClasses[LibraryClassName]
1346 else:
1347 LibraryPath = self.Platform.LibraryClasses[LibraryClassName, ModuleType]
1348 if LibraryPath == None or LibraryPath == "":
1349 LibraryPath = M.LibraryClasses[LibraryClassName]
1350 if LibraryPath == None or LibraryPath == "":
1351 EdkLogger.error("build", RESOURCE_NOT_AVAILABLE,
1352 "Instance of library class [%s] is not found" % LibraryClassName,
1353 File=self.MetaFile,
1354 ExtraData="in [%s] [%s]\n\tconsumed by module [%s]" % (str(M), self.Arch, str(Module)))
1355
1356 LibraryModule = self.BuildDatabase[LibraryPath, self.Arch, self.BuildTarget, self.ToolChain]
1357 # for those forced library instance (NULL library), add a fake library class
1358 if LibraryClassName.startswith("NULL"):
1359 LibraryModule.LibraryClass.append(LibraryClassObject(LibraryClassName, [ModuleType]))
1360 elif LibraryModule.LibraryClass == None \
1361 or len(LibraryModule.LibraryClass) == 0 \
1362 or (ModuleType != 'USER_DEFINED'
1363 and ModuleType not in LibraryModule.LibraryClass[0].SupModList):
1364 # only USER_DEFINED can link against any library instance despite of its SupModList
1365 EdkLogger.error("build", OPTION_MISSING,
1366 "Module type [%s] is not supported by library instance [%s]" \
1367 % (ModuleType, LibraryPath), File=self.MetaFile,
1368 ExtraData="consumed by [%s]" % str(Module))
1369
1370 LibraryInstance[LibraryClassName] = LibraryModule
1371 LibraryConsumerList.append(LibraryModule)
1372 EdkLogger.verbose("\t" + str(LibraryClassName) + " : " + str(LibraryModule))
1373 else:
1374 LibraryModule = LibraryInstance[LibraryClassName]
1375
1376 if LibraryModule == None:
1377 continue
1378
1379 if LibraryModule.ConstructorList != [] and LibraryModule not in Constructor:
1380 Constructor.append(LibraryModule)
1381
1382 if LibraryModule not in ConsumedByList:
1383 ConsumedByList[LibraryModule] = []
1384 # don't add current module itself to consumer list
1385 if M != Module:
1386 if M in ConsumedByList[LibraryModule]:
1387 continue
1388 ConsumedByList[LibraryModule].append(M)
1389 #
1390 # Initialize the sorted output list to the empty set
1391 #
1392 SortedLibraryList = []
1393 #
1394 # Q <- Set of all nodes with no incoming edges
1395 #
1396 LibraryList = [] #LibraryInstance.values()
1397 Q = []
1398 for LibraryClassName in LibraryInstance:
1399 M = LibraryInstance[LibraryClassName]
1400 LibraryList.append(M)
1401 if ConsumedByList[M] == []:
1402 Q.append(M)
1403
1404 #
1405 # start the DAG algorithm
1406 #
1407 while True:
1408 EdgeRemoved = True
1409 while Q == [] and EdgeRemoved:
1410 EdgeRemoved = False
1411 # for each node Item with a Constructor
1412 for Item in LibraryList:
1413 if Item not in Constructor:
1414 continue
1415 # for each Node without a constructor with an edge e from Item to Node
1416 for Node in ConsumedByList[Item]:
1417 if Node in Constructor:
1418 continue
1419 # remove edge e from the graph if Node has no constructor
1420 ConsumedByList[Item].remove(Node)
1421 EdgeRemoved = True
1422 if ConsumedByList[Item] == []:
1423 # insert Item into Q
1424 Q.insert(0, Item)
1425 break
1426 if Q != []:
1427 break
1428 # DAG is done if there's no more incoming edge for all nodes
1429 if Q == []:
1430 break
1431
1432 # remove node from Q
1433 Node = Q.pop()
1434 # output Node
1435 SortedLibraryList.append(Node)
1436
1437 # for each node Item with an edge e from Node to Item do
1438 for Item in LibraryList:
1439 if Node not in ConsumedByList[Item]:
1440 continue
1441 # remove edge e from the graph
1442 ConsumedByList[Item].remove(Node)
1443
1444 if ConsumedByList[Item] != []:
1445 continue
1446 # insert Item into Q, if Item has no other incoming edges
1447 Q.insert(0, Item)
1448
1449 #
1450 # if any remaining node Item in the graph has a constructor and an incoming edge, then the graph has a cycle
1451 #
1452 for Item in LibraryList:
1453 if ConsumedByList[Item] != [] and Item in Constructor and len(Constructor) > 1:
1454 ErrorMessage = "\tconsumed by " + "\n\tconsumed by ".join([str(L) for L in ConsumedByList[Item]])
1455 EdkLogger.error("build", BUILD_ERROR, 'Library [%s] with constructors has a cycle' % str(Item),
1456 ExtraData=ErrorMessage, File=self.MetaFile)
1457 if Item not in SortedLibraryList:
1458 SortedLibraryList.append(Item)
1459
1460 #
1461 # Build the list of constructor and destructir names
1462 # The DAG Topo sort produces the destructor order, so the list of constructors must generated in the reverse order
1463 #
1464 SortedLibraryList.reverse()
1465 return SortedLibraryList
1466
1467
1468 ## Override PCD setting (type, value, ...)
1469 #
1470 # @param ToPcd The PCD to be overrided
1471 # @param FromPcd The PCD overrideing from
1472 #
1473 def _OverridePcd(self, ToPcd, FromPcd, Module=""):
1474 #
1475 # in case there's PCDs coming from FDF file, which have no type given.
1476 # at this point, ToPcd.Type has the type found from dependent
1477 # package
1478 #
1479 if FromPcd != None:
1480 if ToPcd.Pending and FromPcd.Type not in [None, '']:
1481 ToPcd.Type = FromPcd.Type
1482 elif (ToPcd.Type not in [None, '']) and (FromPcd.Type not in [None, ''])\
1483 and (ToPcd.Type != FromPcd.Type) and (ToPcd.Type in FromPcd.Type):
1484 if ToPcd.Type.strip() == "DynamicEx":
1485 ToPcd.Type = FromPcd.Type
1486 elif ToPcd.Type not in [None, ''] and FromPcd.Type not in [None, ''] \
1487 and ToPcd.Type != FromPcd.Type:
1488 EdkLogger.error("build", OPTION_CONFLICT, "Mismatched PCD type",
1489 ExtraData="%s.%s is defined as [%s] in module %s, but as [%s] in platform."\
1490 % (ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName,
1491 ToPcd.Type, Module, FromPcd.Type),
1492 File=self.MetaFile)
1493
1494 if FromPcd.MaxDatumSize not in [None, '']:
1495 ToPcd.MaxDatumSize = FromPcd.MaxDatumSize
1496 if FromPcd.DefaultValue not in [None, '']:
1497 ToPcd.DefaultValue = FromPcd.DefaultValue
1498 if FromPcd.TokenValue not in [None, '']:
1499 ToPcd.TokenValue = FromPcd.TokenValue
1500 if FromPcd.MaxDatumSize not in [None, '']:
1501 ToPcd.MaxDatumSize = FromPcd.MaxDatumSize
1502 if FromPcd.DatumType not in [None, '']:
1503 ToPcd.DatumType = FromPcd.DatumType
1504 if FromPcd.SkuInfoList not in [None, '', []]:
1505 ToPcd.SkuInfoList = FromPcd.SkuInfoList
1506
1507 # check the validation of datum
1508 IsValid, Cause = CheckPcdDatum(ToPcd.DatumType, ToPcd.DefaultValue)
1509 if not IsValid:
1510 EdkLogger.error('build', FORMAT_INVALID, Cause, File=self.MetaFile,
1511 ExtraData="%s.%s" % (ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName))
1512
1513 if ToPcd.DatumType == "VOID*" and ToPcd.MaxDatumSize in ['', None]:
1514 EdkLogger.debug(EdkLogger.DEBUG_9, "No MaxDatumSize specified for PCD %s.%s" \
1515 % (ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName))
1516 Value = ToPcd.DefaultValue
1517 if Value in [None, '']:
1518 ToPcd.MaxDatumSize = 1
1519 elif Value[0] == 'L':
1520 ToPcd.MaxDatumSize = str(len(Value) * 2)
1521 elif Value[0] == '{':
1522 ToPcd.MaxDatumSize = str(len(Value.split(',')))
1523 else:
1524 ToPcd.MaxDatumSize = str(len(Value))
1525
1526 # apply default SKU for dynamic PCDS if specified one is not available
1527 if (ToPcd.Type in PCD_DYNAMIC_TYPE_LIST or ToPcd.Type in PCD_DYNAMIC_EX_TYPE_LIST) \
1528 and ToPcd.SkuInfoList in [None, {}, '']:
1529 if self.Platform.SkuName in self.Platform.SkuIds:
1530 SkuName = self.Platform.SkuName
1531 else:
1532 SkuName = 'DEFAULT'
1533 ToPcd.SkuInfoList = {
1534 SkuName : SkuInfoClass(SkuName, self.Platform.SkuIds[SkuName], '', '', '', '', '', ToPcd.DefaultValue)
1535 }
1536
1537 ## Apply PCD setting defined platform to a module
1538 #
1539 # @param Module The module from which the PCD setting will be overrided
1540 #
1541 # @retval PCD_list The list PCDs with settings from platform
1542 #
1543 def ApplyPcdSetting(self, Module, Pcds):
1544 # for each PCD in module
1545 for Name,Guid in Pcds:
1546 PcdInModule = Pcds[Name,Guid]
1547 # find out the PCD setting in platform
1548 if (Name,Guid) in self.Platform.Pcds:
1549 PcdInPlatform = self.Platform.Pcds[Name,Guid]
1550 else:
1551 PcdInPlatform = None
1552 # then override the settings if any
1553 self._OverridePcd(PcdInModule, PcdInPlatform, Module)
1554 # resolve the VariableGuid value
1555 for SkuId in PcdInModule.SkuInfoList:
1556 Sku = PcdInModule.SkuInfoList[SkuId]
1557 if Sku.VariableGuid == '': continue
1558 Sku.VariableGuidValue = GuidValue(Sku.VariableGuid, self.PackageList)
1559 if Sku.VariableGuidValue == None:
1560 PackageList = "\n\t".join([str(P) for P in self.PackageList])
1561 EdkLogger.error(
1562 'build',
1563 RESOURCE_NOT_AVAILABLE,
1564 "Value of GUID [%s] is not found in" % Sku.VariableGuid,
1565 ExtraData=PackageList + "\n\t(used with %s.%s from module %s)" \
1566 % (Guid, Name, str(Module)),
1567 File=self.MetaFile
1568 )
1569
1570 # override PCD settings with module specific setting
1571 if Module in self.Platform.Modules:
1572 PlatformModule = self.Platform.Modules[str(Module)]
1573 for Key in PlatformModule.Pcds:
1574 if Key in Pcds:
1575 self._OverridePcd(Pcds[Key], PlatformModule.Pcds[Key], Module)
1576 return Pcds.values()
1577
1578 ## Resolve library names to library modules
1579 #
1580 # (for Edk.x modules)
1581 #
1582 # @param Module The module from which the library names will be resolved
1583 #
1584 # @retval library_list The list of library modules
1585 #
1586 def ResolveLibraryReference(self, Module):
1587 EdkLogger.verbose("")
1588 EdkLogger.verbose("Library instances of module [%s] [%s]:" % (str(Module), self.Arch))
1589 LibraryConsumerList = [Module]
1590
1591 # "CompilerStub" is a must for Edk modules
1592 if Module.Libraries:
1593 Module.Libraries.append("CompilerStub")
1594 LibraryList = []
1595 while len(LibraryConsumerList) > 0:
1596 M = LibraryConsumerList.pop()
1597 for LibraryName in M.Libraries:
1598 Library = self.Platform.LibraryClasses[LibraryName, ':dummy:']
1599 if Library == None:
1600 for Key in self.Platform.LibraryClasses.data.keys():
1601 if LibraryName.upper() == Key.upper():
1602 Library = self.Platform.LibraryClasses[Key, ':dummy:']
1603 break
1604 if Library == None:
1605 EdkLogger.warn("build", "Library [%s] is not found" % LibraryName, File=str(M),
1606 ExtraData="\t%s [%s]" % (str(Module), self.Arch))
1607 continue
1608
1609 if Library not in LibraryList:
1610 LibraryList.append(Library)
1611 LibraryConsumerList.append(Library)
1612 EdkLogger.verbose("\t" + LibraryName + " : " + str(Library) + ' ' + str(type(Library)))
1613 return LibraryList
1614
1615 ## Calculate the priority value of the build option
1616 #
1617 # @param Key Build option definition contain: TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
1618 #
1619 # @retval Value Priority value based on the priority list.
1620 #
1621 def CalculatePriorityValue(self, Key):
1622 Target, ToolChain, Arch, CommandType, Attr = Key.split('_')
1623 PriorityValue = 0x11111
1624 if Target == "*":
1625 PriorityValue &= 0x01111
1626 if ToolChain == "*":
1627 PriorityValue &= 0x10111
1628 if Arch == "*":
1629 PriorityValue &= 0x11011
1630 if CommandType == "*":
1631 PriorityValue &= 0x11101
1632 if Attr == "*":
1633 PriorityValue &= 0x11110
1634
1635 return self.PrioList["0x%0.5x"%PriorityValue]
1636
1637
1638 ## Expand * in build option key
1639 #
1640 # @param Options Options to be expanded
1641 #
1642 # @retval options Options expanded
1643 #
1644 def _ExpandBuildOption(self, Options, ModuleStyle=None):
1645 BuildOptions = {}
1646 FamilyMatch = False
1647 FamilyIsNull = True
1648
1649 OverrideList = {}
1650 #
1651 # Construct a list contain the build options which need override.
1652 #
1653 for Key in Options:
1654 #
1655 # Key[0] -- tool family
1656 # Key[1] -- TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
1657 #
1658 if Key[0] == self.BuildRuleFamily :
1659 Target, ToolChain, Arch, CommandType, Attr = Key[1].split('_')
1660 if Target == self.BuildTarget or Target == "*":
1661 if ToolChain == self.ToolChain or ToolChain == "*":
1662 if Arch == self.Arch or Arch == "*":
1663 if Options[Key].startswith("="):
1664 if OverrideList.get(Key[1]) != None:
1665 OverrideList.pop(Key[1])
1666 OverrideList[Key[1]] = Options[Key]
1667
1668 #
1669 # Use the highest priority value.
1670 #
1671 if (len(OverrideList) >= 2):
1672 KeyList = OverrideList.keys()
1673 for Index in range(len(KeyList)):
1674 NowKey = KeyList[Index]
1675 Target1, ToolChain1, Arch1, CommandType1, Attr1 = NowKey.split("_")
1676 for Index1 in range(len(KeyList) - Index - 1):
1677 NextKey = KeyList[Index1 + Index + 1]
1678 #
1679 # Compare two Key, if one is included by another, choose the higher priority one
1680 #
1681 Target2, ToolChain2, Arch2, CommandType2, Attr2 = NextKey.split("_")
1682 if Target1 == Target2 or Target1 == "*" or Target2 == "*":
1683 if ToolChain1 == ToolChain2 or ToolChain1 == "*" or ToolChain2 == "*":
1684 if Arch1 == Arch2 or Arch1 == "*" or Arch2 == "*":
1685 if CommandType1 == CommandType2 or CommandType1 == "*" or CommandType2 == "*":
1686 if Attr1 == Attr2 or Attr1 == "*" or Attr2 == "*":
1687 if self.CalculatePriorityValue(NowKey) > self.CalculatePriorityValue(NextKey):
1688 if Options.get((self.BuildRuleFamily, NextKey)) != None:
1689 Options.pop((self.BuildRuleFamily, NextKey))
1690 else:
1691 if Options.get((self.BuildRuleFamily, NowKey)) != None:
1692 Options.pop((self.BuildRuleFamily, NowKey))
1693
1694
1695 for Key in Options:
1696 if ModuleStyle != None and len (Key) > 2:
1697 # Check Module style is EDK or EDKII.
1698 # Only append build option for the matched style module.
1699 if ModuleStyle == EDK_NAME and Key[2] != EDK_NAME:
1700 continue
1701 elif ModuleStyle == EDKII_NAME and Key[2] != EDKII_NAME:
1702 continue
1703 Family = Key[0]
1704 Target, Tag, Arch, Tool, Attr = Key[1].split("_")
1705 # if tool chain family doesn't match, skip it
1706 if Tool in self.ToolDefinition and Family != "":
1707 FamilyIsNull = False
1708 if self.ToolDefinition[Tool].get(TAB_TOD_DEFINES_BUILDRULEFAMILY, "") != "":
1709 if Family != self.ToolDefinition[Tool][TAB_TOD_DEFINES_BUILDRULEFAMILY]:
1710 continue
1711 elif Family != self.ToolDefinition[Tool][TAB_TOD_DEFINES_FAMILY]:
1712 continue
1713 FamilyMatch = True
1714 # expand any wildcard
1715 if Target == "*" or Target == self.BuildTarget:
1716 if Tag == "*" or Tag == self.ToolChain:
1717 if Arch == "*" or Arch == self.Arch:
1718 if Tool not in BuildOptions:
1719 BuildOptions[Tool] = {}
1720 if Attr != "FLAGS" or Attr not in BuildOptions[Tool]:
1721 BuildOptions[Tool][Attr] = Options[Key]
1722 else:
1723 # append options for the same tool
1724 BuildOptions[Tool][Attr] += " " + Options[Key]
1725 # Build Option Family has been checked, which need't to be checked again for family.
1726 if FamilyMatch or FamilyIsNull:
1727 return BuildOptions
1728
1729 for Key in Options:
1730 if ModuleStyle != None and len (Key) > 2:
1731 # Check Module style is EDK or EDKII.
1732 # Only append build option for the matched style module.
1733 if ModuleStyle == EDK_NAME and Key[2] != EDK_NAME:
1734 continue
1735 elif ModuleStyle == EDKII_NAME and Key[2] != EDKII_NAME:
1736 continue
1737 Family = Key[0]
1738 Target, Tag, Arch, Tool, Attr = Key[1].split("_")
1739 # if tool chain family doesn't match, skip it
1740 if Tool not in self.ToolDefinition or Family =="":
1741 continue
1742 # option has been added before
1743 if Family != self.ToolDefinition[Tool][TAB_TOD_DEFINES_FAMILY]:
1744 continue
1745
1746 # expand any wildcard
1747 if Target == "*" or Target == self.BuildTarget:
1748 if Tag == "*" or Tag == self.ToolChain:
1749 if Arch == "*" or Arch == self.Arch:
1750 if Tool not in BuildOptions:
1751 BuildOptions[Tool] = {}
1752 if Attr != "FLAGS" or Attr not in BuildOptions[Tool]:
1753 BuildOptions[Tool][Attr] = Options[Key]
1754 else:
1755 # append options for the same tool
1756 BuildOptions[Tool][Attr] += " " + Options[Key]
1757 return BuildOptions
1758
1759 ## Append build options in platform to a module
1760 #
1761 # @param Module The module to which the build options will be appened
1762 #
1763 # @retval options The options appended with build options in platform
1764 #
1765 def ApplyBuildOption(self, Module):
1766 # Get the different options for the different style module
1767 if Module.AutoGenVersion < 0x00010005:
1768 PlatformOptions = self.EdkBuildOption
1769 else:
1770 PlatformOptions = self.EdkIIBuildOption
1771 ModuleOptions = self._ExpandBuildOption(Module.BuildOptions)
1772 if Module in self.Platform.Modules:
1773 PlatformModule = self.Platform.Modules[str(Module)]
1774 PlatformModuleOptions = self._ExpandBuildOption(PlatformModule.BuildOptions)
1775 else:
1776 PlatformModuleOptions = {}
1777
1778 AllTools = set(ModuleOptions.keys() + PlatformOptions.keys() + PlatformModuleOptions.keys() + self.ToolDefinition.keys())
1779 BuildOptions = {}
1780 for Tool in AllTools:
1781 if Tool not in BuildOptions:
1782 BuildOptions[Tool] = {}
1783
1784 for Options in [self.ToolDefinition, ModuleOptions, PlatformOptions, PlatformModuleOptions]:
1785 if Tool not in Options:
1786 continue
1787 for Attr in Options[Tool]:
1788 Value = Options[Tool][Attr]
1789 if Attr not in BuildOptions[Tool]:
1790 BuildOptions[Tool][Attr] = ""
1791 # check if override is indicated
1792 if Value.startswith('='):
1793 BuildOptions[Tool][Attr] = Value[1:]
1794 else:
1795 BuildOptions[Tool][Attr] += " " + Value
1796 if Module.AutoGenVersion < 0x00010005 and self.Workspace.UniFlag != None:
1797 #
1798 # Override UNI flag only for EDK module.
1799 #
1800 if 'BUILD' not in BuildOptions:
1801 BuildOptions['BUILD'] = {}
1802 BuildOptions['BUILD']['FLAGS'] = self.Workspace.UniFlag
1803 return BuildOptions
1804
1805 Platform = property(_GetPlatform)
1806 Name = property(_GetName)
1807 Guid = property(_GetGuid)
1808 Version = property(_GetVersion)
1809
1810 OutputDir = property(_GetOutputDir)
1811 BuildDir = property(_GetBuildDir)
1812 MakeFileDir = property(_GetMakeFileDir)
1813 FdfFile = property(_GetFdfFile)
1814
1815 PcdTokenNumber = property(_GetPcdTokenNumbers) # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber
1816 DynamicPcdList = property(_GetDynamicPcdList) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
1817 NonDynamicPcdList = property(_GetNonDynamicPcdList) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
1818 PackageList = property(_GetPackageList)
1819
1820 ToolDefinition = property(_GetToolDefinition) # toolcode : tool path
1821 ToolDefinitionFile = property(_GetToolDefFile) # toolcode : lib path
1822 ToolChainFamily = property(_GetToolChainFamily)
1823 BuildRuleFamily = property(_GetBuildRuleFamily)
1824 BuildOption = property(_GetBuildOptions) # toolcode : option
1825 EdkBuildOption = property(_GetEdkBuildOptions) # edktoolcode : option
1826 EdkIIBuildOption = property(_GetEdkIIBuildOptions) # edkiitoolcode : option
1827
1828 BuildCommand = property(_GetBuildCommand)
1829 BuildRule = property(_GetBuildRule)
1830 ModuleAutoGenList = property(_GetModuleAutoGenList)
1831 LibraryAutoGenList = property(_GetLibraryAutoGenList)
1832
1833 ## ModuleAutoGen class
1834 #
1835 # This class encapsules the AutoGen behaviors for the build tools. In addition to
1836 # the generation of AutoGen.h and AutoGen.c, it will generate *.depex file according
1837 # to the [depex] section in module's inf file.
1838 #
1839 class ModuleAutoGen(AutoGen):
1840 ## The real constructor of ModuleAutoGen
1841 #
1842 # This method is not supposed to be called by users of ModuleAutoGen. It's
1843 # only used by factory method __new__() to do real initialization work for an
1844 # object of ModuleAutoGen
1845 #
1846 # @param Workspace EdkIIWorkspaceBuild object
1847 # @param ModuleFile The path of module file
1848 # @param Target Build target (DEBUG, RELEASE)
1849 # @param Toolchain Name of tool chain
1850 # @param Arch The arch the module supports
1851 # @param PlatformFile Platform meta-file
1852 #
1853 def _Init(self, Workspace, ModuleFile, Target, Toolchain, Arch, PlatformFile):
1854 EdkLogger.debug(EdkLogger.DEBUG_9, "AutoGen module [%s] [%s]" % (ModuleFile, Arch))
1855 GlobalData.gProcessingFile = "%s [%s, %s, %s]" % (ModuleFile, Arch, Toolchain, Target)
1856
1857 self.Workspace = Workspace
1858 self.WorkspaceDir = Workspace.WorkspaceDir
1859
1860 self.MetaFile = ModuleFile
1861 self.PlatformInfo = PlatformAutoGen(Workspace, PlatformFile, Target, Toolchain, Arch)
1862 # check if this module is employed by active platform
1863 if not self.PlatformInfo.ValidModule(self.MetaFile):
1864 EdkLogger.verbose("Module [%s] for [%s] is not employed by active platform\n" \
1865 % (self.MetaFile, Arch))
1866 return False
1867
1868 self.SourceDir = self.MetaFile.SubDir
1869 self.SourceOverrideDir = None
1870 # use overrided path defined in DSC file
1871 if self.MetaFile.Key in GlobalData.gOverrideDir:
1872 self.SourceOverrideDir = GlobalData.gOverrideDir[self.MetaFile.Key]
1873
1874 self.ToolChain = Toolchain
1875 self.BuildTarget = Target
1876 self.Arch = Arch
1877 self.ToolChainFamily = self.PlatformInfo.ToolChainFamily
1878 self.BuildRuleFamily = self.PlatformInfo.BuildRuleFamily
1879
1880 self.IsMakeFileCreated = False
1881 self.IsCodeFileCreated = False
1882 self.IsAsBuiltInfCreated = False
1883 self.DepexGenerated = False
1884
1885 self.BuildDatabase = self.Workspace.BuildDatabase
1886
1887 self._Module = None
1888 self._Name = None
1889 self._Guid = None
1890 self._Version = None
1891 self._ModuleType = None
1892 self._ComponentType = None
1893 self._PcdIsDriver = None
1894 self._AutoGenVersion = None
1895 self._LibraryFlag = None
1896 self._CustomMakefile = None
1897 self._Macro = None
1898
1899 self._BuildDir = None
1900 self._OutputDir = None
1901 self._DebugDir = None
1902 self._MakeFileDir = None
1903
1904 self._IncludePathList = None
1905 self._AutoGenFileList = None
1906 self._UnicodeFileList = None
1907 self._SourceFileList = None
1908 self._ObjectFileList = None
1909 self._BinaryFileList = None
1910
1911 self._DependentPackageList = None
1912 self._DependentLibraryList = None
1913 self._LibraryAutoGenList = None
1914 self._DerivedPackageList = None
1915 self._ModulePcdList = None
1916 self._LibraryPcdList = None
1917 self._GuidList = None
1918 self._ProtocolList = None
1919 self._PpiList = None
1920 self._DepexList = None
1921 self._DepexExpressionList = None
1922 self._BuildOption = None
1923 self._BuildOptionIncPathList = None
1924 self._BuildTargets = None
1925 self._IntroBuildTargetList = None
1926 self._FinalBuildTargetList = None
1927 self._FileTypes = None
1928 self._BuildRules = None
1929
1930 return True
1931
1932 def __repr__(self):
1933 return "%s [%s]" % (self.MetaFile, self.Arch)
1934
1935 # Macros could be used in build_rule.txt (also Makefile)
1936 def _GetMacros(self):
1937 if self._Macro == None:
1938 self._Macro = sdict()
1939 self._Macro["WORKSPACE" ] = self.WorkspaceDir
1940 self._Macro["MODULE_NAME" ] = self.Name
1941 self._Macro["MODULE_GUID" ] = self.Guid
1942 self._Macro["MODULE_VERSION" ] = self.Version
1943 self._Macro["MODULE_TYPE" ] = self.ModuleType
1944 self._Macro["MODULE_FILE" ] = str(self.MetaFile)
1945 self._Macro["MODULE_FILE_BASE_NAME" ] = self.MetaFile.BaseName
1946 self._Macro["MODULE_RELATIVE_DIR" ] = self.SourceDir
1947 self._Macro["MODULE_DIR" ] = self.SourceDir
1948
1949 self._Macro["BASE_NAME" ] = self.Name
1950
1951 self._Macro["ARCH" ] = self.Arch
1952 self._Macro["TOOLCHAIN" ] = self.ToolChain
1953 self._Macro["TOOLCHAIN_TAG" ] = self.ToolChain
1954 self._Macro["TOOL_CHAIN_TAG" ] = self.ToolChain
1955 self._Macro["TARGET" ] = self.BuildTarget
1956
1957 self._Macro["BUILD_DIR" ] = self.PlatformInfo.BuildDir
1958 self._Macro["BIN_DIR" ] = os.path.join(self.PlatformInfo.BuildDir, self.Arch)
1959 self._Macro["LIB_DIR" ] = os.path.join(self.PlatformInfo.BuildDir, self.Arch)
1960 self._Macro["MODULE_BUILD_DIR" ] = self.BuildDir
1961 self._Macro["OUTPUT_DIR" ] = self.OutputDir
1962 self._Macro["DEBUG_DIR" ] = self.DebugDir
1963 return self._Macro
1964
1965 ## Return the module build data object
1966 def _GetModule(self):
1967 if self._Module == None:
1968 self._Module = self.Workspace.BuildDatabase[self.MetaFile, self.Arch, self.BuildTarget, self.ToolChain]
1969 return self._Module
1970
1971 ## Return the module name
1972 def _GetBaseName(self):
1973 return self.Module.BaseName
1974
1975 ## Return the module DxsFile if exist
1976 def _GetDxsFile(self):
1977 return self.Module.DxsFile
1978
1979 ## Return the module SourceOverridePath
1980 def _GetSourceOverridePath(self):
1981 return self.Module.SourceOverridePath
1982
1983 ## Return the module meta-file GUID
1984 def _GetGuid(self):
1985 return self.Module.Guid
1986
1987 ## Return the module version
1988 def _GetVersion(self):
1989 return self.Module.Version
1990
1991 ## Return the module type
1992 def _GetModuleType(self):
1993 return self.Module.ModuleType
1994
1995 ## Return the component type (for Edk.x style of module)
1996 def _GetComponentType(self):
1997 return self.Module.ComponentType
1998
1999 ## Return the build type
2000 def _GetBuildType(self):
2001 return self.Module.BuildType
2002
2003 ## Return the PCD_IS_DRIVER setting
2004 def _GetPcdIsDriver(self):
2005 return self.Module.PcdIsDriver
2006
2007 ## Return the autogen version, i.e. module meta-file version
2008 def _GetAutoGenVersion(self):
2009 return self.Module.AutoGenVersion
2010
2011 ## Check if the module is library or not
2012 def _IsLibrary(self):
2013 if self._LibraryFlag == None:
2014 if self.Module.LibraryClass != None and self.Module.LibraryClass != []:
2015 self._LibraryFlag = True
2016 else:
2017 self._LibraryFlag = False
2018 return self._LibraryFlag
2019
2020 ## Return the directory to store intermediate files of the module
2021 def _GetBuildDir(self):
2022 if self._BuildDir == None:
2023 self._BuildDir = path.join(
2024 self.PlatformInfo.BuildDir,
2025 self.Arch,
2026 self.SourceDir,
2027 self.MetaFile.BaseName
2028 )
2029 CreateDirectory(self._BuildDir)
2030 return self._BuildDir
2031
2032 ## Return the directory to store the intermediate object files of the mdoule
2033 def _GetOutputDir(self):
2034 if self._OutputDir == None:
2035 self._OutputDir = path.join(self.BuildDir, "OUTPUT")
2036 CreateDirectory(self._OutputDir)
2037 return self._OutputDir
2038
2039 ## Return the directory to store auto-gened source files of the mdoule
2040 def _GetDebugDir(self):
2041 if self._DebugDir == None:
2042 self._DebugDir = path.join(self.BuildDir, "DEBUG")
2043 CreateDirectory(self._DebugDir)
2044 return self._DebugDir
2045
2046 ## Return the path of custom file
2047 def _GetCustomMakefile(self):
2048 if self._CustomMakefile == None:
2049 self._CustomMakefile = {}
2050 for Type in self.Module.CustomMakefile:
2051 if Type in gMakeTypeMap:
2052 MakeType = gMakeTypeMap[Type]
2053 else:
2054 MakeType = 'nmake'
2055 if self.SourceOverrideDir != None:
2056 File = os.path.join(self.SourceOverrideDir, self.Module.CustomMakefile[Type])
2057 if not os.path.exists(File):
2058 File = os.path.join(self.SourceDir, self.Module.CustomMakefile[Type])
2059 else:
2060 File = os.path.join(self.SourceDir, self.Module.CustomMakefile[Type])
2061 self._CustomMakefile[MakeType] = File
2062 return self._CustomMakefile
2063
2064 ## Return the directory of the makefile
2065 #
2066 # @retval string The directory string of module's makefile
2067 #
2068 def _GetMakeFileDir(self):
2069 return self.BuildDir
2070
2071 ## Return build command string
2072 #
2073 # @retval string Build command string
2074 #
2075 def _GetBuildCommand(self):
2076 return self.PlatformInfo.BuildCommand
2077
2078 ## Get object list of all packages the module and its dependent libraries belong to
2079 #
2080 # @retval list The list of package object
2081 #
2082 def _GetDerivedPackageList(self):
2083 PackageList = []
2084 for M in [self.Module] + self.DependentLibraryList:
2085 for Package in M.Packages:
2086 if Package in PackageList:
2087 continue
2088 PackageList.append(Package)
2089 return PackageList
2090
2091 ## Merge dependency expression
2092 #
2093 # @retval list The token list of the dependency expression after parsed
2094 #
2095 def _GetDepexTokenList(self):
2096 if self._DepexList == None:
2097 self._DepexList = {}
2098 if self.DxsFile or self.IsLibrary or TAB_DEPENDENCY_EXPRESSION_FILE in self.FileTypes:
2099 return self._DepexList
2100
2101 self._DepexList[self.ModuleType] = []
2102
2103 for ModuleType in self._DepexList:
2104 DepexList = self._DepexList[ModuleType]
2105 #
2106 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
2107 #
2108 for M in [self.Module] + self.DependentLibraryList:
2109 Inherited = False
2110 for D in M.Depex[self.Arch, ModuleType]:
2111 if DepexList != []:
2112 DepexList.append('AND')
2113 DepexList.append('(')
2114 DepexList.extend(D)
2115 if DepexList[-1] == 'END': # no need of a END at this time
2116 DepexList.pop()
2117 DepexList.append(')')
2118 Inherited = True
2119 if Inherited:
2120 EdkLogger.verbose("DEPEX[%s] (+%s) = %s" % (self.Name, M.BaseName, DepexList))
2121 if 'BEFORE' in DepexList or 'AFTER' in DepexList:
2122 break
2123 if len(DepexList) > 0:
2124 EdkLogger.verbose('')
2125 return self._DepexList
2126
2127 ## Merge dependency expression
2128 #
2129 # @retval list The token list of the dependency expression after parsed
2130 #
2131 def _GetDepexExpressionTokenList(self):
2132 if self._DepexExpressionList == None:
2133 self._DepexExpressionList = {}
2134 if self.DxsFile or self.IsLibrary or TAB_DEPENDENCY_EXPRESSION_FILE in self.FileTypes:
2135 return self._DepexExpressionList
2136
2137 self._DepexExpressionList[self.ModuleType] = ''
2138
2139 for ModuleType in self._DepexExpressionList:
2140 DepexExpressionList = self._DepexExpressionList[ModuleType]
2141 #
2142 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
2143 #
2144 for M in [self.Module] + self.DependentLibraryList:
2145 Inherited = False
2146 for D in M.DepexExpression[self.Arch, ModuleType]:
2147 if DepexExpressionList != '':
2148 DepexExpressionList += ' AND '
2149 DepexExpressionList += '('
2150 DepexExpressionList += D
2151 DepexExpressionList = DepexExpressionList.rstrip('END').strip()
2152 DepexExpressionList += ')'
2153 Inherited = True
2154 if Inherited:
2155 EdkLogger.verbose("DEPEX[%s] (+%s) = %s" % (self.Name, M.BaseName, DepexExpressionList))
2156 if 'BEFORE' in DepexExpressionList or 'AFTER' in DepexExpressionList:
2157 break
2158 if len(DepexExpressionList) > 0:
2159 EdkLogger.verbose('')
2160 self._DepexExpressionList[ModuleType] = DepexExpressionList
2161 return self._DepexExpressionList
2162
2163 ## Return the list of specification version required for the module
2164 #
2165 # @retval list The list of specification defined in module file
2166 #
2167 def _GetSpecification(self):
2168 return self.Module.Specification
2169
2170 ## Tool option for the module build
2171 #
2172 # @param PlatformInfo The object of PlatformBuildInfo
2173 # @retval dict The dict containing valid options
2174 #
2175 def _GetModuleBuildOption(self):
2176 if self._BuildOption == None:
2177 self._BuildOption = self.PlatformInfo.ApplyBuildOption(self.Module)
2178 return self._BuildOption
2179
2180 ## Get include path list from tool option for the module build
2181 #
2182 # @retval list The include path list
2183 #
2184 def _GetBuildOptionIncPathList(self):
2185 if self._BuildOptionIncPathList == None:
2186 #
2187 # Regular expression for finding Include Directories, the difference between MSFT and INTEL/GCC/RVCT
2188 # is the former use /I , the Latter used -I to specify include directories
2189 #
2190 if self.PlatformInfo.ToolChainFamily in ('MSFT'):
2191 gBuildOptIncludePattern = re.compile(r"(?:.*?)/I[ \t]*([^ ]*)", re.MULTILINE|re.DOTALL)
2192 elif self.PlatformInfo.ToolChainFamily in ('INTEL', 'GCC', 'RVCT'):
2193 gBuildOptIncludePattern = re.compile(r"(?:.*?)-I[ \t]*([^ ]*)", re.MULTILINE|re.DOTALL)
2194 else:
2195 #
2196 # New ToolChainFamily, don't known whether there is option to specify include directories
2197 #
2198 self._BuildOptionIncPathList = []
2199 return self._BuildOptionIncPathList
2200
2201 BuildOptionIncPathList = []
2202 for Tool in ('CC', 'PP', 'VFRPP', 'ASLPP', 'ASLCC', 'APP', 'ASM'):
2203 Attr = 'FLAGS'
2204 try:
2205 FlagOption = self.BuildOption[Tool][Attr]
2206 except KeyError:
2207 FlagOption = ''
2208
2209 if self.PlatformInfo.ToolChainFamily != 'RVCT':
2210 IncPathList = [NormPath(Path, self.Macros) for Path in gBuildOptIncludePattern.findall(FlagOption)]
2211 else:
2212 #
2213 # RVCT may specify a list of directory seperated by commas
2214 #
2215 IncPathList = []
2216 for Path in gBuildOptIncludePattern.findall(FlagOption):
2217 PathList = GetSplitList(Path, TAB_COMMA_SPLIT)
2218 IncPathList += [NormPath(PathEntry, self.Macros) for PathEntry in PathList]
2219
2220 #
2221 # EDK II modules must not reference header files outside of the packages they depend on or
2222 # within the module's directory tree. Report error if violation.
2223 #
2224 if self.AutoGenVersion >= 0x00010005 and len(IncPathList) > 0:
2225 for Path in IncPathList:
2226 if (Path not in self.IncludePathList) and (CommonPath([Path, self.MetaFile.Dir]) != self.MetaFile.Dir):
2227 ErrMsg = "The include directory for the EDK II module in this line is invalid %s specified in %s FLAGS '%s'" % (Path, Tool, FlagOption)
2228 EdkLogger.error("build",
2229 PARAMETER_INVALID,
2230 ExtraData = ErrMsg,
2231 File = str(self.MetaFile))
2232
2233
2234 BuildOptionIncPathList += IncPathList
2235
2236 self._BuildOptionIncPathList = BuildOptionIncPathList
2237
2238 return self._BuildOptionIncPathList
2239
2240 ## Return a list of files which can be built from source
2241 #
2242 # What kind of files can be built is determined by build rules in
2243 # $(WORKSPACE)/Conf/build_rule.txt and toolchain family.
2244 #
2245 def _GetSourceFileList(self):
2246 if self._SourceFileList == None:
2247 self._SourceFileList = []
2248 for F in self.Module.Sources:
2249 # match tool chain
2250 if F.TagName not in ("", "*", self.ToolChain):
2251 EdkLogger.debug(EdkLogger.DEBUG_9, "The toolchain [%s] for processing file [%s] is found, "
2252 "but [%s] is needed" % (F.TagName, str(F), self.ToolChain))
2253 continue
2254 # match tool chain family
2255 if F.ToolChainFamily not in ("", "*", self.ToolChainFamily):
2256 EdkLogger.debug(
2257 EdkLogger.DEBUG_0,
2258 "The file [%s] must be built by tools of [%s], " \
2259 "but current toolchain family is [%s]" \
2260 % (str(F), F.ToolChainFamily, self.ToolChainFamily))
2261 continue
2262
2263 # add the file path into search path list for file including
2264 if F.Dir not in self.IncludePathList and self.AutoGenVersion >= 0x00010005:
2265 self.IncludePathList.insert(0, F.Dir)
2266 self._SourceFileList.append(F)
2267 self._ApplyBuildRule(F, TAB_UNKNOWN_FILE)
2268 return self._SourceFileList
2269
2270 ## Return the list of unicode files
2271 def _GetUnicodeFileList(self):
2272 if self._UnicodeFileList == None:
2273 if TAB_UNICODE_FILE in self.FileTypes:
2274 self._UnicodeFileList = self.FileTypes[TAB_UNICODE_FILE]
2275 else:
2276 self._UnicodeFileList = []
2277 return self._UnicodeFileList
2278
2279 ## Return a list of files which can be built from binary
2280 #
2281 # "Build" binary files are just to copy them to build directory.
2282 #
2283 # @retval list The list of files which can be built later
2284 #
2285 def _GetBinaryFiles(self):
2286 if self._BinaryFileList == None:
2287 self._BinaryFileList = []
2288 for F in self.Module.Binaries:
2289 if F.Target not in ['COMMON', '*'] and F.Target != self.BuildTarget:
2290 continue
2291 self._BinaryFileList.append(F)
2292 self._ApplyBuildRule(F, F.Type)
2293 return self._BinaryFileList
2294
2295 def _GetBuildRules(self):
2296 if self._BuildRules == None:
2297 BuildRules = {}
2298 BuildRuleDatabase = self.PlatformInfo.BuildRule
2299 for Type in BuildRuleDatabase.FileTypeList:
2300 #first try getting build rule by BuildRuleFamily
2301 RuleObject = BuildRuleDatabase[Type, self.BuildType, self.Arch, self.BuildRuleFamily]
2302 if not RuleObject:
2303 # build type is always module type, but ...
2304 if self.ModuleType != self.BuildType:
2305 RuleObject = BuildRuleDatabase[Type, self.ModuleType, self.Arch, self.BuildRuleFamily]
2306 #second try getting build rule by ToolChainFamily
2307 if not RuleObject:
2308 RuleObject = BuildRuleDatabase[Type, self.BuildType, self.Arch, self.ToolChainFamily]
2309 if not RuleObject:
2310 # build type is always module type, but ...
2311 if self.ModuleType != self.BuildType:
2312 RuleObject = BuildRuleDatabase[Type, self.ModuleType, self.Arch, self.ToolChainFamily]
2313 if not RuleObject:
2314 continue
2315 RuleObject = RuleObject.Instantiate(self.Macros)
2316 BuildRules[Type] = RuleObject
2317 for Ext in RuleObject.SourceFileExtList:
2318 BuildRules[Ext] = RuleObject
2319 self._BuildRules = BuildRules
2320 return self._BuildRules
2321
2322 def _ApplyBuildRule(self, File, FileType):
2323 if self._BuildTargets == None:
2324 self._IntroBuildTargetList = set()
2325 self._FinalBuildTargetList = set()
2326 self._BuildTargets = {}
2327 self._FileTypes = {}
2328
2329 LastTarget = None
2330 RuleChain = []
2331 SourceList = [File]
2332 Index = 0
2333 while Index < len(SourceList):
2334 Source = SourceList[Index]
2335 Index = Index + 1
2336
2337 if Source != File:
2338 CreateDirectory(Source.Dir)
2339
2340 if File.IsBinary and File == Source and self._BinaryFileList != None and File in self._BinaryFileList:
2341 # Skip all files that are not binary libraries
2342 if not self.IsLibrary:
2343 continue
2344 RuleObject = self.BuildRules[TAB_DEFAULT_BINARY_FILE]
2345 elif FileType in self.BuildRules:
2346 RuleObject = self.BuildRules[FileType]
2347 elif Source.Ext in self.BuildRules:
2348 RuleObject = self.BuildRules[Source.Ext]
2349 else:
2350 # stop at no more rules
2351 if LastTarget:
2352 self._FinalBuildTargetList.add(LastTarget)
2353 break
2354
2355 FileType = RuleObject.SourceFileType
2356 if FileType not in self._FileTypes:
2357 self._FileTypes[FileType] = set()
2358 self._FileTypes[FileType].add(Source)
2359
2360 # stop at STATIC_LIBRARY for library
2361 if self.IsLibrary and FileType == TAB_STATIC_LIBRARY:
2362 if LastTarget:
2363 self._FinalBuildTargetList.add(LastTarget)
2364 break
2365
2366 Target = RuleObject.Apply(Source)
2367 if not Target:
2368 if LastTarget:
2369 self._FinalBuildTargetList.add(LastTarget)
2370 break
2371 elif not Target.Outputs:
2372 # Only do build for target with outputs
2373 self._FinalBuildTargetList.add(Target)
2374
2375 if FileType not in self._BuildTargets:
2376 self._BuildTargets[FileType] = set()
2377 self._BuildTargets[FileType].add(Target)
2378
2379 if not Source.IsBinary and Source == File:
2380 self._IntroBuildTargetList.add(Target)
2381
2382 # to avoid cyclic rule
2383 if FileType in RuleChain:
2384 break
2385
2386 RuleChain.append(FileType)
2387 SourceList.extend(Target.Outputs)
2388 LastTarget = Target
2389 FileType = TAB_UNKNOWN_FILE
2390
2391 def _GetTargets(self):
2392 if self._BuildTargets == None:
2393 self._IntroBuildTargetList = set()
2394 self._FinalBuildTargetList = set()
2395 self._BuildTargets = {}
2396 self._FileTypes = {}
2397
2398 #TRICK: call _GetSourceFileList to apply build rule for source files
2399 if self.SourceFileList:
2400 pass
2401
2402 #TRICK: call _GetBinaryFileList to apply build rule for binary files
2403 if self.BinaryFileList:
2404 pass
2405
2406 return self._BuildTargets
2407
2408 def _GetIntroTargetList(self):
2409 self._GetTargets()
2410 return self._IntroBuildTargetList
2411
2412 def _GetFinalTargetList(self):
2413 self._GetTargets()
2414 return self._FinalBuildTargetList
2415
2416 def _GetFileTypes(self):
2417 self._GetTargets()
2418 return self._FileTypes
2419
2420 ## Get the list of package object the module depends on
2421 #
2422 # @retval list The package object list
2423 #
2424 def _GetDependentPackageList(self):
2425 return self.Module.Packages
2426
2427 ## Return the list of auto-generated code file
2428 #
2429 # @retval list The list of auto-generated file
2430 #
2431 def _GetAutoGenFileList(self):
2432 UniStringAutoGenC = True
2433 UniStringBinBuffer = StringIO()
2434 if self.BuildType == 'UEFI_HII':
2435 UniStringAutoGenC = False
2436 if self._AutoGenFileList == None:
2437 self._AutoGenFileList = {}
2438 AutoGenC = TemplateString()
2439 AutoGenH = TemplateString()
2440 StringH = TemplateString()
2441 GenC.CreateCode(self, AutoGenC, AutoGenH, StringH, UniStringAutoGenC, UniStringBinBuffer)
2442 if str(AutoGenC) != "" and TAB_C_CODE_FILE in self.FileTypes:
2443 AutoFile = PathClass(gAutoGenCodeFileName, self.DebugDir)
2444 self._AutoGenFileList[AutoFile] = str(AutoGenC)
2445 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
2446 if str(AutoGenH) != "":
2447 AutoFile = PathClass(gAutoGenHeaderFileName, self.DebugDir)
2448 self._AutoGenFileList[AutoFile] = str(AutoGenH)
2449 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
2450 if str(StringH) != "":
2451 AutoFile = PathClass(gAutoGenStringFileName % {"module_name":self.Name}, self.DebugDir)
2452 self._AutoGenFileList[AutoFile] = str(StringH)
2453 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
2454 if UniStringBinBuffer != None and UniStringBinBuffer.getvalue() != "":
2455 AutoFile = PathClass(gAutoGenStringFormFileName % {"module_name":self.Name}, self.OutputDir)
2456 self._AutoGenFileList[AutoFile] = UniStringBinBuffer.getvalue()
2457 AutoFile.IsBinary = True
2458 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
2459 if UniStringBinBuffer != None:
2460 UniStringBinBuffer.close()
2461 return self._AutoGenFileList
2462
2463 ## Return the list of library modules explicitly or implicityly used by this module
2464 def _GetLibraryList(self):
2465 if self._DependentLibraryList == None:
2466 # only merge library classes and PCD for non-library module
2467 if self.IsLibrary:
2468 self._DependentLibraryList = []
2469 else:
2470 if self.AutoGenVersion < 0x00010005:
2471 self._DependentLibraryList = self.PlatformInfo.ResolveLibraryReference(self.Module)
2472 else:
2473 self._DependentLibraryList = self.PlatformInfo.ApplyLibraryInstance(self.Module)
2474 return self._DependentLibraryList
2475
2476 ## Get the list of PCDs from current module
2477 #
2478 # @retval list The list of PCD
2479 #
2480 def _GetModulePcdList(self):
2481 if self._ModulePcdList == None:
2482 # apply PCD settings from platform
2483 self._ModulePcdList = self.PlatformInfo.ApplyPcdSetting(self.Module, self.Module.Pcds)
2484 return self._ModulePcdList
2485
2486 ## Get the list of PCDs from dependent libraries
2487 #
2488 # @retval list The list of PCD
2489 #
2490 def _GetLibraryPcdList(self):
2491 if self._LibraryPcdList == None:
2492 Pcds = sdict()
2493 if not self.IsLibrary:
2494 # get PCDs from dependent libraries
2495 for Library in self.DependentLibraryList:
2496 for Key in Library.Pcds:
2497 # skip duplicated PCDs
2498 if Key in self.Module.Pcds or Key in Pcds:
2499 continue
2500 Pcds[Key] = copy.copy(Library.Pcds[Key])
2501 # apply PCD settings from platform
2502 self._LibraryPcdList = self.PlatformInfo.ApplyPcdSetting(self.Module, Pcds)
2503 else:
2504 self._LibraryPcdList = []
2505 return self._LibraryPcdList
2506
2507 ## Get the GUID value mapping
2508 #
2509 # @retval dict The mapping between GUID cname and its value
2510 #
2511 def _GetGuidList(self):
2512 if self._GuidList == None:
2513 self._GuidList = self.Module.Guids
2514 for Library in self.DependentLibraryList:
2515 self._GuidList.update(Library.Guids)
2516 return self._GuidList
2517
2518 ## Get the protocol value mapping
2519 #
2520 # @retval dict The mapping between protocol cname and its value
2521 #
2522 def _GetProtocolList(self):
2523 if self._ProtocolList == None:
2524 self._ProtocolList = self.Module.Protocols
2525 for Library in self.DependentLibraryList:
2526 self._ProtocolList.update(Library.Protocols)
2527 return self._ProtocolList
2528
2529 ## Get the PPI value mapping
2530 #
2531 # @retval dict The mapping between PPI cname and its value
2532 #
2533 def _GetPpiList(self):
2534 if self._PpiList == None:
2535 self._PpiList = self.Module.Ppis
2536 for Library in self.DependentLibraryList:
2537 self._PpiList.update(Library.Ppis)
2538 return self._PpiList
2539
2540 ## Get the list of include search path
2541 #
2542 # @retval list The list path
2543 #
2544 def _GetIncludePathList(self):
2545 if self._IncludePathList == None:
2546 self._IncludePathList = []
2547 if self.AutoGenVersion < 0x00010005:
2548 for Inc in self.Module.Includes:
2549 if Inc not in self._IncludePathList:
2550 self._IncludePathList.append(Inc)
2551 # for Edk modules
2552 Inc = path.join(Inc, self.Arch.capitalize())
2553 if os.path.exists(Inc) and Inc not in self._IncludePathList:
2554 self._IncludePathList.append(Inc)
2555 # Edk module needs to put DEBUG_DIR at the end of search path and not to use SOURCE_DIR all the time
2556 self._IncludePathList.append(self.DebugDir)
2557 else:
2558 self._IncludePathList.append(self.MetaFile.Dir)
2559 self._IncludePathList.append(self.DebugDir)
2560
2561 for Package in self.Module.Packages:
2562 PackageDir = path.join(self.WorkspaceDir, Package.MetaFile.Dir)
2563 if PackageDir not in self._IncludePathList:
2564 self._IncludePathList.append(PackageDir)
2565 for Inc in Package.Includes:
2566 if Inc not in self._IncludePathList:
2567 self._IncludePathList.append(str(Inc))
2568 return self._IncludePathList
2569
2570 ## Create AsBuilt INF file the module
2571 #
2572 def CreateAsBuiltInf(self):
2573 if self.IsAsBuiltInfCreated:
2574 return
2575
2576 # Skip the following code for EDK I inf
2577 if self.AutoGenVersion < 0x00010005:
2578 return
2579
2580 # Skip the following code for libraries
2581 if self.IsLibrary:
2582 return
2583
2584 # Skip the following code for modules with no source files
2585 if self.SourceFileList == None or self.SourceFileList == []:
2586 return
2587
2588 # Skip the following code for modules without any binary files
2589 if self.BinaryFileList <> None and self.BinaryFileList <> []:
2590 return
2591
2592 ### TODO: How to handles mixed source and binary modules
2593
2594 # Find all DynamicEx PCDs used by this module and dependent libraries
2595 # Also find all packages that the DynamicEx PCDs depend on
2596 Pcds = []
2597 Packages = []
2598 for Pcd in self.ModulePcdList + self.LibraryPcdList:
2599 if Pcd.Type in GenC.gDynamicExPcd:
2600 if Pcd not in Pcds:
2601 Pcds += [Pcd]
2602 for Package in self.DerivedPackageList:
2603 if Package not in Packages:
2604 if (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, 'DynamicEx') in Package.Pcds:
2605 Packages += [Package]
2606 elif (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, 'Dynamic') in Package.Pcds:
2607 Packages += [Package]
2608
2609 ModuleType = self.ModuleType
2610 if ModuleType == 'UEFI_DRIVER' and self.DepexGenerated:
2611 ModuleType = 'DXE_DRIVER'
2612
2613 AsBuiltInfDict = {
2614 'module_name' : self.Name,
2615 'module_guid' : self.Guid,
2616 'module_module_type' : ModuleType,
2617 'module_version_string' : self.Version,
2618 'module_uefi_specification_version' : [],
2619 'module_pi_specification_version' : [],
2620 'module_arch' : self.Arch,
2621 'package_item' : ['%s' % (Package.MetaFile.File.replace('\\','/')) for Package in Packages],
2622 'binary_item' : [],
2623 'pcd_item' : [],
2624 'flags_item' : []
2625 }
2626
2627 if 'UEFI_SPECIFICATION_VERSION' in self.Specification:
2628 AsBuiltInfDict['module_uefi_specification_version'] += [self.Specification['UEFI_SPECIFICATION_VERSION']]
2629 if 'PI_SPECIFICATION_VERSION' in self.Specification:
2630 AsBuiltInfDict['module_pi_specification_version'] += [self.Specification['PI_SPECIFICATION_VERSION']]
2631
2632 OutputDir = self.OutputDir.replace('\\','/').strip('/')
2633 if self.ModuleType in ['BASE', 'USER_DEFINED']:
2634 for Item in self.CodaTargetList:
2635 File = Item.Target.Path.replace('\\','/').strip('/').replace(OutputDir,'').strip('/')
2636 if Item.Target.Ext.lower() == '.aml':
2637 AsBuiltInfDict['binary_item'] += ['ASL|' + File]
2638 elif Item.Target.Ext.lower() == '.acpi':
2639 AsBuiltInfDict['binary_item'] += ['ACPI|' + File]
2640 else:
2641 AsBuiltInfDict['binary_item'] += ['BIN|' + File]
2642 else:
2643 for Item in self.CodaTargetList:
2644 File = Item.Target.Path.replace('\\','/').strip('/').replace(OutputDir,'').strip('/')
2645 if Item.Target.Ext.lower() == '.efi':
2646 AsBuiltInfDict['binary_item'] += ['PE32|' + self.Name + '.efi']
2647 else:
2648 AsBuiltInfDict['binary_item'] += ['BIN|' + File]
2649 if self.DepexGenerated:
2650 if self.ModuleType in ['PEIM']:
2651 AsBuiltInfDict['binary_item'] += ['PEI_DEPEX|' + self.Name + '.depex']
2652 if self.ModuleType in ['DXE_DRIVER','DXE_RUNTIME_DRIVER','DXE_SAL_DRIVER','UEFI_DRIVER']:
2653 AsBuiltInfDict['binary_item'] += ['DXE_DEPEX|' + self.Name + '.depex']
2654 if self.ModuleType in ['DXE_SMM_DRIVER']:
2655 AsBuiltInfDict['binary_item'] += ['SMM_DEPEX|' + self.Name + '.depex']
2656
2657 for Pcd in Pcds:
2658 AsBuiltInfDict['pcd_item'] += [Pcd.TokenSpaceGuidCName + '.' + Pcd.TokenCName]
2659
2660 for Item in self.BuildOption:
2661 if 'FLAGS' in self.BuildOption[Item]:
2662 AsBuiltInfDict['flags_item'] += ['%s:%s_%s_%s_%s_FLAGS = %s' % (self.ToolChainFamily, self.BuildTarget, self.ToolChain, self.Arch, Item, self.BuildOption[Item]['FLAGS'].strip())]
2663
2664 AsBuiltInf = TemplateString()
2665 AsBuiltInf.Append(gAsBuiltInfHeaderString.Replace(AsBuiltInfDict))
2666
2667 SaveFileOnChange(os.path.join(self.OutputDir, self.Name + '.inf'), str(AsBuiltInf), False)
2668
2669 self.IsAsBuiltInfCreated = True
2670
2671 ## Create makefile for the module and its dependent libraries
2672 #
2673 # @param CreateLibraryMakeFile Flag indicating if or not the makefiles of
2674 # dependent libraries will be created
2675 #
2676 def CreateMakeFile(self, CreateLibraryMakeFile=True):
2677 if self.IsMakeFileCreated:
2678 return
2679
2680 if not self.IsLibrary and CreateLibraryMakeFile:
2681 for LibraryAutoGen in self.LibraryAutoGenList:
2682 LibraryAutoGen.CreateMakeFile()
2683
2684 if len(self.CustomMakefile) == 0:
2685 Makefile = GenMake.ModuleMakefile(self)
2686 else:
2687 Makefile = GenMake.CustomMakefile(self)
2688 if Makefile.Generate():
2689 EdkLogger.debug(EdkLogger.DEBUG_9, "Generated makefile for module %s [%s]" %
2690 (self.Name, self.Arch))
2691 else:
2692 EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of makefile for module %s [%s]" %
2693 (self.Name, self.Arch))
2694
2695 self.IsMakeFileCreated = True
2696
2697 ## Create autogen code for the module and its dependent libraries
2698 #
2699 # @param CreateLibraryCodeFile Flag indicating if or not the code of
2700 # dependent libraries will be created
2701 #
2702 def CreateCodeFile(self, CreateLibraryCodeFile=True):
2703 if self.IsCodeFileCreated:
2704 return
2705
2706 if not self.IsLibrary and CreateLibraryCodeFile:
2707 for LibraryAutoGen in self.LibraryAutoGenList:
2708 LibraryAutoGen.CreateCodeFile()
2709
2710 AutoGenList = []
2711 IgoredAutoGenList = []
2712
2713 for File in self.AutoGenFileList:
2714 if GenC.Generate(File.Path, self.AutoGenFileList[File], File.IsBinary):
2715 #Ignore Edk AutoGen.c
2716 if self.AutoGenVersion < 0x00010005 and File.Name == 'AutoGen.c':
2717 continue
2718
2719 AutoGenList.append(str(File))
2720 else:
2721 IgoredAutoGenList.append(str(File))
2722
2723 # Skip the following code for EDK I inf
2724 if self.AutoGenVersion < 0x00010005:
2725 return
2726
2727 for ModuleType in self.DepexList:
2728 # Ignore empty [depex] section or [depex] section for "USER_DEFINED" module
2729 if len(self.DepexList[ModuleType]) == 0 or ModuleType == "USER_DEFINED":
2730 continue
2731
2732 Dpx = GenDepex.DependencyExpression(self.DepexList[ModuleType], ModuleType, True)
2733 DpxFile = gAutoGenDepexFileName % {"module_name" : self.Name}
2734
2735 if len(Dpx.PostfixNotation) <> 0:
2736 self.DepexGenerated = True
2737
2738 if Dpx.Generate(path.join(self.OutputDir, DpxFile)):
2739 AutoGenList.append(str(DpxFile))
2740 else:
2741 IgoredAutoGenList.append(str(DpxFile))
2742
2743 if IgoredAutoGenList == []:
2744 EdkLogger.debug(EdkLogger.DEBUG_9, "Generated [%s] files for module %s [%s]" %
2745 (" ".join(AutoGenList), self.Name, self.Arch))
2746 elif AutoGenList == []:
2747 EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of [%s] files for module %s [%s]" %
2748 (" ".join(IgoredAutoGenList), self.Name, self.Arch))
2749 else:
2750 EdkLogger.debug(EdkLogger.DEBUG_9, "Generated [%s] (skipped %s) files for module %s [%s]" %
2751 (" ".join(AutoGenList), " ".join(IgoredAutoGenList), self.Name, self.Arch))
2752
2753 self.IsCodeFileCreated = True
2754 return AutoGenList
2755
2756 ## Summarize the ModuleAutoGen objects of all libraries used by this module
2757 def _GetLibraryAutoGenList(self):
2758 if self._LibraryAutoGenList == None:
2759 self._LibraryAutoGenList = []
2760 for Library in self.DependentLibraryList:
2761 La = ModuleAutoGen(
2762 self.Workspace,
2763 Library.MetaFile,
2764 self.BuildTarget,
2765 self.ToolChain,
2766 self.Arch,
2767 self.PlatformInfo.MetaFile
2768 )
2769 if La not in self._LibraryAutoGenList:
2770 self._LibraryAutoGenList.append(La)
2771 for Lib in La.CodaTargetList:
2772 self._ApplyBuildRule(Lib.Target, TAB_UNKNOWN_FILE)
2773 return self._LibraryAutoGenList
2774
2775 Module = property(_GetModule)
2776 Name = property(_GetBaseName)
2777 Guid = property(_GetGuid)
2778 Version = property(_GetVersion)
2779 ModuleType = property(_GetModuleType)
2780 ComponentType = property(_GetComponentType)
2781 BuildType = property(_GetBuildType)
2782 PcdIsDriver = property(_GetPcdIsDriver)
2783 AutoGenVersion = property(_GetAutoGenVersion)
2784 Macros = property(_GetMacros)
2785 Specification = property(_GetSpecification)
2786
2787 IsLibrary = property(_IsLibrary)
2788
2789 BuildDir = property(_GetBuildDir)
2790 OutputDir = property(_GetOutputDir)
2791 DebugDir = property(_GetDebugDir)
2792 MakeFileDir = property(_GetMakeFileDir)
2793 CustomMakefile = property(_GetCustomMakefile)
2794
2795 IncludePathList = property(_GetIncludePathList)
2796 AutoGenFileList = property(_GetAutoGenFileList)
2797 UnicodeFileList = property(_GetUnicodeFileList)
2798 SourceFileList = property(_GetSourceFileList)
2799 BinaryFileList = property(_GetBinaryFiles) # FileType : [File List]
2800 Targets = property(_GetTargets)
2801 IntroTargetList = property(_GetIntroTargetList)
2802 CodaTargetList = property(_GetFinalTargetList)
2803 FileTypes = property(_GetFileTypes)
2804 BuildRules = property(_GetBuildRules)
2805
2806 DependentPackageList = property(_GetDependentPackageList)
2807 DependentLibraryList = property(_GetLibraryList)
2808 LibraryAutoGenList = property(_GetLibraryAutoGenList)
2809 DerivedPackageList = property(_GetDerivedPackageList)
2810
2811 ModulePcdList = property(_GetModulePcdList)
2812 LibraryPcdList = property(_GetLibraryPcdList)
2813 GuidList = property(_GetGuidList)
2814 ProtocolList = property(_GetProtocolList)
2815 PpiList = property(_GetPpiList)
2816 DepexList = property(_GetDepexTokenList)
2817 DxsFile = property(_GetDxsFile)
2818 DepexExpressionList = property(_GetDepexExpressionTokenList)
2819 BuildOption = property(_GetModuleBuildOption)
2820 BuildOptionIncPathList = property(_GetBuildOptionIncPathList)
2821 BuildCommand = property(_GetBuildCommand)
2822
2823 # This acts like the main() function for the script, unless it is 'import'ed into another script.
2824 if __name__ == '__main__':
2825 pass
2826