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