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