]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/AutoGen/AutoGen.py
BaseTools: Support Structure PCD value assignment in DEC/DSC
[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.Arch.upper()) and (ModuleType.upper() != TAB_ARCH_COMMON):
3061 DepexList.append({(Arch, ModuleType): DepexExpr})
3062 else:
3063 if Arch.upper() == TAB_ARCH_COMMON or \
3064 (Arch.upper() == self.Arch.upper() and \
3065 ModuleType.upper() in [TAB_ARCH_COMMON, self.ModuleType.upper()]):
3066 DepexList.append({(Arch, ModuleType): DepexExpr})
3067
3068 #the type of build module is USER_DEFINED.
3069 if self.ModuleType.upper() == SUP_MODULE_USER_DEFINED:
3070 for Depex in DepexList:
3071 for key in Depex.keys():
3072 DepexStr += '[Depex.%s.%s]\n' % key
3073 DepexStr += '\n'.join(['# '+ val for val in Depex[key]])
3074 DepexStr += '\n\n'
3075 if not DepexStr:
3076 return '[Depex.%s]\n' % self.Arch
3077 return DepexStr
3078
3079 #the type of build module not is USER_DEFINED.
3080 Count = 0
3081 for Depex in DepexList:
3082 Count += 1
3083 if DepexStr != '':
3084 DepexStr += ' AND '
3085 DepexStr += '('
3086 for D in Depex.values():
3087 DepexStr += ' '.join([val for val in D])
3088 Index = DepexStr.find('END')
3089 if Index > -1 and Index == len(DepexStr) - 3:
3090 DepexStr = DepexStr[:-3]
3091 DepexStr = DepexStr.strip()
3092 DepexStr += ')'
3093 if Count == 1:
3094 DepexStr = DepexStr.lstrip('(').rstrip(')').strip()
3095 if not DepexStr:
3096 return '[Depex.%s]\n' % self.Arch
3097 return '[Depex.%s]\n# ' % self.Arch + DepexStr
3098
3099 ## Merge dependency expression
3100 #
3101 # @retval list The token list of the dependency expression after parsed
3102 #
3103 def _GetDepexTokenList(self):
3104 if self._DepexList == None:
3105 self._DepexList = {}
3106 if self.DxsFile or self.IsLibrary or TAB_DEPENDENCY_EXPRESSION_FILE in self.FileTypes:
3107 return self._DepexList
3108
3109 self._DepexList[self.ModuleType] = []
3110
3111 for ModuleType in self._DepexList:
3112 DepexList = self._DepexList[ModuleType]
3113 #
3114 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
3115 #
3116 for M in [self.Module] + self.DependentLibraryList:
3117 Inherited = False
3118 for D in M.Depex[self.Arch, ModuleType]:
3119 if DepexList != []:
3120 DepexList.append('AND')
3121 DepexList.append('(')
3122 DepexList.extend(D)
3123 if DepexList[-1] == 'END': # no need of a END at this time
3124 DepexList.pop()
3125 DepexList.append(')')
3126 Inherited = True
3127 if Inherited:
3128 EdkLogger.verbose("DEPEX[%s] (+%s) = %s" % (self.Name, M.BaseName, DepexList))
3129 if 'BEFORE' in DepexList or 'AFTER' in DepexList:
3130 break
3131 if len(DepexList) > 0:
3132 EdkLogger.verbose('')
3133 return self._DepexList
3134
3135 ## Merge dependency expression
3136 #
3137 # @retval list The token list of the dependency expression after parsed
3138 #
3139 def _GetDepexExpressionTokenList(self):
3140 if self._DepexExpressionList == None:
3141 self._DepexExpressionList = {}
3142 if self.DxsFile or self.IsLibrary or TAB_DEPENDENCY_EXPRESSION_FILE in self.FileTypes:
3143 return self._DepexExpressionList
3144
3145 self._DepexExpressionList[self.ModuleType] = ''
3146
3147 for ModuleType in self._DepexExpressionList:
3148 DepexExpressionList = self._DepexExpressionList[ModuleType]
3149 #
3150 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
3151 #
3152 for M in [self.Module] + self.DependentLibraryList:
3153 Inherited = False
3154 for D in M.DepexExpression[self.Arch, ModuleType]:
3155 if DepexExpressionList != '':
3156 DepexExpressionList += ' AND '
3157 DepexExpressionList += '('
3158 DepexExpressionList += D
3159 DepexExpressionList = DepexExpressionList.rstrip('END').strip()
3160 DepexExpressionList += ')'
3161 Inherited = True
3162 if Inherited:
3163 EdkLogger.verbose("DEPEX[%s] (+%s) = %s" % (self.Name, M.BaseName, DepexExpressionList))
3164 if 'BEFORE' in DepexExpressionList or 'AFTER' in DepexExpressionList:
3165 break
3166 if len(DepexExpressionList) > 0:
3167 EdkLogger.verbose('')
3168 self._DepexExpressionList[ModuleType] = DepexExpressionList
3169 return self._DepexExpressionList
3170
3171 # Get the tiano core user extension, it is contain dependent library.
3172 # @retval: a list contain tiano core userextension.
3173 #
3174 def _GetTianoCoreUserExtensionList(self):
3175 TianoCoreUserExtentionList = []
3176 for M in [self.Module] + self.DependentLibraryList:
3177 Filename = M.MetaFile.Path
3178 InfObj = InfSectionParser.InfSectionParser(Filename)
3179 TianoCoreUserExtenList = InfObj.GetUserExtensionTianoCore()
3180 for TianoCoreUserExtent in TianoCoreUserExtenList:
3181 for Section in TianoCoreUserExtent.keys():
3182 ItemList = Section.split(TAB_SPLIT)
3183 Arch = self.Arch
3184 if len(ItemList) == 4:
3185 Arch = ItemList[3]
3186 if Arch.upper() == TAB_ARCH_COMMON or Arch.upper() == self.Arch.upper():
3187 TianoCoreList = []
3188 TianoCoreList.extend([TAB_SECTION_START + Section + TAB_SECTION_END])
3189 TianoCoreList.extend(TianoCoreUserExtent[Section][:])
3190 TianoCoreList.append('\n')
3191 TianoCoreUserExtentionList.append(TianoCoreList)
3192
3193 return TianoCoreUserExtentionList
3194
3195 ## Return the list of specification version required for the module
3196 #
3197 # @retval list The list of specification defined in module file
3198 #
3199 def _GetSpecification(self):
3200 return self.Module.Specification
3201
3202 ## Tool option for the module build
3203 #
3204 # @param PlatformInfo The object of PlatformBuildInfo
3205 # @retval dict The dict containing valid options
3206 #
3207 def _GetModuleBuildOption(self):
3208 if self._BuildOption == None:
3209 self._BuildOption, self.BuildRuleOrder = self.PlatformInfo.ApplyBuildOption(self.Module)
3210 if self.BuildRuleOrder:
3211 self.BuildRuleOrder = ['.%s' % Ext for Ext in self.BuildRuleOrder.split()]
3212 return self._BuildOption
3213
3214 ## Get include path list from tool option for the module build
3215 #
3216 # @retval list The include path list
3217 #
3218 def _GetBuildOptionIncPathList(self):
3219 if self._BuildOptionIncPathList == None:
3220 #
3221 # Regular expression for finding Include Directories, the difference between MSFT and INTEL/GCC/RVCT
3222 # is the former use /I , the Latter used -I to specify include directories
3223 #
3224 if self.PlatformInfo.ToolChainFamily in ('MSFT'):
3225 gBuildOptIncludePattern = re.compile(r"(?:.*?)/I[ \t]*([^ ]*)", re.MULTILINE | re.DOTALL)
3226 elif self.PlatformInfo.ToolChainFamily in ('INTEL', 'GCC', 'RVCT'):
3227 gBuildOptIncludePattern = re.compile(r"(?:.*?)-I[ \t]*([^ ]*)", re.MULTILINE | re.DOTALL)
3228 else:
3229 #
3230 # New ToolChainFamily, don't known whether there is option to specify include directories
3231 #
3232 self._BuildOptionIncPathList = []
3233 return self._BuildOptionIncPathList
3234
3235 BuildOptionIncPathList = []
3236 for Tool in ('CC', 'PP', 'VFRPP', 'ASLPP', 'ASLCC', 'APP', 'ASM'):
3237 Attr = 'FLAGS'
3238 try:
3239 FlagOption = self.BuildOption[Tool][Attr]
3240 except KeyError:
3241 FlagOption = ''
3242
3243 if self.PlatformInfo.ToolChainFamily != 'RVCT':
3244 IncPathList = [NormPath(Path, self.Macros) for Path in gBuildOptIncludePattern.findall(FlagOption)]
3245 else:
3246 #
3247 # RVCT may specify a list of directory seperated by commas
3248 #
3249 IncPathList = []
3250 for Path in gBuildOptIncludePattern.findall(FlagOption):
3251 PathList = GetSplitList(Path, TAB_COMMA_SPLIT)
3252 IncPathList += [NormPath(PathEntry, self.Macros) for PathEntry in PathList]
3253
3254 #
3255 # EDK II modules must not reference header files outside of the packages they depend on or
3256 # within the module's directory tree. Report error if violation.
3257 #
3258 if self.AutoGenVersion >= 0x00010005 and len(IncPathList) > 0:
3259 for Path in IncPathList:
3260 if (Path not in self.IncludePathList) and (CommonPath([Path, self.MetaFile.Dir]) != self.MetaFile.Dir):
3261 ErrMsg = "The include directory for the EDK II module in this line is invalid %s specified in %s FLAGS '%s'" % (Path, Tool, FlagOption)
3262 EdkLogger.error("build",
3263 PARAMETER_INVALID,
3264 ExtraData=ErrMsg,
3265 File=str(self.MetaFile))
3266
3267
3268 BuildOptionIncPathList += IncPathList
3269
3270 self._BuildOptionIncPathList = BuildOptionIncPathList
3271
3272 return self._BuildOptionIncPathList
3273
3274 ## Return a list of files which can be built from source
3275 #
3276 # What kind of files can be built is determined by build rules in
3277 # $(CONF_DIRECTORY)/build_rule.txt and toolchain family.
3278 #
3279 def _GetSourceFileList(self):
3280 if self._SourceFileList == None:
3281 self._SourceFileList = []
3282 for F in self.Module.Sources:
3283 # match tool chain
3284 if F.TagName not in ("", "*", self.ToolChain):
3285 EdkLogger.debug(EdkLogger.DEBUG_9, "The toolchain [%s] for processing file [%s] is found, "
3286 "but [%s] is needed" % (F.TagName, str(F), self.ToolChain))
3287 continue
3288 # match tool chain family or build rule family
3289 if F.ToolChainFamily not in ("", "*", self.ToolChainFamily, self.BuildRuleFamily):
3290 EdkLogger.debug(
3291 EdkLogger.DEBUG_0,
3292 "The file [%s] must be built by tools of [%s], " \
3293 "but current toolchain family is [%s], buildrule family is [%s]" \
3294 % (str(F), F.ToolChainFamily, self.ToolChainFamily, self.BuildRuleFamily))
3295 continue
3296
3297 # add the file path into search path list for file including
3298 if F.Dir not in self.IncludePathList and self.AutoGenVersion >= 0x00010005:
3299 self.IncludePathList.insert(0, F.Dir)
3300 self._SourceFileList.append(F)
3301
3302 self._MatchBuildRuleOrder(self._SourceFileList)
3303
3304 for F in self._SourceFileList:
3305 self._ApplyBuildRule(F, TAB_UNKNOWN_FILE)
3306 return self._SourceFileList
3307
3308 def _MatchBuildRuleOrder(self, FileList):
3309 Order_Dict = {}
3310 self._GetModuleBuildOption()
3311 for SingleFile in FileList:
3312 if self.BuildRuleOrder and SingleFile.Ext in self.BuildRuleOrder and SingleFile.Ext in self.BuildRules:
3313 key = SingleFile.Path.split(SingleFile.Ext)[0]
3314 if key in Order_Dict:
3315 Order_Dict[key].append(SingleFile.Ext)
3316 else:
3317 Order_Dict[key] = [SingleFile.Ext]
3318
3319 RemoveList = []
3320 for F in Order_Dict:
3321 if len(Order_Dict[F]) > 1:
3322 Order_Dict[F].sort(key=lambda i: self.BuildRuleOrder.index(i))
3323 for Ext in Order_Dict[F][1:]:
3324 RemoveList.append(F + Ext)
3325
3326 for item in RemoveList:
3327 FileList.remove(item)
3328
3329 return FileList
3330
3331 ## Return the list of unicode files
3332 def _GetUnicodeFileList(self):
3333 if self._UnicodeFileList == None:
3334 if TAB_UNICODE_FILE in self.FileTypes:
3335 self._UnicodeFileList = self.FileTypes[TAB_UNICODE_FILE]
3336 else:
3337 self._UnicodeFileList = []
3338 return self._UnicodeFileList
3339
3340 ## Return the list of vfr files
3341 def _GetVfrFileList(self):
3342 if self._VfrFileList == None:
3343 if TAB_VFR_FILE in self.FileTypes:
3344 self._VfrFileList = self.FileTypes[TAB_VFR_FILE]
3345 else:
3346 self._VfrFileList = []
3347 return self._VfrFileList
3348
3349 ## Return the list of Image Definition files
3350 def _GetIdfFileList(self):
3351 if self._IdfFileList == None:
3352 if TAB_IMAGE_FILE in self.FileTypes:
3353 self._IdfFileList = self.FileTypes[TAB_IMAGE_FILE]
3354 else:
3355 self._IdfFileList = []
3356 return self._IdfFileList
3357
3358 ## Return a list of files which can be built from binary
3359 #
3360 # "Build" binary files are just to copy them to build directory.
3361 #
3362 # @retval list The list of files which can be built later
3363 #
3364 def _GetBinaryFiles(self):
3365 if self._BinaryFileList == None:
3366 self._BinaryFileList = []
3367 for F in self.Module.Binaries:
3368 if F.Target not in ['COMMON', '*'] and F.Target != self.BuildTarget:
3369 continue
3370 self._BinaryFileList.append(F)
3371 self._ApplyBuildRule(F, F.Type)
3372 return self._BinaryFileList
3373
3374 def _GetBuildRules(self):
3375 if self._BuildRules == None:
3376 BuildRules = {}
3377 BuildRuleDatabase = self.PlatformInfo.BuildRule
3378 for Type in BuildRuleDatabase.FileTypeList:
3379 #first try getting build rule by BuildRuleFamily
3380 RuleObject = BuildRuleDatabase[Type, self.BuildType, self.Arch, self.BuildRuleFamily]
3381 if not RuleObject:
3382 # build type is always module type, but ...
3383 if self.ModuleType != self.BuildType:
3384 RuleObject = BuildRuleDatabase[Type, self.ModuleType, self.Arch, self.BuildRuleFamily]
3385 #second try getting build rule by ToolChainFamily
3386 if not RuleObject:
3387 RuleObject = BuildRuleDatabase[Type, self.BuildType, self.Arch, self.ToolChainFamily]
3388 if not RuleObject:
3389 # build type is always module type, but ...
3390 if self.ModuleType != self.BuildType:
3391 RuleObject = BuildRuleDatabase[Type, self.ModuleType, self.Arch, self.ToolChainFamily]
3392 if not RuleObject:
3393 continue
3394 RuleObject = RuleObject.Instantiate(self.Macros)
3395 BuildRules[Type] = RuleObject
3396 for Ext in RuleObject.SourceFileExtList:
3397 BuildRules[Ext] = RuleObject
3398 self._BuildRules = BuildRules
3399 return self._BuildRules
3400
3401 def _ApplyBuildRule(self, File, FileType):
3402 if self._BuildTargets == None:
3403 self._IntroBuildTargetList = set()
3404 self._FinalBuildTargetList = set()
3405 self._BuildTargets = {}
3406 self._FileTypes = {}
3407
3408 SubDirectory = os.path.join(self.OutputDir, File.SubDir)
3409 if not os.path.exists(SubDirectory):
3410 CreateDirectory(SubDirectory)
3411 LastTarget = None
3412 RuleChain = []
3413 SourceList = [File]
3414 Index = 0
3415 #
3416 # Make sure to get build rule order value
3417 #
3418 self._GetModuleBuildOption()
3419
3420 while Index < len(SourceList):
3421 Source = SourceList[Index]
3422 Index = Index + 1
3423
3424 if Source != File:
3425 CreateDirectory(Source.Dir)
3426
3427 if File.IsBinary and File == Source and self._BinaryFileList != None and File in self._BinaryFileList:
3428 # Skip all files that are not binary libraries
3429 if not self.IsLibrary:
3430 continue
3431 RuleObject = self.BuildRules[TAB_DEFAULT_BINARY_FILE]
3432 elif FileType in self.BuildRules:
3433 RuleObject = self.BuildRules[FileType]
3434 elif Source.Ext in self.BuildRules:
3435 RuleObject = self.BuildRules[Source.Ext]
3436 else:
3437 # stop at no more rules
3438 if LastTarget:
3439 self._FinalBuildTargetList.add(LastTarget)
3440 break
3441
3442 FileType = RuleObject.SourceFileType
3443 if FileType not in self._FileTypes:
3444 self._FileTypes[FileType] = set()
3445 self._FileTypes[FileType].add(Source)
3446
3447 # stop at STATIC_LIBRARY for library
3448 if self.IsLibrary and FileType == TAB_STATIC_LIBRARY:
3449 if LastTarget:
3450 self._FinalBuildTargetList.add(LastTarget)
3451 break
3452
3453 Target = RuleObject.Apply(Source, self.BuildRuleOrder)
3454 if not Target:
3455 if LastTarget:
3456 self._FinalBuildTargetList.add(LastTarget)
3457 break
3458 elif not Target.Outputs:
3459 # Only do build for target with outputs
3460 self._FinalBuildTargetList.add(Target)
3461
3462 if FileType not in self._BuildTargets:
3463 self._BuildTargets[FileType] = set()
3464 self._BuildTargets[FileType].add(Target)
3465
3466 if not Source.IsBinary and Source == File:
3467 self._IntroBuildTargetList.add(Target)
3468
3469 # to avoid cyclic rule
3470 if FileType in RuleChain:
3471 break
3472
3473 RuleChain.append(FileType)
3474 SourceList.extend(Target.Outputs)
3475 LastTarget = Target
3476 FileType = TAB_UNKNOWN_FILE
3477
3478 def _GetTargets(self):
3479 if self._BuildTargets == None:
3480 self._IntroBuildTargetList = set()
3481 self._FinalBuildTargetList = set()
3482 self._BuildTargets = {}
3483 self._FileTypes = {}
3484
3485 #TRICK: call _GetSourceFileList to apply build rule for source files
3486 if self.SourceFileList:
3487 pass
3488
3489 #TRICK: call _GetBinaryFileList to apply build rule for binary files
3490 if self.BinaryFileList:
3491 pass
3492
3493 return self._BuildTargets
3494
3495 def _GetIntroTargetList(self):
3496 self._GetTargets()
3497 return self._IntroBuildTargetList
3498
3499 def _GetFinalTargetList(self):
3500 self._GetTargets()
3501 return self._FinalBuildTargetList
3502
3503 def _GetFileTypes(self):
3504 self._GetTargets()
3505 return self._FileTypes
3506
3507 ## Get the list of package object the module depends on
3508 #
3509 # @retval list The package object list
3510 #
3511 def _GetDependentPackageList(self):
3512 return self.Module.Packages
3513
3514 ## Return the list of auto-generated code file
3515 #
3516 # @retval list The list of auto-generated file
3517 #
3518 def _GetAutoGenFileList(self):
3519 UniStringAutoGenC = True
3520 IdfStringAutoGenC = True
3521 UniStringBinBuffer = StringIO()
3522 IdfGenBinBuffer = StringIO()
3523 if self.BuildType == 'UEFI_HII':
3524 UniStringAutoGenC = False
3525 IdfStringAutoGenC = False
3526 if self._AutoGenFileList == None:
3527 self._AutoGenFileList = {}
3528 AutoGenC = TemplateString()
3529 AutoGenH = TemplateString()
3530 StringH = TemplateString()
3531 StringIdf = TemplateString()
3532 GenC.CreateCode(self, AutoGenC, AutoGenH, StringH, UniStringAutoGenC, UniStringBinBuffer, StringIdf, IdfStringAutoGenC, IdfGenBinBuffer)
3533 #
3534 # AutoGen.c is generated if there are library classes in inf, or there are object files
3535 #
3536 if str(AutoGenC) != "" and (len(self.Module.LibraryClasses) > 0
3537 or TAB_OBJECT_FILE in self.FileTypes):
3538 AutoFile = PathClass(gAutoGenCodeFileName, self.DebugDir)
3539 self._AutoGenFileList[AutoFile] = str(AutoGenC)
3540 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
3541 if str(AutoGenH) != "":
3542 AutoFile = PathClass(gAutoGenHeaderFileName, self.DebugDir)
3543 self._AutoGenFileList[AutoFile] = str(AutoGenH)
3544 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
3545 if str(StringH) != "":
3546 AutoFile = PathClass(gAutoGenStringFileName % {"module_name":self.Name}, self.DebugDir)
3547 self._AutoGenFileList[AutoFile] = str(StringH)
3548 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
3549 if UniStringBinBuffer != None and UniStringBinBuffer.getvalue() != "":
3550 AutoFile = PathClass(gAutoGenStringFormFileName % {"module_name":self.Name}, self.OutputDir)
3551 self._AutoGenFileList[AutoFile] = UniStringBinBuffer.getvalue()
3552 AutoFile.IsBinary = True
3553 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
3554 if UniStringBinBuffer != None:
3555 UniStringBinBuffer.close()
3556 if str(StringIdf) != "":
3557 AutoFile = PathClass(gAutoGenImageDefFileName % {"module_name":self.Name}, self.DebugDir)
3558 self._AutoGenFileList[AutoFile] = str(StringIdf)
3559 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
3560 if IdfGenBinBuffer != None and IdfGenBinBuffer.getvalue() != "":
3561 AutoFile = PathClass(gAutoGenIdfFileName % {"module_name":self.Name}, self.OutputDir)
3562 self._AutoGenFileList[AutoFile] = IdfGenBinBuffer.getvalue()
3563 AutoFile.IsBinary = True
3564 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
3565 if IdfGenBinBuffer != None:
3566 IdfGenBinBuffer.close()
3567 return self._AutoGenFileList
3568
3569 ## Return the list of library modules explicitly or implicityly used by this module
3570 def _GetLibraryList(self):
3571 if self._DependentLibraryList == None:
3572 # only merge library classes and PCD for non-library module
3573 if self.IsLibrary:
3574 self._DependentLibraryList = []
3575 else:
3576 if self.AutoGenVersion < 0x00010005:
3577 self._DependentLibraryList = self.PlatformInfo.ResolveLibraryReference(self.Module)
3578 else:
3579 self._DependentLibraryList = self.PlatformInfo.ApplyLibraryInstance(self.Module)
3580 return self._DependentLibraryList
3581
3582 @staticmethod
3583 def UpdateComments(Recver, Src):
3584 for Key in Src:
3585 if Key not in Recver:
3586 Recver[Key] = []
3587 Recver[Key].extend(Src[Key])
3588 ## Get the list of PCDs from current module
3589 #
3590 # @retval list The list of PCD
3591 #
3592 def _GetModulePcdList(self):
3593 if self._ModulePcdList == None:
3594 # apply PCD settings from platform
3595 self._ModulePcdList = self.PlatformInfo.ApplyPcdSetting(self.Module, self.Module.Pcds)
3596 self.UpdateComments(self._PcdComments, self.Module.PcdComments)
3597 return self._ModulePcdList
3598
3599 ## Get the list of PCDs from dependent libraries
3600 #
3601 # @retval list The list of PCD
3602 #
3603 def _GetLibraryPcdList(self):
3604 if self._LibraryPcdList == None:
3605 Pcds = sdict()
3606 if not self.IsLibrary:
3607 # get PCDs from dependent libraries
3608 for Library in self.DependentLibraryList:
3609 self.UpdateComments(self._PcdComments, Library.PcdComments)
3610 for Key in Library.Pcds:
3611 # skip duplicated PCDs
3612 if Key in self.Module.Pcds or Key in Pcds:
3613 continue
3614 Pcds[Key] = copy.copy(Library.Pcds[Key])
3615 # apply PCD settings from platform
3616 self._LibraryPcdList = self.PlatformInfo.ApplyPcdSetting(self.Module, Pcds)
3617 else:
3618 self._LibraryPcdList = []
3619 return self._LibraryPcdList
3620
3621 ## Get the GUID value mapping
3622 #
3623 # @retval dict The mapping between GUID cname and its value
3624 #
3625 def _GetGuidList(self):
3626 if self._GuidList == None:
3627 self._GuidList = sdict()
3628 self._GuidList.update(self.Module.Guids)
3629 for Library in self.DependentLibraryList:
3630 self._GuidList.update(Library.Guids)
3631 self.UpdateComments(self._GuidComments, Library.GuidComments)
3632 self.UpdateComments(self._GuidComments, self.Module.GuidComments)
3633 return self._GuidList
3634
3635 def GetGuidsUsedByPcd(self):
3636 if self._GuidsUsedByPcd == None:
3637 self._GuidsUsedByPcd = sdict()
3638 self._GuidsUsedByPcd.update(self.Module.GetGuidsUsedByPcd())
3639 for Library in self.DependentLibraryList:
3640 self._GuidsUsedByPcd.update(Library.GetGuidsUsedByPcd())
3641 return self._GuidsUsedByPcd
3642 ## Get the protocol value mapping
3643 #
3644 # @retval dict The mapping between protocol cname and its value
3645 #
3646 def _GetProtocolList(self):
3647 if self._ProtocolList == None:
3648 self._ProtocolList = sdict()
3649 self._ProtocolList.update(self.Module.Protocols)
3650 for Library in self.DependentLibraryList:
3651 self._ProtocolList.update(Library.Protocols)
3652 self.UpdateComments(self._ProtocolComments, Library.ProtocolComments)
3653 self.UpdateComments(self._ProtocolComments, self.Module.ProtocolComments)
3654 return self._ProtocolList
3655
3656 ## Get the PPI value mapping
3657 #
3658 # @retval dict The mapping between PPI cname and its value
3659 #
3660 def _GetPpiList(self):
3661 if self._PpiList == None:
3662 self._PpiList = sdict()
3663 self._PpiList.update(self.Module.Ppis)
3664 for Library in self.DependentLibraryList:
3665 self._PpiList.update(Library.Ppis)
3666 self.UpdateComments(self._PpiComments, Library.PpiComments)
3667 self.UpdateComments(self._PpiComments, self.Module.PpiComments)
3668 return self._PpiList
3669
3670 ## Get the list of include search path
3671 #
3672 # @retval list The list path
3673 #
3674 def _GetIncludePathList(self):
3675 if self._IncludePathList == None:
3676 self._IncludePathList = []
3677 if self.AutoGenVersion < 0x00010005:
3678 for Inc in self.Module.Includes:
3679 if Inc not in self._IncludePathList:
3680 self._IncludePathList.append(Inc)
3681 # for Edk modules
3682 Inc = path.join(Inc, self.Arch.capitalize())
3683 if os.path.exists(Inc) and Inc not in self._IncludePathList:
3684 self._IncludePathList.append(Inc)
3685 # Edk module needs to put DEBUG_DIR at the end of search path and not to use SOURCE_DIR all the time
3686 self._IncludePathList.append(self.DebugDir)
3687 else:
3688 self._IncludePathList.append(self.MetaFile.Dir)
3689 self._IncludePathList.append(self.DebugDir)
3690
3691 for Package in self.Module.Packages:
3692 PackageDir = mws.join(self.WorkspaceDir, Package.MetaFile.Dir)
3693 if PackageDir not in self._IncludePathList:
3694 self._IncludePathList.append(PackageDir)
3695 IncludesList = Package.Includes
3696 if Package._PrivateIncludes:
3697 if not self.MetaFile.Path.startswith(PackageDir):
3698 IncludesList = list(set(Package.Includes).difference(set(Package._PrivateIncludes)))
3699 for Inc in IncludesList:
3700 if Inc not in self._IncludePathList:
3701 self._IncludePathList.append(str(Inc))
3702 return self._IncludePathList
3703
3704 def _GetIncludePathLength(self):
3705 self._IncludePathLength = 0
3706 if self._IncludePathList:
3707 for inc in self._IncludePathList:
3708 self._IncludePathLength += len(' ' + inc)
3709 return self._IncludePathLength
3710
3711 ## Get HII EX PCDs which maybe used by VFR
3712 #
3713 # efivarstore used by VFR may relate with HII EX PCDs
3714 # Get the variable name and GUID from efivarstore and HII EX PCD
3715 # List the HII EX PCDs in As Built INF if both name and GUID match.
3716 #
3717 # @retval list HII EX PCDs
3718 #
3719 def _GetPcdsMaybeUsedByVfr(self):
3720 if not self.SourceFileList:
3721 return []
3722
3723 NameGuids = []
3724 for SrcFile in self.SourceFileList:
3725 if SrcFile.Ext.lower() != '.vfr':
3726 continue
3727 Vfri = os.path.join(self.OutputDir, SrcFile.BaseName + '.i')
3728 if not os.path.exists(Vfri):
3729 continue
3730 VfriFile = open(Vfri, 'r')
3731 Content = VfriFile.read()
3732 VfriFile.close()
3733 Pos = Content.find('efivarstore')
3734 while Pos != -1:
3735 #
3736 # Make sure 'efivarstore' is the start of efivarstore statement
3737 # In case of the value of 'name' (name = efivarstore) is equal to 'efivarstore'
3738 #
3739 Index = Pos - 1
3740 while Index >= 0 and Content[Index] in ' \t\r\n':
3741 Index -= 1
3742 if Index >= 0 and Content[Index] != ';':
3743 Pos = Content.find('efivarstore', Pos + len('efivarstore'))
3744 continue
3745 #
3746 # 'efivarstore' must be followed by name and guid
3747 #
3748 Name = gEfiVarStoreNamePattern.search(Content, Pos)
3749 if not Name:
3750 break
3751 Guid = gEfiVarStoreGuidPattern.search(Content, Pos)
3752 if not Guid:
3753 break
3754 NameArray = ConvertStringToByteArray('L"' + Name.group(1) + '"')
3755 NameGuids.append((NameArray, GuidStructureStringToGuidString(Guid.group(1))))
3756 Pos = Content.find('efivarstore', Name.end())
3757 if not NameGuids:
3758 return []
3759 HiiExPcds = []
3760 for Pcd in self.PlatformInfo.Platform.Pcds.values():
3761 if Pcd.Type != TAB_PCDS_DYNAMIC_EX_HII:
3762 continue
3763 for SkuName in Pcd.SkuInfoList:
3764 SkuInfo = Pcd.SkuInfoList[SkuName]
3765 Name = ConvertStringToByteArray(SkuInfo.VariableName)
3766 Value = GuidValue(SkuInfo.VariableGuid, self.PlatformInfo.PackageList, self.MetaFile.Path)
3767 if not Value:
3768 continue
3769 Guid = GuidStructureStringToGuidString(Value)
3770 if (Name, Guid) in NameGuids and Pcd not in HiiExPcds:
3771 HiiExPcds.append(Pcd)
3772 break
3773
3774 return HiiExPcds
3775
3776 def _GenOffsetBin(self):
3777 VfrUniBaseName = {}
3778 for SourceFile in self.Module.Sources:
3779 if SourceFile.Type.upper() == ".VFR" :
3780 #
3781 # search the .map file to find the offset of vfr binary in the PE32+/TE file.
3782 #
3783 VfrUniBaseName[SourceFile.BaseName] = (SourceFile.BaseName + "Bin")
3784 if SourceFile.Type.upper() == ".UNI" :
3785 #
3786 # search the .map file to find the offset of Uni strings binary in the PE32+/TE file.
3787 #
3788 VfrUniBaseName["UniOffsetName"] = (self.Name + "Strings")
3789
3790 if len(VfrUniBaseName) == 0:
3791 return None
3792 MapFileName = os.path.join(self.OutputDir, self.Name + ".map")
3793 EfiFileName = os.path.join(self.OutputDir, self.Name + ".efi")
3794 VfrUniOffsetList = GetVariableOffset(MapFileName, EfiFileName, VfrUniBaseName.values())
3795 if not VfrUniOffsetList:
3796 return None
3797
3798 OutputName = '%sOffset.bin' % self.Name
3799 UniVfrOffsetFileName = os.path.join( self.OutputDir, OutputName)
3800
3801 try:
3802 fInputfile = open(UniVfrOffsetFileName, "wb+", 0)
3803 except:
3804 EdkLogger.error("build", FILE_OPEN_FAILURE, "File open failed for %s" % UniVfrOffsetFileName,None)
3805
3806 # Use a instance of StringIO to cache data
3807 fStringIO = StringIO('')
3808
3809 for Item in VfrUniOffsetList:
3810 if (Item[0].find("Strings") != -1):
3811 #
3812 # UNI offset in image.
3813 # GUID + Offset
3814 # { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } }
3815 #
3816 UniGuid = [0xe0, 0xc5, 0x13, 0x89, 0xf6, 0x33, 0x86, 0x4d, 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66]
3817 UniGuid = [chr(ItemGuid) for ItemGuid in UniGuid]
3818 fStringIO.write(''.join(UniGuid))
3819 UniValue = pack ('Q', int (Item[1], 16))
3820 fStringIO.write (UniValue)
3821 else:
3822 #
3823 # VFR binary offset in image.
3824 # GUID + Offset
3825 # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } };
3826 #
3827 VfrGuid = [0xb4, 0x7c, 0xbc, 0xd0, 0x47, 0x6a, 0x5f, 0x49, 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2]
3828 VfrGuid = [chr(ItemGuid) for ItemGuid in VfrGuid]
3829 fStringIO.write(''.join(VfrGuid))
3830 type (Item[1])
3831 VfrValue = pack ('Q', int (Item[1], 16))
3832 fStringIO.write (VfrValue)
3833 #
3834 # write data into file.
3835 #
3836 try :
3837 fInputfile.write (fStringIO.getvalue())
3838 except:
3839 EdkLogger.error("build", FILE_WRITE_FAILURE, "Write data to file %s failed, please check whether the "
3840 "file been locked or using by other applications." %UniVfrOffsetFileName,None)
3841
3842 fStringIO.close ()
3843 fInputfile.close ()
3844 return OutputName
3845
3846 ## Create AsBuilt INF file the module
3847 #
3848 def CreateAsBuiltInf(self, IsOnlyCopy = False):
3849 self.OutputFile = []
3850 if IsOnlyCopy:
3851 if GlobalData.gBinCacheDest:
3852 self.CopyModuleToCache()
3853 return
3854
3855 if self.IsAsBuiltInfCreated:
3856 return
3857
3858 # Skip the following code for EDK I inf
3859 if self.AutoGenVersion < 0x00010005:
3860 return
3861
3862 # Skip the following code for libraries
3863 if self.IsLibrary:
3864 return
3865
3866 # Skip the following code for modules with no source files
3867 if self.SourceFileList == None or self.SourceFileList == []:
3868 return
3869
3870 # Skip the following code for modules without any binary files
3871 if self.BinaryFileList <> None and self.BinaryFileList <> []:
3872 return
3873
3874 ### TODO: How to handles mixed source and binary modules
3875
3876 # Find all DynamicEx and PatchableInModule PCDs used by this module and dependent libraries
3877 # Also find all packages that the DynamicEx PCDs depend on
3878 Pcds = []
3879 PatchablePcds = []
3880 Packages = []
3881 PcdCheckList = []
3882 PcdTokenSpaceList = []
3883 for Pcd in self.ModulePcdList + self.LibraryPcdList:
3884 if Pcd.Type == TAB_PCDS_PATCHABLE_IN_MODULE:
3885 PatchablePcds += [Pcd]
3886 PcdCheckList.append((Pcd.TokenCName, Pcd.TokenSpaceGuidCName, 'PatchableInModule'))
3887 elif Pcd.Type in GenC.gDynamicExPcd:
3888 if Pcd not in Pcds:
3889 Pcds += [Pcd]
3890 PcdCheckList.append((Pcd.TokenCName, Pcd.TokenSpaceGuidCName, 'DynamicEx'))
3891 PcdCheckList.append((Pcd.TokenCName, Pcd.TokenSpaceGuidCName, 'Dynamic'))
3892 PcdTokenSpaceList.append(Pcd.TokenSpaceGuidCName)
3893 GuidList = sdict()
3894 GuidList.update(self.GuidList)
3895 for TokenSpace in self.GetGuidsUsedByPcd():
3896 # If token space is not referred by patch PCD or Ex PCD, remove the GUID from GUID list
3897 # The GUIDs in GUIDs section should really be the GUIDs in source INF or referred by Ex an patch PCDs
3898 if TokenSpace not in PcdTokenSpaceList and TokenSpace in GuidList:
3899 GuidList.pop(TokenSpace)
3900 CheckList = (GuidList, self.PpiList, self.ProtocolList, PcdCheckList)
3901 for Package in self.DerivedPackageList:
3902 if Package in Packages:
3903 continue
3904 BeChecked = (Package.Guids, Package.Ppis, Package.Protocols, Package.Pcds)
3905 Found = False
3906 for Index in range(len(BeChecked)):
3907 for Item in CheckList[Index]:
3908 if Item in BeChecked[Index]:
3909 Packages += [Package]
3910 Found = True
3911 break
3912 if Found: break
3913
3914 VfrPcds = self._GetPcdsMaybeUsedByVfr()
3915 for Pkg in self.PlatformInfo.PackageList:
3916 if Pkg in Packages:
3917 continue
3918 for VfrPcd in VfrPcds:
3919 if ((VfrPcd.TokenCName, VfrPcd.TokenSpaceGuidCName, 'DynamicEx') in Pkg.Pcds or
3920 (VfrPcd.TokenCName, VfrPcd.TokenSpaceGuidCName, 'Dynamic') in Pkg.Pcds):
3921 Packages += [Pkg]
3922 break
3923
3924 ModuleType = self.ModuleType
3925 if ModuleType == 'UEFI_DRIVER' and self.DepexGenerated:
3926 ModuleType = 'DXE_DRIVER'
3927
3928 DriverType = ''
3929 if self.PcdIsDriver != '':
3930 DriverType = self.PcdIsDriver
3931
3932 Guid = self.Guid
3933 MDefs = self.Module.Defines
3934
3935 AsBuiltInfDict = {
3936 'module_name' : self.Name,
3937 'module_guid' : Guid,
3938 'module_module_type' : ModuleType,
3939 'module_version_string' : [MDefs['VERSION_STRING']] if 'VERSION_STRING' in MDefs else [],
3940 'pcd_is_driver_string' : [],
3941 'module_uefi_specification_version' : [],
3942 'module_pi_specification_version' : [],
3943 'module_entry_point' : self.Module.ModuleEntryPointList,
3944 'module_unload_image' : self.Module.ModuleUnloadImageList,
3945 'module_constructor' : self.Module.ConstructorList,
3946 'module_destructor' : self.Module.DestructorList,
3947 'module_shadow' : [MDefs['SHADOW']] if 'SHADOW' in MDefs else [],
3948 'module_pci_vendor_id' : [MDefs['PCI_VENDOR_ID']] if 'PCI_VENDOR_ID' in MDefs else [],
3949 'module_pci_device_id' : [MDefs['PCI_DEVICE_ID']] if 'PCI_DEVICE_ID' in MDefs else [],
3950 'module_pci_class_code' : [MDefs['PCI_CLASS_CODE']] if 'PCI_CLASS_CODE' in MDefs else [],
3951 'module_pci_revision' : [MDefs['PCI_REVISION']] if 'PCI_REVISION' in MDefs else [],
3952 'module_build_number' : [MDefs['BUILD_NUMBER']] if 'BUILD_NUMBER' in MDefs else [],
3953 'module_spec' : [MDefs['SPEC']] if 'SPEC' in MDefs else [],
3954 'module_uefi_hii_resource_section' : [MDefs['UEFI_HII_RESOURCE_SECTION']] if 'UEFI_HII_RESOURCE_SECTION' in MDefs else [],
3955 'module_uni_file' : [MDefs['MODULE_UNI_FILE']] if 'MODULE_UNI_FILE' in MDefs else [],
3956 'module_arch' : self.Arch,
3957 'package_item' : ['%s' % (Package.MetaFile.File.replace('\\', '/')) for Package in Packages],
3958 'binary_item' : [],
3959 'patchablepcd_item' : [],
3960 'pcd_item' : [],
3961 'protocol_item' : [],
3962 'ppi_item' : [],
3963 'guid_item' : [],
3964 'flags_item' : [],
3965 'libraryclasses_item' : []
3966 }
3967
3968 if 'MODULE_UNI_FILE' in MDefs:
3969 UNIFile = os.path.join(self.MetaFile.Dir, MDefs['MODULE_UNI_FILE'])
3970 if os.path.isfile(UNIFile):
3971 shutil.copy2(UNIFile, self.OutputDir)
3972
3973 if self.AutoGenVersion > int(gInfSpecVersion, 0):
3974 AsBuiltInfDict['module_inf_version'] = '0x%08x' % self.AutoGenVersion
3975 else:
3976 AsBuiltInfDict['module_inf_version'] = gInfSpecVersion
3977
3978 if DriverType:
3979 AsBuiltInfDict['pcd_is_driver_string'] += [DriverType]
3980
3981 if 'UEFI_SPECIFICATION_VERSION' in self.Specification:
3982 AsBuiltInfDict['module_uefi_specification_version'] += [self.Specification['UEFI_SPECIFICATION_VERSION']]
3983 if 'PI_SPECIFICATION_VERSION' in self.Specification:
3984 AsBuiltInfDict['module_pi_specification_version'] += [self.Specification['PI_SPECIFICATION_VERSION']]
3985
3986 OutputDir = self.OutputDir.replace('\\', '/').strip('/')
3987 for Item in self.CodaTargetList:
3988 File = Item.Target.Path.replace('\\', '/').strip('/').replace(OutputDir, '').strip('/')
3989 if File not in self.OutputFile:
3990 self.OutputFile.append(File)
3991 if Item.Target.Ext.lower() == '.aml':
3992 AsBuiltInfDict['binary_item'] += ['ASL|' + File]
3993 elif Item.Target.Ext.lower() == '.acpi':
3994 AsBuiltInfDict['binary_item'] += ['ACPI|' + File]
3995 elif Item.Target.Ext.lower() == '.efi':
3996 AsBuiltInfDict['binary_item'] += ['PE32|' + self.Name + '.efi']
3997 else:
3998 AsBuiltInfDict['binary_item'] += ['BIN|' + File]
3999 if self.DepexGenerated:
4000 if self.Name + '.depex' not in self.OutputFile:
4001 self.OutputFile.append(self.Name + '.depex')
4002 if self.ModuleType in ['PEIM']:
4003 AsBuiltInfDict['binary_item'] += ['PEI_DEPEX|' + self.Name + '.depex']
4004 if self.ModuleType in ['DXE_DRIVER', 'DXE_RUNTIME_DRIVER', 'DXE_SAL_DRIVER', 'UEFI_DRIVER']:
4005 AsBuiltInfDict['binary_item'] += ['DXE_DEPEX|' + self.Name + '.depex']
4006 if self.ModuleType in ['DXE_SMM_DRIVER']:
4007 AsBuiltInfDict['binary_item'] += ['SMM_DEPEX|' + self.Name + '.depex']
4008
4009 Bin = self._GenOffsetBin()
4010 if Bin:
4011 AsBuiltInfDict['binary_item'] += ['BIN|%s' % Bin]
4012 if Bin not in self.OutputFile:
4013 self.OutputFile.append(Bin)
4014
4015 for Root, Dirs, Files in os.walk(OutputDir):
4016 for File in Files:
4017 if File.lower().endswith('.pdb'):
4018 AsBuiltInfDict['binary_item'] += ['DISPOSABLE|' + File]
4019 if File not in self.OutputFile:
4020 self.OutputFile.append(File)
4021 HeaderComments = self.Module.HeaderComments
4022 StartPos = 0
4023 for Index in range(len(HeaderComments)):
4024 if HeaderComments[Index].find('@BinaryHeader') != -1:
4025 HeaderComments[Index] = HeaderComments[Index].replace('@BinaryHeader', '@file')
4026 StartPos = Index
4027 break
4028 AsBuiltInfDict['header_comments'] = '\n'.join(HeaderComments[StartPos:]).replace(':#', '://')
4029 AsBuiltInfDict['tail_comments'] = '\n'.join(self.Module.TailComments)
4030
4031 GenList = [
4032 (self.ProtocolList, self._ProtocolComments, 'protocol_item'),
4033 (self.PpiList, self._PpiComments, 'ppi_item'),
4034 (GuidList, self._GuidComments, 'guid_item')
4035 ]
4036 for Item in GenList:
4037 for CName in Item[0]:
4038 Comments = ''
4039 if CName in Item[1]:
4040 Comments = '\n '.join(Item[1][CName])
4041 Entry = CName
4042 if Comments:
4043 Entry = Comments + '\n ' + CName
4044 AsBuiltInfDict[Item[2]].append(Entry)
4045 PatchList = parsePcdInfoFromMapFile(
4046 os.path.join(self.OutputDir, self.Name + '.map'),
4047 os.path.join(self.OutputDir, self.Name + '.efi')
4048 )
4049 if PatchList:
4050 for Pcd in PatchablePcds:
4051 TokenCName = Pcd.TokenCName
4052 for PcdItem in GlobalData.MixedPcd:
4053 if (Pcd.TokenCName, Pcd.TokenSpaceGuidCName) in GlobalData.MixedPcd[PcdItem]:
4054 TokenCName = PcdItem[0]
4055 break
4056 for PatchPcd in PatchList:
4057 if TokenCName == PatchPcd[0]:
4058 break
4059 else:
4060 continue
4061 PcdValue = ''
4062 if Pcd.DatumType == 'BOOLEAN':
4063 BoolValue = Pcd.DefaultValue.upper()
4064 if BoolValue == 'TRUE':
4065 Pcd.DefaultValue = '1'
4066 elif BoolValue == 'FALSE':
4067 Pcd.DefaultValue = '0'
4068
4069 if Pcd.DatumType in ['UINT8', 'UINT16', 'UINT32', 'UINT64', 'BOOLEAN']:
4070 HexFormat = '0x%02x'
4071 if Pcd.DatumType == 'UINT16':
4072 HexFormat = '0x%04x'
4073 elif Pcd.DatumType == 'UINT32':
4074 HexFormat = '0x%08x'
4075 elif Pcd.DatumType == 'UINT64':
4076 HexFormat = '0x%016x'
4077 PcdValue = HexFormat % int(Pcd.DefaultValue, 0)
4078 else:
4079 if Pcd.MaxDatumSize == None or Pcd.MaxDatumSize == '':
4080 EdkLogger.error("build", AUTOGEN_ERROR,
4081 "Unknown [MaxDatumSize] of PCD [%s.%s]" % (Pcd.TokenSpaceGuidCName, TokenCName)
4082 )
4083 ArraySize = int(Pcd.MaxDatumSize, 0)
4084 PcdValue = Pcd.DefaultValue
4085 if PcdValue[0] != '{':
4086 Unicode = False
4087 if PcdValue[0] == 'L':
4088 Unicode = True
4089 PcdValue = PcdValue.lstrip('L')
4090 PcdValue = eval(PcdValue)
4091 NewValue = '{'
4092 for Index in range(0, len(PcdValue)):
4093 if Unicode:
4094 CharVal = ord(PcdValue[Index])
4095 NewValue = NewValue + '0x%02x' % (CharVal & 0x00FF) + ', ' \
4096 + '0x%02x' % (CharVal >> 8) + ', '
4097 else:
4098 NewValue = NewValue + '0x%02x' % (ord(PcdValue[Index]) % 0x100) + ', '
4099 Padding = '0x00, '
4100 if Unicode:
4101 Padding = Padding * 2
4102 ArraySize = ArraySize / 2
4103 if ArraySize < (len(PcdValue) + 1):
4104 EdkLogger.error("build", AUTOGEN_ERROR,
4105 "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd.TokenSpaceGuidCName, TokenCName)
4106 )
4107 if ArraySize > len(PcdValue) + 1:
4108 NewValue = NewValue + Padding * (ArraySize - len(PcdValue) - 1)
4109 PcdValue = NewValue + Padding.strip().rstrip(',') + '}'
4110 elif len(PcdValue.split(',')) <= ArraySize:
4111 PcdValue = PcdValue.rstrip('}') + ', 0x00' * (ArraySize - len(PcdValue.split(',')))
4112 PcdValue += '}'
4113 else:
4114 EdkLogger.error("build", AUTOGEN_ERROR,
4115 "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd.TokenSpaceGuidCName, TokenCName)
4116 )
4117 PcdItem = '%s.%s|%s|0x%X' % \
4118 (Pcd.TokenSpaceGuidCName, TokenCName, PcdValue, PatchPcd[1])
4119 PcdComments = ''
4120 if (Pcd.TokenSpaceGuidCName, Pcd.TokenCName) in self._PcdComments:
4121 PcdComments = '\n '.join(self._PcdComments[Pcd.TokenSpaceGuidCName, Pcd.TokenCName])
4122 if PcdComments:
4123 PcdItem = PcdComments + '\n ' + PcdItem
4124 AsBuiltInfDict['patchablepcd_item'].append(PcdItem)
4125
4126 HiiPcds = []
4127 for Pcd in Pcds + VfrPcds:
4128 PcdComments = ''
4129 PcdCommentList = []
4130 HiiInfo = ''
4131 SkuId = ''
4132 TokenCName = Pcd.TokenCName
4133 for PcdItem in GlobalData.MixedPcd:
4134 if (Pcd.TokenCName, Pcd.TokenSpaceGuidCName) in GlobalData.MixedPcd[PcdItem]:
4135 TokenCName = PcdItem[0]
4136 break
4137 if Pcd.Type == TAB_PCDS_DYNAMIC_EX_HII:
4138 for SkuName in Pcd.SkuInfoList:
4139 SkuInfo = Pcd.SkuInfoList[SkuName]
4140 SkuId = SkuInfo.SkuId
4141 HiiInfo = '## %s|%s|%s' % (SkuInfo.VariableName, SkuInfo.VariableGuid, SkuInfo.VariableOffset)
4142 break
4143 if SkuId:
4144 #
4145 # Don't generate duplicated HII PCD
4146 #
4147 if (SkuId, Pcd.TokenSpaceGuidCName, Pcd.TokenCName) in HiiPcds:
4148 continue
4149 else:
4150 HiiPcds.append((SkuId, Pcd.TokenSpaceGuidCName, Pcd.TokenCName))
4151 if (Pcd.TokenSpaceGuidCName, Pcd.TokenCName) in self._PcdComments:
4152 PcdCommentList = self._PcdComments[Pcd.TokenSpaceGuidCName, Pcd.TokenCName][:]
4153 if HiiInfo:
4154 UsageIndex = -1
4155 UsageStr = ''
4156 for Index, Comment in enumerate(PcdCommentList):
4157 for Usage in UsageList:
4158 if Comment.find(Usage) != -1:
4159 UsageStr = Usage
4160 UsageIndex = Index
4161 break
4162 if UsageIndex != -1:
4163 PcdCommentList[UsageIndex] = '## %s %s %s' % (UsageStr, HiiInfo, PcdCommentList[UsageIndex].replace(UsageStr, ''))
4164 else:
4165 PcdCommentList.append('## UNDEFINED ' + HiiInfo)
4166 PcdComments = '\n '.join(PcdCommentList)
4167 PcdEntry = Pcd.TokenSpaceGuidCName + '.' + TokenCName
4168 if PcdComments:
4169 PcdEntry = PcdComments + '\n ' + PcdEntry
4170 AsBuiltInfDict['pcd_item'] += [PcdEntry]
4171 for Item in self.BuildOption:
4172 if 'FLAGS' in self.BuildOption[Item]:
4173 AsBuiltInfDict['flags_item'] += ['%s:%s_%s_%s_%s_FLAGS = %s' % (self.ToolChainFamily, self.BuildTarget, self.ToolChain, self.Arch, Item, self.BuildOption[Item]['FLAGS'].strip())]
4174
4175 # Generated LibraryClasses section in comments.
4176 for Library in self.LibraryAutoGenList:
4177 AsBuiltInfDict['libraryclasses_item'] += [Library.MetaFile.File.replace('\\', '/')]
4178
4179 # Generated UserExtensions TianoCore section.
4180 # All tianocore user extensions are copied.
4181 UserExtStr = ''
4182 for TianoCore in self._GetTianoCoreUserExtensionList():
4183 UserExtStr += '\n'.join(TianoCore)
4184 ExtensionFile = os.path.join(self.MetaFile.Dir, TianoCore[1])
4185 if os.path.isfile(ExtensionFile):
4186 shutil.copy2(ExtensionFile, self.OutputDir)
4187 AsBuiltInfDict['userextension_tianocore_item'] = UserExtStr
4188
4189 # Generated depex expression section in comments.
4190 AsBuiltInfDict['depexsection_item'] = ''
4191 DepexExpresion = self._GetDepexExpresionString()
4192 if DepexExpresion:
4193 AsBuiltInfDict['depexsection_item'] = DepexExpresion
4194
4195 AsBuiltInf = TemplateString()
4196 AsBuiltInf.Append(gAsBuiltInfHeaderString.Replace(AsBuiltInfDict))
4197
4198 SaveFileOnChange(os.path.join(self.OutputDir, self.Name + '.inf'), str(AsBuiltInf), False)
4199
4200 self.IsAsBuiltInfCreated = True
4201 if GlobalData.gBinCacheDest:
4202 self.CopyModuleToCache()
4203
4204 def CopyModuleToCache(self):
4205 FileDir = path.join(GlobalData.gBinCacheDest, self.Arch, self.SourceDir, self.MetaFile.BaseName)
4206 CreateDirectory (FileDir)
4207 HashFile = path.join(self.BuildDir, self.Name + '.hash')
4208 ModuleFile = path.join(self.OutputDir, self.Name + '.inf')
4209 if os.path.exists(HashFile):
4210 shutil.copy2(HashFile, FileDir)
4211 if os.path.exists(ModuleFile):
4212 shutil.copy2(ModuleFile, FileDir)
4213 if not self.OutputFile:
4214 Ma = self.Workspace.BuildDatabase[PathClass(ModuleFile), self.Arch, self.BuildTarget, self.ToolChain]
4215 self.OutputFile = Ma.Binaries
4216 if self.OutputFile:
4217 for File in self.OutputFile:
4218 File = str(File)
4219 if not os.path.isabs(File):
4220 File = os.path.join(self.OutputDir, File)
4221 if os.path.exists(File):
4222 shutil.copy2(File, FileDir)
4223
4224 def AttemptModuleCacheCopy(self):
4225 if self.IsBinaryModule:
4226 return False
4227 FileDir = path.join(GlobalData.gBinCacheSource, self.Arch, self.SourceDir, self.MetaFile.BaseName)
4228 HashFile = path.join(FileDir, self.Name + '.hash')
4229 if os.path.exists(HashFile):
4230 f = open(HashFile, 'r')
4231 CacheHash = f.read()
4232 f.close()
4233 if GlobalData.gModuleHash[self.Arch][self.Name]:
4234 if CacheHash == GlobalData.gModuleHash[self.Arch][self.Name]:
4235 for root, dir, files in os.walk(FileDir):
4236 for f in files:
4237 if self.Name + '.hash' in f:
4238 shutil.copy2(HashFile, self.BuildDir)
4239 else:
4240 File = path.join(root, f)
4241 shutil.copy2(File, self.OutputDir)
4242 if self.Name == "PcdPeim" or self.Name == "PcdDxe":
4243 CreatePcdDatabaseCode(self, TemplateString(), TemplateString())
4244 return True
4245 return False
4246
4247 ## Create makefile for the module and its dependent libraries
4248 #
4249 # @param CreateLibraryMakeFile Flag indicating if or not the makefiles of
4250 # dependent libraries will be created
4251 #
4252 def CreateMakeFile(self, CreateLibraryMakeFile=True, GenFfsList = []):
4253 # Ignore generating makefile when it is a binary module
4254 if self.IsBinaryModule:
4255 return
4256
4257 if self.IsMakeFileCreated:
4258 return
4259 self.GenFfsList = GenFfsList
4260 if not self.IsLibrary and CreateLibraryMakeFile:
4261 for LibraryAutoGen in self.LibraryAutoGenList:
4262 LibraryAutoGen.CreateMakeFile()
4263
4264 if self.CanSkip():
4265 return
4266
4267 if len(self.CustomMakefile) == 0:
4268 Makefile = GenMake.ModuleMakefile(self)
4269 else:
4270 Makefile = GenMake.CustomMakefile(self)
4271 if Makefile.Generate():
4272 EdkLogger.debug(EdkLogger.DEBUG_9, "Generated makefile for module %s [%s]" %
4273 (self.Name, self.Arch))
4274 else:
4275 EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of makefile for module %s [%s]" %
4276 (self.Name, self.Arch))
4277
4278 self.CreateTimeStamp(Makefile)
4279 self.IsMakeFileCreated = True
4280
4281 def CopyBinaryFiles(self):
4282 for File in self.Module.Binaries:
4283 SrcPath = File.Path
4284 DstPath = os.path.join(self.OutputDir , os.path.basename(SrcPath))
4285 CopyLongFilePath(SrcPath, DstPath)
4286 ## Create autogen code for the module and its dependent libraries
4287 #
4288 # @param CreateLibraryCodeFile Flag indicating if or not the code of
4289 # dependent libraries will be created
4290 #
4291 def CreateCodeFile(self, CreateLibraryCodeFile=True):
4292 if self.IsCodeFileCreated:
4293 return
4294
4295 # Need to generate PcdDatabase even PcdDriver is binarymodule
4296 if self.IsBinaryModule and self.PcdIsDriver != '':
4297 CreatePcdDatabaseCode(self, TemplateString(), TemplateString())
4298 return
4299 if self.IsBinaryModule:
4300 if self.IsLibrary:
4301 self.CopyBinaryFiles()
4302 return
4303
4304 if not self.IsLibrary and CreateLibraryCodeFile:
4305 for LibraryAutoGen in self.LibraryAutoGenList:
4306 LibraryAutoGen.CreateCodeFile()
4307
4308 if self.CanSkip():
4309 return
4310
4311 AutoGenList = []
4312 IgoredAutoGenList = []
4313
4314 for File in self.AutoGenFileList:
4315 if GenC.Generate(File.Path, self.AutoGenFileList[File], File.IsBinary):
4316 #Ignore Edk AutoGen.c
4317 if self.AutoGenVersion < 0x00010005 and File.Name == 'AutoGen.c':
4318 continue
4319
4320 AutoGenList.append(str(File))
4321 else:
4322 IgoredAutoGenList.append(str(File))
4323
4324 # Skip the following code for EDK I inf
4325 if self.AutoGenVersion < 0x00010005:
4326 return
4327
4328 for ModuleType in self.DepexList:
4329 # Ignore empty [depex] section or [depex] section for "USER_DEFINED" module
4330 if len(self.DepexList[ModuleType]) == 0 or ModuleType == "USER_DEFINED":
4331 continue
4332
4333 Dpx = GenDepex.DependencyExpression(self.DepexList[ModuleType], ModuleType, True)
4334 DpxFile = gAutoGenDepexFileName % {"module_name" : self.Name}
4335
4336 if len(Dpx.PostfixNotation) <> 0:
4337 self.DepexGenerated = True
4338
4339 if Dpx.Generate(path.join(self.OutputDir, DpxFile)):
4340 AutoGenList.append(str(DpxFile))
4341 else:
4342 IgoredAutoGenList.append(str(DpxFile))
4343
4344 if IgoredAutoGenList == []:
4345 EdkLogger.debug(EdkLogger.DEBUG_9, "Generated [%s] files for module %s [%s]" %
4346 (" ".join(AutoGenList), self.Name, self.Arch))
4347 elif AutoGenList == []:
4348 EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of [%s] files for module %s [%s]" %
4349 (" ".join(IgoredAutoGenList), self.Name, self.Arch))
4350 else:
4351 EdkLogger.debug(EdkLogger.DEBUG_9, "Generated [%s] (skipped %s) files for module %s [%s]" %
4352 (" ".join(AutoGenList), " ".join(IgoredAutoGenList), self.Name, self.Arch))
4353
4354 self.IsCodeFileCreated = True
4355 return AutoGenList
4356
4357 ## Summarize the ModuleAutoGen objects of all libraries used by this module
4358 def _GetLibraryAutoGenList(self):
4359 if self._LibraryAutoGenList == None:
4360 self._LibraryAutoGenList = []
4361 for Library in self.DependentLibraryList:
4362 La = ModuleAutoGen(
4363 self.Workspace,
4364 Library.MetaFile,
4365 self.BuildTarget,
4366 self.ToolChain,
4367 self.Arch,
4368 self.PlatformInfo.MetaFile
4369 )
4370 if La not in self._LibraryAutoGenList:
4371 self._LibraryAutoGenList.append(La)
4372 for Lib in La.CodaTargetList:
4373 self._ApplyBuildRule(Lib.Target, TAB_UNKNOWN_FILE)
4374 return self._LibraryAutoGenList
4375
4376 def GenModuleHash(self):
4377 if self.Arch not in GlobalData.gModuleHash:
4378 GlobalData.gModuleHash[self.Arch] = {}
4379 m = hashlib.md5()
4380 # Add Platform level hash
4381 m.update(GlobalData.gPlatformHash)
4382 # Add Package level hash
4383 if self.DependentPackageList:
4384 for Pkg in self.DependentPackageList:
4385 if Pkg.PackageName in GlobalData.gPackageHash[self.Arch]:
4386 m.update(GlobalData.gPackageHash[self.Arch][Pkg.PackageName])
4387
4388 # Add Library hash
4389 if self.LibraryAutoGenList:
4390 for Lib in self.LibraryAutoGenList:
4391 if Lib.Name not in GlobalData.gModuleHash[self.Arch]:
4392 Lib.GenModuleHash()
4393 m.update(GlobalData.gModuleHash[self.Arch][Lib.Name])
4394
4395 # Add Module self
4396 f = open(str(self.MetaFile), 'r')
4397 Content = f.read()
4398 f.close()
4399 m.update(Content)
4400 # Add Module's source files
4401 if self.SourceFileList:
4402 for File in self.SourceFileList:
4403 f = open(str(File), 'r')
4404 Content = f.read()
4405 f.close()
4406 m.update(Content)
4407
4408 ModuleHashFile = path.join(self.BuildDir, self.Name + ".hash")
4409 if self.Name not in GlobalData.gModuleHash[self.Arch]:
4410 GlobalData.gModuleHash[self.Arch][self.Name] = m.hexdigest()
4411 if GlobalData.gBinCacheSource:
4412 CacheValid = self.AttemptModuleCacheCopy()
4413 if CacheValid:
4414 return False
4415 return SaveFileOnChange(ModuleHashFile, m.hexdigest(), True)
4416
4417 ## Decide whether we can skip the ModuleAutoGen process
4418 def CanSkipbyHash(self):
4419 if GlobalData.gUseHashCache:
4420 return not self.GenModuleHash()
4421
4422 ## Decide whether we can skip the ModuleAutoGen process
4423 # If any source file is newer than the module than we cannot skip
4424 #
4425 def CanSkip(self):
4426 if not os.path.exists(self.GetTimeStampPath()):
4427 return False
4428 #last creation time of the module
4429 DstTimeStamp = os.stat(self.GetTimeStampPath())[8]
4430
4431 SrcTimeStamp = self.Workspace._SrcTimeStamp
4432 if SrcTimeStamp > DstTimeStamp:
4433 return False
4434
4435 with open(self.GetTimeStampPath(),'r') as f:
4436 for source in f:
4437 source = source.rstrip('\n')
4438 if not os.path.exists(source):
4439 return False
4440 if source not in ModuleAutoGen.TimeDict :
4441 ModuleAutoGen.TimeDict[source] = os.stat(source)[8]
4442 if ModuleAutoGen.TimeDict[source] > DstTimeStamp:
4443 return False
4444 return True
4445
4446 def GetTimeStampPath(self):
4447 if self._TimeStampPath == None:
4448 self._TimeStampPath = os.path.join(self.MakeFileDir, 'AutoGenTimeStamp')
4449 return self._TimeStampPath
4450 def CreateTimeStamp(self, Makefile):
4451
4452 FileSet = set()
4453
4454 FileSet.add (self.MetaFile.Path)
4455
4456 for SourceFile in self.Module.Sources:
4457 FileSet.add (SourceFile.Path)
4458
4459 for Lib in self.DependentLibraryList:
4460 FileSet.add (Lib.MetaFile.Path)
4461
4462 for f in self.AutoGenDepSet:
4463 FileSet.add (f.Path)
4464
4465 if os.path.exists (self.GetTimeStampPath()):
4466 os.remove (self.GetTimeStampPath())
4467 with open(self.GetTimeStampPath(), 'w+') as file:
4468 for f in FileSet:
4469 print >> file, f
4470
4471 Module = property(_GetModule)
4472 Name = property(_GetBaseName)
4473 Guid = property(_GetGuid)
4474 Version = property(_GetVersion)
4475 ModuleType = property(_GetModuleType)
4476 ComponentType = property(_GetComponentType)
4477 BuildType = property(_GetBuildType)
4478 PcdIsDriver = property(_GetPcdIsDriver)
4479 AutoGenVersion = property(_GetAutoGenVersion)
4480 Macros = property(_GetMacros)
4481 Specification = property(_GetSpecification)
4482
4483 IsLibrary = property(_IsLibrary)
4484 IsBinaryModule = property(_IsBinaryModule)
4485 BuildDir = property(_GetBuildDir)
4486 OutputDir = property(_GetOutputDir)
4487 FfsOutputDir = property(_GetFfsOutputDir)
4488 DebugDir = property(_GetDebugDir)
4489 MakeFileDir = property(_GetMakeFileDir)
4490 CustomMakefile = property(_GetCustomMakefile)
4491
4492 IncludePathList = property(_GetIncludePathList)
4493 IncludePathLength = property(_GetIncludePathLength)
4494 AutoGenFileList = property(_GetAutoGenFileList)
4495 UnicodeFileList = property(_GetUnicodeFileList)
4496 VfrFileList = property(_GetVfrFileList)
4497 SourceFileList = property(_GetSourceFileList)
4498 BinaryFileList = property(_GetBinaryFiles) # FileType : [File List]
4499 Targets = property(_GetTargets)
4500 IntroTargetList = property(_GetIntroTargetList)
4501 CodaTargetList = property(_GetFinalTargetList)
4502 FileTypes = property(_GetFileTypes)
4503 BuildRules = property(_GetBuildRules)
4504 IdfFileList = property(_GetIdfFileList)
4505
4506 DependentPackageList = property(_GetDependentPackageList)
4507 DependentLibraryList = property(_GetLibraryList)
4508 LibraryAutoGenList = property(_GetLibraryAutoGenList)
4509 DerivedPackageList = property(_GetDerivedPackageList)
4510
4511 ModulePcdList = property(_GetModulePcdList)
4512 LibraryPcdList = property(_GetLibraryPcdList)
4513 GuidList = property(_GetGuidList)
4514 ProtocolList = property(_GetProtocolList)
4515 PpiList = property(_GetPpiList)
4516 DepexList = property(_GetDepexTokenList)
4517 DxsFile = property(_GetDxsFile)
4518 DepexExpressionList = property(_GetDepexExpressionTokenList)
4519 BuildOption = property(_GetModuleBuildOption)
4520 BuildOptionIncPathList = property(_GetBuildOptionIncPathList)
4521 BuildCommand = property(_GetBuildCommand)
4522
4523 FixedAtBuildPcds = property(_GetFixedAtBuildPcds)
4524
4525 # This acts like the main() function for the script, unless it is 'import'ed into another script.
4526 if __name__ == '__main__':
4527 pass
4528