]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/AutoGen/AutoGen.py
BaseTools: Enhance parse performance by optimize ValueExpressionEx
[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 - 2018, 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 Common.LongFilePathOs as os
17 import re
18 import os.path as path
19 import copy
20 import uuid
21
22 import GenC
23 import GenMake
24 import GenDepex
25 from StringIO import StringIO
26
27 from StrGather import *
28 from BuildEngine import BuildRule
29
30 from Common.LongFilePathSupport import CopyLongFilePath
31 from Common.BuildToolError import *
32 from Common.DataType import *
33 from Common.Misc import *
34 from Common.String import *
35 import Common.GlobalData as GlobalData
36 from GenFds.FdfParser import *
37 from CommonDataClass.CommonClass import SkuInfoClass
38 from Workspace.BuildClassObject import *
39 from GenPatchPcdTable.GenPatchPcdTable import parsePcdInfoFromMapFile
40 import Common.VpdInfoFile as VpdInfoFile
41 from GenPcdDb import CreatePcdDatabaseCode
42 from Workspace.MetaFileCommentParser import UsageList
43 from Common.MultipleWorkspace import MultipleWorkspace as mws
44 import InfSectionParser
45 import datetime
46 import hashlib
47 from GenVar import VariableMgr,var_info
48
49 ## Regular expression for splitting Dependency Expression string into tokens
50 gDepexTokenPattern = re.compile("(\(|\)|\w+| \S+\.inf)")
51
52 #
53 # Match name = variable
54 #
55 gEfiVarStoreNamePattern = re.compile("\s*name\s*=\s*(\w+)")
56 #
57 # The format of guid in efivarstore statement likes following and must be correct:
58 # guid = {0xA04A27f4, 0xDF00, 0x4D42, {0xB5, 0x52, 0x39, 0x51, 0x13, 0x02, 0x11, 0x3D}}
59 #
60 gEfiVarStoreGuidPattern = re.compile("\s*guid\s*=\s*({.*?{.*?}\s*})")
61
62 ## Mapping Makefile type
63 gMakeTypeMap = {"MSFT":"nmake", "GCC":"gmake"}
64
65
66 ## Build rule configuration file
67 gDefaultBuildRuleFile = 'build_rule.txt'
68
69 ## Tools definition configuration file
70 gDefaultToolsDefFile = 'tools_def.txt'
71
72 ## Build rule default version
73 AutoGenReqBuildRuleVerNum = "0.1"
74
75 ## default file name for AutoGen
76 gAutoGenCodeFileName = "AutoGen.c"
77 gAutoGenHeaderFileName = "AutoGen.h"
78 gAutoGenStringFileName = "%(module_name)sStrDefs.h"
79 gAutoGenStringFormFileName = "%(module_name)sStrDefs.hpk"
80 gAutoGenDepexFileName = "%(module_name)s.depex"
81 gAutoGenImageDefFileName = "%(module_name)sImgDefs.h"
82 gAutoGenIdfFileName = "%(module_name)sIdf.hpk"
83 gInfSpecVersion = "0x00010017"
84
85 #
86 # Template string to generic AsBuilt INF
87 #
88 gAsBuiltInfHeaderString = TemplateString("""${header_comments}
89
90 # DO NOT EDIT
91 # FILE auto-generated
92
93 [Defines]
94 INF_VERSION = ${module_inf_version}
95 BASE_NAME = ${module_name}
96 FILE_GUID = ${module_guid}
97 MODULE_TYPE = ${module_module_type}${BEGIN}
98 VERSION_STRING = ${module_version_string}${END}${BEGIN}
99 PCD_IS_DRIVER = ${pcd_is_driver_string}${END}${BEGIN}
100 UEFI_SPECIFICATION_VERSION = ${module_uefi_specification_version}${END}${BEGIN}
101 PI_SPECIFICATION_VERSION = ${module_pi_specification_version}${END}${BEGIN}
102 ENTRY_POINT = ${module_entry_point}${END}${BEGIN}
103 UNLOAD_IMAGE = ${module_unload_image}${END}${BEGIN}
104 CONSTRUCTOR = ${module_constructor}${END}${BEGIN}
105 DESTRUCTOR = ${module_destructor}${END}${BEGIN}
106 SHADOW = ${module_shadow}${END}${BEGIN}
107 PCI_VENDOR_ID = ${module_pci_vendor_id}${END}${BEGIN}
108 PCI_DEVICE_ID = ${module_pci_device_id}${END}${BEGIN}
109 PCI_CLASS_CODE = ${module_pci_class_code}${END}${BEGIN}
110 PCI_REVISION = ${module_pci_revision}${END}${BEGIN}
111 BUILD_NUMBER = ${module_build_number}${END}${BEGIN}
112 SPEC = ${module_spec}${END}${BEGIN}
113 UEFI_HII_RESOURCE_SECTION = ${module_uefi_hii_resource_section}${END}${BEGIN}
114 MODULE_UNI_FILE = ${module_uni_file}${END}
115
116 [Packages.${module_arch}]${BEGIN}
117 ${package_item}${END}
118
119 [Binaries.${module_arch}]${BEGIN}
120 ${binary_item}${END}
121
122 [PatchPcd.${module_arch}]${BEGIN}
123 ${patchablepcd_item}
124 ${END}
125
126 [Protocols.${module_arch}]${BEGIN}
127 ${protocol_item}
128 ${END}
129
130 [Ppis.${module_arch}]${BEGIN}
131 ${ppi_item}
132 ${END}
133
134 [Guids.${module_arch}]${BEGIN}
135 ${guid_item}
136 ${END}
137
138 [PcdEx.${module_arch}]${BEGIN}
139 ${pcd_item}
140 ${END}
141
142 [LibraryClasses.${module_arch}]
143 ## @LIB_INSTANCES${BEGIN}
144 # ${libraryclasses_item}${END}
145
146 ${depexsection_item}
147
148 ${userextension_tianocore_item}
149
150 ${tail_comments}
151
152 [BuildOptions.${module_arch}]
153 ## @AsBuilt${BEGIN}
154 ## ${flags_item}${END}
155 """)
156
157 ## Base class for AutoGen
158 #
159 # This class just implements the cache mechanism of AutoGen objects.
160 #
161 class AutoGen(object):
162 # database to maintain the objects of xxxAutoGen
163 _CACHE_ = {} # (BuildTarget, ToolChain) : {ARCH : {platform file: AutoGen object}}}
164
165 ## Factory method
166 #
167 # @param Class class object of real AutoGen class
168 # (WorkspaceAutoGen, ModuleAutoGen or PlatformAutoGen)
169 # @param Workspace Workspace directory or WorkspaceAutoGen object
170 # @param MetaFile The path of meta file
171 # @param Target Build target
172 # @param Toolchain Tool chain name
173 # @param Arch Target arch
174 # @param *args The specific class related parameters
175 # @param **kwargs The specific class related dict parameters
176 #
177 def __new__(Class, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):
178 # check if the object has been created
179 Key = (Target, Toolchain)
180 if Key not in Class._CACHE_ or Arch not in Class._CACHE_[Key] \
181 or MetaFile not in Class._CACHE_[Key][Arch]:
182 AutoGenObject = super(AutoGen, Class).__new__(Class)
183 # call real constructor
184 if not AutoGenObject._Init(Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):
185 return None
186 if Key not in Class._CACHE_:
187 Class._CACHE_[Key] = {}
188 if Arch not in Class._CACHE_[Key]:
189 Class._CACHE_[Key][Arch] = {}
190 Class._CACHE_[Key][Arch][MetaFile] = AutoGenObject
191 else:
192 AutoGenObject = Class._CACHE_[Key][Arch][MetaFile]
193
194 return AutoGenObject
195
196 ## hash() operator
197 #
198 # The file path of platform file will be used to represent hash value of this object
199 #
200 # @retval int Hash value of the file path of platform file
201 #
202 def __hash__(self):
203 return hash(self.MetaFile)
204
205 ## str() operator
206 #
207 # The file path of platform file will be used to represent this object
208 #
209 # @retval string String of platform file path
210 #
211 def __str__(self):
212 return str(self.MetaFile)
213
214 ## "==" operator
215 def __eq__(self, Other):
216 return Other and self.MetaFile == Other
217
218 ## Workspace AutoGen class
219 #
220 # This class is used mainly to control the whole platform build for different
221 # architecture. This class will generate top level makefile.
222 #
223 class WorkspaceAutoGen(AutoGen):
224 ## Real constructor of WorkspaceAutoGen
225 #
226 # This method behaves the same as __init__ except that it needs explicit invoke
227 # (in super class's __new__ method)
228 #
229 # @param WorkspaceDir Root directory of workspace
230 # @param ActivePlatform Meta-file of active platform
231 # @param Target Build target
232 # @param Toolchain Tool chain name
233 # @param ArchList List of architecture of current build
234 # @param MetaFileDb Database containing meta-files
235 # @param BuildConfig Configuration of build
236 # @param ToolDefinition Tool chain definitions
237 # @param FlashDefinitionFile File of flash definition
238 # @param Fds FD list to be generated
239 # @param Fvs FV list to be generated
240 # @param Caps Capsule list to be generated
241 # @param SkuId SKU id from command line
242 #
243 def _Init(self, WorkspaceDir, ActivePlatform, Target, Toolchain, ArchList, MetaFileDb,
244 BuildConfig, ToolDefinition, FlashDefinitionFile='', Fds=None, Fvs=None, Caps=None, SkuId='', UniFlag=None,
245 Progress=None, BuildModule=None):
246 if Fds is None:
247 Fds = []
248 if Fvs is None:
249 Fvs = []
250 if Caps is None:
251 Caps = []
252 self.BuildDatabase = MetaFileDb
253 self.MetaFile = ActivePlatform
254 self.WorkspaceDir = WorkspaceDir
255 self.Platform = self.BuildDatabase[self.MetaFile, 'COMMON', Target, Toolchain]
256 GlobalData.gActivePlatform = self.Platform
257 self.BuildTarget = Target
258 self.ToolChain = Toolchain
259 self.ArchList = ArchList
260 self.SkuId = SkuId
261 self.UniFlag = UniFlag
262
263 self.TargetTxt = BuildConfig
264 self.ToolDef = ToolDefinition
265 self.FdfFile = FlashDefinitionFile
266 self.FdTargetList = Fds
267 self.FvTargetList = Fvs
268 self.CapTargetList = Caps
269 self.AutoGenObjectList = []
270 self._BuildDir = None
271 self._FvDir = None
272 self._MakeFileDir = None
273 self._BuildCommand = None
274 self._GuidDict = {}
275
276 # there's many relative directory operations, so ...
277 os.chdir(self.WorkspaceDir)
278
279 #
280 # Merge Arch
281 #
282 if not self.ArchList:
283 ArchList = set(self.Platform.SupArchList)
284 else:
285 ArchList = set(self.ArchList) & set(self.Platform.SupArchList)
286 if not ArchList:
287 EdkLogger.error("build", PARAMETER_INVALID,
288 ExtraData = "Invalid ARCH specified. [Valid ARCH: %s]" % (" ".join(self.Platform.SupArchList)))
289 elif self.ArchList and len(ArchList) != len(self.ArchList):
290 SkippedArchList = set(self.ArchList).symmetric_difference(set(self.Platform.SupArchList))
291 EdkLogger.verbose("\nArch [%s] is ignored because the platform supports [%s] only!"
292 % (" ".join(SkippedArchList), " ".join(self.Platform.SupArchList)))
293 self.ArchList = tuple(ArchList)
294
295 # Validate build target
296 if self.BuildTarget not in self.Platform.BuildTargets:
297 EdkLogger.error("build", PARAMETER_INVALID,
298 ExtraData="Build target [%s] is not supported by the platform. [Valid target: %s]"
299 % (self.BuildTarget, " ".join(self.Platform.BuildTargets)))
300
301
302 # parse FDF file to get PCDs in it, if any
303 if not self.FdfFile:
304 self.FdfFile = self.Platform.FlashDefinition
305
306 EdkLogger.info("")
307 if self.ArchList:
308 EdkLogger.info('%-16s = %s' % ("Architecture(s)", ' '.join(self.ArchList)))
309 EdkLogger.info('%-16s = %s' % ("Build target", self.BuildTarget))
310 EdkLogger.info('%-16s = %s' % ("Toolchain", self.ToolChain))
311
312 EdkLogger.info('\n%-24s = %s' % ("Active Platform", self.Platform))
313 if BuildModule:
314 EdkLogger.info('%-24s = %s' % ("Active Module", BuildModule))
315
316 if self.FdfFile:
317 EdkLogger.info('%-24s = %s' % ("Flash Image Definition", self.FdfFile))
318
319 EdkLogger.verbose("\nFLASH_DEFINITION = %s" % self.FdfFile)
320
321 if Progress:
322 Progress.Start("\nProcessing meta-data")
323
324 if self.FdfFile:
325 #
326 # Mark now build in AutoGen Phase
327 #
328 GlobalData.gAutoGenPhase = True
329 Fdf = FdfParser(self.FdfFile.Path)
330 Fdf.ParseFile()
331 GlobalData.gFdfParser = Fdf
332 GlobalData.gAutoGenPhase = False
333 PcdSet = Fdf.Profile.PcdDict
334 if Fdf.CurrentFdName and Fdf.CurrentFdName in Fdf.Profile.FdDict:
335 FdDict = Fdf.Profile.FdDict[Fdf.CurrentFdName]
336 for FdRegion in FdDict.RegionList:
337 if str(FdRegion.RegionType) is 'FILE' and self.Platform.VpdToolGuid in str(FdRegion.RegionDataList):
338 if int(FdRegion.Offset) % 8 != 0:
339 EdkLogger.error("build", FORMAT_INVALID, 'The VPD Base Address %s must be 8-byte aligned.' % (FdRegion.Offset))
340 ModuleList = Fdf.Profile.InfList
341 self.FdfProfile = Fdf.Profile
342 for fvname in self.FvTargetList:
343 if fvname.upper() not in self.FdfProfile.FvDict:
344 EdkLogger.error("build", OPTION_VALUE_INVALID,
345 "No such an FV in FDF file: %s" % fvname)
346
347 # In DSC file may use FILE_GUID to override the module, then in the Platform.Modules use FILE_GUIDmodule.inf as key,
348 # but the path (self.MetaFile.Path) is the real path
349 for key in self.FdfProfile.InfDict:
350 if key == 'ArchTBD':
351 Platform_cache = {}
352 MetaFile_cache = {}
353 for Arch in self.ArchList:
354 Platform_cache[Arch] = self.BuildDatabase[self.MetaFile, Arch, Target, Toolchain]
355 MetaFile_cache[Arch] = []
356 for Pkey in Platform_cache[Arch].Modules.keys():
357 MetaFile_cache[Arch].append(Platform_cache[Arch].Modules[Pkey].MetaFile)
358 for Inf in self.FdfProfile.InfDict[key]:
359 ModuleFile = PathClass(NormPath(Inf), GlobalData.gWorkspace, Arch)
360 for Arch in self.ArchList:
361 if ModuleFile in MetaFile_cache[Arch]:
362 break
363 else:
364 ModuleData = self.BuildDatabase[ModuleFile, Arch, Target, Toolchain]
365 if not ModuleData.IsBinaryModule:
366 EdkLogger.error('build', PARSER_ERROR, "Module %s NOT found in DSC file; Is it really a binary module?" % ModuleFile)
367
368 else:
369 for Arch in self.ArchList:
370 if Arch == key:
371 Platform = self.BuildDatabase[self.MetaFile, Arch, Target, Toolchain]
372 MetaFileList = []
373 for Pkey in Platform.Modules.keys():
374 MetaFileList.append(Platform.Modules[Pkey].MetaFile)
375 for Inf in self.FdfProfile.InfDict[key]:
376 ModuleFile = PathClass(NormPath(Inf), GlobalData.gWorkspace, Arch)
377 if ModuleFile in MetaFileList:
378 continue
379 ModuleData = self.BuildDatabase[ModuleFile, Arch, Target, Toolchain]
380 if not ModuleData.IsBinaryModule:
381 EdkLogger.error('build', PARSER_ERROR, "Module %s NOT found in DSC file; Is it really a binary module?" % ModuleFile)
382
383 else:
384 PcdSet = {}
385 ModuleList = []
386 self.FdfProfile = None
387 if self.FdTargetList:
388 EdkLogger.info("No flash definition file found. FD [%s] will be ignored." % " ".join(self.FdTargetList))
389 self.FdTargetList = []
390 if self.FvTargetList:
391 EdkLogger.info("No flash definition file found. FV [%s] will be ignored." % " ".join(self.FvTargetList))
392 self.FvTargetList = []
393 if self.CapTargetList:
394 EdkLogger.info("No flash definition file found. Capsule [%s] will be ignored." % " ".join(self.CapTargetList))
395 self.CapTargetList = []
396
397 # apply SKU and inject PCDs from Flash Definition file
398 for Arch in self.ArchList:
399 Platform = self.BuildDatabase[self.MetaFile, Arch, Target, Toolchain]
400
401 DecPcds = {}
402 DecPcdsKey = set()
403 PGen = PlatformAutoGen(self, self.MetaFile, Target, Toolchain, Arch)
404 if GlobalData.BuildOptionPcd:
405 for i, pcd in enumerate(GlobalData.BuildOptionPcd):
406 if type(pcd) is tuple:
407 continue
408 (pcdname, pcdvalue) = pcd.split('=')
409 if not pcdvalue:
410 EdkLogger.error('build', AUTOGEN_ERROR, "No Value specified for the PCD %s." % (pcdname))
411 if '.' in pcdname:
412 (TokenSpaceGuidCName, TokenCName) = pcdname.split('.')
413 HasTokenSpace = True
414 else:
415 TokenCName = pcdname
416 TokenSpaceGuidCName = ''
417 HasTokenSpace = False
418 TokenSpaceGuidCNameList = []
419 FoundFlag = False
420 PcdDatumType = ''
421 NewValue = ''
422 for package in PGen.PackageList:
423 Guids = package.Guids
424 self._GuidDict.update(Guids)
425 for package in PGen.PackageList:
426 for key in package.Pcds:
427 PcdItem = package.Pcds[key]
428 if HasTokenSpace:
429 if (PcdItem.TokenCName, PcdItem.TokenSpaceGuidCName) == (TokenCName, TokenSpaceGuidCName):
430 PcdDatumType = PcdItem.DatumType
431 if pcdvalue.startswith('H'):
432 try:
433 pcdvalue = ValueExpressionEx(pcdvalue[1:], PcdDatumType, self._GuidDict)(True)
434 except BadExpression, Value:
435 if Value.result > 1:
436 EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s", %s' %
437 (TokenSpaceGuidCName, TokenCName, pcdvalue, Value))
438 pcdvalue = 'H' + pcdvalue
439 NewValue = BuildOptionPcdValueFormat(TokenSpaceGuidCName, TokenCName, PcdDatumType, pcdvalue)
440 FoundFlag = True
441 else:
442 if PcdItem.TokenCName == TokenCName:
443 if not PcdItem.TokenSpaceGuidCName in TokenSpaceGuidCNameList:
444 if len (TokenSpaceGuidCNameList) < 1:
445 TokenSpaceGuidCNameList.append(PcdItem.TokenSpaceGuidCName)
446 PcdDatumType = PcdItem.DatumType
447 TokenSpaceGuidCName = PcdItem.TokenSpaceGuidCName
448 if pcdvalue.startswith('H'):
449 try:
450 pcdvalue = ValueExpressionEx(pcdvalue[1:], PcdDatumType, self._GuidDict)(True)
451 except BadExpression, Value:
452 EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s", %s' %
453 (TokenSpaceGuidCName, TokenCName, pcdvalue, Value))
454 pcdvalue = 'H' + pcdvalue
455 NewValue = BuildOptionPcdValueFormat(TokenSpaceGuidCName, TokenCName, PcdDatumType, pcdvalue)
456 FoundFlag = True
457 else:
458 EdkLogger.error(
459 'build',
460 AUTOGEN_ERROR,
461 "The Pcd %s is found under multiple different TokenSpaceGuid: %s and %s." % (TokenCName, PcdItem.TokenSpaceGuidCName, TokenSpaceGuidCNameList[0])
462 )
463
464 GlobalData.BuildOptionPcd[i] = (TokenSpaceGuidCName, TokenCName, NewValue)
465
466 if not FoundFlag:
467 if HasTokenSpace:
468 EdkLogger.error('build', AUTOGEN_ERROR, "The Pcd %s.%s is not found in the DEC file." % (TokenSpaceGuidCName, TokenCName))
469 else:
470 EdkLogger.error('build', AUTOGEN_ERROR, "The Pcd %s is not found in the DEC file." % (TokenCName))
471
472 for BuildData in PGen.BuildDatabase._CACHE_.values():
473 if BuildData.Arch != Arch:
474 continue
475 if BuildData.MetaFile.Ext == '.dec':
476 continue
477 for key in BuildData.Pcds:
478 PcdItem = BuildData.Pcds[key]
479 if (TokenSpaceGuidCName, TokenCName) == (PcdItem.TokenSpaceGuidCName, PcdItem.TokenCName):
480 PcdItem.DefaultValue = NewValue
481
482 if (TokenCName, TokenSpaceGuidCName) in PcdSet:
483 PcdSet[(TokenCName, TokenSpaceGuidCName)] = NewValue
484
485 SourcePcdDict = {'DynamicEx':[], 'PatchableInModule':[],'Dynamic':[],'FixedAtBuild':[]}
486 BinaryPcdDict = {'DynamicEx':[], 'PatchableInModule':[]}
487 SourcePcdDict_Keys = SourcePcdDict.keys()
488 BinaryPcdDict_Keys = BinaryPcdDict.keys()
489
490 # generate the SourcePcdDict and BinaryPcdDict
491 for BuildData in PGen.BuildDatabase._CACHE_.values():
492 if BuildData.Arch != Arch:
493 continue
494 if BuildData.MetaFile.Ext == '.inf':
495 for key in BuildData.Pcds:
496 if BuildData.Pcds[key].Pending:
497 if key in Platform.Pcds:
498 PcdInPlatform = Platform.Pcds[key]
499 if PcdInPlatform.Type not in [None, '']:
500 BuildData.Pcds[key].Type = PcdInPlatform.Type
501
502 if BuildData.MetaFile in Platform.Modules:
503 PlatformModule = Platform.Modules[str(BuildData.MetaFile)]
504 if key in PlatformModule.Pcds:
505 PcdInPlatform = PlatformModule.Pcds[key]
506 if PcdInPlatform.Type not in [None, '']:
507 BuildData.Pcds[key].Type = PcdInPlatform.Type
508
509 if 'DynamicEx' in BuildData.Pcds[key].Type:
510 if BuildData.IsBinaryModule:
511 if (BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName) not in BinaryPcdDict['DynamicEx']:
512 BinaryPcdDict['DynamicEx'].append((BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName))
513 else:
514 if (BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName) not in SourcePcdDict['DynamicEx']:
515 SourcePcdDict['DynamicEx'].append((BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName))
516
517 elif 'PatchableInModule' in BuildData.Pcds[key].Type:
518 if BuildData.MetaFile.Ext == '.inf':
519 if BuildData.IsBinaryModule:
520 if (BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName) not in BinaryPcdDict['PatchableInModule']:
521 BinaryPcdDict['PatchableInModule'].append((BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName))
522 else:
523 if (BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName) not in SourcePcdDict['PatchableInModule']:
524 SourcePcdDict['PatchableInModule'].append((BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName))
525
526 elif 'Dynamic' in BuildData.Pcds[key].Type:
527 if (BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName) not in SourcePcdDict['Dynamic']:
528 SourcePcdDict['Dynamic'].append((BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName))
529 elif 'FixedAtBuild' in BuildData.Pcds[key].Type:
530 if (BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName) not in SourcePcdDict['FixedAtBuild']:
531 SourcePcdDict['FixedAtBuild'].append((BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName))
532 else:
533 pass
534 #
535 # A PCD can only use one type for all source modules
536 #
537 for i in SourcePcdDict_Keys:
538 for j in SourcePcdDict_Keys:
539 if i != j:
540 IntersectionList = list(set(SourcePcdDict[i]).intersection(set(SourcePcdDict[j])))
541 if len(IntersectionList) > 0:
542 EdkLogger.error(
543 'build',
544 FORMAT_INVALID,
545 "Building modules from source INFs, following PCD use %s and %s access method. It must be corrected to use only one access method." % (i, j),
546 ExtraData="%s" % '\n\t'.join([str(P[1]+'.'+P[0]) for P in IntersectionList])
547 )
548 else:
549 pass
550
551 #
552 # intersection the BinaryPCD for Mixed PCD
553 #
554 for i in BinaryPcdDict_Keys:
555 for j in BinaryPcdDict_Keys:
556 if i != j:
557 IntersectionList = list(set(BinaryPcdDict[i]).intersection(set(BinaryPcdDict[j])))
558 for item in IntersectionList:
559 NewPcd1 = (item[0] + '_' + i, item[1])
560 NewPcd2 = (item[0] + '_' + j, item[1])
561 if item not in GlobalData.MixedPcd:
562 GlobalData.MixedPcd[item] = [NewPcd1, NewPcd2]
563 else:
564 if NewPcd1 not in GlobalData.MixedPcd[item]:
565 GlobalData.MixedPcd[item].append(NewPcd1)
566 if NewPcd2 not in GlobalData.MixedPcd[item]:
567 GlobalData.MixedPcd[item].append(NewPcd2)
568 else:
569 pass
570
571 #
572 # intersection the SourcePCD and BinaryPCD for Mixed PCD
573 #
574 for i in SourcePcdDict_Keys:
575 for j in BinaryPcdDict_Keys:
576 if i != j:
577 IntersectionList = list(set(SourcePcdDict[i]).intersection(set(BinaryPcdDict[j])))
578 for item in IntersectionList:
579 NewPcd1 = (item[0] + '_' + i, item[1])
580 NewPcd2 = (item[0] + '_' + j, item[1])
581 if item not in GlobalData.MixedPcd:
582 GlobalData.MixedPcd[item] = [NewPcd1, NewPcd2]
583 else:
584 if NewPcd1 not in GlobalData.MixedPcd[item]:
585 GlobalData.MixedPcd[item].append(NewPcd1)
586 if NewPcd2 not in GlobalData.MixedPcd[item]:
587 GlobalData.MixedPcd[item].append(NewPcd2)
588 else:
589 pass
590
591 for BuildData in PGen.BuildDatabase._CACHE_.values():
592 if BuildData.Arch != Arch:
593 continue
594 for key in BuildData.Pcds:
595 for SinglePcd in GlobalData.MixedPcd:
596 if (BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName) == SinglePcd:
597 for item in GlobalData.MixedPcd[SinglePcd]:
598 Pcd_Type = item[0].split('_')[-1]
599 if (Pcd_Type == BuildData.Pcds[key].Type) or (Pcd_Type == TAB_PCDS_DYNAMIC_EX and BuildData.Pcds[key].Type in GenC.gDynamicExPcd) or \
600 (Pcd_Type == TAB_PCDS_DYNAMIC and BuildData.Pcds[key].Type in GenC.gDynamicPcd):
601 Value = BuildData.Pcds[key]
602 Value.TokenCName = BuildData.Pcds[key].TokenCName + '_' + Pcd_Type
603 if len(key) == 2:
604 newkey = (Value.TokenCName, key[1])
605 elif len(key) == 3:
606 newkey = (Value.TokenCName, key[1], key[2])
607 del BuildData.Pcds[key]
608 BuildData.Pcds[newkey] = Value
609 break
610 else:
611 pass
612 break
613 else:
614 pass
615
616 # handle the mixed pcd in FDF file
617 for key in PcdSet:
618 if key in GlobalData.MixedPcd:
619 Value = PcdSet[key]
620 del PcdSet[key]
621 for item in GlobalData.MixedPcd[key]:
622 PcdSet[item] = Value
623
624 #Collect package set information from INF of FDF
625 PkgSet = set()
626 for Inf in ModuleList:
627 ModuleFile = PathClass(NormPath(Inf), GlobalData.gWorkspace, Arch)
628 if ModuleFile in Platform.Modules:
629 continue
630 ModuleData = self.BuildDatabase[ModuleFile, Arch, Target, Toolchain]
631 PkgSet.update(ModuleData.Packages)
632 Pkgs = list(PkgSet) + list(PGen.PackageList)
633 for Pkg in Pkgs:
634 for Pcd in Pkg.Pcds:
635 DecPcds[Pcd[0], Pcd[1]] = Pkg.Pcds[Pcd]
636 DecPcdsKey.add((Pcd[0], Pcd[1], Pcd[2]))
637
638 Platform.SkuName = self.SkuId
639 for Name, Guid in PcdSet:
640 if (Name, Guid) not in DecPcds:
641 EdkLogger.error(
642 'build',
643 PARSER_ERROR,
644 "PCD (%s.%s) used in FDF is not declared in DEC files." % (Guid, Name),
645 File = self.FdfProfile.PcdFileLineDict[Name, Guid][0],
646 Line = self.FdfProfile.PcdFileLineDict[Name, Guid][1]
647 )
648 else:
649 # Check whether Dynamic or DynamicEx PCD used in FDF file. If used, build break and give a error message.
650 if (Name, Guid, TAB_PCDS_FIXED_AT_BUILD) in DecPcdsKey \
651 or (Name, Guid, TAB_PCDS_PATCHABLE_IN_MODULE) in DecPcdsKey \
652 or (Name, Guid, TAB_PCDS_FEATURE_FLAG) in DecPcdsKey:
653 Platform.AddPcd(Name, Guid, PcdSet[Name, Guid])
654 continue
655 elif (Name, Guid, TAB_PCDS_DYNAMIC) in DecPcdsKey or (Name, Guid, TAB_PCDS_DYNAMIC_EX) in DecPcdsKey:
656 EdkLogger.error(
657 'build',
658 PARSER_ERROR,
659 "Using Dynamic or DynamicEx type of PCD [%s.%s] in FDF file is not allowed." % (Guid, Name),
660 File = self.FdfProfile.PcdFileLineDict[Name, Guid][0],
661 Line = self.FdfProfile.PcdFileLineDict[Name, Guid][1]
662 )
663
664 Pa = PlatformAutoGen(self, self.MetaFile, Target, Toolchain, Arch)
665 #
666 # Explicitly collect platform's dynamic PCDs
667 #
668 Pa.CollectPlatformDynamicPcds()
669 Pa.CollectFixedAtBuildPcds()
670 self.AutoGenObjectList.append(Pa)
671
672 #
673 # Generate Package level hash value
674 #
675 GlobalData.gPackageHash[Arch] = {}
676 if GlobalData.gUseHashCache:
677 for Pkg in Pkgs:
678 self._GenPkgLevelHash(Pkg)
679
680 #
681 # Check PCDs token value conflict in each DEC file.
682 #
683 self._CheckAllPcdsTokenValueConflict()
684
685 #
686 # Check PCD type and definition between DSC and DEC
687 #
688 self._CheckPcdDefineAndType()
689
690 # if self.FdfFile:
691 # self._CheckDuplicateInFV(Fdf)
692
693 #
694 # Create BuildOptions Macro & PCD metafile, also add the Active Platform and FDF file.
695 #
696 content = 'gCommandLineDefines: '
697 content += str(GlobalData.gCommandLineDefines)
698 content += os.linesep
699 content += 'BuildOptionPcd: '
700 content += str(GlobalData.BuildOptionPcd)
701 content += os.linesep
702 content += 'Active Platform: '
703 content += str(self.Platform)
704 content += os.linesep
705 if self.FdfFile:
706 content += 'Flash Image Definition: '
707 content += str(self.FdfFile)
708 content += os.linesep
709 SaveFileOnChange(os.path.join(self.BuildDir, 'BuildOptions'), content, False)
710
711 #
712 # Create PcdToken Number file for Dynamic/DynamicEx Pcd.
713 #
714 PcdTokenNumber = 'PcdTokenNumber: '
715 if Pa.PcdTokenNumber:
716 if Pa.DynamicPcdList:
717 for Pcd in Pa.DynamicPcdList:
718 PcdTokenNumber += os.linesep
719 PcdTokenNumber += str((Pcd.TokenCName, Pcd.TokenSpaceGuidCName))
720 PcdTokenNumber += ' : '
721 PcdTokenNumber += str(Pa.PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName])
722 SaveFileOnChange(os.path.join(self.BuildDir, 'PcdTokenNumber'), PcdTokenNumber, False)
723
724 #
725 # Get set of workspace metafiles
726 #
727 AllWorkSpaceMetaFiles = self._GetMetaFiles(Target, Toolchain, Arch)
728
729 #
730 # Retrieve latest modified time of all metafiles
731 #
732 SrcTimeStamp = 0
733 for f in AllWorkSpaceMetaFiles:
734 if os.stat(f)[8] > SrcTimeStamp:
735 SrcTimeStamp = os.stat(f)[8]
736 self._SrcTimeStamp = SrcTimeStamp
737
738 if GlobalData.gUseHashCache:
739 m = hashlib.md5()
740 for files in AllWorkSpaceMetaFiles:
741 if files.endswith('.dec'):
742 continue
743 f = open(files, 'r')
744 Content = f.read()
745 f.close()
746 m.update(Content)
747 SaveFileOnChange(os.path.join(self.BuildDir, 'AutoGen.hash'), m.hexdigest(), True)
748 GlobalData.gPlatformHash = m.hexdigest()
749
750 #
751 # Write metafile list to build directory
752 #
753 AutoGenFilePath = os.path.join(self.BuildDir, 'AutoGen')
754 if os.path.exists (AutoGenFilePath):
755 os.remove(AutoGenFilePath)
756 if not os.path.exists(self.BuildDir):
757 os.makedirs(self.BuildDir)
758 with open(os.path.join(self.BuildDir, 'AutoGen'), 'w+') as file:
759 for f in AllWorkSpaceMetaFiles:
760 print >> file, f
761 return True
762
763 def _GenPkgLevelHash(self, Pkg):
764 PkgDir = os.path.join(self.BuildDir, Pkg.Arch, Pkg.PackageName)
765 CreateDirectory(PkgDir)
766 HashFile = os.path.join(PkgDir, Pkg.PackageName + '.hash')
767 m = hashlib.md5()
768 # Get .dec file's hash value
769 f = open(Pkg.MetaFile.Path, 'r')
770 Content = f.read()
771 f.close()
772 m.update(Content)
773 # Get include files hash value
774 if Pkg.Includes:
775 for inc in Pkg.Includes:
776 for Root, Dirs, Files in os.walk(str(inc)):
777 for File in Files:
778 File_Path = os.path.join(Root, File)
779 f = open(File_Path, 'r')
780 Content = f.read()
781 f.close()
782 m.update(Content)
783 SaveFileOnChange(HashFile, m.hexdigest(), True)
784 if Pkg.PackageName not in GlobalData.gPackageHash[Pkg.Arch]:
785 GlobalData.gPackageHash[Pkg.Arch][Pkg.PackageName] = m.hexdigest()
786
787 def _GetMetaFiles(self, Target, Toolchain, Arch):
788 AllWorkSpaceMetaFiles = set()
789 #
790 # add fdf
791 #
792 if self.FdfFile:
793 AllWorkSpaceMetaFiles.add (self.FdfFile.Path)
794 if self.FdfFile:
795 FdfFiles = GlobalData.gFdfParser.GetAllIncludedFile()
796 for f in FdfFiles:
797 AllWorkSpaceMetaFiles.add (f.FileName)
798 #
799 # add dsc
800 #
801 AllWorkSpaceMetaFiles.add(self.MetaFile.Path)
802
803 #
804 # add build_rule.txt & tools_def.txt
805 #
806 AllWorkSpaceMetaFiles.add(os.path.join(GlobalData.gConfDirectory, gDefaultBuildRuleFile))
807 AllWorkSpaceMetaFiles.add(os.path.join(GlobalData.gConfDirectory, gDefaultToolsDefFile))
808
809 # add BuildOption metafile
810 #
811 AllWorkSpaceMetaFiles.add(os.path.join(self.BuildDir, 'BuildOptions'))
812
813 # add PcdToken Number file for Dynamic/DynamicEx Pcd
814 #
815 AllWorkSpaceMetaFiles.add(os.path.join(self.BuildDir, 'PcdTokenNumber'))
816
817 for Arch in self.ArchList:
818 Platform = self.BuildDatabase[self.MetaFile, Arch, Target, Toolchain]
819 PGen = PlatformAutoGen(self, self.MetaFile, Target, Toolchain, Arch)
820
821 #
822 # add dec
823 #
824 for Package in PGen.PackageList:
825 AllWorkSpaceMetaFiles.add(Package.MetaFile.Path)
826
827 #
828 # add included dsc
829 #
830 for filePath in Platform._RawData.IncludedFiles:
831 AllWorkSpaceMetaFiles.add(filePath.Path)
832
833 return AllWorkSpaceMetaFiles
834
835 ## _CheckDuplicateInFV() method
836 #
837 # Check whether there is duplicate modules/files exist in FV section.
838 # The check base on the file GUID;
839 #
840 def _CheckDuplicateInFV(self, Fdf):
841 for Fv in Fdf.Profile.FvDict:
842 _GuidDict = {}
843 for FfsFile in Fdf.Profile.FvDict[Fv].FfsList:
844 if FfsFile.InfFileName and FfsFile.NameGuid == None:
845 #
846 # Get INF file GUID
847 #
848 InfFoundFlag = False
849 for Pa in self.AutoGenObjectList:
850 if InfFoundFlag:
851 break
852 for Module in Pa.ModuleAutoGenList:
853 if path.normpath(Module.MetaFile.File) == path.normpath(FfsFile.InfFileName):
854 InfFoundFlag = True
855 if not Module.Guid.upper() in _GuidDict.keys():
856 _GuidDict[Module.Guid.upper()] = FfsFile
857 break
858 else:
859 EdkLogger.error("build",
860 FORMAT_INVALID,
861 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile.CurrentLineNum,
862 FfsFile.CurrentLineContent,
863 _GuidDict[Module.Guid.upper()].CurrentLineNum,
864 _GuidDict[Module.Guid.upper()].CurrentLineContent,
865 Module.Guid.upper()),
866 ExtraData=self.FdfFile)
867 #
868 # Some INF files not have entity in DSC file.
869 #
870 if not InfFoundFlag:
871 if FfsFile.InfFileName.find('$') == -1:
872 InfPath = NormPath(FfsFile.InfFileName)
873 if not os.path.exists(InfPath):
874 EdkLogger.error('build', GENFDS_ERROR, "Non-existant Module %s !" % (FfsFile.InfFileName))
875
876 PathClassObj = PathClass(FfsFile.InfFileName, self.WorkspaceDir)
877 #
878 # Here we just need to get FILE_GUID from INF file, use 'COMMON' as ARCH attribute. and use
879 # BuildObject from one of AutoGenObjectList is enough.
880 #
881 InfObj = self.AutoGenObjectList[0].BuildDatabase.WorkspaceDb.BuildObject[PathClassObj, 'COMMON', self.BuildTarget, self.ToolChain]
882 if not InfObj.Guid.upper() in _GuidDict.keys():
883 _GuidDict[InfObj.Guid.upper()] = FfsFile
884 else:
885 EdkLogger.error("build",
886 FORMAT_INVALID,
887 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile.CurrentLineNum,
888 FfsFile.CurrentLineContent,
889 _GuidDict[InfObj.Guid.upper()].CurrentLineNum,
890 _GuidDict[InfObj.Guid.upper()].CurrentLineContent,
891 InfObj.Guid.upper()),
892 ExtraData=self.FdfFile)
893 InfFoundFlag = False
894
895 if FfsFile.NameGuid != None:
896 _CheckPCDAsGuidPattern = re.compile("^PCD\(.+\..+\)$")
897
898 #
899 # If the NameGuid reference a PCD name.
900 # The style must match: PCD(xxxx.yyy)
901 #
902 if _CheckPCDAsGuidPattern.match(FfsFile.NameGuid):
903 #
904 # Replace the PCD value.
905 #
906 _PcdName = FfsFile.NameGuid.lstrip("PCD(").rstrip(")")
907 PcdFoundFlag = False
908 for Pa in self.AutoGenObjectList:
909 if not PcdFoundFlag:
910 for PcdItem in Pa.AllPcdList:
911 if (PcdItem.TokenSpaceGuidCName + "." + PcdItem.TokenCName) == _PcdName:
912 #
913 # First convert from CFormatGuid to GUID string
914 #
915 _PcdGuidString = GuidStructureStringToGuidString(PcdItem.DefaultValue)
916
917 if not _PcdGuidString:
918 #
919 # Then try Byte array.
920 #
921 _PcdGuidString = GuidStructureByteArrayToGuidString(PcdItem.DefaultValue)
922
923 if not _PcdGuidString:
924 #
925 # Not Byte array or CFormat GUID, raise error.
926 #
927 EdkLogger.error("build",
928 FORMAT_INVALID,
929 "The format of PCD value is incorrect. PCD: %s , Value: %s\n" % (_PcdName, PcdItem.DefaultValue),
930 ExtraData=self.FdfFile)
931
932 if not _PcdGuidString.upper() in _GuidDict.keys():
933 _GuidDict[_PcdGuidString.upper()] = FfsFile
934 PcdFoundFlag = True
935 break
936 else:
937 EdkLogger.error("build",
938 FORMAT_INVALID,
939 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile.CurrentLineNum,
940 FfsFile.CurrentLineContent,
941 _GuidDict[_PcdGuidString.upper()].CurrentLineNum,
942 _GuidDict[_PcdGuidString.upper()].CurrentLineContent,
943 FfsFile.NameGuid.upper()),
944 ExtraData=self.FdfFile)
945
946 if not FfsFile.NameGuid.upper() in _GuidDict.keys():
947 _GuidDict[FfsFile.NameGuid.upper()] = FfsFile
948 else:
949 #
950 # Two raw file GUID conflict.
951 #
952 EdkLogger.error("build",
953 FORMAT_INVALID,
954 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile.CurrentLineNum,
955 FfsFile.CurrentLineContent,
956 _GuidDict[FfsFile.NameGuid.upper()].CurrentLineNum,
957 _GuidDict[FfsFile.NameGuid.upper()].CurrentLineContent,
958 FfsFile.NameGuid.upper()),
959 ExtraData=self.FdfFile)
960
961
962 def _CheckPcdDefineAndType(self):
963 PcdTypeList = [
964 "FixedAtBuild", "PatchableInModule", "FeatureFlag",
965 "Dynamic", #"DynamicHii", "DynamicVpd",
966 "DynamicEx", # "DynamicExHii", "DynamicExVpd"
967 ]
968
969 # This dict store PCDs which are not used by any modules with specified arches
970 UnusedPcd = sdict()
971 for Pa in self.AutoGenObjectList:
972 # Key of DSC's Pcds dictionary is PcdCName, TokenSpaceGuid
973 for Pcd in Pa.Platform.Pcds:
974 PcdType = Pa.Platform.Pcds[Pcd].Type
975
976 # If no PCD type, this PCD comes from FDF
977 if not PcdType:
978 continue
979
980 # Try to remove Hii and Vpd suffix
981 if PcdType.startswith("DynamicEx"):
982 PcdType = "DynamicEx"
983 elif PcdType.startswith("Dynamic"):
984 PcdType = "Dynamic"
985
986 for Package in Pa.PackageList:
987 # Key of DEC's Pcds dictionary is PcdCName, TokenSpaceGuid, PcdType
988 if (Pcd[0], Pcd[1], PcdType) in Package.Pcds:
989 break
990 for Type in PcdTypeList:
991 if (Pcd[0], Pcd[1], Type) in Package.Pcds:
992 EdkLogger.error(
993 'build',
994 FORMAT_INVALID,
995 "Type [%s] of PCD [%s.%s] in DSC file doesn't match the type [%s] defined in DEC file." \
996 % (Pa.Platform.Pcds[Pcd].Type, Pcd[1], Pcd[0], Type),
997 ExtraData=None
998 )
999 return
1000 else:
1001 UnusedPcd.setdefault(Pcd, []).append(Pa.Arch)
1002
1003 for Pcd in UnusedPcd:
1004 EdkLogger.warn(
1005 'build',
1006 "The PCD was not specified by any INF module in the platform for the given architecture.\n"
1007 "\tPCD: [%s.%s]\n\tPlatform: [%s]\n\tArch: %s"
1008 % (Pcd[1], Pcd[0], os.path.basename(str(self.MetaFile)), str(UnusedPcd[Pcd])),
1009 ExtraData=None
1010 )
1011
1012 def __repr__(self):
1013 return "%s [%s]" % (self.MetaFile, ", ".join(self.ArchList))
1014
1015 ## Return the directory to store FV files
1016 def _GetFvDir(self):
1017 if self._FvDir == None:
1018 self._FvDir = path.join(self.BuildDir, 'FV')
1019 return self._FvDir
1020
1021 ## Return the directory to store all intermediate and final files built
1022 def _GetBuildDir(self):
1023 if self._BuildDir == None:
1024 return self.AutoGenObjectList[0].BuildDir
1025
1026 ## Return the build output directory platform specifies
1027 def _GetOutputDir(self):
1028 return self.Platform.OutputDirectory
1029
1030 ## Return platform name
1031 def _GetName(self):
1032 return self.Platform.PlatformName
1033
1034 ## Return meta-file GUID
1035 def _GetGuid(self):
1036 return self.Platform.Guid
1037
1038 ## Return platform version
1039 def _GetVersion(self):
1040 return self.Platform.Version
1041
1042 ## Return paths of tools
1043 def _GetToolDefinition(self):
1044 return self.AutoGenObjectList[0].ToolDefinition
1045
1046 ## Return directory of platform makefile
1047 #
1048 # @retval string Makefile directory
1049 #
1050 def _GetMakeFileDir(self):
1051 if self._MakeFileDir == None:
1052 self._MakeFileDir = self.BuildDir
1053 return self._MakeFileDir
1054
1055 ## Return build command string
1056 #
1057 # @retval string Build command string
1058 #
1059 def _GetBuildCommand(self):
1060 if self._BuildCommand == None:
1061 # BuildCommand should be all the same. So just get one from platform AutoGen
1062 self._BuildCommand = self.AutoGenObjectList[0].BuildCommand
1063 return self._BuildCommand
1064
1065 ## Check the PCDs token value conflict in each DEC file.
1066 #
1067 # Will cause build break and raise error message while two PCDs conflict.
1068 #
1069 # @return None
1070 #
1071 def _CheckAllPcdsTokenValueConflict(self):
1072 for Pa in self.AutoGenObjectList:
1073 for Package in Pa.PackageList:
1074 PcdList = Package.Pcds.values()
1075 PcdList.sort(lambda x, y: cmp(int(x.TokenValue, 0), int(y.TokenValue, 0)))
1076 Count = 0
1077 while (Count < len(PcdList) - 1) :
1078 Item = PcdList[Count]
1079 ItemNext = PcdList[Count + 1]
1080 #
1081 # Make sure in the same token space the TokenValue should be unique
1082 #
1083 if (int(Item.TokenValue, 0) == int(ItemNext.TokenValue, 0)):
1084 SameTokenValuePcdList = []
1085 SameTokenValuePcdList.append(Item)
1086 SameTokenValuePcdList.append(ItemNext)
1087 RemainPcdListLength = len(PcdList) - Count - 2
1088 for ValueSameCount in range(RemainPcdListLength):
1089 if int(PcdList[len(PcdList) - RemainPcdListLength + ValueSameCount].TokenValue, 0) == int(Item.TokenValue, 0):
1090 SameTokenValuePcdList.append(PcdList[len(PcdList) - RemainPcdListLength + ValueSameCount])
1091 else:
1092 break;
1093 #
1094 # Sort same token value PCD list with TokenGuid and TokenCName
1095 #
1096 SameTokenValuePcdList.sort(lambda x, y: cmp("%s.%s" % (x.TokenSpaceGuidCName, x.TokenCName), "%s.%s" % (y.TokenSpaceGuidCName, y.TokenCName)))
1097 SameTokenValuePcdListCount = 0
1098 while (SameTokenValuePcdListCount < len(SameTokenValuePcdList) - 1):
1099 Flag = False
1100 TemListItem = SameTokenValuePcdList[SameTokenValuePcdListCount]
1101 TemListItemNext = SameTokenValuePcdList[SameTokenValuePcdListCount + 1]
1102
1103 if (TemListItem.TokenSpaceGuidCName == TemListItemNext.TokenSpaceGuidCName) and (TemListItem.TokenCName != TemListItemNext.TokenCName):
1104 for PcdItem in GlobalData.MixedPcd:
1105 if (TemListItem.TokenCName, TemListItem.TokenSpaceGuidCName) in GlobalData.MixedPcd[PcdItem] or \
1106 (TemListItemNext.TokenCName, TemListItemNext.TokenSpaceGuidCName) in GlobalData.MixedPcd[PcdItem]:
1107 Flag = True
1108 if not Flag:
1109 EdkLogger.error(
1110 'build',
1111 FORMAT_INVALID,
1112 "The TokenValue [%s] of PCD [%s.%s] is conflict with: [%s.%s] in %s"\
1113 % (TemListItem.TokenValue, TemListItem.TokenSpaceGuidCName, TemListItem.TokenCName, TemListItemNext.TokenSpaceGuidCName, TemListItemNext.TokenCName, Package),
1114 ExtraData=None
1115 )
1116 SameTokenValuePcdListCount += 1
1117 Count += SameTokenValuePcdListCount
1118 Count += 1
1119
1120 PcdList = Package.Pcds.values()
1121 PcdList.sort(lambda x, y: cmp("%s.%s" % (x.TokenSpaceGuidCName, x.TokenCName), "%s.%s" % (y.TokenSpaceGuidCName, y.TokenCName)))
1122 Count = 0
1123 while (Count < len(PcdList) - 1) :
1124 Item = PcdList[Count]
1125 ItemNext = PcdList[Count + 1]
1126 #
1127 # Check PCDs with same TokenSpaceGuidCName.TokenCName have same token value as well.
1128 #
1129 if (Item.TokenSpaceGuidCName == ItemNext.TokenSpaceGuidCName) and (Item.TokenCName == ItemNext.TokenCName) and (int(Item.TokenValue, 0) != int(ItemNext.TokenValue, 0)):
1130 EdkLogger.error(
1131 'build',
1132 FORMAT_INVALID,
1133 "The TokenValue [%s] of PCD [%s.%s] in %s defined in two places should be same as well."\
1134 % (Item.TokenValue, Item.TokenSpaceGuidCName, Item.TokenCName, Package),
1135 ExtraData=None
1136 )
1137 Count += 1
1138 ## Generate fds command
1139 def _GenFdsCommand(self):
1140 return (GenMake.TopLevelMakefile(self)._TEMPLATE_.Replace(GenMake.TopLevelMakefile(self)._TemplateDict)).strip()
1141
1142 ## Create makefile for the platform and modules in it
1143 #
1144 # @param CreateDepsMakeFile Flag indicating if the makefile for
1145 # modules will be created as well
1146 #
1147 def CreateMakeFile(self, CreateDepsMakeFile=False):
1148 if CreateDepsMakeFile:
1149 for Pa in self.AutoGenObjectList:
1150 Pa.CreateMakeFile(CreateDepsMakeFile)
1151
1152 ## Create autogen code for platform and modules
1153 #
1154 # Since there's no autogen code for platform, this method will do nothing
1155 # if CreateModuleCodeFile is set to False.
1156 #
1157 # @param CreateDepsCodeFile Flag indicating if creating module's
1158 # autogen code file or not
1159 #
1160 def CreateCodeFile(self, CreateDepsCodeFile=False):
1161 if not CreateDepsCodeFile:
1162 return
1163 for Pa in self.AutoGenObjectList:
1164 Pa.CreateCodeFile(CreateDepsCodeFile)
1165
1166 ## Create AsBuilt INF file the platform
1167 #
1168 def CreateAsBuiltInf(self):
1169 return
1170
1171 Name = property(_GetName)
1172 Guid = property(_GetGuid)
1173 Version = property(_GetVersion)
1174 OutputDir = property(_GetOutputDir)
1175
1176 ToolDefinition = property(_GetToolDefinition) # toolcode : tool path
1177
1178 BuildDir = property(_GetBuildDir)
1179 FvDir = property(_GetFvDir)
1180 MakeFileDir = property(_GetMakeFileDir)
1181 BuildCommand = property(_GetBuildCommand)
1182 GenFdsCommand = property(_GenFdsCommand)
1183
1184 ## AutoGen class for platform
1185 #
1186 # PlatformAutoGen class will process the original information in platform
1187 # file in order to generate makefile for platform.
1188 #
1189 class PlatformAutoGen(AutoGen):
1190 #
1191 # Used to store all PCDs for both PEI and DXE phase, in order to generate
1192 # correct PCD database
1193 #
1194 _DynaPcdList_ = []
1195 _NonDynaPcdList_ = []
1196 _PlatformPcds = {}
1197
1198 #
1199 # The priority list while override build option
1200 #
1201 PrioList = {"0x11111" : 16, # TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE (Highest)
1202 "0x01111" : 15, # ******_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
1203 "0x10111" : 14, # TARGET_*********_ARCH_COMMANDTYPE_ATTRIBUTE
1204 "0x00111" : 13, # ******_*********_ARCH_COMMANDTYPE_ATTRIBUTE
1205 "0x11011" : 12, # TARGET_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
1206 "0x01011" : 11, # ******_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
1207 "0x10011" : 10, # TARGET_*********_****_COMMANDTYPE_ATTRIBUTE
1208 "0x00011" : 9, # ******_*********_****_COMMANDTYPE_ATTRIBUTE
1209 "0x11101" : 8, # TARGET_TOOLCHAIN_ARCH_***********_ATTRIBUTE
1210 "0x01101" : 7, # ******_TOOLCHAIN_ARCH_***********_ATTRIBUTE
1211 "0x10101" : 6, # TARGET_*********_ARCH_***********_ATTRIBUTE
1212 "0x00101" : 5, # ******_*********_ARCH_***********_ATTRIBUTE
1213 "0x11001" : 4, # TARGET_TOOLCHAIN_****_***********_ATTRIBUTE
1214 "0x01001" : 3, # ******_TOOLCHAIN_****_***********_ATTRIBUTE
1215 "0x10001" : 2, # TARGET_*********_****_***********_ATTRIBUTE
1216 "0x00001" : 1} # ******_*********_****_***********_ATTRIBUTE (Lowest)
1217
1218 ## The real constructor of PlatformAutoGen
1219 #
1220 # This method is not supposed to be called by users of PlatformAutoGen. It's
1221 # only used by factory method __new__() to do real initialization work for an
1222 # object of PlatformAutoGen
1223 #
1224 # @param Workspace WorkspaceAutoGen object
1225 # @param PlatformFile Platform file (DSC file)
1226 # @param Target Build target (DEBUG, RELEASE)
1227 # @param Toolchain Name of tool chain
1228 # @param Arch arch of the platform supports
1229 #
1230 def _Init(self, Workspace, PlatformFile, Target, Toolchain, Arch):
1231 EdkLogger.debug(EdkLogger.DEBUG_9, "AutoGen platform [%s] [%s]" % (PlatformFile, Arch))
1232 GlobalData.gProcessingFile = "%s [%s, %s, %s]" % (PlatformFile, Arch, Toolchain, Target)
1233
1234 self.MetaFile = PlatformFile
1235 self.Workspace = Workspace
1236 self.WorkspaceDir = Workspace.WorkspaceDir
1237 self.ToolChain = Toolchain
1238 self.BuildTarget = Target
1239 self.Arch = Arch
1240 self.SourceDir = PlatformFile.SubDir
1241 self.SourceOverrideDir = None
1242 self.FdTargetList = self.Workspace.FdTargetList
1243 self.FvTargetList = self.Workspace.FvTargetList
1244 self.AllPcdList = []
1245 # get the original module/package/platform objects
1246 self.BuildDatabase = Workspace.BuildDatabase
1247 self.DscBuildDataObj = Workspace.Platform
1248 self._GuidDict = Workspace._GuidDict
1249
1250 # flag indicating if the makefile/C-code file has been created or not
1251 self.IsMakeFileCreated = False
1252 self.IsCodeFileCreated = False
1253
1254 self._Platform = None
1255 self._Name = None
1256 self._Guid = None
1257 self._Version = None
1258
1259 self._BuildRule = None
1260 self._SourceDir = None
1261 self._BuildDir = None
1262 self._OutputDir = None
1263 self._FvDir = None
1264 self._MakeFileDir = None
1265 self._FdfFile = None
1266
1267 self._PcdTokenNumber = None # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber
1268 self._DynamicPcdList = None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
1269 self._NonDynamicPcdList = None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
1270 self._NonDynamicPcdDict = {}
1271
1272 self._ToolDefinitions = None
1273 self._ToolDefFile = None # toolcode : tool path
1274 self._ToolChainFamily = None
1275 self._BuildRuleFamily = None
1276 self._BuildOption = None # toolcode : option
1277 self._EdkBuildOption = None # edktoolcode : option
1278 self._EdkIIBuildOption = None # edkiitoolcode : option
1279 self._PackageList = None
1280 self._ModuleAutoGenList = None
1281 self._LibraryAutoGenList = None
1282 self._BuildCommand = None
1283 self._AsBuildInfList = []
1284 self._AsBuildModuleList = []
1285
1286 self.VariableInfo = None
1287
1288 if GlobalData.gFdfParser != None:
1289 self._AsBuildInfList = GlobalData.gFdfParser.Profile.InfList
1290 for Inf in self._AsBuildInfList:
1291 InfClass = PathClass(NormPath(Inf), GlobalData.gWorkspace, self.Arch)
1292 M = self.BuildDatabase[InfClass, self.Arch, self.BuildTarget, self.ToolChain]
1293 if not M.IsSupportedArch:
1294 continue
1295 self._AsBuildModuleList.append(InfClass)
1296 # get library/modules for build
1297 self.LibraryBuildDirectoryList = []
1298 self.ModuleBuildDirectoryList = []
1299
1300 return True
1301
1302 def __repr__(self):
1303 return "%s [%s]" % (self.MetaFile, self.Arch)
1304
1305 ## Create autogen code for platform and modules
1306 #
1307 # Since there's no autogen code for platform, this method will do nothing
1308 # if CreateModuleCodeFile is set to False.
1309 #
1310 # @param CreateModuleCodeFile Flag indicating if creating module's
1311 # autogen code file or not
1312 #
1313 def CreateCodeFile(self, CreateModuleCodeFile=False):
1314 # only module has code to be greated, so do nothing if CreateModuleCodeFile is False
1315 if self.IsCodeFileCreated or not CreateModuleCodeFile:
1316 return
1317
1318 for Ma in self.ModuleAutoGenList:
1319 Ma.CreateCodeFile(True)
1320
1321 # don't do this twice
1322 self.IsCodeFileCreated = True
1323
1324 ## Generate Fds Command
1325 def _GenFdsCommand(self):
1326 return self.Workspace.GenFdsCommand
1327
1328 ## Create makefile for the platform and mdoules in it
1329 #
1330 # @param CreateModuleMakeFile Flag indicating if the makefile for
1331 # modules will be created as well
1332 #
1333 def CreateMakeFile(self, CreateModuleMakeFile=False, FfsCommand = {}):
1334 if CreateModuleMakeFile:
1335 for ModuleFile in self.Platform.Modules:
1336 Ma = ModuleAutoGen(self.Workspace, ModuleFile, self.BuildTarget,
1337 self.ToolChain, self.Arch, self.MetaFile)
1338 if (ModuleFile.File, self.Arch) in FfsCommand:
1339 Ma.CreateMakeFile(True, FfsCommand[ModuleFile.File, self.Arch])
1340 else:
1341 Ma.CreateMakeFile(True)
1342 #Ma.CreateAsBuiltInf()
1343
1344 # no need to create makefile for the platform more than once
1345 if self.IsMakeFileCreated:
1346 return
1347
1348 # create library/module build dirs for platform
1349 Makefile = GenMake.PlatformMakefile(self)
1350 self.LibraryBuildDirectoryList = Makefile.GetLibraryBuildDirectoryList()
1351 self.ModuleBuildDirectoryList = Makefile.GetModuleBuildDirectoryList()
1352
1353 self.IsMakeFileCreated = True
1354
1355 ## Deal with Shared FixedAtBuild Pcds
1356 #
1357 def CollectFixedAtBuildPcds(self):
1358 for LibAuto in self.LibraryAutoGenList:
1359 FixedAtBuildPcds = {}
1360 ShareFixedAtBuildPcdsSameValue = {}
1361 for Module in LibAuto._ReferenceModules:
1362 for Pcd in Module.FixedAtBuildPcds + LibAuto.FixedAtBuildPcds:
1363 key = ".".join((Pcd.TokenSpaceGuidCName,Pcd.TokenCName))
1364 if key not in FixedAtBuildPcds:
1365 ShareFixedAtBuildPcdsSameValue[key] = True
1366 FixedAtBuildPcds[key] = Pcd.DefaultValue
1367 else:
1368 if FixedAtBuildPcds[key] != Pcd.DefaultValue:
1369 ShareFixedAtBuildPcdsSameValue[key] = False
1370 for Pcd in LibAuto.FixedAtBuildPcds:
1371 key = ".".join((Pcd.TokenSpaceGuidCName,Pcd.TokenCName))
1372 if (Pcd.TokenCName,Pcd.TokenSpaceGuidCName) not in self.NonDynamicPcdDict:
1373 continue
1374 else:
1375 DscPcd = self.NonDynamicPcdDict[(Pcd.TokenCName,Pcd.TokenSpaceGuidCName)]
1376 if DscPcd.Type != "FixedAtBuild":
1377 continue
1378 if key in ShareFixedAtBuildPcdsSameValue and ShareFixedAtBuildPcdsSameValue[key]:
1379 LibAuto.ConstPcd[key] = Pcd.DefaultValue
1380
1381 def CollectVariables(self, DynamicPcdSet):
1382
1383 VpdRegionSize = 0
1384 VpdRegionBase = 0
1385 if self.Workspace.FdfFile:
1386 FdDict = self.Workspace.FdfProfile.FdDict[GlobalData.gFdfParser.CurrentFdName]
1387 for FdRegion in FdDict.RegionList:
1388 for item in FdRegion.RegionDataList:
1389 if self.Platform.VpdToolGuid.strip() and self.Platform.VpdToolGuid in item:
1390 VpdRegionSize = FdRegion.Size
1391 VpdRegionBase = FdRegion.Offset
1392 break
1393
1394
1395 VariableInfo = VariableMgr(self.DscBuildDataObj._GetDefaultStores(),self.DscBuildDataObj._GetSkuIds())
1396 VariableInfo.SetVpdRegionMaxSize(VpdRegionSize)
1397 VariableInfo.SetVpdRegionOffset(VpdRegionBase)
1398 Index = 0
1399 for Pcd in DynamicPcdSet:
1400 pcdname = ".".join((Pcd.TokenSpaceGuidCName,Pcd.TokenCName))
1401 for SkuName in Pcd.SkuInfoList:
1402 Sku = Pcd.SkuInfoList[SkuName]
1403 SkuId = Sku.SkuId
1404 if SkuId == None or SkuId == '':
1405 continue
1406 if len(Sku.VariableName) > 0:
1407 VariableGuidStructure = Sku.VariableGuidValue
1408 VariableGuid = GuidStructureStringToGuidString(VariableGuidStructure)
1409 for StorageName in Sku.DefaultStoreDict:
1410 VariableInfo.append_variable(var_info(Index,pcdname,StorageName,SkuName, StringToArray(Sku.VariableName),VariableGuid, Sku.VariableOffset, Sku.VariableAttribute , Sku.HiiDefaultValue,Sku.DefaultStoreDict[StorageName],Pcd.DatumType))
1411 Index += 1
1412 return VariableInfo
1413
1414 def UpdateNVStoreMaxSize(self,OrgVpdFile):
1415 if self.VariableInfo:
1416 VpdMapFilePath = os.path.join(self.BuildDir, "FV", "%s.map" % self.Platform.VpdToolGuid)
1417 PcdNvStoreDfBuffer = [item for item in self._DynamicPcdList if item.TokenCName == "PcdNvStoreDefaultValueBuffer" and item.TokenSpaceGuidCName == "gEfiMdeModulePkgTokenSpaceGuid"]
1418
1419 if PcdNvStoreDfBuffer:
1420 if os.path.exists(VpdMapFilePath):
1421 OrgVpdFile.Read(VpdMapFilePath)
1422 PcdItems = OrgVpdFile.GetOffset(PcdNvStoreDfBuffer[0])
1423 NvStoreOffset = PcdItems.values()[0].strip() if PcdItems else '0'
1424 else:
1425 EdkLogger.error("build", FILE_READ_FAILURE, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath)
1426
1427 NvStoreOffset = int(NvStoreOffset,16) if NvStoreOffset.upper().startswith("0X") else int(NvStoreOffset)
1428 default_skuobj = PcdNvStoreDfBuffer[0].SkuInfoList.get("DEFAULT")
1429 maxsize = self.VariableInfo.VpdRegionSize - NvStoreOffset if self.VariableInfo.VpdRegionSize else len(default_skuobj.DefaultValue.split(","))
1430 var_data = self.VariableInfo.PatchNVStoreDefaultMaxSize(maxsize)
1431
1432 if var_data and default_skuobj:
1433 default_skuobj.DefaultValue = var_data
1434 PcdNvStoreDfBuffer[0].DefaultValue = var_data
1435 PcdNvStoreDfBuffer[0].SkuInfoList.clear()
1436 PcdNvStoreDfBuffer[0].SkuInfoList['DEFAULT'] = default_skuobj
1437 PcdNvStoreDfBuffer[0].MaxDatumSize = str(len(default_skuobj.DefaultValue.split(",")))
1438
1439 return OrgVpdFile
1440
1441 ## Collect dynamic PCDs
1442 #
1443 # Gather dynamic PCDs list from each module and their settings from platform
1444 # This interface should be invoked explicitly when platform action is created.
1445 #
1446 def CollectPlatformDynamicPcds(self):
1447 # Override the platform Pcd's value by build option
1448 if GlobalData.BuildOptionPcd:
1449 for key in self.Platform.Pcds:
1450 PlatformPcd = self.Platform.Pcds[key]
1451 for PcdItem in GlobalData.BuildOptionPcd:
1452 if (PlatformPcd.TokenSpaceGuidCName, PlatformPcd.TokenCName) == (PcdItem[0], PcdItem[1]):
1453 PlatformPcd.DefaultValue = PcdItem[2]
1454 if PlatformPcd.SkuInfoList:
1455 Sku = PlatformPcd.SkuInfoList[PlatformPcd.SkuInfoList.keys()[0]]
1456 Sku.DefaultValue = PcdItem[2]
1457 break
1458
1459 for key in self.Platform.Pcds:
1460 for SinglePcd in GlobalData.MixedPcd:
1461 if (self.Platform.Pcds[key].TokenCName, self.Platform.Pcds[key].TokenSpaceGuidCName) == SinglePcd:
1462 for item in GlobalData.MixedPcd[SinglePcd]:
1463 Pcd_Type = item[0].split('_')[-1]
1464 if (Pcd_Type == self.Platform.Pcds[key].Type) or (Pcd_Type == TAB_PCDS_DYNAMIC_EX and self.Platform.Pcds[key].Type in GenC.gDynamicExPcd) or \
1465 (Pcd_Type == TAB_PCDS_DYNAMIC and self.Platform.Pcds[key].Type in GenC.gDynamicPcd):
1466 Value = self.Platform.Pcds[key]
1467 Value.TokenCName = self.Platform.Pcds[key].TokenCName + '_' + Pcd_Type
1468 if len(key) == 2:
1469 newkey = (Value.TokenCName, key[1])
1470 elif len(key) == 3:
1471 newkey = (Value.TokenCName, key[1], key[2])
1472 del self.Platform.Pcds[key]
1473 self.Platform.Pcds[newkey] = Value
1474 break
1475 else:
1476 pass
1477 break
1478 else:
1479 pass
1480
1481 # for gathering error information
1482 NoDatumTypePcdList = set()
1483 PcdNotInDb = []
1484 self._GuidValue = {}
1485 FdfModuleList = []
1486 for InfName in self._AsBuildInfList:
1487 InfName = mws.join(self.WorkspaceDir, InfName)
1488 FdfModuleList.append(os.path.normpath(InfName))
1489 for F in self.Platform.Modules.keys():
1490 M = ModuleAutoGen(self.Workspace, F, self.BuildTarget, self.ToolChain, self.Arch, self.MetaFile)
1491 #GuidValue.update(M.Guids)
1492
1493 self.Platform.Modules[F].M = M
1494
1495 for PcdFromModule in M.ModulePcdList + M.LibraryPcdList:
1496 # make sure that the "VOID*" kind of datum has MaxDatumSize set
1497 if PcdFromModule.DatumType == "VOID*" and PcdFromModule.MaxDatumSize in [None, '']:
1498 NoDatumTypePcdList.add("%s.%s [%s]" % (PcdFromModule.TokenSpaceGuidCName, PcdFromModule.TokenCName, F))
1499
1500 # Check the PCD from Binary INF or Source INF
1501 if M.IsBinaryModule == True:
1502 PcdFromModule.IsFromBinaryInf = True
1503
1504 # Check the PCD from DSC or not
1505 if (PcdFromModule.TokenCName, PcdFromModule.TokenSpaceGuidCName) in self.Platform.Pcds.keys():
1506 PcdFromModule.IsFromDsc = True
1507 else:
1508 PcdFromModule.IsFromDsc = False
1509 if PcdFromModule.Type in GenC.gDynamicPcd or PcdFromModule.Type in GenC.gDynamicExPcd:
1510 if F.Path not in FdfModuleList:
1511 # If one of the Source built modules listed in the DSC is not listed
1512 # in FDF modules, and the INF lists a PCD can only use the PcdsDynamic
1513 # access method (it is only listed in the DEC file that declares the
1514 # PCD as PcdsDynamic), then build tool will report warning message
1515 # notify the PI that they are attempting to build a module that must
1516 # be included in a flash image in order to be functional. These Dynamic
1517 # PCD will not be added into the Database unless it is used by other
1518 # modules that are included in the FDF file.
1519 if PcdFromModule.Type in GenC.gDynamicPcd and \
1520 PcdFromModule.IsFromBinaryInf == False:
1521 # Print warning message to let the developer make a determine.
1522 if PcdFromModule not in PcdNotInDb:
1523 PcdNotInDb.append(PcdFromModule)
1524 continue
1525 # If one of the Source built modules listed in the DSC is not listed in
1526 # FDF modules, and the INF lists a PCD can only use the PcdsDynamicEx
1527 # access method (it is only listed in the DEC file that declares the
1528 # PCD as PcdsDynamicEx), then DO NOT break the build; DO NOT add the
1529 # PCD to the Platform's PCD Database.
1530 if PcdFromModule.Type in GenC.gDynamicExPcd:
1531 if PcdFromModule not in PcdNotInDb:
1532 PcdNotInDb.append(PcdFromModule)
1533 continue
1534 #
1535 # If a dynamic PCD used by a PEM module/PEI module & DXE module,
1536 # it should be stored in Pcd PEI database, If a dynamic only
1537 # used by DXE module, it should be stored in DXE PCD database.
1538 # The default Phase is DXE
1539 #
1540 if M.ModuleType in ["PEIM", "PEI_CORE"]:
1541 PcdFromModule.Phase = "PEI"
1542 if PcdFromModule not in self._DynaPcdList_:
1543 self._DynaPcdList_.append(PcdFromModule)
1544 elif PcdFromModule.Phase == 'PEI':
1545 # overwrite any the same PCD existing, if Phase is PEI
1546 Index = self._DynaPcdList_.index(PcdFromModule)
1547 self._DynaPcdList_[Index] = PcdFromModule
1548 elif PcdFromModule not in self._NonDynaPcdList_:
1549 self._NonDynaPcdList_.append(PcdFromModule)
1550 elif PcdFromModule in self._NonDynaPcdList_ and PcdFromModule.IsFromBinaryInf == True:
1551 Index = self._NonDynaPcdList_.index(PcdFromModule)
1552 if self._NonDynaPcdList_[Index].IsFromBinaryInf == False:
1553 #The PCD from Binary INF will override the same one from source INF
1554 self._NonDynaPcdList_.remove (self._NonDynaPcdList_[Index])
1555 PcdFromModule.Pending = False
1556 self._NonDynaPcdList_.append (PcdFromModule)
1557 # Parse the DynamicEx PCD from the AsBuild INF module list of FDF.
1558 DscModuleList = []
1559 for ModuleInf in self.Platform.Modules.keys():
1560 DscModuleList.append (os.path.normpath(ModuleInf.Path))
1561 # add the PCD from modules that listed in FDF but not in DSC to Database
1562 for InfName in FdfModuleList:
1563 if InfName not in DscModuleList:
1564 InfClass = PathClass(InfName)
1565 M = self.BuildDatabase[InfClass, self.Arch, self.BuildTarget, self.ToolChain]
1566 # If a module INF in FDF but not in current arch's DSC module list, it must be module (either binary or source)
1567 # for different Arch. PCDs in source module for different Arch is already added before, so skip the source module here.
1568 # For binary module, if in current arch, we need to list the PCDs into database.
1569 if not M.IsSupportedArch:
1570 continue
1571 # Override the module PCD setting by platform setting
1572 ModulePcdList = self.ApplyPcdSetting(M, M.Pcds)
1573 for PcdFromModule in ModulePcdList:
1574 PcdFromModule.IsFromBinaryInf = True
1575 PcdFromModule.IsFromDsc = False
1576 # Only allow the DynamicEx and Patchable PCD in AsBuild INF
1577 if PcdFromModule.Type not in GenC.gDynamicExPcd and PcdFromModule.Type not in TAB_PCDS_PATCHABLE_IN_MODULE:
1578 EdkLogger.error("build", AUTOGEN_ERROR, "PCD setting error",
1579 File=self.MetaFile,
1580 ExtraData="\n\tExisted %s PCD %s in:\n\t\t%s\n"
1581 % (PcdFromModule.Type, PcdFromModule.TokenCName, InfName))
1582 # make sure that the "VOID*" kind of datum has MaxDatumSize set
1583 if PcdFromModule.DatumType == "VOID*" and PcdFromModule.MaxDatumSize in [None, '']:
1584 NoDatumTypePcdList.add("%s.%s [%s]" % (PcdFromModule.TokenSpaceGuidCName, PcdFromModule.TokenCName, InfName))
1585 if M.ModuleType in ["PEIM", "PEI_CORE"]:
1586 PcdFromModule.Phase = "PEI"
1587 if PcdFromModule not in self._DynaPcdList_ and PcdFromModule.Type in GenC.gDynamicExPcd:
1588 self._DynaPcdList_.append(PcdFromModule)
1589 elif PcdFromModule not in self._NonDynaPcdList_ and PcdFromModule.Type in TAB_PCDS_PATCHABLE_IN_MODULE:
1590 self._NonDynaPcdList_.append(PcdFromModule)
1591 if PcdFromModule in self._DynaPcdList_ and PcdFromModule.Phase == 'PEI' and PcdFromModule.Type in GenC.gDynamicExPcd:
1592 # Overwrite the phase of any the same PCD existing, if Phase is PEI.
1593 # It is to solve the case that a dynamic PCD used by a PEM module/PEI
1594 # module & DXE module at a same time.
1595 # Overwrite the type of the PCDs in source INF by the type of AsBuild
1596 # INF file as DynamicEx.
1597 Index = self._DynaPcdList_.index(PcdFromModule)
1598 self._DynaPcdList_[Index].Phase = PcdFromModule.Phase
1599 self._DynaPcdList_[Index].Type = PcdFromModule.Type
1600 for PcdFromModule in self._NonDynaPcdList_:
1601 # If a PCD is not listed in the DSC file, but binary INF files used by
1602 # this platform all (that use this PCD) list the PCD in a [PatchPcds]
1603 # section, AND all source INF files used by this platform the build
1604 # that use the PCD list the PCD in either a [Pcds] or [PatchPcds]
1605 # section, then the tools must NOT add the PCD to the Platform's PCD
1606 # Database; the build must assign the access method for this PCD as
1607 # PcdsPatchableInModule.
1608 if PcdFromModule not in self._DynaPcdList_:
1609 continue
1610 Index = self._DynaPcdList_.index(PcdFromModule)
1611 if PcdFromModule.IsFromDsc == False and \
1612 PcdFromModule.Type in TAB_PCDS_PATCHABLE_IN_MODULE and \
1613 PcdFromModule.IsFromBinaryInf == True and \
1614 self._DynaPcdList_[Index].IsFromBinaryInf == False:
1615 Index = self._DynaPcdList_.index(PcdFromModule)
1616 self._DynaPcdList_.remove (self._DynaPcdList_[Index])
1617
1618 # print out error information and break the build, if error found
1619 if len(NoDatumTypePcdList) > 0:
1620 NoDatumTypePcdListString = "\n\t\t".join(NoDatumTypePcdList)
1621 EdkLogger.error("build", AUTOGEN_ERROR, "PCD setting error",
1622 File=self.MetaFile,
1623 ExtraData="\n\tPCD(s) without MaxDatumSize:\n\t\t%s\n"
1624 % NoDatumTypePcdListString)
1625 self._NonDynamicPcdList = self._NonDynaPcdList_
1626 self._DynamicPcdList = self._DynaPcdList_
1627 #
1628 # Sort dynamic PCD list to:
1629 # 1) If PCD's datum type is VOID* and value is unicode string which starts with L, the PCD item should
1630 # try to be put header of dynamicd List
1631 # 2) If PCD is HII type, the PCD item should be put after unicode type PCD
1632 #
1633 # The reason of sorting is make sure the unicode string is in double-byte alignment in string table.
1634 #
1635 UnicodePcdArray = set()
1636 HiiPcdArray = set()
1637 OtherPcdArray = set()
1638 VpdPcdDict = {}
1639 VpdFile = VpdInfoFile.VpdInfoFile()
1640 NeedProcessVpdMapFile = False
1641
1642 for pcd in self.Platform.Pcds.keys():
1643 if pcd not in self._PlatformPcds.keys():
1644 self._PlatformPcds[pcd] = self.Platform.Pcds[pcd]
1645
1646 for item in self._PlatformPcds:
1647 if self._PlatformPcds[item].DatumType and self._PlatformPcds[item].DatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64, TAB_VOID, "BOOLEAN"]:
1648 self._PlatformPcds[item].DatumType = "VOID*"
1649
1650 if (self.Workspace.ArchList[-1] == self.Arch):
1651 for Pcd in self._DynamicPcdList:
1652 # just pick the a value to determine whether is unicode string type
1653 Sku = Pcd.SkuInfoList[Pcd.SkuInfoList.keys()[0]]
1654 Sku.VpdOffset = Sku.VpdOffset.strip()
1655
1656 if Pcd.DatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64, TAB_VOID, "BOOLEAN"]:
1657 Pcd.DatumType = "VOID*"
1658
1659 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
1660 # if found HII type PCD then insert to right of UnicodeIndex
1661 if Pcd.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD]:
1662 VpdPcdDict[(Pcd.TokenCName, Pcd.TokenSpaceGuidCName)] = Pcd
1663
1664 #Collect DynamicHii PCD values and assign it to DynamicExVpd PCD gEfiMdeModulePkgTokenSpaceGuid.PcdNvStoreDefaultValueBuffer
1665 PcdNvStoreDfBuffer = VpdPcdDict.get(("PcdNvStoreDefaultValueBuffer","gEfiMdeModulePkgTokenSpaceGuid"))
1666 if PcdNvStoreDfBuffer:
1667 self.VariableInfo = self.CollectVariables(self._DynamicPcdList)
1668 vardump = self.VariableInfo.dump()
1669 if vardump:
1670 PcdNvStoreDfBuffer.DefaultValue = vardump
1671 for skuname in PcdNvStoreDfBuffer.SkuInfoList:
1672 PcdNvStoreDfBuffer.SkuInfoList[skuname].DefaultValue = vardump
1673 PcdNvStoreDfBuffer.MaxDatumSize = str(len(vardump.split(",")))
1674
1675 PlatformPcds = self._PlatformPcds.keys()
1676 PlatformPcds.sort()
1677 #
1678 # Add VPD type PCD into VpdFile and determine whether the VPD PCD need to be fixed up.
1679 #
1680 VpdSkuMap = {}
1681 for PcdKey in PlatformPcds:
1682 Pcd = self._PlatformPcds[PcdKey]
1683 if Pcd.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD] and \
1684 PcdKey in VpdPcdDict:
1685 Pcd = VpdPcdDict[PcdKey]
1686 SkuValueMap = {}
1687 DefaultSku = Pcd.SkuInfoList.get('DEFAULT')
1688 if DefaultSku:
1689 PcdValue = DefaultSku.DefaultValue
1690 if PcdValue not in SkuValueMap:
1691 SkuValueMap[PcdValue] = []
1692 VpdFile.Add(Pcd, 'DEFAULT',DefaultSku.VpdOffset)
1693 SkuValueMap[PcdValue].append(DefaultSku)
1694
1695 for (SkuName,Sku) in Pcd.SkuInfoList.items():
1696 Sku.VpdOffset = Sku.VpdOffset.strip()
1697 PcdValue = Sku.DefaultValue
1698 if PcdValue == "":
1699 PcdValue = Pcd.DefaultValue
1700 if Sku.VpdOffset != '*':
1701 if PcdValue.startswith("{"):
1702 Alignment = 8
1703 elif PcdValue.startswith("L"):
1704 Alignment = 2
1705 else:
1706 Alignment = 1
1707 try:
1708 VpdOffset = int(Sku.VpdOffset)
1709 except:
1710 try:
1711 VpdOffset = int(Sku.VpdOffset, 16)
1712 except:
1713 EdkLogger.error("build", FORMAT_INVALID, "Invalid offset value %s for PCD %s.%s." % (Sku.VpdOffset, Pcd.TokenSpaceGuidCName, Pcd.TokenCName))
1714 if VpdOffset % Alignment != 0:
1715 if PcdValue.startswith("{"):
1716 EdkLogger.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(Pcd.TokenSpaceGuidCName, Pcd.TokenCName), File=self.MetaFile)
1717 else:
1718 EdkLogger.error("build", FORMAT_INVALID, 'The offset value of PCD %s.%s should be %s-byte aligned.' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName, Alignment))
1719 if PcdValue not in SkuValueMap:
1720 SkuValueMap[PcdValue] = []
1721 VpdFile.Add(Pcd, SkuName,Sku.VpdOffset)
1722 SkuValueMap[PcdValue].append(Sku)
1723 # if the offset of a VPD is *, then it need to be fixed up by third party tool.
1724 if not NeedProcessVpdMapFile and Sku.VpdOffset == "*":
1725 NeedProcessVpdMapFile = True
1726 if self.Platform.VpdToolGuid == None or self.Platform.VpdToolGuid == '':
1727 EdkLogger.error("Build", FILE_NOT_FOUND, \
1728 "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.")
1729
1730 VpdSkuMap[PcdKey] = SkuValueMap
1731 #
1732 # Fix the PCDs define in VPD PCD section that never referenced by module.
1733 # An example is PCD for signature usage.
1734 #
1735 for DscPcd in PlatformPcds:
1736 DscPcdEntry = self._PlatformPcds[DscPcd]
1737 if DscPcdEntry.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD]:
1738 if not (self.Platform.VpdToolGuid == None or self.Platform.VpdToolGuid == ''):
1739 FoundFlag = False
1740 for VpdPcd in VpdFile._VpdArray.keys():
1741 # This PCD has been referenced by module
1742 if (VpdPcd.TokenSpaceGuidCName == DscPcdEntry.TokenSpaceGuidCName) and \
1743 (VpdPcd.TokenCName == DscPcdEntry.TokenCName):
1744 FoundFlag = True
1745
1746 # Not found, it should be signature
1747 if not FoundFlag :
1748 # just pick the a value to determine whether is unicode string type
1749 SkuValueMap = {}
1750 SkuObjList = DscPcdEntry.SkuInfoList.items()
1751 DefaultSku = DscPcdEntry.SkuInfoList.get('DEFAULT')
1752 if DefaultSku:
1753 defaultindex = SkuObjList.index(('DEFAULT',DefaultSku))
1754 SkuObjList[0],SkuObjList[defaultindex] = SkuObjList[defaultindex],SkuObjList[0]
1755 for (SkuName,Sku) in SkuObjList:
1756 Sku.VpdOffset = Sku.VpdOffset.strip()
1757
1758 # Need to iterate DEC pcd information to get the value & datumtype
1759 for eachDec in self.PackageList:
1760 for DecPcd in eachDec.Pcds:
1761 DecPcdEntry = eachDec.Pcds[DecPcd]
1762 if (DecPcdEntry.TokenSpaceGuidCName == DscPcdEntry.TokenSpaceGuidCName) and \
1763 (DecPcdEntry.TokenCName == DscPcdEntry.TokenCName):
1764 # Print warning message to let the developer make a determine.
1765 EdkLogger.warn("build", "Unreferenced vpd pcd used!",
1766 File=self.MetaFile, \
1767 ExtraData = "PCD: %s.%s used in the DSC file %s is unreferenced." \
1768 %(DscPcdEntry.TokenSpaceGuidCName, DscPcdEntry.TokenCName, self.Platform.MetaFile.Path))
1769
1770 DscPcdEntry.DatumType = DecPcdEntry.DatumType
1771 DscPcdEntry.DefaultValue = DecPcdEntry.DefaultValue
1772 DscPcdEntry.TokenValue = DecPcdEntry.TokenValue
1773 DscPcdEntry.TokenSpaceGuidValue = eachDec.Guids[DecPcdEntry.TokenSpaceGuidCName]
1774 # Only fix the value while no value provided in DSC file.
1775 if (Sku.DefaultValue == "" or Sku.DefaultValue==None):
1776 DscPcdEntry.SkuInfoList[DscPcdEntry.SkuInfoList.keys()[0]].DefaultValue = DecPcdEntry.DefaultValue
1777
1778 if DscPcdEntry not in self._DynamicPcdList:
1779 self._DynamicPcdList.append(DscPcdEntry)
1780 Sku.VpdOffset = Sku.VpdOffset.strip()
1781 PcdValue = Sku.DefaultValue
1782 if PcdValue == "":
1783 PcdValue = DscPcdEntry.DefaultValue
1784 if Sku.VpdOffset != '*':
1785 if PcdValue.startswith("{"):
1786 Alignment = 8
1787 elif PcdValue.startswith("L"):
1788 Alignment = 2
1789 else:
1790 Alignment = 1
1791 try:
1792 VpdOffset = int(Sku.VpdOffset)
1793 except:
1794 try:
1795 VpdOffset = int(Sku.VpdOffset, 16)
1796 except:
1797 EdkLogger.error("build", FORMAT_INVALID, "Invalid offset value %s for PCD %s.%s." % (Sku.VpdOffset, DscPcdEntry.TokenSpaceGuidCName, DscPcdEntry.TokenCName))
1798 if VpdOffset % Alignment != 0:
1799 if PcdValue.startswith("{"):
1800 EdkLogger.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(DscPcdEntry.TokenSpaceGuidCName, DscPcdEntry.TokenCName), File=self.MetaFile)
1801 else:
1802 EdkLogger.error("build", FORMAT_INVALID, 'The offset value of PCD %s.%s should be %s-byte aligned.' % (DscPcdEntry.TokenSpaceGuidCName, DscPcdEntry.TokenCName, Alignment))
1803 if PcdValue not in SkuValueMap:
1804 SkuValueMap[PcdValue] = []
1805 VpdFile.Add(DscPcdEntry, SkuName,Sku.VpdOffset)
1806 SkuValueMap[PcdValue].append(Sku)
1807 if not NeedProcessVpdMapFile and Sku.VpdOffset == "*":
1808 NeedProcessVpdMapFile = True
1809 if DscPcdEntry.DatumType == 'VOID*' and PcdValue.startswith("L"):
1810 UnicodePcdArray.add(DscPcdEntry)
1811 elif len(Sku.VariableName) > 0:
1812 HiiPcdArray.add(DscPcdEntry)
1813 else:
1814 OtherPcdArray.add(DscPcdEntry)
1815
1816 # if the offset of a VPD is *, then it need to be fixed up by third party tool.
1817 VpdSkuMap[DscPcd] = SkuValueMap
1818 if (self.Platform.FlashDefinition == None or self.Platform.FlashDefinition == '') and \
1819 VpdFile.GetCount() != 0:
1820 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE,
1821 "Fail to get FLASH_DEFINITION definition in DSC file %s which is required when DSC contains VPD PCD." % str(self.Platform.MetaFile))
1822
1823 if VpdFile.GetCount() != 0:
1824
1825 self.FixVpdOffset(VpdFile)
1826
1827 self.FixVpdOffset(self.UpdateNVStoreMaxSize(VpdFile))
1828
1829 # Process VPD map file generated by third party BPDG tool
1830 if NeedProcessVpdMapFile:
1831 VpdMapFilePath = os.path.join(self.BuildDir, "FV", "%s.map" % self.Platform.VpdToolGuid)
1832 if os.path.exists(VpdMapFilePath):
1833 VpdFile.Read(VpdMapFilePath)
1834
1835 # Fixup "*" offset
1836 for pcd in VpdSkuMap:
1837 vpdinfo = VpdFile.GetVpdInfo(pcd)
1838 if vpdinfo is None:
1839 # just pick the a value to determine whether is unicode string type
1840 continue
1841 for pcdvalue in VpdSkuMap[pcd]:
1842 for sku in VpdSkuMap[pcd][pcdvalue]:
1843 for item in vpdinfo:
1844 if item[2] == pcdvalue:
1845 sku.VpdOffset = item[1]
1846 else:
1847 EdkLogger.error("build", FILE_READ_FAILURE, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath)
1848
1849 # Delete the DynamicPcdList At the last time enter into this function
1850 for Pcd in self._DynamicPcdList:
1851 # just pick the a value to determine whether is unicode string type
1852 Sku = Pcd.SkuInfoList[Pcd.SkuInfoList.keys()[0]]
1853 Sku.VpdOffset = Sku.VpdOffset.strip()
1854
1855 if Pcd.DatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64, TAB_VOID, "BOOLEAN"]:
1856 Pcd.DatumType = "VOID*"
1857
1858 PcdValue = Sku.DefaultValue
1859 if Pcd.DatumType == 'VOID*' and PcdValue.startswith("L"):
1860 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
1861 UnicodePcdArray.add(Pcd)
1862 elif len(Sku.VariableName) > 0:
1863 # if found HII type PCD then insert to right of UnicodeIndex
1864 HiiPcdArray.add(Pcd)
1865 else:
1866 OtherPcdArray.add(Pcd)
1867 del self._DynamicPcdList[:]
1868 self._DynamicPcdList.extend(list(UnicodePcdArray))
1869 self._DynamicPcdList.extend(list(HiiPcdArray))
1870 self._DynamicPcdList.extend(list(OtherPcdArray))
1871 allskuset = [(SkuName,Sku.SkuId) for pcd in self._DynamicPcdList for (SkuName,Sku) in pcd.SkuInfoList.items()]
1872 for pcd in self._DynamicPcdList:
1873 if len(pcd.SkuInfoList) == 1:
1874 for (SkuName,SkuId) in allskuset:
1875 if type(SkuId) in (str,unicode) and eval(SkuId) == 0 or SkuId == 0:
1876 continue
1877 pcd.SkuInfoList[SkuName] = copy.deepcopy(pcd.SkuInfoList['DEFAULT'])
1878 pcd.SkuInfoList[SkuName].SkuId = SkuId
1879 self.AllPcdList = self._NonDynamicPcdList + self._DynamicPcdList
1880
1881 def FixVpdOffset(self,VpdFile ):
1882 FvPath = os.path.join(self.BuildDir, "FV")
1883 if not os.path.exists(FvPath):
1884 try:
1885 os.makedirs(FvPath)
1886 except:
1887 EdkLogger.error("build", FILE_WRITE_FAILURE, "Fail to create FV folder under %s" % self.BuildDir)
1888
1889 VpdFilePath = os.path.join(FvPath, "%s.txt" % self.Platform.VpdToolGuid)
1890
1891 if VpdFile.Write(VpdFilePath):
1892 # retrieve BPDG tool's path from tool_def.txt according to VPD_TOOL_GUID defined in DSC file.
1893 BPDGToolName = None
1894 for ToolDef in self.ToolDefinition.values():
1895 if ToolDef.has_key("GUID") and ToolDef["GUID"] == self.Platform.VpdToolGuid:
1896 if not ToolDef.has_key("PATH"):
1897 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE, "PATH attribute was not provided for BPDG guid tool %s in tools_def.txt" % self.Platform.VpdToolGuid)
1898 BPDGToolName = ToolDef["PATH"]
1899 break
1900 # Call third party GUID BPDG tool.
1901 if BPDGToolName != None:
1902 VpdInfoFile.CallExtenalBPDGTool(BPDGToolName, VpdFilePath)
1903 else:
1904 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.")
1905
1906 ## Return the platform build data object
1907 def _GetPlatform(self):
1908 if self._Platform == None:
1909 self._Platform = self.BuildDatabase[self.MetaFile, self.Arch, self.BuildTarget, self.ToolChain]
1910 return self._Platform
1911
1912 ## Return platform name
1913 def _GetName(self):
1914 return self.Platform.PlatformName
1915
1916 ## Return the meta file GUID
1917 def _GetGuid(self):
1918 return self.Platform.Guid
1919
1920 ## Return the platform version
1921 def _GetVersion(self):
1922 return self.Platform.Version
1923
1924 ## Return the FDF file name
1925 def _GetFdfFile(self):
1926 if self._FdfFile == None:
1927 if self.Workspace.FdfFile != "":
1928 self._FdfFile= mws.join(self.WorkspaceDir, self.Workspace.FdfFile)
1929 else:
1930 self._FdfFile = ''
1931 return self._FdfFile
1932
1933 ## Return the build output directory platform specifies
1934 def _GetOutputDir(self):
1935 return self.Platform.OutputDirectory
1936
1937 ## Return the directory to store all intermediate and final files built
1938 def _GetBuildDir(self):
1939 if self._BuildDir == None:
1940 if os.path.isabs(self.OutputDir):
1941 self._BuildDir = path.join(
1942 path.abspath(self.OutputDir),
1943 self.BuildTarget + "_" + self.ToolChain,
1944 )
1945 else:
1946 self._BuildDir = path.join(
1947 self.WorkspaceDir,
1948 self.OutputDir,
1949 self.BuildTarget + "_" + self.ToolChain,
1950 )
1951 GlobalData.gBuildDirectory = self._BuildDir
1952 return self._BuildDir
1953
1954 ## Return directory of platform makefile
1955 #
1956 # @retval string Makefile directory
1957 #
1958 def _GetMakeFileDir(self):
1959 if self._MakeFileDir == None:
1960 self._MakeFileDir = path.join(self.BuildDir, self.Arch)
1961 return self._MakeFileDir
1962
1963 ## Return build command string
1964 #
1965 # @retval string Build command string
1966 #
1967 def _GetBuildCommand(self):
1968 if self._BuildCommand == None:
1969 self._BuildCommand = []
1970 if "MAKE" in self.ToolDefinition and "PATH" in self.ToolDefinition["MAKE"]:
1971 self._BuildCommand += SplitOption(self.ToolDefinition["MAKE"]["PATH"])
1972 if "FLAGS" in self.ToolDefinition["MAKE"]:
1973 NewOption = self.ToolDefinition["MAKE"]["FLAGS"].strip()
1974 if NewOption != '':
1975 self._BuildCommand += SplitOption(NewOption)
1976 return self._BuildCommand
1977
1978 ## Get tool chain definition
1979 #
1980 # Get each tool defition for given tool chain from tools_def.txt and platform
1981 #
1982 def _GetToolDefinition(self):
1983 if self._ToolDefinitions == None:
1984 ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDictionary
1985 if TAB_TOD_DEFINES_COMMAND_TYPE not in self.Workspace.ToolDef.ToolsDefTxtDatabase:
1986 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "No tools found in configuration",
1987 ExtraData="[%s]" % self.MetaFile)
1988 self._ToolDefinitions = {}
1989 DllPathList = set()
1990 for Def in ToolDefinition:
1991 Target, Tag, Arch, Tool, Attr = Def.split("_")
1992 if Target != self.BuildTarget or Tag != self.ToolChain or Arch != self.Arch:
1993 continue
1994
1995 Value = ToolDefinition[Def]
1996 # don't record the DLL
1997 if Attr == "DLL":
1998 DllPathList.add(Value)
1999 continue
2000
2001 if Tool not in self._ToolDefinitions:
2002 self._ToolDefinitions[Tool] = {}
2003 self._ToolDefinitions[Tool][Attr] = Value
2004
2005 ToolsDef = ''
2006 MakePath = ''
2007 if GlobalData.gOptions.SilentMode and "MAKE" in self._ToolDefinitions:
2008 if "FLAGS" not in self._ToolDefinitions["MAKE"]:
2009 self._ToolDefinitions["MAKE"]["FLAGS"] = ""
2010 self._ToolDefinitions["MAKE"]["FLAGS"] += " -s"
2011 MakeFlags = ''
2012 for Tool in self._ToolDefinitions:
2013 for Attr in self._ToolDefinitions[Tool]:
2014 Value = self._ToolDefinitions[Tool][Attr]
2015 if Tool in self.BuildOption and Attr in self.BuildOption[Tool]:
2016 # check if override is indicated
2017 if self.BuildOption[Tool][Attr].startswith('='):
2018 Value = self.BuildOption[Tool][Attr][1:]
2019 else:
2020 if Attr != 'PATH':
2021 Value += " " + self.BuildOption[Tool][Attr]
2022 else:
2023 Value = self.BuildOption[Tool][Attr]
2024
2025 if Attr == "PATH":
2026 # Don't put MAKE definition in the file
2027 if Tool == "MAKE":
2028 MakePath = Value
2029 else:
2030 ToolsDef += "%s = %s\n" % (Tool, Value)
2031 elif Attr != "DLL":
2032 # Don't put MAKE definition in the file
2033 if Tool == "MAKE":
2034 if Attr == "FLAGS":
2035 MakeFlags = Value
2036 else:
2037 ToolsDef += "%s_%s = %s\n" % (Tool, Attr, Value)
2038 ToolsDef += "\n"
2039
2040 SaveFileOnChange(self.ToolDefinitionFile, ToolsDef)
2041 for DllPath in DllPathList:
2042 os.environ["PATH"] = DllPath + os.pathsep + os.environ["PATH"]
2043 os.environ["MAKE_FLAGS"] = MakeFlags
2044
2045 return self._ToolDefinitions
2046
2047 ## Return the paths of tools
2048 def _GetToolDefFile(self):
2049 if self._ToolDefFile == None:
2050 self._ToolDefFile = os.path.join(self.MakeFileDir, "TOOLS_DEF." + self.Arch)
2051 return self._ToolDefFile
2052
2053 ## Retrieve the toolchain family of given toolchain tag. Default to 'MSFT'.
2054 def _GetToolChainFamily(self):
2055 if self._ToolChainFamily == None:
2056 ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDatabase
2057 if TAB_TOD_DEFINES_FAMILY not in ToolDefinition \
2058 or self.ToolChain not in ToolDefinition[TAB_TOD_DEFINES_FAMILY] \
2059 or not ToolDefinition[TAB_TOD_DEFINES_FAMILY][self.ToolChain]:
2060 EdkLogger.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
2061 % self.ToolChain)
2062 self._ToolChainFamily = "MSFT"
2063 else:
2064 self._ToolChainFamily = ToolDefinition[TAB_TOD_DEFINES_FAMILY][self.ToolChain]
2065 return self._ToolChainFamily
2066
2067 def _GetBuildRuleFamily(self):
2068 if self._BuildRuleFamily == None:
2069 ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDatabase
2070 if TAB_TOD_DEFINES_BUILDRULEFAMILY not in ToolDefinition \
2071 or self.ToolChain not in ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY] \
2072 or not ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY][self.ToolChain]:
2073 EdkLogger.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
2074 % self.ToolChain)
2075 self._BuildRuleFamily = "MSFT"
2076 else:
2077 self._BuildRuleFamily = ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY][self.ToolChain]
2078 return self._BuildRuleFamily
2079
2080 ## Return the build options specific for all modules in this platform
2081 def _GetBuildOptions(self):
2082 if self._BuildOption == None:
2083 self._BuildOption = self._ExpandBuildOption(self.Platform.BuildOptions)
2084 return self._BuildOption
2085
2086 ## Return the build options specific for EDK modules in this platform
2087 def _GetEdkBuildOptions(self):
2088 if self._EdkBuildOption == None:
2089 self._EdkBuildOption = self._ExpandBuildOption(self.Platform.BuildOptions, EDK_NAME)
2090 return self._EdkBuildOption
2091
2092 ## Return the build options specific for EDKII modules in this platform
2093 def _GetEdkIIBuildOptions(self):
2094 if self._EdkIIBuildOption == None:
2095 self._EdkIIBuildOption = self._ExpandBuildOption(self.Platform.BuildOptions, EDKII_NAME)
2096 return self._EdkIIBuildOption
2097
2098 ## Parse build_rule.txt in Conf Directory.
2099 #
2100 # @retval BuildRule object
2101 #
2102 def _GetBuildRule(self):
2103 if self._BuildRule == None:
2104 BuildRuleFile = None
2105 if TAB_TAT_DEFINES_BUILD_RULE_CONF in self.Workspace.TargetTxt.TargetTxtDictionary:
2106 BuildRuleFile = self.Workspace.TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_BUILD_RULE_CONF]
2107 if BuildRuleFile in [None, '']:
2108 BuildRuleFile = gDefaultBuildRuleFile
2109 self._BuildRule = BuildRule(BuildRuleFile)
2110 if self._BuildRule._FileVersion == "":
2111 self._BuildRule._FileVersion = AutoGenReqBuildRuleVerNum
2112 else:
2113 if self._BuildRule._FileVersion < AutoGenReqBuildRuleVerNum :
2114 # If Build Rule's version is less than the version number required by the tools, halting the build.
2115 EdkLogger.error("build", AUTOGEN_ERROR,
2116 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])"\
2117 % (self._BuildRule._FileVersion, AutoGenReqBuildRuleVerNum))
2118
2119 return self._BuildRule
2120
2121 ## Summarize the packages used by modules in this platform
2122 def _GetPackageList(self):
2123 if self._PackageList == None:
2124 self._PackageList = set()
2125 for La in self.LibraryAutoGenList:
2126 self._PackageList.update(La.DependentPackageList)
2127 for Ma in self.ModuleAutoGenList:
2128 self._PackageList.update(Ma.DependentPackageList)
2129 #Collect package set information from INF of FDF
2130 PkgSet = set()
2131 for ModuleFile in self._AsBuildModuleList:
2132 if ModuleFile in self.Platform.Modules:
2133 continue
2134 ModuleData = self.BuildDatabase[ModuleFile, self.Arch, self.BuildTarget, self.ToolChain]
2135 PkgSet.update(ModuleData.Packages)
2136 self._PackageList = list(self._PackageList) + list (PkgSet)
2137 return self._PackageList
2138
2139 def _GetNonDynamicPcdDict(self):
2140 if self._NonDynamicPcdDict:
2141 return self._NonDynamicPcdDict
2142 for Pcd in self.NonDynamicPcdList:
2143 self._NonDynamicPcdDict[(Pcd.TokenCName,Pcd.TokenSpaceGuidCName)] = Pcd
2144 return self._NonDynamicPcdDict
2145
2146 ## Get list of non-dynamic PCDs
2147 def _GetNonDynamicPcdList(self):
2148 if self._NonDynamicPcdList == None:
2149 self.CollectPlatformDynamicPcds()
2150 return self._NonDynamicPcdList
2151
2152 ## Get list of dynamic PCDs
2153 def _GetDynamicPcdList(self):
2154 if self._DynamicPcdList == None:
2155 self.CollectPlatformDynamicPcds()
2156 return self._DynamicPcdList
2157
2158 ## Generate Token Number for all PCD
2159 def _GetPcdTokenNumbers(self):
2160 if self._PcdTokenNumber == None:
2161 self._PcdTokenNumber = sdict()
2162 TokenNumber = 1
2163 #
2164 # Make the Dynamic and DynamicEx PCD use within different TokenNumber area.
2165 # Such as:
2166 #
2167 # Dynamic PCD:
2168 # TokenNumber 0 ~ 10
2169 # DynamicEx PCD:
2170 # TokeNumber 11 ~ 20
2171 #
2172 for Pcd in self.DynamicPcdList:
2173 if Pcd.Phase == "PEI":
2174 if Pcd.Type in ["Dynamic", "DynamicDefault", "DynamicVpd", "DynamicHii"]:
2175 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))
2176 self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
2177 TokenNumber += 1
2178
2179 for Pcd in self.DynamicPcdList:
2180 if Pcd.Phase == "PEI":
2181 if Pcd.Type in ["DynamicEx", "DynamicExDefault", "DynamicExVpd", "DynamicExHii"]:
2182 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))
2183 self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
2184 TokenNumber += 1
2185
2186 for Pcd in self.DynamicPcdList:
2187 if Pcd.Phase == "DXE":
2188 if Pcd.Type in ["Dynamic", "DynamicDefault", "DynamicVpd", "DynamicHii"]:
2189 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))
2190 self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
2191 TokenNumber += 1
2192
2193 for Pcd in self.DynamicPcdList:
2194 if Pcd.Phase == "DXE":
2195 if Pcd.Type in ["DynamicEx", "DynamicExDefault", "DynamicExVpd", "DynamicExHii"]:
2196 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))
2197 self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
2198 TokenNumber += 1
2199
2200 for Pcd in self.NonDynamicPcdList:
2201 self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
2202 TokenNumber += 1
2203 return self._PcdTokenNumber
2204
2205 ## Summarize ModuleAutoGen objects of all modules/libraries to be built for this platform
2206 def _GetAutoGenObjectList(self):
2207 self._ModuleAutoGenList = []
2208 self._LibraryAutoGenList = []
2209 for ModuleFile in self.Platform.Modules:
2210 Ma = ModuleAutoGen(
2211 self.Workspace,
2212 ModuleFile,
2213 self.BuildTarget,
2214 self.ToolChain,
2215 self.Arch,
2216 self.MetaFile
2217 )
2218 if Ma not in self._ModuleAutoGenList:
2219 self._ModuleAutoGenList.append(Ma)
2220 for La in Ma.LibraryAutoGenList:
2221 if La not in self._LibraryAutoGenList:
2222 self._LibraryAutoGenList.append(La)
2223 if Ma not in La._ReferenceModules:
2224 La._ReferenceModules.append(Ma)
2225
2226 ## Summarize ModuleAutoGen objects of all modules to be built for this platform
2227 def _GetModuleAutoGenList(self):
2228 if self._ModuleAutoGenList == None:
2229 self._GetAutoGenObjectList()
2230 return self._ModuleAutoGenList
2231
2232 ## Summarize ModuleAutoGen objects of all libraries to be built for this platform
2233 def _GetLibraryAutoGenList(self):
2234 if self._LibraryAutoGenList == None:
2235 self._GetAutoGenObjectList()
2236 return self._LibraryAutoGenList
2237
2238 ## Test if a module is supported by the platform
2239 #
2240 # An error will be raised directly if the module or its arch is not supported
2241 # by the platform or current configuration
2242 #
2243 def ValidModule(self, Module):
2244 return Module in self.Platform.Modules or Module in self.Platform.LibraryInstances \
2245 or Module in self._AsBuildModuleList
2246
2247 ## Resolve the library classes in a module to library instances
2248 #
2249 # This method will not only resolve library classes but also sort the library
2250 # instances according to the dependency-ship.
2251 #
2252 # @param Module The module from which the library classes will be resolved
2253 #
2254 # @retval library_list List of library instances sorted
2255 #
2256 def ApplyLibraryInstance(self, Module):
2257 # Cover the case that the binary INF file is list in the FDF file but not DSC file, return empty list directly
2258 if str(Module) not in self.Platform.Modules:
2259 return []
2260
2261 ModuleType = Module.ModuleType
2262
2263 # for overridding library instances with module specific setting
2264 PlatformModule = self.Platform.Modules[str(Module)]
2265
2266 # add forced library instances (specified under LibraryClasses sections)
2267 #
2268 # If a module has a MODULE_TYPE of USER_DEFINED,
2269 # do not link in NULL library class instances from the global [LibraryClasses.*] sections.
2270 #
2271 if Module.ModuleType != SUP_MODULE_USER_DEFINED:
2272 for LibraryClass in self.Platform.LibraryClasses.GetKeys():
2273 if LibraryClass.startswith("NULL") and self.Platform.LibraryClasses[LibraryClass, Module.ModuleType]:
2274 Module.LibraryClasses[LibraryClass] = self.Platform.LibraryClasses[LibraryClass, Module.ModuleType]
2275
2276 # add forced library instances (specified in module overrides)
2277 for LibraryClass in PlatformModule.LibraryClasses:
2278 if LibraryClass.startswith("NULL"):
2279 Module.LibraryClasses[LibraryClass] = PlatformModule.LibraryClasses[LibraryClass]
2280
2281 # EdkII module
2282 LibraryConsumerList = [Module]
2283 Constructor = []
2284 ConsumedByList = sdict()
2285 LibraryInstance = sdict()
2286
2287 EdkLogger.verbose("")
2288 EdkLogger.verbose("Library instances of module [%s] [%s]:" % (str(Module), self.Arch))
2289 while len(LibraryConsumerList) > 0:
2290 M = LibraryConsumerList.pop()
2291 for LibraryClassName in M.LibraryClasses:
2292 if LibraryClassName not in LibraryInstance:
2293 # override library instance for this module
2294 if LibraryClassName in PlatformModule.LibraryClasses:
2295 LibraryPath = PlatformModule.LibraryClasses[LibraryClassName]
2296 else:
2297 LibraryPath = self.Platform.LibraryClasses[LibraryClassName, ModuleType]
2298 if LibraryPath == None or LibraryPath == "":
2299 LibraryPath = M.LibraryClasses[LibraryClassName]
2300 if LibraryPath == None or LibraryPath == "":
2301 EdkLogger.error("build", RESOURCE_NOT_AVAILABLE,
2302 "Instance of library class [%s] is not found" % LibraryClassName,
2303 File=self.MetaFile,
2304 ExtraData="in [%s] [%s]\n\tconsumed by module [%s]" % (str(M), self.Arch, str(Module)))
2305
2306 LibraryModule = self.BuildDatabase[LibraryPath, self.Arch, self.BuildTarget, self.ToolChain]
2307 # for those forced library instance (NULL library), add a fake library class
2308 if LibraryClassName.startswith("NULL"):
2309 LibraryModule.LibraryClass.append(LibraryClassObject(LibraryClassName, [ModuleType]))
2310 elif LibraryModule.LibraryClass == None \
2311 or len(LibraryModule.LibraryClass) == 0 \
2312 or (ModuleType != 'USER_DEFINED'
2313 and ModuleType not in LibraryModule.LibraryClass[0].SupModList):
2314 # only USER_DEFINED can link against any library instance despite of its SupModList
2315 EdkLogger.error("build", OPTION_MISSING,
2316 "Module type [%s] is not supported by library instance [%s]" \
2317 % (ModuleType, LibraryPath), File=self.MetaFile,
2318 ExtraData="consumed by [%s]" % str(Module))
2319
2320 LibraryInstance[LibraryClassName] = LibraryModule
2321 LibraryConsumerList.append(LibraryModule)
2322 EdkLogger.verbose("\t" + str(LibraryClassName) + " : " + str(LibraryModule))
2323 else:
2324 LibraryModule = LibraryInstance[LibraryClassName]
2325
2326 if LibraryModule == None:
2327 continue
2328
2329 if LibraryModule.ConstructorList != [] and LibraryModule not in Constructor:
2330 Constructor.append(LibraryModule)
2331
2332 if LibraryModule not in ConsumedByList:
2333 ConsumedByList[LibraryModule] = []
2334 # don't add current module itself to consumer list
2335 if M != Module:
2336 if M in ConsumedByList[LibraryModule]:
2337 continue
2338 ConsumedByList[LibraryModule].append(M)
2339 #
2340 # Initialize the sorted output list to the empty set
2341 #
2342 SortedLibraryList = []
2343 #
2344 # Q <- Set of all nodes with no incoming edges
2345 #
2346 LibraryList = [] #LibraryInstance.values()
2347 Q = []
2348 for LibraryClassName in LibraryInstance:
2349 M = LibraryInstance[LibraryClassName]
2350 LibraryList.append(M)
2351 if ConsumedByList[M] == []:
2352 Q.append(M)
2353
2354 #
2355 # start the DAG algorithm
2356 #
2357 while True:
2358 EdgeRemoved = True
2359 while Q == [] and EdgeRemoved:
2360 EdgeRemoved = False
2361 # for each node Item with a Constructor
2362 for Item in LibraryList:
2363 if Item not in Constructor:
2364 continue
2365 # for each Node without a constructor with an edge e from Item to Node
2366 for Node in ConsumedByList[Item]:
2367 if Node in Constructor:
2368 continue
2369 # remove edge e from the graph if Node has no constructor
2370 ConsumedByList[Item].remove(Node)
2371 EdgeRemoved = True
2372 if ConsumedByList[Item] == []:
2373 # insert Item into Q
2374 Q.insert(0, Item)
2375 break
2376 if Q != []:
2377 break
2378 # DAG is done if there's no more incoming edge for all nodes
2379 if Q == []:
2380 break
2381
2382 # remove node from Q
2383 Node = Q.pop()
2384 # output Node
2385 SortedLibraryList.append(Node)
2386
2387 # for each node Item with an edge e from Node to Item do
2388 for Item in LibraryList:
2389 if Node not in ConsumedByList[Item]:
2390 continue
2391 # remove edge e from the graph
2392 ConsumedByList[Item].remove(Node)
2393
2394 if ConsumedByList[Item] != []:
2395 continue
2396 # insert Item into Q, if Item has no other incoming edges
2397 Q.insert(0, Item)
2398
2399 #
2400 # if any remaining node Item in the graph has a constructor and an incoming edge, then the graph has a cycle
2401 #
2402 for Item in LibraryList:
2403 if ConsumedByList[Item] != [] and Item in Constructor and len(Constructor) > 1:
2404 ErrorMessage = "\tconsumed by " + "\n\tconsumed by ".join([str(L) for L in ConsumedByList[Item]])
2405 EdkLogger.error("build", BUILD_ERROR, 'Library [%s] with constructors has a cycle' % str(Item),
2406 ExtraData=ErrorMessage, File=self.MetaFile)
2407 if Item not in SortedLibraryList:
2408 SortedLibraryList.append(Item)
2409
2410 #
2411 # Build the list of constructor and destructir names
2412 # The DAG Topo sort produces the destructor order, so the list of constructors must generated in the reverse order
2413 #
2414 SortedLibraryList.reverse()
2415 return SortedLibraryList
2416
2417
2418 ## Override PCD setting (type, value, ...)
2419 #
2420 # @param ToPcd The PCD to be overrided
2421 # @param FromPcd The PCD overrideing from
2422 #
2423 def _OverridePcd(self, ToPcd, FromPcd, Module=""):
2424 #
2425 # in case there's PCDs coming from FDF file, which have no type given.
2426 # at this point, ToPcd.Type has the type found from dependent
2427 # package
2428 #
2429 TokenCName = ToPcd.TokenCName
2430 for PcdItem in GlobalData.MixedPcd:
2431 if (ToPcd.TokenCName, ToPcd.TokenSpaceGuidCName) in GlobalData.MixedPcd[PcdItem]:
2432 TokenCName = PcdItem[0]
2433 break
2434 if FromPcd != None:
2435 if GlobalData.BuildOptionPcd:
2436 for pcd in GlobalData.BuildOptionPcd:
2437 if (FromPcd.TokenSpaceGuidCName, FromPcd.TokenCName) == (pcd[0], pcd[1]):
2438 FromPcd.DefaultValue = pcd[2]
2439 break
2440 if ToPcd.Pending and FromPcd.Type not in [None, '']:
2441 ToPcd.Type = FromPcd.Type
2442 elif (ToPcd.Type not in [None, '']) and (FromPcd.Type not in [None, ''])\
2443 and (ToPcd.Type != FromPcd.Type) and (ToPcd.Type in FromPcd.Type):
2444 if ToPcd.Type.strip() == "DynamicEx":
2445 ToPcd.Type = FromPcd.Type
2446 elif ToPcd.Type not in [None, ''] and FromPcd.Type not in [None, ''] \
2447 and ToPcd.Type != FromPcd.Type:
2448 EdkLogger.error("build", OPTION_CONFLICT, "Mismatched PCD type",
2449 ExtraData="%s.%s is defined as [%s] in module %s, but as [%s] in platform."\
2450 % (ToPcd.TokenSpaceGuidCName, TokenCName,
2451 ToPcd.Type, Module, FromPcd.Type),
2452 File=self.MetaFile)
2453
2454 if FromPcd.MaxDatumSize not in [None, '']:
2455 ToPcd.MaxDatumSize = FromPcd.MaxDatumSize
2456 if FromPcd.DefaultValue not in [None, '']:
2457 ToPcd.DefaultValue = FromPcd.DefaultValue
2458 if FromPcd.TokenValue not in [None, '']:
2459 ToPcd.TokenValue = FromPcd.TokenValue
2460 if FromPcd.MaxDatumSize not in [None, '']:
2461 ToPcd.MaxDatumSize = FromPcd.MaxDatumSize
2462 if FromPcd.DatumType not in [None, '']:
2463 ToPcd.DatumType = FromPcd.DatumType
2464 if FromPcd.SkuInfoList not in [None, '', []]:
2465 ToPcd.SkuInfoList = FromPcd.SkuInfoList
2466 # Add Flexible PCD format parse
2467 if ToPcd.DefaultValue:
2468 try:
2469 ToPcd.DefaultValue = ValueExpressionEx(ToPcd.DefaultValue, ToPcd.DatumType, self._GuidDict)(True)
2470 except BadExpression, Value:
2471 EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s", %s' %(ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName, ToPcd.DefaultValue, Value),
2472 File=self.MetaFile)
2473
2474 # check the validation of datum
2475 IsValid, Cause = CheckPcdDatum(ToPcd.DatumType, ToPcd.DefaultValue)
2476 if not IsValid:
2477 EdkLogger.error('build', FORMAT_INVALID, Cause, File=self.MetaFile,
2478 ExtraData="%s.%s" % (ToPcd.TokenSpaceGuidCName, TokenCName))
2479 ToPcd.validateranges = FromPcd.validateranges
2480 ToPcd.validlists = FromPcd.validlists
2481 ToPcd.expressions = FromPcd.expressions
2482
2483 if ToPcd.DatumType == "VOID*" and ToPcd.MaxDatumSize in ['', None]:
2484 EdkLogger.debug(EdkLogger.DEBUG_9, "No MaxDatumSize specified for PCD %s.%s" \
2485 % (ToPcd.TokenSpaceGuidCName, TokenCName))
2486 Value = ToPcd.DefaultValue
2487 if Value in [None, '']:
2488 ToPcd.MaxDatumSize = '1'
2489 elif Value[0] == 'L':
2490 ToPcd.MaxDatumSize = str((len(Value) - 2) * 2)
2491 elif Value[0] == '{':
2492 ToPcd.MaxDatumSize = str(len(Value.split(',')))
2493 else:
2494 ToPcd.MaxDatumSize = str(len(Value) - 1)
2495
2496 # apply default SKU for dynamic PCDS if specified one is not available
2497 if (ToPcd.Type in PCD_DYNAMIC_TYPE_LIST or ToPcd.Type in PCD_DYNAMIC_EX_TYPE_LIST) \
2498 and ToPcd.SkuInfoList in [None, {}, '']:
2499 if self.Platform.SkuName in self.Platform.SkuIds:
2500 SkuName = self.Platform.SkuName
2501 else:
2502 SkuName = 'DEFAULT'
2503 ToPcd.SkuInfoList = {
2504 SkuName : SkuInfoClass(SkuName, self.Platform.SkuIds[SkuName][0], '', '', '', '', '', ToPcd.DefaultValue)
2505 }
2506
2507 ## Apply PCD setting defined platform to a module
2508 #
2509 # @param Module The module from which the PCD setting will be overrided
2510 #
2511 # @retval PCD_list The list PCDs with settings from platform
2512 #
2513 def ApplyPcdSetting(self, Module, Pcds):
2514 # for each PCD in module
2515 for Name, Guid in Pcds:
2516 PcdInModule = Pcds[Name, Guid]
2517 # find out the PCD setting in platform
2518 if (Name, Guid) in self.Platform.Pcds:
2519 PcdInPlatform = self.Platform.Pcds[Name, Guid]
2520 else:
2521 PcdInPlatform = None
2522 # then override the settings if any
2523 self._OverridePcd(PcdInModule, PcdInPlatform, Module)
2524 # resolve the VariableGuid value
2525 for SkuId in PcdInModule.SkuInfoList:
2526 Sku = PcdInModule.SkuInfoList[SkuId]
2527 if Sku.VariableGuid == '': continue
2528 Sku.VariableGuidValue = GuidValue(Sku.VariableGuid, self.PackageList, self.MetaFile.Path)
2529 if Sku.VariableGuidValue == None:
2530 PackageList = "\n\t".join([str(P) for P in self.PackageList])
2531 EdkLogger.error(
2532 'build',
2533 RESOURCE_NOT_AVAILABLE,
2534 "Value of GUID [%s] is not found in" % Sku.VariableGuid,
2535 ExtraData=PackageList + "\n\t(used with %s.%s from module %s)" \
2536 % (Guid, Name, str(Module)),
2537 File=self.MetaFile
2538 )
2539
2540 # override PCD settings with module specific setting
2541 if Module in self.Platform.Modules:
2542 PlatformModule = self.Platform.Modules[str(Module)]
2543 for Key in PlatformModule.Pcds:
2544 Flag = False
2545 if Key in Pcds:
2546 ToPcd = Pcds[Key]
2547 Flag = True
2548 elif Key in GlobalData.MixedPcd:
2549 for PcdItem in GlobalData.MixedPcd[Key]:
2550 if PcdItem in Pcds:
2551 ToPcd = Pcds[PcdItem]
2552 Flag = True
2553 break
2554 if Flag:
2555 self._OverridePcd(ToPcd, PlatformModule.Pcds[Key], Module)
2556 return Pcds.values()
2557
2558 ## Resolve library names to library modules
2559 #
2560 # (for Edk.x modules)
2561 #
2562 # @param Module The module from which the library names will be resolved
2563 #
2564 # @retval library_list The list of library modules
2565 #
2566 def ResolveLibraryReference(self, Module):
2567 EdkLogger.verbose("")
2568 EdkLogger.verbose("Library instances of module [%s] [%s]:" % (str(Module), self.Arch))
2569 LibraryConsumerList = [Module]
2570
2571 # "CompilerStub" is a must for Edk modules
2572 if Module.Libraries:
2573 Module.Libraries.append("CompilerStub")
2574 LibraryList = []
2575 while len(LibraryConsumerList) > 0:
2576 M = LibraryConsumerList.pop()
2577 for LibraryName in M.Libraries:
2578 Library = self.Platform.LibraryClasses[LibraryName, ':dummy:']
2579 if Library == None:
2580 for Key in self.Platform.LibraryClasses.data.keys():
2581 if LibraryName.upper() == Key.upper():
2582 Library = self.Platform.LibraryClasses[Key, ':dummy:']
2583 break
2584 if Library == None:
2585 EdkLogger.warn("build", "Library [%s] is not found" % LibraryName, File=str(M),
2586 ExtraData="\t%s [%s]" % (str(Module), self.Arch))
2587 continue
2588
2589 if Library not in LibraryList:
2590 LibraryList.append(Library)
2591 LibraryConsumerList.append(Library)
2592 EdkLogger.verbose("\t" + LibraryName + " : " + str(Library) + ' ' + str(type(Library)))
2593 return LibraryList
2594
2595 ## Calculate the priority value of the build option
2596 #
2597 # @param Key Build option definition contain: TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
2598 #
2599 # @retval Value Priority value based on the priority list.
2600 #
2601 def CalculatePriorityValue(self, Key):
2602 Target, ToolChain, Arch, CommandType, Attr = Key.split('_')
2603 PriorityValue = 0x11111
2604 if Target == "*":
2605 PriorityValue &= 0x01111
2606 if ToolChain == "*":
2607 PriorityValue &= 0x10111
2608 if Arch == "*":
2609 PriorityValue &= 0x11011
2610 if CommandType == "*":
2611 PriorityValue &= 0x11101
2612 if Attr == "*":
2613 PriorityValue &= 0x11110
2614
2615 return self.PrioList["0x%0.5x" % PriorityValue]
2616
2617
2618 ## Expand * in build option key
2619 #
2620 # @param Options Options to be expanded
2621 #
2622 # @retval options Options expanded
2623 #
2624 def _ExpandBuildOption(self, Options, ModuleStyle=None):
2625 BuildOptions = {}
2626 FamilyMatch = False
2627 FamilyIsNull = True
2628
2629 OverrideList = {}
2630 #
2631 # Construct a list contain the build options which need override.
2632 #
2633 for Key in Options:
2634 #
2635 # Key[0] -- tool family
2636 # Key[1] -- TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
2637 #
2638 if (Key[0] == self.BuildRuleFamily and
2639 (ModuleStyle == None or len(Key) < 3 or (len(Key) > 2 and Key[2] == ModuleStyle))):
2640 Target, ToolChain, Arch, CommandType, Attr = Key[1].split('_')
2641 if Target == self.BuildTarget or Target == "*":
2642 if ToolChain == self.ToolChain or ToolChain == "*":
2643 if Arch == self.Arch or Arch == "*":
2644 if Options[Key].startswith("="):
2645 if OverrideList.get(Key[1]) != None:
2646 OverrideList.pop(Key[1])
2647 OverrideList[Key[1]] = Options[Key]
2648
2649 #
2650 # Use the highest priority value.
2651 #
2652 if (len(OverrideList) >= 2):
2653 KeyList = OverrideList.keys()
2654 for Index in range(len(KeyList)):
2655 NowKey = KeyList[Index]
2656 Target1, ToolChain1, Arch1, CommandType1, Attr1 = NowKey.split("_")
2657 for Index1 in range(len(KeyList) - Index - 1):
2658 NextKey = KeyList[Index1 + Index + 1]
2659 #
2660 # Compare two Key, if one is included by another, choose the higher priority one
2661 #
2662 Target2, ToolChain2, Arch2, CommandType2, Attr2 = NextKey.split("_")
2663 if Target1 == Target2 or Target1 == "*" or Target2 == "*":
2664 if ToolChain1 == ToolChain2 or ToolChain1 == "*" or ToolChain2 == "*":
2665 if Arch1 == Arch2 or Arch1 == "*" or Arch2 == "*":
2666 if CommandType1 == CommandType2 or CommandType1 == "*" or CommandType2 == "*":
2667 if Attr1 == Attr2 or Attr1 == "*" or Attr2 == "*":
2668 if self.CalculatePriorityValue(NowKey) > self.CalculatePriorityValue(NextKey):
2669 if Options.get((self.BuildRuleFamily, NextKey)) != None:
2670 Options.pop((self.BuildRuleFamily, NextKey))
2671 else:
2672 if Options.get((self.BuildRuleFamily, NowKey)) != None:
2673 Options.pop((self.BuildRuleFamily, NowKey))
2674
2675 for Key in Options:
2676 if ModuleStyle != None and len (Key) > 2:
2677 # Check Module style is EDK or EDKII.
2678 # Only append build option for the matched style module.
2679 if ModuleStyle == EDK_NAME and Key[2] != EDK_NAME:
2680 continue
2681 elif ModuleStyle == EDKII_NAME and Key[2] != EDKII_NAME:
2682 continue
2683 Family = Key[0]
2684 Target, Tag, Arch, Tool, Attr = Key[1].split("_")
2685 # if tool chain family doesn't match, skip it
2686 if Tool in self.ToolDefinition and Family != "":
2687 FamilyIsNull = False
2688 if self.ToolDefinition[Tool].get(TAB_TOD_DEFINES_BUILDRULEFAMILY, "") != "":
2689 if Family != self.ToolDefinition[Tool][TAB_TOD_DEFINES_BUILDRULEFAMILY]:
2690 continue
2691 elif Family != self.ToolDefinition[Tool][TAB_TOD_DEFINES_FAMILY]:
2692 continue
2693 FamilyMatch = True
2694 # expand any wildcard
2695 if Target == "*" or Target == self.BuildTarget:
2696 if Tag == "*" or Tag == self.ToolChain:
2697 if Arch == "*" or Arch == self.Arch:
2698 if Tool not in BuildOptions:
2699 BuildOptions[Tool] = {}
2700 if Attr != "FLAGS" or Attr not in BuildOptions[Tool] or Options[Key].startswith('='):
2701 BuildOptions[Tool][Attr] = Options[Key]
2702 else:
2703 # append options for the same tool except PATH
2704 if Attr != 'PATH':
2705 BuildOptions[Tool][Attr] += " " + Options[Key]
2706 else:
2707 BuildOptions[Tool][Attr] = Options[Key]
2708 # Build Option Family has been checked, which need't to be checked again for family.
2709 if FamilyMatch or FamilyIsNull:
2710 return BuildOptions
2711
2712 for Key in Options:
2713 if ModuleStyle != None and len (Key) > 2:
2714 # Check Module style is EDK or EDKII.
2715 # Only append build option for the matched style module.
2716 if ModuleStyle == EDK_NAME and Key[2] != EDK_NAME:
2717 continue
2718 elif ModuleStyle == EDKII_NAME and Key[2] != EDKII_NAME:
2719 continue
2720 Family = Key[0]
2721 Target, Tag, Arch, Tool, Attr = Key[1].split("_")
2722 # if tool chain family doesn't match, skip it
2723 if Tool not in self.ToolDefinition or Family == "":
2724 continue
2725 # option has been added before
2726 if Family != self.ToolDefinition[Tool][TAB_TOD_DEFINES_FAMILY]:
2727 continue
2728
2729 # expand any wildcard
2730 if Target == "*" or Target == self.BuildTarget:
2731 if Tag == "*" or Tag == self.ToolChain:
2732 if Arch == "*" or Arch == self.Arch:
2733 if Tool not in BuildOptions:
2734 BuildOptions[Tool] = {}
2735 if Attr != "FLAGS" or Attr not in BuildOptions[Tool] or Options[Key].startswith('='):
2736 BuildOptions[Tool][Attr] = Options[Key]
2737 else:
2738 # append options for the same tool except PATH
2739 if Attr != 'PATH':
2740 BuildOptions[Tool][Attr] += " " + Options[Key]
2741 else:
2742 BuildOptions[Tool][Attr] = Options[Key]
2743 return BuildOptions
2744
2745 ## Append build options in platform to a module
2746 #
2747 # @param Module The module to which the build options will be appened
2748 #
2749 # @retval options The options appended with build options in platform
2750 #
2751 def ApplyBuildOption(self, Module):
2752 # Get the different options for the different style module
2753 if Module.AutoGenVersion < 0x00010005:
2754 PlatformOptions = self.EdkBuildOption
2755 ModuleTypeOptions = self.Platform.GetBuildOptionsByModuleType(EDK_NAME, Module.ModuleType)
2756 else:
2757 PlatformOptions = self.EdkIIBuildOption
2758 ModuleTypeOptions = self.Platform.GetBuildOptionsByModuleType(EDKII_NAME, Module.ModuleType)
2759 ModuleTypeOptions = self._ExpandBuildOption(ModuleTypeOptions)
2760 ModuleOptions = self._ExpandBuildOption(Module.BuildOptions)
2761 if Module in self.Platform.Modules:
2762 PlatformModule = self.Platform.Modules[str(Module)]
2763 PlatformModuleOptions = self._ExpandBuildOption(PlatformModule.BuildOptions)
2764 else:
2765 PlatformModuleOptions = {}
2766
2767 BuildRuleOrder = None
2768 for Options in [self.ToolDefinition, ModuleOptions, PlatformOptions, ModuleTypeOptions, PlatformModuleOptions]:
2769 for Tool in Options:
2770 for Attr in Options[Tool]:
2771 if Attr == TAB_TOD_DEFINES_BUILDRULEORDER:
2772 BuildRuleOrder = Options[Tool][Attr]
2773
2774 AllTools = set(ModuleOptions.keys() + PlatformOptions.keys() +
2775 PlatformModuleOptions.keys() + ModuleTypeOptions.keys() +
2776 self.ToolDefinition.keys())
2777 BuildOptions = {}
2778 for Tool in AllTools:
2779 if Tool not in BuildOptions:
2780 BuildOptions[Tool] = {}
2781
2782 for Options in [self.ToolDefinition, ModuleOptions, PlatformOptions, ModuleTypeOptions, PlatformModuleOptions]:
2783 if Tool not in Options:
2784 continue
2785 for Attr in Options[Tool]:
2786 Value = Options[Tool][Attr]
2787 #
2788 # Do not generate it in Makefile
2789 #
2790 if Attr == TAB_TOD_DEFINES_BUILDRULEORDER:
2791 continue
2792 if Attr not in BuildOptions[Tool]:
2793 BuildOptions[Tool][Attr] = ""
2794 # check if override is indicated
2795 if Value.startswith('='):
2796 ToolPath = Value[1:]
2797 ToolPath = mws.handleWsMacro(ToolPath)
2798 BuildOptions[Tool][Attr] = ToolPath
2799 else:
2800 Value = mws.handleWsMacro(Value)
2801 if Attr != 'PATH':
2802 BuildOptions[Tool][Attr] += " " + Value
2803 else:
2804 BuildOptions[Tool][Attr] = Value
2805 if Module.AutoGenVersion < 0x00010005 and self.Workspace.UniFlag != None:
2806 #
2807 # Override UNI flag only for EDK module.
2808 #
2809 if 'BUILD' not in BuildOptions:
2810 BuildOptions['BUILD'] = {}
2811 BuildOptions['BUILD']['FLAGS'] = self.Workspace.UniFlag
2812 return BuildOptions, BuildRuleOrder
2813
2814 Platform = property(_GetPlatform)
2815 Name = property(_GetName)
2816 Guid = property(_GetGuid)
2817 Version = property(_GetVersion)
2818
2819 OutputDir = property(_GetOutputDir)
2820 BuildDir = property(_GetBuildDir)
2821 MakeFileDir = property(_GetMakeFileDir)
2822 FdfFile = property(_GetFdfFile)
2823
2824 PcdTokenNumber = property(_GetPcdTokenNumbers) # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber
2825 DynamicPcdList = property(_GetDynamicPcdList) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
2826 NonDynamicPcdList = property(_GetNonDynamicPcdList) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
2827 NonDynamicPcdDict = property(_GetNonDynamicPcdDict)
2828 PackageList = property(_GetPackageList)
2829
2830 ToolDefinition = property(_GetToolDefinition) # toolcode : tool path
2831 ToolDefinitionFile = property(_GetToolDefFile) # toolcode : lib path
2832 ToolChainFamily = property(_GetToolChainFamily)
2833 BuildRuleFamily = property(_GetBuildRuleFamily)
2834 BuildOption = property(_GetBuildOptions) # toolcode : option
2835 EdkBuildOption = property(_GetEdkBuildOptions) # edktoolcode : option
2836 EdkIIBuildOption = property(_GetEdkIIBuildOptions) # edkiitoolcode : option
2837
2838 BuildCommand = property(_GetBuildCommand)
2839 BuildRule = property(_GetBuildRule)
2840 ModuleAutoGenList = property(_GetModuleAutoGenList)
2841 LibraryAutoGenList = property(_GetLibraryAutoGenList)
2842 GenFdsCommand = property(_GenFdsCommand)
2843
2844 ## ModuleAutoGen class
2845 #
2846 # This class encapsules the AutoGen behaviors for the build tools. In addition to
2847 # the generation of AutoGen.h and AutoGen.c, it will generate *.depex file according
2848 # to the [depex] section in module's inf file.
2849 #
2850 class ModuleAutoGen(AutoGen):
2851 ## Cache the timestamps of metafiles of every module in a class variable
2852 #
2853 TimeDict = {}
2854
2855 ## The real constructor of ModuleAutoGen
2856 #
2857 # This method is not supposed to be called by users of ModuleAutoGen. It's
2858 # only used by factory method __new__() to do real initialization work for an
2859 # object of ModuleAutoGen
2860 #
2861 # @param Workspace EdkIIWorkspaceBuild object
2862 # @param ModuleFile The path of module file
2863 # @param Target Build target (DEBUG, RELEASE)
2864 # @param Toolchain Name of tool chain
2865 # @param Arch The arch the module supports
2866 # @param PlatformFile Platform meta-file
2867 #
2868 def _Init(self, Workspace, ModuleFile, Target, Toolchain, Arch, PlatformFile):
2869 EdkLogger.debug(EdkLogger.DEBUG_9, "AutoGen module [%s] [%s]" % (ModuleFile, Arch))
2870 GlobalData.gProcessingFile = "%s [%s, %s, %s]" % (ModuleFile, Arch, Toolchain, Target)
2871
2872 self.Workspace = Workspace
2873 self.WorkspaceDir = Workspace.WorkspaceDir
2874
2875 self.MetaFile = ModuleFile
2876 self.PlatformInfo = PlatformAutoGen(Workspace, PlatformFile, Target, Toolchain, Arch)
2877 # check if this module is employed by active platform
2878 if not self.PlatformInfo.ValidModule(self.MetaFile):
2879 EdkLogger.verbose("Module [%s] for [%s] is not employed by active platform\n" \
2880 % (self.MetaFile, Arch))
2881 return False
2882
2883 self.SourceDir = self.MetaFile.SubDir
2884 self.SourceDir = mws.relpath(self.SourceDir, self.WorkspaceDir)
2885
2886 self.SourceOverrideDir = None
2887 # use overrided path defined in DSC file
2888 if self.MetaFile.Key in GlobalData.gOverrideDir:
2889 self.SourceOverrideDir = GlobalData.gOverrideDir[self.MetaFile.Key]
2890
2891 self.ToolChain = Toolchain
2892 self.BuildTarget = Target
2893 self.Arch = Arch
2894 self.ToolChainFamily = self.PlatformInfo.ToolChainFamily
2895 self.BuildRuleFamily = self.PlatformInfo.BuildRuleFamily
2896
2897 self.IsMakeFileCreated = False
2898 self.IsCodeFileCreated = False
2899 self.IsAsBuiltInfCreated = False
2900 self.DepexGenerated = False
2901
2902 self.BuildDatabase = self.Workspace.BuildDatabase
2903 self.BuildRuleOrder = None
2904 self.BuildTime = 0
2905
2906 self._Module = None
2907 self._Name = None
2908 self._Guid = None
2909 self._Version = None
2910 self._ModuleType = None
2911 self._ComponentType = None
2912 self._PcdIsDriver = None
2913 self._AutoGenVersion = None
2914 self._LibraryFlag = None
2915 self._CustomMakefile = None
2916 self._Macro = None
2917
2918 self._BuildDir = None
2919 self._OutputDir = None
2920 self._FfsOutputDir = None
2921 self._DebugDir = None
2922 self._MakeFileDir = None
2923
2924 self._IncludePathList = None
2925 self._IncludePathLength = 0
2926 self._AutoGenFileList = None
2927 self._UnicodeFileList = None
2928 self._VfrFileList = None
2929 self._IdfFileList = None
2930 self._SourceFileList = None
2931 self._ObjectFileList = None
2932 self._BinaryFileList = None
2933
2934 self._DependentPackageList = None
2935 self._DependentLibraryList = None
2936 self._LibraryAutoGenList = None
2937 self._DerivedPackageList = None
2938 self._ModulePcdList = None
2939 self._LibraryPcdList = None
2940 self._PcdComments = sdict()
2941 self._GuidList = None
2942 self._GuidsUsedByPcd = None
2943 self._GuidComments = sdict()
2944 self._ProtocolList = None
2945 self._ProtocolComments = sdict()
2946 self._PpiList = None
2947 self._PpiComments = sdict()
2948 self._DepexList = None
2949 self._DepexExpressionList = None
2950 self._BuildOption = None
2951 self._BuildOptionIncPathList = None
2952 self._BuildTargets = None
2953 self._IntroBuildTargetList = None
2954 self._FinalBuildTargetList = None
2955 self._FileTypes = None
2956 self._BuildRules = None
2957
2958 self._TimeStampPath = None
2959
2960 self.AutoGenDepSet = set()
2961
2962
2963 ## The Modules referenced to this Library
2964 # Only Library has this attribute
2965 self._ReferenceModules = []
2966
2967 ## Store the FixedAtBuild Pcds
2968 #
2969 self._FixedAtBuildPcds = []
2970 self.ConstPcd = {}
2971 return True
2972
2973 def __repr__(self):
2974 return "%s [%s]" % (self.MetaFile, self.Arch)
2975
2976 # Get FixedAtBuild Pcds of this Module
2977 def _GetFixedAtBuildPcds(self):
2978 if self._FixedAtBuildPcds:
2979 return self._FixedAtBuildPcds
2980 for Pcd in self.ModulePcdList:
2981 if Pcd.Type != "FixedAtBuild":
2982 continue
2983 if Pcd not in self._FixedAtBuildPcds:
2984 self._FixedAtBuildPcds.append(Pcd)
2985
2986 return self._FixedAtBuildPcds
2987
2988 def _GetUniqueBaseName(self):
2989 BaseName = self.Name
2990 for Module in self.PlatformInfo.ModuleAutoGenList:
2991 if Module.MetaFile == self.MetaFile:
2992 continue
2993 if Module.Name == self.Name:
2994 if uuid.UUID(Module.Guid) == uuid.UUID(self.Guid):
2995 EdkLogger.error("build", FILE_DUPLICATED, 'Modules have same BaseName and FILE_GUID:\n'
2996 ' %s\n %s' % (Module.MetaFile, self.MetaFile))
2997 BaseName = '%s_%s' % (self.Name, self.Guid)
2998 return BaseName
2999
3000 # Macros could be used in build_rule.txt (also Makefile)
3001 def _GetMacros(self):
3002 if self._Macro == None:
3003 self._Macro = sdict()
3004 self._Macro["WORKSPACE" ] = self.WorkspaceDir
3005 self._Macro["MODULE_NAME" ] = self.Name
3006 self._Macro["MODULE_NAME_GUID" ] = self._GetUniqueBaseName()
3007 self._Macro["MODULE_GUID" ] = self.Guid
3008 self._Macro["MODULE_VERSION" ] = self.Version
3009 self._Macro["MODULE_TYPE" ] = self.ModuleType
3010 self._Macro["MODULE_FILE" ] = str(self.MetaFile)
3011 self._Macro["MODULE_FILE_BASE_NAME" ] = self.MetaFile.BaseName
3012 self._Macro["MODULE_RELATIVE_DIR" ] = self.SourceDir
3013 self._Macro["MODULE_DIR" ] = self.SourceDir
3014
3015 self._Macro["BASE_NAME" ] = self.Name
3016
3017 self._Macro["ARCH" ] = self.Arch
3018 self._Macro["TOOLCHAIN" ] = self.ToolChain
3019 self._Macro["TOOLCHAIN_TAG" ] = self.ToolChain
3020 self._Macro["TOOL_CHAIN_TAG" ] = self.ToolChain
3021 self._Macro["TARGET" ] = self.BuildTarget
3022
3023 self._Macro["BUILD_DIR" ] = self.PlatformInfo.BuildDir
3024 self._Macro["BIN_DIR" ] = os.path.join(self.PlatformInfo.BuildDir, self.Arch)
3025 self._Macro["LIB_DIR" ] = os.path.join(self.PlatformInfo.BuildDir, self.Arch)
3026 self._Macro["MODULE_BUILD_DIR" ] = self.BuildDir
3027 self._Macro["OUTPUT_DIR" ] = self.OutputDir
3028 self._Macro["DEBUG_DIR" ] = self.DebugDir
3029 self._Macro["DEST_DIR_OUTPUT" ] = self.OutputDir
3030 self._Macro["DEST_DIR_DEBUG" ] = self.DebugDir
3031 self._Macro["PLATFORM_NAME" ] = self.PlatformInfo.Name
3032 self._Macro["PLATFORM_GUID" ] = self.PlatformInfo.Guid
3033 self._Macro["PLATFORM_VERSION" ] = self.PlatformInfo.Version
3034 self._Macro["PLATFORM_RELATIVE_DIR" ] = self.PlatformInfo.SourceDir
3035 self._Macro["PLATFORM_DIR" ] = mws.join(self.WorkspaceDir, self.PlatformInfo.SourceDir)
3036 self._Macro["PLATFORM_OUTPUT_DIR" ] = self.PlatformInfo.OutputDir
3037 self._Macro["FFS_OUTPUT_DIR" ] = self.FfsOutputDir
3038 return self._Macro
3039
3040 ## Return the module build data object
3041 def _GetModule(self):
3042 if self._Module == None:
3043 self._Module = self.Workspace.BuildDatabase[self.MetaFile, self.Arch, self.BuildTarget, self.ToolChain]
3044 return self._Module
3045
3046 ## Return the module name
3047 def _GetBaseName(self):
3048 return self.Module.BaseName
3049
3050 ## Return the module DxsFile if exist
3051 def _GetDxsFile(self):
3052 return self.Module.DxsFile
3053
3054 ## Return the module SourceOverridePath
3055 def _GetSourceOverridePath(self):
3056 return self.Module.SourceOverridePath
3057
3058 ## Return the module meta-file GUID
3059 def _GetGuid(self):
3060 #
3061 # To build same module more than once, the module path with FILE_GUID overridden has
3062 # the file name FILE_GUIDmodule.inf, but the relative path (self.MetaFile.File) is the realy path
3063 # in DSC. The overridden GUID can be retrieved from file name
3064 #
3065 if os.path.basename(self.MetaFile.File) != os.path.basename(self.MetaFile.Path):
3066 #
3067 # Length of GUID is 36
3068 #
3069 return os.path.basename(self.MetaFile.Path)[:36]
3070 return self.Module.Guid
3071
3072 ## Return the module version
3073 def _GetVersion(self):
3074 return self.Module.Version
3075
3076 ## Return the module type
3077 def _GetModuleType(self):
3078 return self.Module.ModuleType
3079
3080 ## Return the component type (for Edk.x style of module)
3081 def _GetComponentType(self):
3082 return self.Module.ComponentType
3083
3084 ## Return the build type
3085 def _GetBuildType(self):
3086 return self.Module.BuildType
3087
3088 ## Return the PCD_IS_DRIVER setting
3089 def _GetPcdIsDriver(self):
3090 return self.Module.PcdIsDriver
3091
3092 ## Return the autogen version, i.e. module meta-file version
3093 def _GetAutoGenVersion(self):
3094 return self.Module.AutoGenVersion
3095
3096 ## Check if the module is library or not
3097 def _IsLibrary(self):
3098 if self._LibraryFlag == None:
3099 if self.Module.LibraryClass != None and self.Module.LibraryClass != []:
3100 self._LibraryFlag = True
3101 else:
3102 self._LibraryFlag = False
3103 return self._LibraryFlag
3104
3105 ## Check if the module is binary module or not
3106 def _IsBinaryModule(self):
3107 return self.Module.IsBinaryModule
3108
3109 ## Return the directory to store intermediate files of the module
3110 def _GetBuildDir(self):
3111 if self._BuildDir == None:
3112 self._BuildDir = path.join(
3113 self.PlatformInfo.BuildDir,
3114 self.Arch,
3115 self.SourceDir,
3116 self.MetaFile.BaseName
3117 )
3118 CreateDirectory(self._BuildDir)
3119 return self._BuildDir
3120
3121 ## Return the directory to store the intermediate object files of the mdoule
3122 def _GetOutputDir(self):
3123 if self._OutputDir == None:
3124 self._OutputDir = path.join(self.BuildDir, "OUTPUT")
3125 CreateDirectory(self._OutputDir)
3126 return self._OutputDir
3127
3128 ## Return the directory to store ffs file
3129 def _GetFfsOutputDir(self):
3130 if self._FfsOutputDir == None:
3131 if GlobalData.gFdfParser != None:
3132 self._FfsOutputDir = path.join(self.PlatformInfo.BuildDir, "FV", "Ffs", self.Guid + self.Name)
3133 else:
3134 self._FfsOutputDir = ''
3135 return self._FfsOutputDir
3136
3137 ## Return the directory to store auto-gened source files of the mdoule
3138 def _GetDebugDir(self):
3139 if self._DebugDir == None:
3140 self._DebugDir = path.join(self.BuildDir, "DEBUG")
3141 CreateDirectory(self._DebugDir)
3142 return self._DebugDir
3143
3144 ## Return the path of custom file
3145 def _GetCustomMakefile(self):
3146 if self._CustomMakefile == None:
3147 self._CustomMakefile = {}
3148 for Type in self.Module.CustomMakefile:
3149 if Type in gMakeTypeMap:
3150 MakeType = gMakeTypeMap[Type]
3151 else:
3152 MakeType = 'nmake'
3153 if self.SourceOverrideDir != None:
3154 File = os.path.join(self.SourceOverrideDir, self.Module.CustomMakefile[Type])
3155 if not os.path.exists(File):
3156 File = os.path.join(self.SourceDir, self.Module.CustomMakefile[Type])
3157 else:
3158 File = os.path.join(self.SourceDir, self.Module.CustomMakefile[Type])
3159 self._CustomMakefile[MakeType] = File
3160 return self._CustomMakefile
3161
3162 ## Return the directory of the makefile
3163 #
3164 # @retval string The directory string of module's makefile
3165 #
3166 def _GetMakeFileDir(self):
3167 return self.BuildDir
3168
3169 ## Return build command string
3170 #
3171 # @retval string Build command string
3172 #
3173 def _GetBuildCommand(self):
3174 return self.PlatformInfo.BuildCommand
3175
3176 ## Get object list of all packages the module and its dependent libraries belong to
3177 #
3178 # @retval list The list of package object
3179 #
3180 def _GetDerivedPackageList(self):
3181 PackageList = []
3182 for M in [self.Module] + self.DependentLibraryList:
3183 for Package in M.Packages:
3184 if Package in PackageList:
3185 continue
3186 PackageList.append(Package)
3187 return PackageList
3188
3189 ## Get the depex string
3190 #
3191 # @return : a string contain all depex expresion.
3192 def _GetDepexExpresionString(self):
3193 DepexStr = ''
3194 DepexList = []
3195 ## DPX_SOURCE IN Define section.
3196 if self.Module.DxsFile:
3197 return DepexStr
3198 for M in [self.Module] + self.DependentLibraryList:
3199 Filename = M.MetaFile.Path
3200 InfObj = InfSectionParser.InfSectionParser(Filename)
3201 DepexExpresionList = InfObj.GetDepexExpresionList()
3202 for DepexExpresion in DepexExpresionList:
3203 for key in DepexExpresion.keys():
3204 Arch, ModuleType = key
3205 DepexExpr = [x for x in DepexExpresion[key] if not str(x).startswith('#')]
3206 # the type of build module is USER_DEFINED.
3207 # All different DEPEX section tags would be copied into the As Built INF file
3208 # and there would be separate DEPEX section tags
3209 if self.ModuleType.upper() == SUP_MODULE_USER_DEFINED:
3210 if (Arch.upper() == self.Arch.upper()) and (ModuleType.upper() != TAB_ARCH_COMMON):
3211 DepexList.append({(Arch, ModuleType): DepexExpr})
3212 else:
3213 if Arch.upper() == TAB_ARCH_COMMON or \
3214 (Arch.upper() == self.Arch.upper() and \
3215 ModuleType.upper() in [TAB_ARCH_COMMON, self.ModuleType.upper()]):
3216 DepexList.append({(Arch, ModuleType): DepexExpr})
3217
3218 #the type of build module is USER_DEFINED.
3219 if self.ModuleType.upper() == SUP_MODULE_USER_DEFINED:
3220 for Depex in DepexList:
3221 for key in Depex.keys():
3222 DepexStr += '[Depex.%s.%s]\n' % key
3223 DepexStr += '\n'.join(['# '+ val for val in Depex[key]])
3224 DepexStr += '\n\n'
3225 if not DepexStr:
3226 return '[Depex.%s]\n' % self.Arch
3227 return DepexStr
3228
3229 #the type of build module not is USER_DEFINED.
3230 Count = 0
3231 for Depex in DepexList:
3232 Count += 1
3233 if DepexStr != '':
3234 DepexStr += ' AND '
3235 DepexStr += '('
3236 for D in Depex.values():
3237 DepexStr += ' '.join([val for val in D])
3238 Index = DepexStr.find('END')
3239 if Index > -1 and Index == len(DepexStr) - 3:
3240 DepexStr = DepexStr[:-3]
3241 DepexStr = DepexStr.strip()
3242 DepexStr += ')'
3243 if Count == 1:
3244 DepexStr = DepexStr.lstrip('(').rstrip(')').strip()
3245 if not DepexStr:
3246 return '[Depex.%s]\n' % self.Arch
3247 return '[Depex.%s]\n# ' % self.Arch + DepexStr
3248
3249 ## Merge dependency expression
3250 #
3251 # @retval list The token list of the dependency expression after parsed
3252 #
3253 def _GetDepexTokenList(self):
3254 if self._DepexList == None:
3255 self._DepexList = {}
3256 if self.DxsFile or self.IsLibrary or TAB_DEPENDENCY_EXPRESSION_FILE in self.FileTypes:
3257 return self._DepexList
3258
3259 self._DepexList[self.ModuleType] = []
3260
3261 for ModuleType in self._DepexList:
3262 DepexList = self._DepexList[ModuleType]
3263 #
3264 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
3265 #
3266 for M in [self.Module] + self.DependentLibraryList:
3267 Inherited = False
3268 for D in M.Depex[self.Arch, ModuleType]:
3269 if DepexList != []:
3270 DepexList.append('AND')
3271 DepexList.append('(')
3272 DepexList.extend(D)
3273 if DepexList[-1] == 'END': # no need of a END at this time
3274 DepexList.pop()
3275 DepexList.append(')')
3276 Inherited = True
3277 if Inherited:
3278 EdkLogger.verbose("DEPEX[%s] (+%s) = %s" % (self.Name, M.BaseName, DepexList))
3279 if 'BEFORE' in DepexList or 'AFTER' in DepexList:
3280 break
3281 if len(DepexList) > 0:
3282 EdkLogger.verbose('')
3283 return self._DepexList
3284
3285 ## Merge dependency expression
3286 #
3287 # @retval list The token list of the dependency expression after parsed
3288 #
3289 def _GetDepexExpressionTokenList(self):
3290 if self._DepexExpressionList == None:
3291 self._DepexExpressionList = {}
3292 if self.DxsFile or self.IsLibrary or TAB_DEPENDENCY_EXPRESSION_FILE in self.FileTypes:
3293 return self._DepexExpressionList
3294
3295 self._DepexExpressionList[self.ModuleType] = ''
3296
3297 for ModuleType in self._DepexExpressionList:
3298 DepexExpressionList = self._DepexExpressionList[ModuleType]
3299 #
3300 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
3301 #
3302 for M in [self.Module] + self.DependentLibraryList:
3303 Inherited = False
3304 for D in M.DepexExpression[self.Arch, ModuleType]:
3305 if DepexExpressionList != '':
3306 DepexExpressionList += ' AND '
3307 DepexExpressionList += '('
3308 DepexExpressionList += D
3309 DepexExpressionList = DepexExpressionList.rstrip('END').strip()
3310 DepexExpressionList += ')'
3311 Inherited = True
3312 if Inherited:
3313 EdkLogger.verbose("DEPEX[%s] (+%s) = %s" % (self.Name, M.BaseName, DepexExpressionList))
3314 if 'BEFORE' in DepexExpressionList or 'AFTER' in DepexExpressionList:
3315 break
3316 if len(DepexExpressionList) > 0:
3317 EdkLogger.verbose('')
3318 self._DepexExpressionList[ModuleType] = DepexExpressionList
3319 return self._DepexExpressionList
3320
3321 # Get the tiano core user extension, it is contain dependent library.
3322 # @retval: a list contain tiano core userextension.
3323 #
3324 def _GetTianoCoreUserExtensionList(self):
3325 TianoCoreUserExtentionList = []
3326 for M in [self.Module] + self.DependentLibraryList:
3327 Filename = M.MetaFile.Path
3328 InfObj = InfSectionParser.InfSectionParser(Filename)
3329 TianoCoreUserExtenList = InfObj.GetUserExtensionTianoCore()
3330 for TianoCoreUserExtent in TianoCoreUserExtenList:
3331 for Section in TianoCoreUserExtent.keys():
3332 ItemList = Section.split(TAB_SPLIT)
3333 Arch = self.Arch
3334 if len(ItemList) == 4:
3335 Arch = ItemList[3]
3336 if Arch.upper() == TAB_ARCH_COMMON or Arch.upper() == self.Arch.upper():
3337 TianoCoreList = []
3338 TianoCoreList.extend([TAB_SECTION_START + Section + TAB_SECTION_END])
3339 TianoCoreList.extend(TianoCoreUserExtent[Section][:])
3340 TianoCoreList.append('\n')
3341 TianoCoreUserExtentionList.append(TianoCoreList)
3342
3343 return TianoCoreUserExtentionList
3344
3345 ## Return the list of specification version required for the module
3346 #
3347 # @retval list The list of specification defined in module file
3348 #
3349 def _GetSpecification(self):
3350 return self.Module.Specification
3351
3352 ## Tool option for the module build
3353 #
3354 # @param PlatformInfo The object of PlatformBuildInfo
3355 # @retval dict The dict containing valid options
3356 #
3357 def _GetModuleBuildOption(self):
3358 if self._BuildOption == None:
3359 self._BuildOption, self.BuildRuleOrder = self.PlatformInfo.ApplyBuildOption(self.Module)
3360 if self.BuildRuleOrder:
3361 self.BuildRuleOrder = ['.%s' % Ext for Ext in self.BuildRuleOrder.split()]
3362 return self._BuildOption
3363
3364 ## Get include path list from tool option for the module build
3365 #
3366 # @retval list The include path list
3367 #
3368 def _GetBuildOptionIncPathList(self):
3369 if self._BuildOptionIncPathList == None:
3370 #
3371 # Regular expression for finding Include Directories, the difference between MSFT and INTEL/GCC/RVCT
3372 # is the former use /I , the Latter used -I to specify include directories
3373 #
3374 if self.PlatformInfo.ToolChainFamily in ('MSFT'):
3375 gBuildOptIncludePattern = re.compile(r"(?:.*?)/I[ \t]*([^ ]*)", re.MULTILINE | re.DOTALL)
3376 elif self.PlatformInfo.ToolChainFamily in ('INTEL', 'GCC', 'RVCT'):
3377 gBuildOptIncludePattern = re.compile(r"(?:.*?)-I[ \t]*([^ ]*)", re.MULTILINE | re.DOTALL)
3378 else:
3379 #
3380 # New ToolChainFamily, don't known whether there is option to specify include directories
3381 #
3382 self._BuildOptionIncPathList = []
3383 return self._BuildOptionIncPathList
3384
3385 BuildOptionIncPathList = []
3386 for Tool in ('CC', 'PP', 'VFRPP', 'ASLPP', 'ASLCC', 'APP', 'ASM'):
3387 Attr = 'FLAGS'
3388 try:
3389 FlagOption = self.BuildOption[Tool][Attr]
3390 except KeyError:
3391 FlagOption = ''
3392
3393 if self.PlatformInfo.ToolChainFamily != 'RVCT':
3394 IncPathList = [NormPath(Path, self.Macros) for Path in gBuildOptIncludePattern.findall(FlagOption)]
3395 else:
3396 #
3397 # RVCT may specify a list of directory seperated by commas
3398 #
3399 IncPathList = []
3400 for Path in gBuildOptIncludePattern.findall(FlagOption):
3401 PathList = GetSplitList(Path, TAB_COMMA_SPLIT)
3402 IncPathList += [NormPath(PathEntry, self.Macros) for PathEntry in PathList]
3403
3404 #
3405 # EDK II modules must not reference header files outside of the packages they depend on or
3406 # within the module's directory tree. Report error if violation.
3407 #
3408 if self.AutoGenVersion >= 0x00010005 and len(IncPathList) > 0:
3409 for Path in IncPathList:
3410 if (Path not in self.IncludePathList) and (CommonPath([Path, self.MetaFile.Dir]) != self.MetaFile.Dir):
3411 ErrMsg = "The include directory for the EDK II module in this line is invalid %s specified in %s FLAGS '%s'" % (Path, Tool, FlagOption)
3412 EdkLogger.error("build",
3413 PARAMETER_INVALID,
3414 ExtraData=ErrMsg,
3415 File=str(self.MetaFile))
3416
3417
3418 BuildOptionIncPathList += IncPathList
3419
3420 self._BuildOptionIncPathList = BuildOptionIncPathList
3421
3422 return self._BuildOptionIncPathList
3423
3424 ## Return a list of files which can be built from source
3425 #
3426 # What kind of files can be built is determined by build rules in
3427 # $(CONF_DIRECTORY)/build_rule.txt and toolchain family.
3428 #
3429 def _GetSourceFileList(self):
3430 if self._SourceFileList == None:
3431 self._SourceFileList = []
3432 for F in self.Module.Sources:
3433 # match tool chain
3434 if F.TagName not in ("", "*", self.ToolChain):
3435 EdkLogger.debug(EdkLogger.DEBUG_9, "The toolchain [%s] for processing file [%s] is found, "
3436 "but [%s] is needed" % (F.TagName, str(F), self.ToolChain))
3437 continue
3438 # match tool chain family or build rule family
3439 if F.ToolChainFamily not in ("", "*", self.ToolChainFamily, self.BuildRuleFamily):
3440 EdkLogger.debug(
3441 EdkLogger.DEBUG_0,
3442 "The file [%s] must be built by tools of [%s], " \
3443 "but current toolchain family is [%s], buildrule family is [%s]" \
3444 % (str(F), F.ToolChainFamily, self.ToolChainFamily, self.BuildRuleFamily))
3445 continue
3446
3447 # add the file path into search path list for file including
3448 if F.Dir not in self.IncludePathList and self.AutoGenVersion >= 0x00010005:
3449 self.IncludePathList.insert(0, F.Dir)
3450 self._SourceFileList.append(F)
3451
3452 self._MatchBuildRuleOrder(self._SourceFileList)
3453
3454 for F in self._SourceFileList:
3455 self._ApplyBuildRule(F, TAB_UNKNOWN_FILE)
3456 return self._SourceFileList
3457
3458 def _MatchBuildRuleOrder(self, FileList):
3459 Order_Dict = {}
3460 self._GetModuleBuildOption()
3461 for SingleFile in FileList:
3462 if self.BuildRuleOrder and SingleFile.Ext in self.BuildRuleOrder and SingleFile.Ext in self.BuildRules:
3463 key = SingleFile.Path.split(SingleFile.Ext)[0]
3464 if key in Order_Dict:
3465 Order_Dict[key].append(SingleFile.Ext)
3466 else:
3467 Order_Dict[key] = [SingleFile.Ext]
3468
3469 RemoveList = []
3470 for F in Order_Dict:
3471 if len(Order_Dict[F]) > 1:
3472 Order_Dict[F].sort(key=lambda i: self.BuildRuleOrder.index(i))
3473 for Ext in Order_Dict[F][1:]:
3474 RemoveList.append(F + Ext)
3475
3476 for item in RemoveList:
3477 FileList.remove(item)
3478
3479 return FileList
3480
3481 ## Return the list of unicode files
3482 def _GetUnicodeFileList(self):
3483 if self._UnicodeFileList == None:
3484 if TAB_UNICODE_FILE in self.FileTypes:
3485 self._UnicodeFileList = self.FileTypes[TAB_UNICODE_FILE]
3486 else:
3487 self._UnicodeFileList = []
3488 return self._UnicodeFileList
3489
3490 ## Return the list of vfr files
3491 def _GetVfrFileList(self):
3492 if self._VfrFileList == None:
3493 if TAB_VFR_FILE in self.FileTypes:
3494 self._VfrFileList = self.FileTypes[TAB_VFR_FILE]
3495 else:
3496 self._VfrFileList = []
3497 return self._VfrFileList
3498
3499 ## Return the list of Image Definition files
3500 def _GetIdfFileList(self):
3501 if self._IdfFileList == None:
3502 if TAB_IMAGE_FILE in self.FileTypes:
3503 self._IdfFileList = self.FileTypes[TAB_IMAGE_FILE]
3504 else:
3505 self._IdfFileList = []
3506 return self._IdfFileList
3507
3508 ## Return a list of files which can be built from binary
3509 #
3510 # "Build" binary files are just to copy them to build directory.
3511 #
3512 # @retval list The list of files which can be built later
3513 #
3514 def _GetBinaryFiles(self):
3515 if self._BinaryFileList == None:
3516 self._BinaryFileList = []
3517 for F in self.Module.Binaries:
3518 if F.Target not in ['COMMON', '*'] and F.Target != self.BuildTarget:
3519 continue
3520 self._BinaryFileList.append(F)
3521 self._ApplyBuildRule(F, F.Type)
3522 return self._BinaryFileList
3523
3524 def _GetBuildRules(self):
3525 if self._BuildRules == None:
3526 BuildRules = {}
3527 BuildRuleDatabase = self.PlatformInfo.BuildRule
3528 for Type in BuildRuleDatabase.FileTypeList:
3529 #first try getting build rule by BuildRuleFamily
3530 RuleObject = BuildRuleDatabase[Type, self.BuildType, self.Arch, self.BuildRuleFamily]
3531 if not RuleObject:
3532 # build type is always module type, but ...
3533 if self.ModuleType != self.BuildType:
3534 RuleObject = BuildRuleDatabase[Type, self.ModuleType, self.Arch, self.BuildRuleFamily]
3535 #second try getting build rule by ToolChainFamily
3536 if not RuleObject:
3537 RuleObject = BuildRuleDatabase[Type, self.BuildType, self.Arch, self.ToolChainFamily]
3538 if not RuleObject:
3539 # build type is always module type, but ...
3540 if self.ModuleType != self.BuildType:
3541 RuleObject = BuildRuleDatabase[Type, self.ModuleType, self.Arch, self.ToolChainFamily]
3542 if not RuleObject:
3543 continue
3544 RuleObject = RuleObject.Instantiate(self.Macros)
3545 BuildRules[Type] = RuleObject
3546 for Ext in RuleObject.SourceFileExtList:
3547 BuildRules[Ext] = RuleObject
3548 self._BuildRules = BuildRules
3549 return self._BuildRules
3550
3551 def _ApplyBuildRule(self, File, FileType):
3552 if self._BuildTargets == None:
3553 self._IntroBuildTargetList = set()
3554 self._FinalBuildTargetList = set()
3555 self._BuildTargets = {}
3556 self._FileTypes = {}
3557
3558 SubDirectory = os.path.join(self.OutputDir, File.SubDir)
3559 if not os.path.exists(SubDirectory):
3560 CreateDirectory(SubDirectory)
3561 LastTarget = None
3562 RuleChain = []
3563 SourceList = [File]
3564 Index = 0
3565 #
3566 # Make sure to get build rule order value
3567 #
3568 self._GetModuleBuildOption()
3569
3570 while Index < len(SourceList):
3571 Source = SourceList[Index]
3572 Index = Index + 1
3573
3574 if Source != File:
3575 CreateDirectory(Source.Dir)
3576
3577 if File.IsBinary and File == Source and self._BinaryFileList != None and File in self._BinaryFileList:
3578 # Skip all files that are not binary libraries
3579 if not self.IsLibrary:
3580 continue
3581 RuleObject = self.BuildRules[TAB_DEFAULT_BINARY_FILE]
3582 elif FileType in self.BuildRules:
3583 RuleObject = self.BuildRules[FileType]
3584 elif Source.Ext in self.BuildRules:
3585 RuleObject = self.BuildRules[Source.Ext]
3586 else:
3587 # stop at no more rules
3588 if LastTarget:
3589 self._FinalBuildTargetList.add(LastTarget)
3590 break
3591
3592 FileType = RuleObject.SourceFileType
3593 if FileType not in self._FileTypes:
3594 self._FileTypes[FileType] = set()
3595 self._FileTypes[FileType].add(Source)
3596
3597 # stop at STATIC_LIBRARY for library
3598 if self.IsLibrary and FileType == TAB_STATIC_LIBRARY:
3599 if LastTarget:
3600 self._FinalBuildTargetList.add(LastTarget)
3601 break
3602
3603 Target = RuleObject.Apply(Source, self.BuildRuleOrder)
3604 if not Target:
3605 if LastTarget:
3606 self._FinalBuildTargetList.add(LastTarget)
3607 break
3608 elif not Target.Outputs:
3609 # Only do build for target with outputs
3610 self._FinalBuildTargetList.add(Target)
3611
3612 if FileType not in self._BuildTargets:
3613 self._BuildTargets[FileType] = set()
3614 self._BuildTargets[FileType].add(Target)
3615
3616 if not Source.IsBinary and Source == File:
3617 self._IntroBuildTargetList.add(Target)
3618
3619 # to avoid cyclic rule
3620 if FileType in RuleChain:
3621 break
3622
3623 RuleChain.append(FileType)
3624 SourceList.extend(Target.Outputs)
3625 LastTarget = Target
3626 FileType = TAB_UNKNOWN_FILE
3627
3628 def _GetTargets(self):
3629 if self._BuildTargets == None:
3630 self._IntroBuildTargetList = set()
3631 self._FinalBuildTargetList = set()
3632 self._BuildTargets = {}
3633 self._FileTypes = {}
3634
3635 #TRICK: call _GetSourceFileList to apply build rule for source files
3636 if self.SourceFileList:
3637 pass
3638
3639 #TRICK: call _GetBinaryFileList to apply build rule for binary files
3640 if self.BinaryFileList:
3641 pass
3642
3643 return self._BuildTargets
3644
3645 def _GetIntroTargetList(self):
3646 self._GetTargets()
3647 return self._IntroBuildTargetList
3648
3649 def _GetFinalTargetList(self):
3650 self._GetTargets()
3651 return self._FinalBuildTargetList
3652
3653 def _GetFileTypes(self):
3654 self._GetTargets()
3655 return self._FileTypes
3656
3657 ## Get the list of package object the module depends on
3658 #
3659 # @retval list The package object list
3660 #
3661 def _GetDependentPackageList(self):
3662 return self.Module.Packages
3663
3664 ## Return the list of auto-generated code file
3665 #
3666 # @retval list The list of auto-generated file
3667 #
3668 def _GetAutoGenFileList(self):
3669 UniStringAutoGenC = True
3670 IdfStringAutoGenC = True
3671 UniStringBinBuffer = StringIO()
3672 IdfGenBinBuffer = StringIO()
3673 if self.BuildType == 'UEFI_HII':
3674 UniStringAutoGenC = False
3675 IdfStringAutoGenC = False
3676 if self._AutoGenFileList == None:
3677 self._AutoGenFileList = {}
3678 AutoGenC = TemplateString()
3679 AutoGenH = TemplateString()
3680 StringH = TemplateString()
3681 StringIdf = TemplateString()
3682 GenC.CreateCode(self, AutoGenC, AutoGenH, StringH, UniStringAutoGenC, UniStringBinBuffer, StringIdf, IdfStringAutoGenC, IdfGenBinBuffer)
3683 #
3684 # AutoGen.c is generated if there are library classes in inf, or there are object files
3685 #
3686 if str(AutoGenC) != "" and (len(self.Module.LibraryClasses) > 0
3687 or TAB_OBJECT_FILE in self.FileTypes):
3688 AutoFile = PathClass(gAutoGenCodeFileName, self.DebugDir)
3689 self._AutoGenFileList[AutoFile] = str(AutoGenC)
3690 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
3691 if str(AutoGenH) != "":
3692 AutoFile = PathClass(gAutoGenHeaderFileName, self.DebugDir)
3693 self._AutoGenFileList[AutoFile] = str(AutoGenH)
3694 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
3695 if str(StringH) != "":
3696 AutoFile = PathClass(gAutoGenStringFileName % {"module_name":self.Name}, self.DebugDir)
3697 self._AutoGenFileList[AutoFile] = str(StringH)
3698 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
3699 if UniStringBinBuffer != None and UniStringBinBuffer.getvalue() != "":
3700 AutoFile = PathClass(gAutoGenStringFormFileName % {"module_name":self.Name}, self.OutputDir)
3701 self._AutoGenFileList[AutoFile] = UniStringBinBuffer.getvalue()
3702 AutoFile.IsBinary = True
3703 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
3704 if UniStringBinBuffer != None:
3705 UniStringBinBuffer.close()
3706 if str(StringIdf) != "":
3707 AutoFile = PathClass(gAutoGenImageDefFileName % {"module_name":self.Name}, self.DebugDir)
3708 self._AutoGenFileList[AutoFile] = str(StringIdf)
3709 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
3710 if IdfGenBinBuffer != None and IdfGenBinBuffer.getvalue() != "":
3711 AutoFile = PathClass(gAutoGenIdfFileName % {"module_name":self.Name}, self.OutputDir)
3712 self._AutoGenFileList[AutoFile] = IdfGenBinBuffer.getvalue()
3713 AutoFile.IsBinary = True
3714 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
3715 if IdfGenBinBuffer != None:
3716 IdfGenBinBuffer.close()
3717 return self._AutoGenFileList
3718
3719 ## Return the list of library modules explicitly or implicityly used by this module
3720 def _GetLibraryList(self):
3721 if self._DependentLibraryList == None:
3722 # only merge library classes and PCD for non-library module
3723 if self.IsLibrary:
3724 self._DependentLibraryList = []
3725 else:
3726 if self.AutoGenVersion < 0x00010005:
3727 self._DependentLibraryList = self.PlatformInfo.ResolveLibraryReference(self.Module)
3728 else:
3729 self._DependentLibraryList = self.PlatformInfo.ApplyLibraryInstance(self.Module)
3730 return self._DependentLibraryList
3731
3732 @staticmethod
3733 def UpdateComments(Recver, Src):
3734 for Key in Src:
3735 if Key not in Recver:
3736 Recver[Key] = []
3737 Recver[Key].extend(Src[Key])
3738 ## Get the list of PCDs from current module
3739 #
3740 # @retval list The list of PCD
3741 #
3742 def _GetModulePcdList(self):
3743 if self._ModulePcdList == None:
3744 # apply PCD settings from platform
3745 self._ModulePcdList = self.PlatformInfo.ApplyPcdSetting(self.Module, self.Module.Pcds)
3746 self.UpdateComments(self._PcdComments, self.Module.PcdComments)
3747 return self._ModulePcdList
3748
3749 ## Get the list of PCDs from dependent libraries
3750 #
3751 # @retval list The list of PCD
3752 #
3753 def _GetLibraryPcdList(self):
3754 if self._LibraryPcdList == None:
3755 Pcds = sdict()
3756 if not self.IsLibrary:
3757 # get PCDs from dependent libraries
3758 for Library in self.DependentLibraryList:
3759 self.UpdateComments(self._PcdComments, Library.PcdComments)
3760 for Key in Library.Pcds:
3761 # skip duplicated PCDs
3762 if Key in self.Module.Pcds or Key in Pcds:
3763 continue
3764 Pcds[Key] = copy.copy(Library.Pcds[Key])
3765 # apply PCD settings from platform
3766 self._LibraryPcdList = self.PlatformInfo.ApplyPcdSetting(self.Module, Pcds)
3767 else:
3768 self._LibraryPcdList = []
3769 return self._LibraryPcdList
3770
3771 ## Get the GUID value mapping
3772 #
3773 # @retval dict The mapping between GUID cname and its value
3774 #
3775 def _GetGuidList(self):
3776 if self._GuidList == None:
3777 self._GuidList = sdict()
3778 self._GuidList.update(self.Module.Guids)
3779 for Library in self.DependentLibraryList:
3780 self._GuidList.update(Library.Guids)
3781 self.UpdateComments(self._GuidComments, Library.GuidComments)
3782 self.UpdateComments(self._GuidComments, self.Module.GuidComments)
3783 return self._GuidList
3784
3785 def GetGuidsUsedByPcd(self):
3786 if self._GuidsUsedByPcd == None:
3787 self._GuidsUsedByPcd = sdict()
3788 self._GuidsUsedByPcd.update(self.Module.GetGuidsUsedByPcd())
3789 for Library in self.DependentLibraryList:
3790 self._GuidsUsedByPcd.update(Library.GetGuidsUsedByPcd())
3791 return self._GuidsUsedByPcd
3792 ## Get the protocol value mapping
3793 #
3794 # @retval dict The mapping between protocol cname and its value
3795 #
3796 def _GetProtocolList(self):
3797 if self._ProtocolList == None:
3798 self._ProtocolList = sdict()
3799 self._ProtocolList.update(self.Module.Protocols)
3800 for Library in self.DependentLibraryList:
3801 self._ProtocolList.update(Library.Protocols)
3802 self.UpdateComments(self._ProtocolComments, Library.ProtocolComments)
3803 self.UpdateComments(self._ProtocolComments, self.Module.ProtocolComments)
3804 return self._ProtocolList
3805
3806 ## Get the PPI value mapping
3807 #
3808 # @retval dict The mapping between PPI cname and its value
3809 #
3810 def _GetPpiList(self):
3811 if self._PpiList == None:
3812 self._PpiList = sdict()
3813 self._PpiList.update(self.Module.Ppis)
3814 for Library in self.DependentLibraryList:
3815 self._PpiList.update(Library.Ppis)
3816 self.UpdateComments(self._PpiComments, Library.PpiComments)
3817 self.UpdateComments(self._PpiComments, self.Module.PpiComments)
3818 return self._PpiList
3819
3820 ## Get the list of include search path
3821 #
3822 # @retval list The list path
3823 #
3824 def _GetIncludePathList(self):
3825 if self._IncludePathList == None:
3826 self._IncludePathList = []
3827 if self.AutoGenVersion < 0x00010005:
3828 for Inc in self.Module.Includes:
3829 if Inc not in self._IncludePathList:
3830 self._IncludePathList.append(Inc)
3831 # for Edk modules
3832 Inc = path.join(Inc, self.Arch.capitalize())
3833 if os.path.exists(Inc) and Inc not in self._IncludePathList:
3834 self._IncludePathList.append(Inc)
3835 # Edk module needs to put DEBUG_DIR at the end of search path and not to use SOURCE_DIR all the time
3836 self._IncludePathList.append(self.DebugDir)
3837 else:
3838 self._IncludePathList.append(self.MetaFile.Dir)
3839 self._IncludePathList.append(self.DebugDir)
3840
3841 for Package in self.Module.Packages:
3842 PackageDir = mws.join(self.WorkspaceDir, Package.MetaFile.Dir)
3843 if PackageDir not in self._IncludePathList:
3844 self._IncludePathList.append(PackageDir)
3845 IncludesList = Package.Includes
3846 if Package._PrivateIncludes:
3847 if not self.MetaFile.Path.startswith(PackageDir):
3848 IncludesList = list(set(Package.Includes).difference(set(Package._PrivateIncludes)))
3849 for Inc in IncludesList:
3850 if Inc not in self._IncludePathList:
3851 self._IncludePathList.append(str(Inc))
3852 return self._IncludePathList
3853
3854 def _GetIncludePathLength(self):
3855 self._IncludePathLength = 0
3856 if self._IncludePathList:
3857 for inc in self._IncludePathList:
3858 self._IncludePathLength += len(' ' + inc)
3859 return self._IncludePathLength
3860
3861 ## Get HII EX PCDs which maybe used by VFR
3862 #
3863 # efivarstore used by VFR may relate with HII EX PCDs
3864 # Get the variable name and GUID from efivarstore and HII EX PCD
3865 # List the HII EX PCDs in As Built INF if both name and GUID match.
3866 #
3867 # @retval list HII EX PCDs
3868 #
3869 def _GetPcdsMaybeUsedByVfr(self):
3870 if not self.SourceFileList:
3871 return []
3872
3873 NameGuids = []
3874 for SrcFile in self.SourceFileList:
3875 if SrcFile.Ext.lower() != '.vfr':
3876 continue
3877 Vfri = os.path.join(self.OutputDir, SrcFile.BaseName + '.i')
3878 if not os.path.exists(Vfri):
3879 continue
3880 VfriFile = open(Vfri, 'r')
3881 Content = VfriFile.read()
3882 VfriFile.close()
3883 Pos = Content.find('efivarstore')
3884 while Pos != -1:
3885 #
3886 # Make sure 'efivarstore' is the start of efivarstore statement
3887 # In case of the value of 'name' (name = efivarstore) is equal to 'efivarstore'
3888 #
3889 Index = Pos - 1
3890 while Index >= 0 and Content[Index] in ' \t\r\n':
3891 Index -= 1
3892 if Index >= 0 and Content[Index] != ';':
3893 Pos = Content.find('efivarstore', Pos + len('efivarstore'))
3894 continue
3895 #
3896 # 'efivarstore' must be followed by name and guid
3897 #
3898 Name = gEfiVarStoreNamePattern.search(Content, Pos)
3899 if not Name:
3900 break
3901 Guid = gEfiVarStoreGuidPattern.search(Content, Pos)
3902 if not Guid:
3903 break
3904 NameArray = ConvertStringToByteArray('L"' + Name.group(1) + '"')
3905 NameGuids.append((NameArray, GuidStructureStringToGuidString(Guid.group(1))))
3906 Pos = Content.find('efivarstore', Name.end())
3907 if not NameGuids:
3908 return []
3909 HiiExPcds = []
3910 for Pcd in self.PlatformInfo.Platform.Pcds.values():
3911 if Pcd.Type != TAB_PCDS_DYNAMIC_EX_HII:
3912 continue
3913 for SkuName in Pcd.SkuInfoList:
3914 SkuInfo = Pcd.SkuInfoList[SkuName]
3915 Name = ConvertStringToByteArray(SkuInfo.VariableName)
3916 Value = GuidValue(SkuInfo.VariableGuid, self.PlatformInfo.PackageList, self.MetaFile.Path)
3917 if not Value:
3918 continue
3919 Guid = GuidStructureStringToGuidString(Value)
3920 if (Name, Guid) in NameGuids and Pcd not in HiiExPcds:
3921 HiiExPcds.append(Pcd)
3922 break
3923
3924 return HiiExPcds
3925
3926 def _GenOffsetBin(self):
3927 VfrUniBaseName = {}
3928 for SourceFile in self.Module.Sources:
3929 if SourceFile.Type.upper() == ".VFR" :
3930 #
3931 # search the .map file to find the offset of vfr binary in the PE32+/TE file.
3932 #
3933 VfrUniBaseName[SourceFile.BaseName] = (SourceFile.BaseName + "Bin")
3934 if SourceFile.Type.upper() == ".UNI" :
3935 #
3936 # search the .map file to find the offset of Uni strings binary in the PE32+/TE file.
3937 #
3938 VfrUniBaseName["UniOffsetName"] = (self.Name + "Strings")
3939
3940 if len(VfrUniBaseName) == 0:
3941 return None
3942 MapFileName = os.path.join(self.OutputDir, self.Name + ".map")
3943 EfiFileName = os.path.join(self.OutputDir, self.Name + ".efi")
3944 VfrUniOffsetList = GetVariableOffset(MapFileName, EfiFileName, VfrUniBaseName.values())
3945 if not VfrUniOffsetList:
3946 return None
3947
3948 OutputName = '%sOffset.bin' % self.Name
3949 UniVfrOffsetFileName = os.path.join( self.OutputDir, OutputName)
3950
3951 try:
3952 fInputfile = open(UniVfrOffsetFileName, "wb+", 0)
3953 except:
3954 EdkLogger.error("build", FILE_OPEN_FAILURE, "File open failed for %s" % UniVfrOffsetFileName,None)
3955
3956 # Use a instance of StringIO to cache data
3957 fStringIO = StringIO('')
3958
3959 for Item in VfrUniOffsetList:
3960 if (Item[0].find("Strings") != -1):
3961 #
3962 # UNI offset in image.
3963 # GUID + Offset
3964 # { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } }
3965 #
3966 UniGuid = [0xe0, 0xc5, 0x13, 0x89, 0xf6, 0x33, 0x86, 0x4d, 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66]
3967 UniGuid = [chr(ItemGuid) for ItemGuid in UniGuid]
3968 fStringIO.write(''.join(UniGuid))
3969 UniValue = pack ('Q', int (Item[1], 16))
3970 fStringIO.write (UniValue)
3971 else:
3972 #
3973 # VFR binary offset in image.
3974 # GUID + Offset
3975 # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } };
3976 #
3977 VfrGuid = [0xb4, 0x7c, 0xbc, 0xd0, 0x47, 0x6a, 0x5f, 0x49, 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2]
3978 VfrGuid = [chr(ItemGuid) for ItemGuid in VfrGuid]
3979 fStringIO.write(''.join(VfrGuid))
3980 type (Item[1])
3981 VfrValue = pack ('Q', int (Item[1], 16))
3982 fStringIO.write (VfrValue)
3983 #
3984 # write data into file.
3985 #
3986 try :
3987 fInputfile.write (fStringIO.getvalue())
3988 except:
3989 EdkLogger.error("build", FILE_WRITE_FAILURE, "Write data to file %s failed, please check whether the "
3990 "file been locked or using by other applications." %UniVfrOffsetFileName,None)
3991
3992 fStringIO.close ()
3993 fInputfile.close ()
3994 return OutputName
3995
3996 ## Create AsBuilt INF file the module
3997 #
3998 def CreateAsBuiltInf(self, IsOnlyCopy = False):
3999 self.OutputFile = []
4000 if IsOnlyCopy:
4001 if GlobalData.gBinCacheDest:
4002 self.CopyModuleToCache()
4003 return
4004
4005 if self.IsAsBuiltInfCreated:
4006 return
4007
4008 # Skip the following code for EDK I inf
4009 if self.AutoGenVersion < 0x00010005:
4010 return
4011
4012 # Skip the following code for libraries
4013 if self.IsLibrary:
4014 return
4015
4016 # Skip the following code for modules with no source files
4017 if self.SourceFileList == None or self.SourceFileList == []:
4018 return
4019
4020 # Skip the following code for modules without any binary files
4021 if self.BinaryFileList <> None and self.BinaryFileList <> []:
4022 return
4023
4024 ### TODO: How to handles mixed source and binary modules
4025
4026 # Find all DynamicEx and PatchableInModule PCDs used by this module and dependent libraries
4027 # Also find all packages that the DynamicEx PCDs depend on
4028 Pcds = []
4029 PatchablePcds = []
4030 Packages = []
4031 PcdCheckList = []
4032 PcdTokenSpaceList = []
4033 for Pcd in self.ModulePcdList + self.LibraryPcdList:
4034 if Pcd.Type == TAB_PCDS_PATCHABLE_IN_MODULE:
4035 PatchablePcds += [Pcd]
4036 PcdCheckList.append((Pcd.TokenCName, Pcd.TokenSpaceGuidCName, 'PatchableInModule'))
4037 elif Pcd.Type in GenC.gDynamicExPcd:
4038 if Pcd not in Pcds:
4039 Pcds += [Pcd]
4040 PcdCheckList.append((Pcd.TokenCName, Pcd.TokenSpaceGuidCName, 'DynamicEx'))
4041 PcdCheckList.append((Pcd.TokenCName, Pcd.TokenSpaceGuidCName, 'Dynamic'))
4042 PcdTokenSpaceList.append(Pcd.TokenSpaceGuidCName)
4043 GuidList = sdict()
4044 GuidList.update(self.GuidList)
4045 for TokenSpace in self.GetGuidsUsedByPcd():
4046 # If token space is not referred by patch PCD or Ex PCD, remove the GUID from GUID list
4047 # The GUIDs in GUIDs section should really be the GUIDs in source INF or referred by Ex an patch PCDs
4048 if TokenSpace not in PcdTokenSpaceList and TokenSpace in GuidList:
4049 GuidList.pop(TokenSpace)
4050 CheckList = (GuidList, self.PpiList, self.ProtocolList, PcdCheckList)
4051 for Package in self.DerivedPackageList:
4052 if Package in Packages:
4053 continue
4054 BeChecked = (Package.Guids, Package.Ppis, Package.Protocols, Package.Pcds)
4055 Found = False
4056 for Index in range(len(BeChecked)):
4057 for Item in CheckList[Index]:
4058 if Item in BeChecked[Index]:
4059 Packages += [Package]
4060 Found = True
4061 break
4062 if Found: break
4063
4064 VfrPcds = self._GetPcdsMaybeUsedByVfr()
4065 for Pkg in self.PlatformInfo.PackageList:
4066 if Pkg in Packages:
4067 continue
4068 for VfrPcd in VfrPcds:
4069 if ((VfrPcd.TokenCName, VfrPcd.TokenSpaceGuidCName, 'DynamicEx') in Pkg.Pcds or
4070 (VfrPcd.TokenCName, VfrPcd.TokenSpaceGuidCName, 'Dynamic') in Pkg.Pcds):
4071 Packages += [Pkg]
4072 break
4073
4074 ModuleType = self.ModuleType
4075 if ModuleType == 'UEFI_DRIVER' and self.DepexGenerated:
4076 ModuleType = 'DXE_DRIVER'
4077
4078 DriverType = ''
4079 if self.PcdIsDriver != '':
4080 DriverType = self.PcdIsDriver
4081
4082 Guid = self.Guid
4083 MDefs = self.Module.Defines
4084
4085 AsBuiltInfDict = {
4086 'module_name' : self.Name,
4087 'module_guid' : Guid,
4088 'module_module_type' : ModuleType,
4089 'module_version_string' : [MDefs['VERSION_STRING']] if 'VERSION_STRING' in MDefs else [],
4090 'pcd_is_driver_string' : [],
4091 'module_uefi_specification_version' : [],
4092 'module_pi_specification_version' : [],
4093 'module_entry_point' : self.Module.ModuleEntryPointList,
4094 'module_unload_image' : self.Module.ModuleUnloadImageList,
4095 'module_constructor' : self.Module.ConstructorList,
4096 'module_destructor' : self.Module.DestructorList,
4097 'module_shadow' : [MDefs['SHADOW']] if 'SHADOW' in MDefs else [],
4098 'module_pci_vendor_id' : [MDefs['PCI_VENDOR_ID']] if 'PCI_VENDOR_ID' in MDefs else [],
4099 'module_pci_device_id' : [MDefs['PCI_DEVICE_ID']] if 'PCI_DEVICE_ID' in MDefs else [],
4100 'module_pci_class_code' : [MDefs['PCI_CLASS_CODE']] if 'PCI_CLASS_CODE' in MDefs else [],
4101 'module_pci_revision' : [MDefs['PCI_REVISION']] if 'PCI_REVISION' in MDefs else [],
4102 'module_build_number' : [MDefs['BUILD_NUMBER']] if 'BUILD_NUMBER' in MDefs else [],
4103 'module_spec' : [MDefs['SPEC']] if 'SPEC' in MDefs else [],
4104 'module_uefi_hii_resource_section' : [MDefs['UEFI_HII_RESOURCE_SECTION']] if 'UEFI_HII_RESOURCE_SECTION' in MDefs else [],
4105 'module_uni_file' : [MDefs['MODULE_UNI_FILE']] if 'MODULE_UNI_FILE' in MDefs else [],
4106 'module_arch' : self.Arch,
4107 'package_item' : ['%s' % (Package.MetaFile.File.replace('\\', '/')) for Package in Packages],
4108 'binary_item' : [],
4109 'patchablepcd_item' : [],
4110 'pcd_item' : [],
4111 'protocol_item' : [],
4112 'ppi_item' : [],
4113 'guid_item' : [],
4114 'flags_item' : [],
4115 'libraryclasses_item' : []
4116 }
4117
4118 if 'MODULE_UNI_FILE' in MDefs:
4119 UNIFile = os.path.join(self.MetaFile.Dir, MDefs['MODULE_UNI_FILE'])
4120 if os.path.isfile(UNIFile):
4121 shutil.copy2(UNIFile, self.OutputDir)
4122
4123 if self.AutoGenVersion > int(gInfSpecVersion, 0):
4124 AsBuiltInfDict['module_inf_version'] = '0x%08x' % self.AutoGenVersion
4125 else:
4126 AsBuiltInfDict['module_inf_version'] = gInfSpecVersion
4127
4128 if DriverType:
4129 AsBuiltInfDict['pcd_is_driver_string'] += [DriverType]
4130
4131 if 'UEFI_SPECIFICATION_VERSION' in self.Specification:
4132 AsBuiltInfDict['module_uefi_specification_version'] += [self.Specification['UEFI_SPECIFICATION_VERSION']]
4133 if 'PI_SPECIFICATION_VERSION' in self.Specification:
4134 AsBuiltInfDict['module_pi_specification_version'] += [self.Specification['PI_SPECIFICATION_VERSION']]
4135
4136 OutputDir = self.OutputDir.replace('\\', '/').strip('/')
4137 DebugDir = self.DebugDir.replace('\\', '/').strip('/')
4138 for Item in self.CodaTargetList:
4139 File = Item.Target.Path.replace('\\', '/').strip('/').replace(DebugDir, '').strip('/')
4140 if File not in self.OutputFile:
4141 self.OutputFile.append(File)
4142 if os.path.isabs(File):
4143 File = File.replace('\\', '/').strip('/').replace(OutputDir, '').strip('/')
4144 if Item.Target.Ext.lower() == '.aml':
4145 AsBuiltInfDict['binary_item'] += ['ASL|' + File]
4146 elif Item.Target.Ext.lower() == '.acpi':
4147 AsBuiltInfDict['binary_item'] += ['ACPI|' + File]
4148 elif Item.Target.Ext.lower() == '.efi':
4149 AsBuiltInfDict['binary_item'] += ['PE32|' + self.Name + '.efi']
4150 else:
4151 AsBuiltInfDict['binary_item'] += ['BIN|' + File]
4152 if self.DepexGenerated:
4153 if self.Name + '.depex' not in self.OutputFile:
4154 self.OutputFile.append(self.Name + '.depex')
4155 if self.ModuleType in ['PEIM']:
4156 AsBuiltInfDict['binary_item'] += ['PEI_DEPEX|' + self.Name + '.depex']
4157 if self.ModuleType in ['DXE_DRIVER', 'DXE_RUNTIME_DRIVER', 'DXE_SAL_DRIVER', 'UEFI_DRIVER']:
4158 AsBuiltInfDict['binary_item'] += ['DXE_DEPEX|' + self.Name + '.depex']
4159 if self.ModuleType in ['DXE_SMM_DRIVER']:
4160 AsBuiltInfDict['binary_item'] += ['SMM_DEPEX|' + self.Name + '.depex']
4161
4162 Bin = self._GenOffsetBin()
4163 if Bin:
4164 AsBuiltInfDict['binary_item'] += ['BIN|%s' % Bin]
4165 if Bin not in self.OutputFile:
4166 self.OutputFile.append(Bin)
4167
4168 for Root, Dirs, Files in os.walk(OutputDir):
4169 for File in Files:
4170 if File.lower().endswith('.pdb'):
4171 AsBuiltInfDict['binary_item'] += ['DISPOSABLE|' + File]
4172 if File not in self.OutputFile:
4173 self.OutputFile.append(File)
4174 HeaderComments = self.Module.HeaderComments
4175 StartPos = 0
4176 for Index in range(len(HeaderComments)):
4177 if HeaderComments[Index].find('@BinaryHeader') != -1:
4178 HeaderComments[Index] = HeaderComments[Index].replace('@BinaryHeader', '@file')
4179 StartPos = Index
4180 break
4181 AsBuiltInfDict['header_comments'] = '\n'.join(HeaderComments[StartPos:]).replace(':#', '://')
4182 AsBuiltInfDict['tail_comments'] = '\n'.join(self.Module.TailComments)
4183
4184 GenList = [
4185 (self.ProtocolList, self._ProtocolComments, 'protocol_item'),
4186 (self.PpiList, self._PpiComments, 'ppi_item'),
4187 (GuidList, self._GuidComments, 'guid_item')
4188 ]
4189 for Item in GenList:
4190 for CName in Item[0]:
4191 Comments = ''
4192 if CName in Item[1]:
4193 Comments = '\n '.join(Item[1][CName])
4194 Entry = CName
4195 if Comments:
4196 Entry = Comments + '\n ' + CName
4197 AsBuiltInfDict[Item[2]].append(Entry)
4198 PatchList = parsePcdInfoFromMapFile(
4199 os.path.join(self.OutputDir, self.Name + '.map'),
4200 os.path.join(self.OutputDir, self.Name + '.efi')
4201 )
4202 if PatchList:
4203 for Pcd in PatchablePcds:
4204 TokenCName = Pcd.TokenCName
4205 for PcdItem in GlobalData.MixedPcd:
4206 if (Pcd.TokenCName, Pcd.TokenSpaceGuidCName) in GlobalData.MixedPcd[PcdItem]:
4207 TokenCName = PcdItem[0]
4208 break
4209 for PatchPcd in PatchList:
4210 if TokenCName == PatchPcd[0]:
4211 break
4212 else:
4213 continue
4214 PcdValue = ''
4215 if Pcd.DatumType == 'BOOLEAN':
4216 BoolValue = Pcd.DefaultValue.upper()
4217 if BoolValue == 'TRUE':
4218 Pcd.DefaultValue = '1'
4219 elif BoolValue == 'FALSE':
4220 Pcd.DefaultValue = '0'
4221
4222 if Pcd.DatumType in ['UINT8', 'UINT16', 'UINT32', 'UINT64', 'BOOLEAN']:
4223 HexFormat = '0x%02x'
4224 if Pcd.DatumType == 'UINT16':
4225 HexFormat = '0x%04x'
4226 elif Pcd.DatumType == 'UINT32':
4227 HexFormat = '0x%08x'
4228 elif Pcd.DatumType == 'UINT64':
4229 HexFormat = '0x%016x'
4230 PcdValue = HexFormat % int(Pcd.DefaultValue, 0)
4231 else:
4232 if Pcd.MaxDatumSize == None or Pcd.MaxDatumSize == '':
4233 EdkLogger.error("build", AUTOGEN_ERROR,
4234 "Unknown [MaxDatumSize] of PCD [%s.%s]" % (Pcd.TokenSpaceGuidCName, TokenCName)
4235 )
4236 ArraySize = int(Pcd.MaxDatumSize, 0)
4237 PcdValue = Pcd.DefaultValue
4238 if PcdValue[0] != '{':
4239 Unicode = False
4240 if PcdValue[0] == 'L':
4241 Unicode = True
4242 PcdValue = PcdValue.lstrip('L')
4243 PcdValue = eval(PcdValue)
4244 NewValue = '{'
4245 for Index in range(0, len(PcdValue)):
4246 if Unicode:
4247 CharVal = ord(PcdValue[Index])
4248 NewValue = NewValue + '0x%02x' % (CharVal & 0x00FF) + ', ' \
4249 + '0x%02x' % (CharVal >> 8) + ', '
4250 else:
4251 NewValue = NewValue + '0x%02x' % (ord(PcdValue[Index]) % 0x100) + ', '
4252 Padding = '0x00, '
4253 if Unicode:
4254 Padding = Padding * 2
4255 ArraySize = ArraySize / 2
4256 if ArraySize < (len(PcdValue) + 1):
4257 EdkLogger.error("build", AUTOGEN_ERROR,
4258 "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd.TokenSpaceGuidCName, TokenCName)
4259 )
4260 if ArraySize > len(PcdValue) + 1:
4261 NewValue = NewValue + Padding * (ArraySize - len(PcdValue) - 1)
4262 PcdValue = NewValue + Padding.strip().rstrip(',') + '}'
4263 elif len(PcdValue.split(',')) <= ArraySize:
4264 PcdValue = PcdValue.rstrip('}') + ', 0x00' * (ArraySize - len(PcdValue.split(',')))
4265 PcdValue += '}'
4266 else:
4267 EdkLogger.error("build", AUTOGEN_ERROR,
4268 "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd.TokenSpaceGuidCName, TokenCName)
4269 )
4270 PcdItem = '%s.%s|%s|0x%X' % \
4271 (Pcd.TokenSpaceGuidCName, TokenCName, PcdValue, PatchPcd[1])
4272 PcdComments = ''
4273 if (Pcd.TokenSpaceGuidCName, Pcd.TokenCName) in self._PcdComments:
4274 PcdComments = '\n '.join(self._PcdComments[Pcd.TokenSpaceGuidCName, Pcd.TokenCName])
4275 if PcdComments:
4276 PcdItem = PcdComments + '\n ' + PcdItem
4277 AsBuiltInfDict['patchablepcd_item'].append(PcdItem)
4278
4279 HiiPcds = []
4280 for Pcd in Pcds + VfrPcds:
4281 PcdComments = ''
4282 PcdCommentList = []
4283 HiiInfo = ''
4284 SkuId = ''
4285 TokenCName = Pcd.TokenCName
4286 for PcdItem in GlobalData.MixedPcd:
4287 if (Pcd.TokenCName, Pcd.TokenSpaceGuidCName) in GlobalData.MixedPcd[PcdItem]:
4288 TokenCName = PcdItem[0]
4289 break
4290 if Pcd.Type == TAB_PCDS_DYNAMIC_EX_HII:
4291 for SkuName in Pcd.SkuInfoList:
4292 SkuInfo = Pcd.SkuInfoList[SkuName]
4293 SkuId = SkuInfo.SkuId
4294 HiiInfo = '## %s|%s|%s' % (SkuInfo.VariableName, SkuInfo.VariableGuid, SkuInfo.VariableOffset)
4295 break
4296 if SkuId:
4297 #
4298 # Don't generate duplicated HII PCD
4299 #
4300 if (SkuId, Pcd.TokenSpaceGuidCName, Pcd.TokenCName) in HiiPcds:
4301 continue
4302 else:
4303 HiiPcds.append((SkuId, Pcd.TokenSpaceGuidCName, Pcd.TokenCName))
4304 if (Pcd.TokenSpaceGuidCName, Pcd.TokenCName) in self._PcdComments:
4305 PcdCommentList = self._PcdComments[Pcd.TokenSpaceGuidCName, Pcd.TokenCName][:]
4306 if HiiInfo:
4307 UsageIndex = -1
4308 UsageStr = ''
4309 for Index, Comment in enumerate(PcdCommentList):
4310 for Usage in UsageList:
4311 if Comment.find(Usage) != -1:
4312 UsageStr = Usage
4313 UsageIndex = Index
4314 break
4315 if UsageIndex != -1:
4316 PcdCommentList[UsageIndex] = '## %s %s %s' % (UsageStr, HiiInfo, PcdCommentList[UsageIndex].replace(UsageStr, ''))
4317 else:
4318 PcdCommentList.append('## UNDEFINED ' + HiiInfo)
4319 PcdComments = '\n '.join(PcdCommentList)
4320 PcdEntry = Pcd.TokenSpaceGuidCName + '.' + TokenCName
4321 if PcdComments:
4322 PcdEntry = PcdComments + '\n ' + PcdEntry
4323 AsBuiltInfDict['pcd_item'] += [PcdEntry]
4324 for Item in self.BuildOption:
4325 if 'FLAGS' in self.BuildOption[Item]:
4326 AsBuiltInfDict['flags_item'] += ['%s:%s_%s_%s_%s_FLAGS = %s' % (self.ToolChainFamily, self.BuildTarget, self.ToolChain, self.Arch, Item, self.BuildOption[Item]['FLAGS'].strip())]
4327
4328 # Generated LibraryClasses section in comments.
4329 for Library in self.LibraryAutoGenList:
4330 AsBuiltInfDict['libraryclasses_item'] += [Library.MetaFile.File.replace('\\', '/')]
4331
4332 # Generated UserExtensions TianoCore section.
4333 # All tianocore user extensions are copied.
4334 UserExtStr = ''
4335 for TianoCore in self._GetTianoCoreUserExtensionList():
4336 UserExtStr += '\n'.join(TianoCore)
4337 ExtensionFile = os.path.join(self.MetaFile.Dir, TianoCore[1])
4338 if os.path.isfile(ExtensionFile):
4339 shutil.copy2(ExtensionFile, self.OutputDir)
4340 AsBuiltInfDict['userextension_tianocore_item'] = UserExtStr
4341
4342 # Generated depex expression section in comments.
4343 AsBuiltInfDict['depexsection_item'] = ''
4344 DepexExpresion = self._GetDepexExpresionString()
4345 if DepexExpresion:
4346 AsBuiltInfDict['depexsection_item'] = DepexExpresion
4347
4348 AsBuiltInf = TemplateString()
4349 AsBuiltInf.Append(gAsBuiltInfHeaderString.Replace(AsBuiltInfDict))
4350
4351 SaveFileOnChange(os.path.join(self.OutputDir, self.Name + '.inf'), str(AsBuiltInf), False)
4352
4353 self.IsAsBuiltInfCreated = True
4354 if GlobalData.gBinCacheDest:
4355 self.CopyModuleToCache()
4356
4357 def CopyModuleToCache(self):
4358 FileDir = path.join(GlobalData.gBinCacheDest, self.Arch, self.SourceDir, self.MetaFile.BaseName)
4359 CreateDirectory (FileDir)
4360 HashFile = path.join(self.BuildDir, self.Name + '.hash')
4361 ModuleFile = path.join(self.OutputDir, self.Name + '.inf')
4362 if os.path.exists(HashFile):
4363 shutil.copy2(HashFile, FileDir)
4364 if os.path.exists(ModuleFile):
4365 shutil.copy2(ModuleFile, FileDir)
4366 if not self.OutputFile:
4367 Ma = self.Workspace.BuildDatabase[PathClass(ModuleFile), self.Arch, self.BuildTarget, self.ToolChain]
4368 self.OutputFile = Ma.Binaries
4369 if self.OutputFile:
4370 for File in self.OutputFile:
4371 File = str(File)
4372 if not os.path.isabs(File):
4373 File = os.path.join(self.OutputDir, File)
4374 if os.path.exists(File):
4375 shutil.copy2(File, FileDir)
4376
4377 def AttemptModuleCacheCopy(self):
4378 if self.IsBinaryModule:
4379 return False
4380 FileDir = path.join(GlobalData.gBinCacheSource, self.Arch, self.SourceDir, self.MetaFile.BaseName)
4381 HashFile = path.join(FileDir, self.Name + '.hash')
4382 if os.path.exists(HashFile):
4383 f = open(HashFile, 'r')
4384 CacheHash = f.read()
4385 f.close()
4386 if GlobalData.gModuleHash[self.Arch][self.Name]:
4387 if CacheHash == GlobalData.gModuleHash[self.Arch][self.Name]:
4388 for root, dir, files in os.walk(FileDir):
4389 for f in files:
4390 if self.Name + '.hash' in f:
4391 shutil.copy2(HashFile, self.BuildDir)
4392 else:
4393 File = path.join(root, f)
4394 shutil.copy2(File, self.OutputDir)
4395 if self.Name == "PcdPeim" or self.Name == "PcdDxe":
4396 CreatePcdDatabaseCode(self, TemplateString(), TemplateString())
4397 return True
4398 return False
4399
4400 ## Create makefile for the module and its dependent libraries
4401 #
4402 # @param CreateLibraryMakeFile Flag indicating if or not the makefiles of
4403 # dependent libraries will be created
4404 #
4405 def CreateMakeFile(self, CreateLibraryMakeFile=True, GenFfsList = []):
4406 # Ignore generating makefile when it is a binary module
4407 if self.IsBinaryModule:
4408 return
4409
4410 if self.IsMakeFileCreated:
4411 return
4412 self.GenFfsList = GenFfsList
4413 if not self.IsLibrary and CreateLibraryMakeFile:
4414 for LibraryAutoGen in self.LibraryAutoGenList:
4415 LibraryAutoGen.CreateMakeFile()
4416
4417 if self.CanSkip():
4418 return
4419
4420 if len(self.CustomMakefile) == 0:
4421 Makefile = GenMake.ModuleMakefile(self)
4422 else:
4423 Makefile = GenMake.CustomMakefile(self)
4424 if Makefile.Generate():
4425 EdkLogger.debug(EdkLogger.DEBUG_9, "Generated makefile for module %s [%s]" %
4426 (self.Name, self.Arch))
4427 else:
4428 EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of makefile for module %s [%s]" %
4429 (self.Name, self.Arch))
4430
4431 self.CreateTimeStamp(Makefile)
4432 self.IsMakeFileCreated = True
4433
4434 def CopyBinaryFiles(self):
4435 for File in self.Module.Binaries:
4436 SrcPath = File.Path
4437 DstPath = os.path.join(self.OutputDir , os.path.basename(SrcPath))
4438 CopyLongFilePath(SrcPath, DstPath)
4439 ## Create autogen code for the module and its dependent libraries
4440 #
4441 # @param CreateLibraryCodeFile Flag indicating if or not the code of
4442 # dependent libraries will be created
4443 #
4444 def CreateCodeFile(self, CreateLibraryCodeFile=True):
4445 if self.IsCodeFileCreated:
4446 return
4447
4448 # Need to generate PcdDatabase even PcdDriver is binarymodule
4449 if self.IsBinaryModule and self.PcdIsDriver != '':
4450 CreatePcdDatabaseCode(self, TemplateString(), TemplateString())
4451 return
4452 if self.IsBinaryModule:
4453 if self.IsLibrary:
4454 self.CopyBinaryFiles()
4455 return
4456
4457 if not self.IsLibrary and CreateLibraryCodeFile:
4458 for LibraryAutoGen in self.LibraryAutoGenList:
4459 LibraryAutoGen.CreateCodeFile()
4460
4461 if self.CanSkip():
4462 return
4463
4464 AutoGenList = []
4465 IgoredAutoGenList = []
4466
4467 for File in self.AutoGenFileList:
4468 if GenC.Generate(File.Path, self.AutoGenFileList[File], File.IsBinary):
4469 #Ignore Edk AutoGen.c
4470 if self.AutoGenVersion < 0x00010005 and File.Name == 'AutoGen.c':
4471 continue
4472
4473 AutoGenList.append(str(File))
4474 else:
4475 IgoredAutoGenList.append(str(File))
4476
4477 # Skip the following code for EDK I inf
4478 if self.AutoGenVersion < 0x00010005:
4479 return
4480
4481 for ModuleType in self.DepexList:
4482 # Ignore empty [depex] section or [depex] section for "USER_DEFINED" module
4483 if len(self.DepexList[ModuleType]) == 0 or ModuleType == "USER_DEFINED":
4484 continue
4485
4486 Dpx = GenDepex.DependencyExpression(self.DepexList[ModuleType], ModuleType, True)
4487 DpxFile = gAutoGenDepexFileName % {"module_name" : self.Name}
4488
4489 if len(Dpx.PostfixNotation) <> 0:
4490 self.DepexGenerated = True
4491
4492 if Dpx.Generate(path.join(self.OutputDir, DpxFile)):
4493 AutoGenList.append(str(DpxFile))
4494 else:
4495 IgoredAutoGenList.append(str(DpxFile))
4496
4497 if IgoredAutoGenList == []:
4498 EdkLogger.debug(EdkLogger.DEBUG_9, "Generated [%s] files for module %s [%s]" %
4499 (" ".join(AutoGenList), self.Name, self.Arch))
4500 elif AutoGenList == []:
4501 EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of [%s] files for module %s [%s]" %
4502 (" ".join(IgoredAutoGenList), self.Name, self.Arch))
4503 else:
4504 EdkLogger.debug(EdkLogger.DEBUG_9, "Generated [%s] (skipped %s) files for module %s [%s]" %
4505 (" ".join(AutoGenList), " ".join(IgoredAutoGenList), self.Name, self.Arch))
4506
4507 self.IsCodeFileCreated = True
4508 return AutoGenList
4509
4510 ## Summarize the ModuleAutoGen objects of all libraries used by this module
4511 def _GetLibraryAutoGenList(self):
4512 if self._LibraryAutoGenList == None:
4513 self._LibraryAutoGenList = []
4514 for Library in self.DependentLibraryList:
4515 La = ModuleAutoGen(
4516 self.Workspace,
4517 Library.MetaFile,
4518 self.BuildTarget,
4519 self.ToolChain,
4520 self.Arch,
4521 self.PlatformInfo.MetaFile
4522 )
4523 if La not in self._LibraryAutoGenList:
4524 self._LibraryAutoGenList.append(La)
4525 for Lib in La.CodaTargetList:
4526 self._ApplyBuildRule(Lib.Target, TAB_UNKNOWN_FILE)
4527 return self._LibraryAutoGenList
4528
4529 def GenModuleHash(self):
4530 if self.Arch not in GlobalData.gModuleHash:
4531 GlobalData.gModuleHash[self.Arch] = {}
4532 m = hashlib.md5()
4533 # Add Platform level hash
4534 m.update(GlobalData.gPlatformHash)
4535 # Add Package level hash
4536 if self.DependentPackageList:
4537 for Pkg in self.DependentPackageList:
4538 if Pkg.PackageName in GlobalData.gPackageHash[self.Arch]:
4539 m.update(GlobalData.gPackageHash[self.Arch][Pkg.PackageName])
4540
4541 # Add Library hash
4542 if self.LibraryAutoGenList:
4543 for Lib in self.LibraryAutoGenList:
4544 if Lib.Name not in GlobalData.gModuleHash[self.Arch]:
4545 Lib.GenModuleHash()
4546 m.update(GlobalData.gModuleHash[self.Arch][Lib.Name])
4547
4548 # Add Module self
4549 f = open(str(self.MetaFile), 'r')
4550 Content = f.read()
4551 f.close()
4552 m.update(Content)
4553 # Add Module's source files
4554 if self.SourceFileList:
4555 for File in self.SourceFileList:
4556 f = open(str(File), 'r')
4557 Content = f.read()
4558 f.close()
4559 m.update(Content)
4560
4561 ModuleHashFile = path.join(self.BuildDir, self.Name + ".hash")
4562 if self.Name not in GlobalData.gModuleHash[self.Arch]:
4563 GlobalData.gModuleHash[self.Arch][self.Name] = m.hexdigest()
4564 if GlobalData.gBinCacheSource:
4565 CacheValid = self.AttemptModuleCacheCopy()
4566 if CacheValid:
4567 return False
4568 return SaveFileOnChange(ModuleHashFile, m.hexdigest(), True)
4569
4570 ## Decide whether we can skip the ModuleAutoGen process
4571 def CanSkipbyHash(self):
4572 if GlobalData.gUseHashCache:
4573 return not self.GenModuleHash()
4574
4575 ## Decide whether we can skip the ModuleAutoGen process
4576 # If any source file is newer than the module than we cannot skip
4577 #
4578 def CanSkip(self):
4579 if not os.path.exists(self.GetTimeStampPath()):
4580 return False
4581 #last creation time of the module
4582 DstTimeStamp = os.stat(self.GetTimeStampPath())[8]
4583
4584 SrcTimeStamp = self.Workspace._SrcTimeStamp
4585 if SrcTimeStamp > DstTimeStamp:
4586 return False
4587
4588 with open(self.GetTimeStampPath(),'r') as f:
4589 for source in f:
4590 source = source.rstrip('\n')
4591 if not os.path.exists(source):
4592 return False
4593 if source not in ModuleAutoGen.TimeDict :
4594 ModuleAutoGen.TimeDict[source] = os.stat(source)[8]
4595 if ModuleAutoGen.TimeDict[source] > DstTimeStamp:
4596 return False
4597 return True
4598
4599 def GetTimeStampPath(self):
4600 if self._TimeStampPath == None:
4601 self._TimeStampPath = os.path.join(self.MakeFileDir, 'AutoGenTimeStamp')
4602 return self._TimeStampPath
4603 def CreateTimeStamp(self, Makefile):
4604
4605 FileSet = set()
4606
4607 FileSet.add (self.MetaFile.Path)
4608
4609 for SourceFile in self.Module.Sources:
4610 FileSet.add (SourceFile.Path)
4611
4612 for Lib in self.DependentLibraryList:
4613 FileSet.add (Lib.MetaFile.Path)
4614
4615 for f in self.AutoGenDepSet:
4616 FileSet.add (f.Path)
4617
4618 if os.path.exists (self.GetTimeStampPath()):
4619 os.remove (self.GetTimeStampPath())
4620 with open(self.GetTimeStampPath(), 'w+') as file:
4621 for f in FileSet:
4622 print >> file, f
4623
4624 Module = property(_GetModule)
4625 Name = property(_GetBaseName)
4626 Guid = property(_GetGuid)
4627 Version = property(_GetVersion)
4628 ModuleType = property(_GetModuleType)
4629 ComponentType = property(_GetComponentType)
4630 BuildType = property(_GetBuildType)
4631 PcdIsDriver = property(_GetPcdIsDriver)
4632 AutoGenVersion = property(_GetAutoGenVersion)
4633 Macros = property(_GetMacros)
4634 Specification = property(_GetSpecification)
4635
4636 IsLibrary = property(_IsLibrary)
4637 IsBinaryModule = property(_IsBinaryModule)
4638 BuildDir = property(_GetBuildDir)
4639 OutputDir = property(_GetOutputDir)
4640 FfsOutputDir = property(_GetFfsOutputDir)
4641 DebugDir = property(_GetDebugDir)
4642 MakeFileDir = property(_GetMakeFileDir)
4643 CustomMakefile = property(_GetCustomMakefile)
4644
4645 IncludePathList = property(_GetIncludePathList)
4646 IncludePathLength = property(_GetIncludePathLength)
4647 AutoGenFileList = property(_GetAutoGenFileList)
4648 UnicodeFileList = property(_GetUnicodeFileList)
4649 VfrFileList = property(_GetVfrFileList)
4650 SourceFileList = property(_GetSourceFileList)
4651 BinaryFileList = property(_GetBinaryFiles) # FileType : [File List]
4652 Targets = property(_GetTargets)
4653 IntroTargetList = property(_GetIntroTargetList)
4654 CodaTargetList = property(_GetFinalTargetList)
4655 FileTypes = property(_GetFileTypes)
4656 BuildRules = property(_GetBuildRules)
4657 IdfFileList = property(_GetIdfFileList)
4658
4659 DependentPackageList = property(_GetDependentPackageList)
4660 DependentLibraryList = property(_GetLibraryList)
4661 LibraryAutoGenList = property(_GetLibraryAutoGenList)
4662 DerivedPackageList = property(_GetDerivedPackageList)
4663
4664 ModulePcdList = property(_GetModulePcdList)
4665 LibraryPcdList = property(_GetLibraryPcdList)
4666 GuidList = property(_GetGuidList)
4667 ProtocolList = property(_GetProtocolList)
4668 PpiList = property(_GetPpiList)
4669 DepexList = property(_GetDepexTokenList)
4670 DxsFile = property(_GetDxsFile)
4671 DepexExpressionList = property(_GetDepexExpressionTokenList)
4672 BuildOption = property(_GetModuleBuildOption)
4673 BuildOptionIncPathList = property(_GetBuildOptionIncPathList)
4674 BuildCommand = property(_GetBuildCommand)
4675
4676 FixedAtBuildPcds = property(_GetFixedAtBuildPcds)
4677
4678 # This acts like the main() function for the script, unless it is 'import'ed into another script.
4679 if __name__ == '__main__':
4680 pass
4681