]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/AutoGen/AutoGen.py
14eb1384c6c738cd102b54d9e4aca029d4085210
[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 if GlobalData.gBinCacheDest:
690 content += 'Cache of .efi location: '
691 content += str(GlobalData.gBinCacheDest)
692 SaveFileOnChange(os.path.join(self.BuildDir, 'BuildOptions'), content, False)
693
694 #
695 # Create PcdToken Number file for Dynamic/DynamicEx Pcd.
696 #
697 PcdTokenNumber = 'PcdTokenNumber: '
698 if Pa.PcdTokenNumber:
699 if Pa.DynamicPcdList:
700 for Pcd in Pa.DynamicPcdList:
701 PcdTokenNumber += os.linesep
702 PcdTokenNumber += str((Pcd.TokenCName, Pcd.TokenSpaceGuidCName))
703 PcdTokenNumber += ' : '
704 PcdTokenNumber += str(Pa.PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName])
705 SaveFileOnChange(os.path.join(self.BuildDir, 'PcdTokenNumber'), PcdTokenNumber, False)
706
707 #
708 # Get set of workspace metafiles
709 #
710 AllWorkSpaceMetaFiles = self._GetMetaFiles(Target, Toolchain, Arch)
711
712 #
713 # Retrieve latest modified time of all metafiles
714 #
715 SrcTimeStamp = 0
716 for f in AllWorkSpaceMetaFiles:
717 if os.stat(f)[8] > SrcTimeStamp:
718 SrcTimeStamp = os.stat(f)[8]
719 self._SrcTimeStamp = SrcTimeStamp
720
721 if GlobalData.gUseHashCache:
722 m = hashlib.md5()
723 for files in AllWorkSpaceMetaFiles:
724 if files.endswith('.dec'):
725 continue
726 f = open(files, 'r')
727 Content = f.read()
728 f.close()
729 m.update(Content)
730 SaveFileOnChange(os.path.join(self.BuildDir, 'AutoGen.hash'), m.hexdigest(), True)
731 GlobalData.gPlatformHash = m.hexdigest()
732
733 #
734 # Write metafile list to build directory
735 #
736 AutoGenFilePath = os.path.join(self.BuildDir, 'AutoGen')
737 if os.path.exists (AutoGenFilePath):
738 os.remove(AutoGenFilePath)
739 if not os.path.exists(self.BuildDir):
740 os.makedirs(self.BuildDir)
741 with open(os.path.join(self.BuildDir, 'AutoGen'), 'w+') as file:
742 for f in AllWorkSpaceMetaFiles:
743 print >> file, f
744 return True
745
746 def _GenPkgLevelHash(self, Pkg):
747 PkgDir = os.path.join(self.BuildDir, Pkg.Arch, Pkg.PackageName)
748 CreateDirectory(PkgDir)
749 HashFile = os.path.join(PkgDir, Pkg.PackageName + '.hash')
750 m = hashlib.md5()
751 # Get .dec file's hash value
752 f = open(Pkg.MetaFile.Path, 'r')
753 Content = f.read()
754 f.close()
755 m.update(Content)
756 # Get include files hash value
757 if Pkg.Includes:
758 for inc in Pkg.Includes:
759 for Root, Dirs, Files in os.walk(str(inc)):
760 for File in Files:
761 File_Path = os.path.join(Root, File)
762 f = open(File_Path, 'r')
763 Content = f.read()
764 f.close()
765 m.update(Content)
766 SaveFileOnChange(HashFile, m.hexdigest(), True)
767 if Pkg.PackageName not in GlobalData.gPackageHash[Pkg.Arch]:
768 GlobalData.gPackageHash[Pkg.Arch][Pkg.PackageName] = m.hexdigest()
769
770 def _GetMetaFiles(self, Target, Toolchain, Arch):
771 AllWorkSpaceMetaFiles = set()
772 #
773 # add fdf
774 #
775 if self.FdfFile:
776 AllWorkSpaceMetaFiles.add (self.FdfFile.Path)
777 if self.FdfFile:
778 FdfFiles = GlobalData.gFdfParser.GetAllIncludedFile()
779 for f in FdfFiles:
780 AllWorkSpaceMetaFiles.add (f.FileName)
781 #
782 # add dsc
783 #
784 AllWorkSpaceMetaFiles.add(self.MetaFile.Path)
785
786 #
787 # add build_rule.txt & tools_def.txt
788 #
789 AllWorkSpaceMetaFiles.add(os.path.join(GlobalData.gConfDirectory, gDefaultBuildRuleFile))
790 AllWorkSpaceMetaFiles.add(os.path.join(GlobalData.gConfDirectory, gDefaultToolsDefFile))
791
792 # add BuildOption metafile
793 #
794 AllWorkSpaceMetaFiles.add(os.path.join(self.BuildDir, 'BuildOptions'))
795
796 # add PcdToken Number file for Dynamic/DynamicEx Pcd
797 #
798 AllWorkSpaceMetaFiles.add(os.path.join(self.BuildDir, 'PcdTokenNumber'))
799
800 for Arch in self.ArchList:
801 Platform = self.BuildDatabase[self.MetaFile, Arch, Target, Toolchain]
802 PGen = PlatformAutoGen(self, self.MetaFile, Target, Toolchain, Arch)
803
804 #
805 # add dec
806 #
807 for Package in PGen.PackageList:
808 AllWorkSpaceMetaFiles.add(Package.MetaFile.Path)
809
810 #
811 # add included dsc
812 #
813 for filePath in Platform._RawData.IncludedFiles:
814 AllWorkSpaceMetaFiles.add(filePath.Path)
815
816 return AllWorkSpaceMetaFiles
817
818 ## _CheckDuplicateInFV() method
819 #
820 # Check whether there is duplicate modules/files exist in FV section.
821 # The check base on the file GUID;
822 #
823 def _CheckDuplicateInFV(self, Fdf):
824 for Fv in Fdf.Profile.FvDict:
825 _GuidDict = {}
826 for FfsFile in Fdf.Profile.FvDict[Fv].FfsList:
827 if FfsFile.InfFileName and FfsFile.NameGuid == None:
828 #
829 # Get INF file GUID
830 #
831 InfFoundFlag = False
832 for Pa in self.AutoGenObjectList:
833 if InfFoundFlag:
834 break
835 for Module in Pa.ModuleAutoGenList:
836 if path.normpath(Module.MetaFile.File) == path.normpath(FfsFile.InfFileName):
837 InfFoundFlag = True
838 if not Module.Guid.upper() in _GuidDict.keys():
839 _GuidDict[Module.Guid.upper()] = FfsFile
840 break
841 else:
842 EdkLogger.error("build",
843 FORMAT_INVALID,
844 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile.CurrentLineNum,
845 FfsFile.CurrentLineContent,
846 _GuidDict[Module.Guid.upper()].CurrentLineNum,
847 _GuidDict[Module.Guid.upper()].CurrentLineContent,
848 Module.Guid.upper()),
849 ExtraData=self.FdfFile)
850 #
851 # Some INF files not have entity in DSC file.
852 #
853 if not InfFoundFlag:
854 if FfsFile.InfFileName.find('$') == -1:
855 InfPath = NormPath(FfsFile.InfFileName)
856 if not os.path.exists(InfPath):
857 EdkLogger.error('build', GENFDS_ERROR, "Non-existant Module %s !" % (FfsFile.InfFileName))
858
859 PathClassObj = PathClass(FfsFile.InfFileName, self.WorkspaceDir)
860 #
861 # Here we just need to get FILE_GUID from INF file, use 'COMMON' as ARCH attribute. and use
862 # BuildObject from one of AutoGenObjectList is enough.
863 #
864 InfObj = self.AutoGenObjectList[0].BuildDatabase.WorkspaceDb.BuildObject[PathClassObj, 'COMMON', self.BuildTarget, self.ToolChain]
865 if not InfObj.Guid.upper() in _GuidDict.keys():
866 _GuidDict[InfObj.Guid.upper()] = FfsFile
867 else:
868 EdkLogger.error("build",
869 FORMAT_INVALID,
870 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile.CurrentLineNum,
871 FfsFile.CurrentLineContent,
872 _GuidDict[InfObj.Guid.upper()].CurrentLineNum,
873 _GuidDict[InfObj.Guid.upper()].CurrentLineContent,
874 InfObj.Guid.upper()),
875 ExtraData=self.FdfFile)
876 InfFoundFlag = False
877
878 if FfsFile.NameGuid != None:
879 _CheckPCDAsGuidPattern = re.compile("^PCD\(.+\..+\)$")
880
881 #
882 # If the NameGuid reference a PCD name.
883 # The style must match: PCD(xxxx.yyy)
884 #
885 if _CheckPCDAsGuidPattern.match(FfsFile.NameGuid):
886 #
887 # Replace the PCD value.
888 #
889 _PcdName = FfsFile.NameGuid.lstrip("PCD(").rstrip(")")
890 PcdFoundFlag = False
891 for Pa in self.AutoGenObjectList:
892 if not PcdFoundFlag:
893 for PcdItem in Pa.AllPcdList:
894 if (PcdItem.TokenSpaceGuidCName + "." + PcdItem.TokenCName) == _PcdName:
895 #
896 # First convert from CFormatGuid to GUID string
897 #
898 _PcdGuidString = GuidStructureStringToGuidString(PcdItem.DefaultValue)
899
900 if not _PcdGuidString:
901 #
902 # Then try Byte array.
903 #
904 _PcdGuidString = GuidStructureByteArrayToGuidString(PcdItem.DefaultValue)
905
906 if not _PcdGuidString:
907 #
908 # Not Byte array or CFormat GUID, raise error.
909 #
910 EdkLogger.error("build",
911 FORMAT_INVALID,
912 "The format of PCD value is incorrect. PCD: %s , Value: %s\n" % (_PcdName, PcdItem.DefaultValue),
913 ExtraData=self.FdfFile)
914
915 if not _PcdGuidString.upper() in _GuidDict.keys():
916 _GuidDict[_PcdGuidString.upper()] = FfsFile
917 PcdFoundFlag = True
918 break
919 else:
920 EdkLogger.error("build",
921 FORMAT_INVALID,
922 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile.CurrentLineNum,
923 FfsFile.CurrentLineContent,
924 _GuidDict[_PcdGuidString.upper()].CurrentLineNum,
925 _GuidDict[_PcdGuidString.upper()].CurrentLineContent,
926 FfsFile.NameGuid.upper()),
927 ExtraData=self.FdfFile)
928
929 if not FfsFile.NameGuid.upper() in _GuidDict.keys():
930 _GuidDict[FfsFile.NameGuid.upper()] = FfsFile
931 else:
932 #
933 # Two raw file GUID conflict.
934 #
935 EdkLogger.error("build",
936 FORMAT_INVALID,
937 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile.CurrentLineNum,
938 FfsFile.CurrentLineContent,
939 _GuidDict[FfsFile.NameGuid.upper()].CurrentLineNum,
940 _GuidDict[FfsFile.NameGuid.upper()].CurrentLineContent,
941 FfsFile.NameGuid.upper()),
942 ExtraData=self.FdfFile)
943
944
945 def _CheckPcdDefineAndType(self):
946 PcdTypeList = [
947 "FixedAtBuild", "PatchableInModule", "FeatureFlag",
948 "Dynamic", #"DynamicHii", "DynamicVpd",
949 "DynamicEx", # "DynamicExHii", "DynamicExVpd"
950 ]
951
952 # This dict store PCDs which are not used by any modules with specified arches
953 UnusedPcd = sdict()
954 for Pa in self.AutoGenObjectList:
955 # Key of DSC's Pcds dictionary is PcdCName, TokenSpaceGuid
956 for Pcd in Pa.Platform.Pcds:
957 PcdType = Pa.Platform.Pcds[Pcd].Type
958
959 # If no PCD type, this PCD comes from FDF
960 if not PcdType:
961 continue
962
963 # Try to remove Hii and Vpd suffix
964 if PcdType.startswith("DynamicEx"):
965 PcdType = "DynamicEx"
966 elif PcdType.startswith("Dynamic"):
967 PcdType = "Dynamic"
968
969 for Package in Pa.PackageList:
970 # Key of DEC's Pcds dictionary is PcdCName, TokenSpaceGuid, PcdType
971 if (Pcd[0], Pcd[1], PcdType) in Package.Pcds:
972 break
973 for Type in PcdTypeList:
974 if (Pcd[0], Pcd[1], Type) in Package.Pcds:
975 EdkLogger.error(
976 'build',
977 FORMAT_INVALID,
978 "Type [%s] of PCD [%s.%s] in DSC file doesn't match the type [%s] defined in DEC file." \
979 % (Pa.Platform.Pcds[Pcd].Type, Pcd[1], Pcd[0], Type),
980 ExtraData=None
981 )
982 return
983 else:
984 UnusedPcd.setdefault(Pcd, []).append(Pa.Arch)
985
986 for Pcd in UnusedPcd:
987 EdkLogger.warn(
988 'build',
989 "The PCD was not specified by any INF module in the platform for the given architecture.\n"
990 "\tPCD: [%s.%s]\n\tPlatform: [%s]\n\tArch: %s"
991 % (Pcd[1], Pcd[0], os.path.basename(str(self.MetaFile)), str(UnusedPcd[Pcd])),
992 ExtraData=None
993 )
994
995 def __repr__(self):
996 return "%s [%s]" % (self.MetaFile, ", ".join(self.ArchList))
997
998 ## Return the directory to store FV files
999 def _GetFvDir(self):
1000 if self._FvDir == None:
1001 self._FvDir = path.join(self.BuildDir, 'FV')
1002 return self._FvDir
1003
1004 ## Return the directory to store all intermediate and final files built
1005 def _GetBuildDir(self):
1006 if self._BuildDir == None:
1007 return self.AutoGenObjectList[0].BuildDir
1008
1009 ## Return the build output directory platform specifies
1010 def _GetOutputDir(self):
1011 return self.Platform.OutputDirectory
1012
1013 ## Return platform name
1014 def _GetName(self):
1015 return self.Platform.PlatformName
1016
1017 ## Return meta-file GUID
1018 def _GetGuid(self):
1019 return self.Platform.Guid
1020
1021 ## Return platform version
1022 def _GetVersion(self):
1023 return self.Platform.Version
1024
1025 ## Return paths of tools
1026 def _GetToolDefinition(self):
1027 return self.AutoGenObjectList[0].ToolDefinition
1028
1029 ## Return directory of platform makefile
1030 #
1031 # @retval string Makefile directory
1032 #
1033 def _GetMakeFileDir(self):
1034 if self._MakeFileDir == None:
1035 self._MakeFileDir = self.BuildDir
1036 return self._MakeFileDir
1037
1038 ## Return build command string
1039 #
1040 # @retval string Build command string
1041 #
1042 def _GetBuildCommand(self):
1043 if self._BuildCommand == None:
1044 # BuildCommand should be all the same. So just get one from platform AutoGen
1045 self._BuildCommand = self.AutoGenObjectList[0].BuildCommand
1046 return self._BuildCommand
1047
1048 ## Check the PCDs token value conflict in each DEC file.
1049 #
1050 # Will cause build break and raise error message while two PCDs conflict.
1051 #
1052 # @return None
1053 #
1054 def _CheckAllPcdsTokenValueConflict(self):
1055 for Pa in self.AutoGenObjectList:
1056 for Package in Pa.PackageList:
1057 PcdList = Package.Pcds.values()
1058 PcdList.sort(lambda x, y: cmp(int(x.TokenValue, 0), int(y.TokenValue, 0)))
1059 Count = 0
1060 while (Count < len(PcdList) - 1) :
1061 Item = PcdList[Count]
1062 ItemNext = PcdList[Count + 1]
1063 #
1064 # Make sure in the same token space the TokenValue should be unique
1065 #
1066 if (int(Item.TokenValue, 0) == int(ItemNext.TokenValue, 0)):
1067 SameTokenValuePcdList = []
1068 SameTokenValuePcdList.append(Item)
1069 SameTokenValuePcdList.append(ItemNext)
1070 RemainPcdListLength = len(PcdList) - Count - 2
1071 for ValueSameCount in range(RemainPcdListLength):
1072 if int(PcdList[len(PcdList) - RemainPcdListLength + ValueSameCount].TokenValue, 0) == int(Item.TokenValue, 0):
1073 SameTokenValuePcdList.append(PcdList[len(PcdList) - RemainPcdListLength + ValueSameCount])
1074 else:
1075 break;
1076 #
1077 # Sort same token value PCD list with TokenGuid and TokenCName
1078 #
1079 SameTokenValuePcdList.sort(lambda x, y: cmp("%s.%s" % (x.TokenSpaceGuidCName, x.TokenCName), "%s.%s" % (y.TokenSpaceGuidCName, y.TokenCName)))
1080 SameTokenValuePcdListCount = 0
1081 while (SameTokenValuePcdListCount < len(SameTokenValuePcdList) - 1):
1082 Flag = False
1083 TemListItem = SameTokenValuePcdList[SameTokenValuePcdListCount]
1084 TemListItemNext = SameTokenValuePcdList[SameTokenValuePcdListCount + 1]
1085
1086 if (TemListItem.TokenSpaceGuidCName == TemListItemNext.TokenSpaceGuidCName) and (TemListItem.TokenCName != TemListItemNext.TokenCName):
1087 for PcdItem in GlobalData.MixedPcd:
1088 if (TemListItem.TokenCName, TemListItem.TokenSpaceGuidCName) in GlobalData.MixedPcd[PcdItem] or \
1089 (TemListItemNext.TokenCName, TemListItemNext.TokenSpaceGuidCName) in GlobalData.MixedPcd[PcdItem]:
1090 Flag = True
1091 if not Flag:
1092 EdkLogger.error(
1093 'build',
1094 FORMAT_INVALID,
1095 "The TokenValue [%s] of PCD [%s.%s] is conflict with: [%s.%s] in %s"\
1096 % (TemListItem.TokenValue, TemListItem.TokenSpaceGuidCName, TemListItem.TokenCName, TemListItemNext.TokenSpaceGuidCName, TemListItemNext.TokenCName, Package),
1097 ExtraData=None
1098 )
1099 SameTokenValuePcdListCount += 1
1100 Count += SameTokenValuePcdListCount
1101 Count += 1
1102
1103 PcdList = Package.Pcds.values()
1104 PcdList.sort(lambda x, y: cmp("%s.%s" % (x.TokenSpaceGuidCName, x.TokenCName), "%s.%s" % (y.TokenSpaceGuidCName, y.TokenCName)))
1105 Count = 0
1106 while (Count < len(PcdList) - 1) :
1107 Item = PcdList[Count]
1108 ItemNext = PcdList[Count + 1]
1109 #
1110 # Check PCDs with same TokenSpaceGuidCName.TokenCName have same token value as well.
1111 #
1112 if (Item.TokenSpaceGuidCName == ItemNext.TokenSpaceGuidCName) and (Item.TokenCName == ItemNext.TokenCName) and (int(Item.TokenValue, 0) != int(ItemNext.TokenValue, 0)):
1113 EdkLogger.error(
1114 'build',
1115 FORMAT_INVALID,
1116 "The TokenValue [%s] of PCD [%s.%s] in %s defined in two places should be same as well."\
1117 % (Item.TokenValue, Item.TokenSpaceGuidCName, Item.TokenCName, Package),
1118 ExtraData=None
1119 )
1120 Count += 1
1121 ## Generate fds command
1122 def _GenFdsCommand(self):
1123 return (GenMake.TopLevelMakefile(self)._TEMPLATE_.Replace(GenMake.TopLevelMakefile(self)._TemplateDict)).strip()
1124
1125 ## Create makefile for the platform and modules in it
1126 #
1127 # @param CreateDepsMakeFile Flag indicating if the makefile for
1128 # modules will be created as well
1129 #
1130 def CreateMakeFile(self, CreateDepsMakeFile=False):
1131 if CreateDepsMakeFile:
1132 for Pa in self.AutoGenObjectList:
1133 Pa.CreateMakeFile(CreateDepsMakeFile)
1134
1135 ## Create autogen code for platform and modules
1136 #
1137 # Since there's no autogen code for platform, this method will do nothing
1138 # if CreateModuleCodeFile is set to False.
1139 #
1140 # @param CreateDepsCodeFile Flag indicating if creating module's
1141 # autogen code file or not
1142 #
1143 def CreateCodeFile(self, CreateDepsCodeFile=False):
1144 if not CreateDepsCodeFile:
1145 return
1146 for Pa in self.AutoGenObjectList:
1147 Pa.CreateCodeFile(CreateDepsCodeFile)
1148
1149 ## Create AsBuilt INF file the platform
1150 #
1151 def CreateAsBuiltInf(self):
1152 return
1153
1154 Name = property(_GetName)
1155 Guid = property(_GetGuid)
1156 Version = property(_GetVersion)
1157 OutputDir = property(_GetOutputDir)
1158
1159 ToolDefinition = property(_GetToolDefinition) # toolcode : tool path
1160
1161 BuildDir = property(_GetBuildDir)
1162 FvDir = property(_GetFvDir)
1163 MakeFileDir = property(_GetMakeFileDir)
1164 BuildCommand = property(_GetBuildCommand)
1165 GenFdsCommand = property(_GenFdsCommand)
1166
1167 ## AutoGen class for platform
1168 #
1169 # PlatformAutoGen class will process the original information in platform
1170 # file in order to generate makefile for platform.
1171 #
1172 class PlatformAutoGen(AutoGen):
1173 #
1174 # Used to store all PCDs for both PEI and DXE phase, in order to generate
1175 # correct PCD database
1176 #
1177 _DynaPcdList_ = []
1178 _NonDynaPcdList_ = []
1179 _PlatformPcds = {}
1180
1181 #
1182 # The priority list while override build option
1183 #
1184 PrioList = {"0x11111" : 16, # TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE (Highest)
1185 "0x01111" : 15, # ******_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
1186 "0x10111" : 14, # TARGET_*********_ARCH_COMMANDTYPE_ATTRIBUTE
1187 "0x00111" : 13, # ******_*********_ARCH_COMMANDTYPE_ATTRIBUTE
1188 "0x11011" : 12, # TARGET_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
1189 "0x01011" : 11, # ******_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
1190 "0x10011" : 10, # TARGET_*********_****_COMMANDTYPE_ATTRIBUTE
1191 "0x00011" : 9, # ******_*********_****_COMMANDTYPE_ATTRIBUTE
1192 "0x11101" : 8, # TARGET_TOOLCHAIN_ARCH_***********_ATTRIBUTE
1193 "0x01101" : 7, # ******_TOOLCHAIN_ARCH_***********_ATTRIBUTE
1194 "0x10101" : 6, # TARGET_*********_ARCH_***********_ATTRIBUTE
1195 "0x00101" : 5, # ******_*********_ARCH_***********_ATTRIBUTE
1196 "0x11001" : 4, # TARGET_TOOLCHAIN_****_***********_ATTRIBUTE
1197 "0x01001" : 3, # ******_TOOLCHAIN_****_***********_ATTRIBUTE
1198 "0x10001" : 2, # TARGET_*********_****_***********_ATTRIBUTE
1199 "0x00001" : 1} # ******_*********_****_***********_ATTRIBUTE (Lowest)
1200
1201 ## The real constructor of PlatformAutoGen
1202 #
1203 # This method is not supposed to be called by users of PlatformAutoGen. It's
1204 # only used by factory method __new__() to do real initialization work for an
1205 # object of PlatformAutoGen
1206 #
1207 # @param Workspace WorkspaceAutoGen object
1208 # @param PlatformFile Platform file (DSC file)
1209 # @param Target Build target (DEBUG, RELEASE)
1210 # @param Toolchain Name of tool chain
1211 # @param Arch arch of the platform supports
1212 #
1213 def _Init(self, Workspace, PlatformFile, Target, Toolchain, Arch):
1214 EdkLogger.debug(EdkLogger.DEBUG_9, "AutoGen platform [%s] [%s]" % (PlatformFile, Arch))
1215 GlobalData.gProcessingFile = "%s [%s, %s, %s]" % (PlatformFile, Arch, Toolchain, Target)
1216
1217 self.MetaFile = PlatformFile
1218 self.Workspace = Workspace
1219 self.WorkspaceDir = Workspace.WorkspaceDir
1220 self.ToolChain = Toolchain
1221 self.BuildTarget = Target
1222 self.Arch = Arch
1223 self.SourceDir = PlatformFile.SubDir
1224 self.SourceOverrideDir = None
1225 self.FdTargetList = self.Workspace.FdTargetList
1226 self.FvTargetList = self.Workspace.FvTargetList
1227 self.AllPcdList = []
1228 # get the original module/package/platform objects
1229 self.BuildDatabase = Workspace.BuildDatabase
1230
1231 # flag indicating if the makefile/C-code file has been created or not
1232 self.IsMakeFileCreated = False
1233 self.IsCodeFileCreated = False
1234
1235 self._Platform = None
1236 self._Name = None
1237 self._Guid = None
1238 self._Version = None
1239
1240 self._BuildRule = None
1241 self._SourceDir = None
1242 self._BuildDir = None
1243 self._OutputDir = None
1244 self._FvDir = None
1245 self._MakeFileDir = None
1246 self._FdfFile = None
1247
1248 self._PcdTokenNumber = None # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber
1249 self._DynamicPcdList = None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
1250 self._NonDynamicPcdList = None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
1251 self._NonDynamicPcdDict = {}
1252
1253 self._ToolDefinitions = None
1254 self._ToolDefFile = None # toolcode : tool path
1255 self._ToolChainFamily = None
1256 self._BuildRuleFamily = None
1257 self._BuildOption = None # toolcode : option
1258 self._EdkBuildOption = None # edktoolcode : option
1259 self._EdkIIBuildOption = None # edkiitoolcode : option
1260 self._PackageList = None
1261 self._ModuleAutoGenList = None
1262 self._LibraryAutoGenList = None
1263 self._BuildCommand = None
1264 self._AsBuildInfList = []
1265 self._AsBuildModuleList = []
1266 if GlobalData.gFdfParser != None:
1267 self._AsBuildInfList = GlobalData.gFdfParser.Profile.InfList
1268 for Inf in self._AsBuildInfList:
1269 InfClass = PathClass(NormPath(Inf), GlobalData.gWorkspace, self.Arch)
1270 M = self.BuildDatabase[InfClass, self.Arch, self.BuildTarget, self.ToolChain]
1271 if not M.IsSupportedArch:
1272 continue
1273 self._AsBuildModuleList.append(InfClass)
1274 # get library/modules for build
1275 self.LibraryBuildDirectoryList = []
1276 self.ModuleBuildDirectoryList = []
1277 return True
1278
1279 def __repr__(self):
1280 return "%s [%s]" % (self.MetaFile, self.Arch)
1281
1282 ## Create autogen code for platform and modules
1283 #
1284 # Since there's no autogen code for platform, this method will do nothing
1285 # if CreateModuleCodeFile is set to False.
1286 #
1287 # @param CreateModuleCodeFile Flag indicating if creating module's
1288 # autogen code file or not
1289 #
1290 def CreateCodeFile(self, CreateModuleCodeFile=False):
1291 # only module has code to be greated, so do nothing if CreateModuleCodeFile is False
1292 if self.IsCodeFileCreated or not CreateModuleCodeFile:
1293 return
1294
1295 for Ma in self.ModuleAutoGenList:
1296 Ma.CreateCodeFile(True)
1297
1298 # don't do this twice
1299 self.IsCodeFileCreated = True
1300
1301 ## Generate Fds Command
1302 def _GenFdsCommand(self):
1303 return self.Workspace.GenFdsCommand
1304
1305 ## Create makefile for the platform and mdoules in it
1306 #
1307 # @param CreateModuleMakeFile Flag indicating if the makefile for
1308 # modules will be created as well
1309 #
1310 def CreateMakeFile(self, CreateModuleMakeFile=False):
1311 if CreateModuleMakeFile:
1312 for ModuleFile in self.Platform.Modules:
1313 Ma = ModuleAutoGen(self.Workspace, ModuleFile, self.BuildTarget,
1314 self.ToolChain, self.Arch, self.MetaFile)
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 if (self.Workspace.ArchList[-1] == self.Arch):
1561 for Pcd in self._DynamicPcdList:
1562 # just pick the a value to determine whether is unicode string type
1563 Sku = Pcd.SkuInfoList[Pcd.SkuInfoList.keys()[0]]
1564 Sku.VpdOffset = Sku.VpdOffset.strip()
1565
1566 PcdValue = Sku.DefaultValue
1567 if Pcd.DatumType == 'VOID*' and PcdValue.startswith("L"):
1568 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
1569 UnicodePcdArray.append(Pcd)
1570 elif len(Sku.VariableName) > 0:
1571 # if found HII type PCD then insert to right of UnicodeIndex
1572 HiiPcdArray.append(Pcd)
1573 else:
1574 OtherPcdArray.append(Pcd)
1575 if Pcd.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD]:
1576 VpdPcdDict[(Pcd.TokenCName, Pcd.TokenSpaceGuidCName)] = Pcd
1577
1578 PlatformPcds = self._PlatformPcds.keys()
1579 PlatformPcds.sort()
1580 #
1581 # Add VPD type PCD into VpdFile and determine whether the VPD PCD need to be fixed up.
1582 #
1583 for PcdKey in PlatformPcds:
1584 Pcd = self._PlatformPcds[PcdKey]
1585 if Pcd.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD] and \
1586 PcdKey in VpdPcdDict:
1587 Pcd = VpdPcdDict[PcdKey]
1588 for (SkuName,Sku) in Pcd.SkuInfoList.items():
1589 Sku.VpdOffset = Sku.VpdOffset.strip()
1590 PcdValue = Sku.DefaultValue
1591 if PcdValue == "":
1592 PcdValue = Pcd.DefaultValue
1593 if Sku.VpdOffset != '*':
1594 if PcdValue.startswith("{"):
1595 Alignment = 8
1596 elif PcdValue.startswith("L"):
1597 Alignment = 2
1598 else:
1599 Alignment = 1
1600 try:
1601 VpdOffset = int(Sku.VpdOffset)
1602 except:
1603 try:
1604 VpdOffset = int(Sku.VpdOffset, 16)
1605 except:
1606 EdkLogger.error("build", FORMAT_INVALID, "Invalid offset value %s for PCD %s.%s." % (Sku.VpdOffset, Pcd.TokenSpaceGuidCName, Pcd.TokenCName))
1607 if VpdOffset % Alignment != 0:
1608 if PcdValue.startswith("{"):
1609 EdkLogger.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(Pcd.TokenSpaceGuidCName, Pcd.TokenCName), File=self.MetaFile)
1610 else:
1611 EdkLogger.error("build", FORMAT_INVALID, 'The offset value of PCD %s.%s should be %s-byte aligned.' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName, Alignment))
1612 VpdFile.Add(Pcd, Sku.VpdOffset)
1613 # if the offset of a VPD is *, then it need to be fixed up by third party tool.
1614 if not NeedProcessVpdMapFile and Sku.VpdOffset == "*":
1615 NeedProcessVpdMapFile = True
1616 if self.Platform.VpdToolGuid == None or self.Platform.VpdToolGuid == '':
1617 EdkLogger.error("Build", FILE_NOT_FOUND, \
1618 "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.")
1619
1620
1621 #
1622 # Fix the PCDs define in VPD PCD section that never referenced by module.
1623 # An example is PCD for signature usage.
1624 #
1625 for DscPcd in PlatformPcds:
1626 DscPcdEntry = self._PlatformPcds[DscPcd]
1627 if DscPcdEntry.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD]:
1628 if not (self.Platform.VpdToolGuid == None or self.Platform.VpdToolGuid == ''):
1629 FoundFlag = False
1630 for VpdPcd in VpdFile._VpdArray.keys():
1631 # This PCD has been referenced by module
1632 if (VpdPcd.TokenSpaceGuidCName == DscPcdEntry.TokenSpaceGuidCName) and \
1633 (VpdPcd.TokenCName == DscPcdEntry.TokenCName):
1634 FoundFlag = True
1635
1636 # Not found, it should be signature
1637 if not FoundFlag :
1638 # just pick the a value to determine whether is unicode string type
1639 for (SkuName,Sku) in DscPcdEntry.SkuInfoList.items():
1640 Sku.VpdOffset = Sku.VpdOffset.strip()
1641
1642 # Need to iterate DEC pcd information to get the value & datumtype
1643 for eachDec in self.PackageList:
1644 for DecPcd in eachDec.Pcds:
1645 DecPcdEntry = eachDec.Pcds[DecPcd]
1646 if (DecPcdEntry.TokenSpaceGuidCName == DscPcdEntry.TokenSpaceGuidCName) and \
1647 (DecPcdEntry.TokenCName == DscPcdEntry.TokenCName):
1648 # Print warning message to let the developer make a determine.
1649 EdkLogger.warn("build", "Unreferenced vpd pcd used!",
1650 File=self.MetaFile, \
1651 ExtraData = "PCD: %s.%s used in the DSC file %s is unreferenced." \
1652 %(DscPcdEntry.TokenSpaceGuidCName, DscPcdEntry.TokenCName, self.Platform.MetaFile.Path))
1653
1654 DscPcdEntry.DatumType = DecPcdEntry.DatumType
1655 DscPcdEntry.DefaultValue = DecPcdEntry.DefaultValue
1656 DscPcdEntry.TokenValue = DecPcdEntry.TokenValue
1657 DscPcdEntry.TokenSpaceGuidValue = eachDec.Guids[DecPcdEntry.TokenSpaceGuidCName]
1658 # Only fix the value while no value provided in DSC file.
1659 if (Sku.DefaultValue == "" or Sku.DefaultValue==None):
1660 DscPcdEntry.SkuInfoList[DscPcdEntry.SkuInfoList.keys()[0]].DefaultValue = DecPcdEntry.DefaultValue
1661
1662 if DscPcdEntry not in self._DynamicPcdList:
1663 self._DynamicPcdList.append(DscPcdEntry)
1664 # Sku = DscPcdEntry.SkuInfoList[DscPcdEntry.SkuInfoList.keys()[0]]
1665 Sku.VpdOffset = Sku.VpdOffset.strip()
1666 PcdValue = Sku.DefaultValue
1667 if PcdValue == "":
1668 PcdValue = DscPcdEntry.DefaultValue
1669 if Sku.VpdOffset != '*':
1670 if PcdValue.startswith("{"):
1671 Alignment = 8
1672 elif PcdValue.startswith("L"):
1673 Alignment = 2
1674 else:
1675 Alignment = 1
1676 try:
1677 VpdOffset = int(Sku.VpdOffset)
1678 except:
1679 try:
1680 VpdOffset = int(Sku.VpdOffset, 16)
1681 except:
1682 EdkLogger.error("build", FORMAT_INVALID, "Invalid offset value %s for PCD %s.%s." % (Sku.VpdOffset, DscPcdEntry.TokenSpaceGuidCName, DscPcdEntry.TokenCName))
1683 if VpdOffset % Alignment != 0:
1684 if PcdValue.startswith("{"):
1685 EdkLogger.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(DscPcdEntry.TokenSpaceGuidCName, DscPcdEntry.TokenCName), File=self.MetaFile)
1686 else:
1687 EdkLogger.error("build", FORMAT_INVALID, 'The offset value of PCD %s.%s should be %s-byte aligned.' % (DscPcdEntry.TokenSpaceGuidCName, DscPcdEntry.TokenCName, Alignment))
1688 VpdFile.Add(DscPcdEntry, Sku.VpdOffset)
1689 if not NeedProcessVpdMapFile and Sku.VpdOffset == "*":
1690 NeedProcessVpdMapFile = True
1691 if DscPcdEntry.DatumType == 'VOID*' and PcdValue.startswith("L"):
1692 UnicodePcdArray.append(DscPcdEntry)
1693 elif len(Sku.VariableName) > 0:
1694 HiiPcdArray.append(DscPcdEntry)
1695 else:
1696 OtherPcdArray.append(DscPcdEntry)
1697
1698 # if the offset of a VPD is *, then it need to be fixed up by third party tool.
1699
1700
1701
1702 if (self.Platform.FlashDefinition == None or self.Platform.FlashDefinition == '') and \
1703 VpdFile.GetCount() != 0:
1704 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE,
1705 "Fail to get FLASH_DEFINITION definition in DSC file %s which is required when DSC contains VPD PCD." % str(self.Platform.MetaFile))
1706
1707 if VpdFile.GetCount() != 0:
1708 FvPath = os.path.join(self.BuildDir, "FV")
1709 if not os.path.exists(FvPath):
1710 try:
1711 os.makedirs(FvPath)
1712 except:
1713 EdkLogger.error("build", FILE_WRITE_FAILURE, "Fail to create FV folder under %s" % self.BuildDir)
1714
1715 VpdFilePath = os.path.join(FvPath, "%s.txt" % self.Platform.VpdToolGuid)
1716
1717 if VpdFile.Write(VpdFilePath):
1718 # retrieve BPDG tool's path from tool_def.txt according to VPD_TOOL_GUID defined in DSC file.
1719 BPDGToolName = None
1720 for ToolDef in self.ToolDefinition.values():
1721 if ToolDef.has_key("GUID") and ToolDef["GUID"] == self.Platform.VpdToolGuid:
1722 if not ToolDef.has_key("PATH"):
1723 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE, "PATH attribute was not provided for BPDG guid tool %s in tools_def.txt" % self.Platform.VpdToolGuid)
1724 BPDGToolName = ToolDef["PATH"]
1725 break
1726 # Call third party GUID BPDG tool.
1727 if BPDGToolName != None:
1728 VpdInfoFile.CallExtenalBPDGTool(BPDGToolName, VpdFilePath)
1729 else:
1730 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.")
1731
1732 # Process VPD map file generated by third party BPDG tool
1733 if NeedProcessVpdMapFile:
1734 VpdMapFilePath = os.path.join(self.BuildDir, "FV", "%s.map" % self.Platform.VpdToolGuid)
1735 if os.path.exists(VpdMapFilePath):
1736 VpdFile.Read(VpdMapFilePath)
1737
1738 # Fixup "*" offset
1739 for Pcd in self._DynamicPcdList:
1740 # just pick the a value to determine whether is unicode string type
1741 i = 0
1742 for (SkuName,Sku) in Pcd.SkuInfoList.items():
1743 if Sku.VpdOffset == "*":
1744 Sku.VpdOffset = VpdFile.GetOffset(Pcd)[i].strip()
1745 i += 1
1746 else:
1747 EdkLogger.error("build", FILE_READ_FAILURE, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath)
1748
1749 # Delete the DynamicPcdList At the last time enter into this function
1750 del self._DynamicPcdList[:]
1751 self._DynamicPcdList.extend(UnicodePcdArray)
1752 self._DynamicPcdList.extend(HiiPcdArray)
1753 self._DynamicPcdList.extend(OtherPcdArray)
1754 self.AllPcdList = self._NonDynamicPcdList + self._DynamicPcdList
1755
1756 ## Return the platform build data object
1757 def _GetPlatform(self):
1758 if self._Platform == None:
1759 self._Platform = self.BuildDatabase[self.MetaFile, self.Arch, self.BuildTarget, self.ToolChain]
1760 return self._Platform
1761
1762 ## Return platform name
1763 def _GetName(self):
1764 return self.Platform.PlatformName
1765
1766 ## Return the meta file GUID
1767 def _GetGuid(self):
1768 return self.Platform.Guid
1769
1770 ## Return the platform version
1771 def _GetVersion(self):
1772 return self.Platform.Version
1773
1774 ## Return the FDF file name
1775 def _GetFdfFile(self):
1776 if self._FdfFile == None:
1777 if self.Workspace.FdfFile != "":
1778 self._FdfFile= mws.join(self.WorkspaceDir, self.Workspace.FdfFile)
1779 else:
1780 self._FdfFile = ''
1781 return self._FdfFile
1782
1783 ## Return the build output directory platform specifies
1784 def _GetOutputDir(self):
1785 return self.Platform.OutputDirectory
1786
1787 ## Return the directory to store all intermediate and final files built
1788 def _GetBuildDir(self):
1789 if self._BuildDir == None:
1790 if os.path.isabs(self.OutputDir):
1791 self._BuildDir = path.join(
1792 path.abspath(self.OutputDir),
1793 self.BuildTarget + "_" + self.ToolChain,
1794 )
1795 else:
1796 self._BuildDir = path.join(
1797 self.WorkspaceDir,
1798 self.OutputDir,
1799 self.BuildTarget + "_" + self.ToolChain,
1800 )
1801 return self._BuildDir
1802
1803 ## Return directory of platform makefile
1804 #
1805 # @retval string Makefile directory
1806 #
1807 def _GetMakeFileDir(self):
1808 if self._MakeFileDir == None:
1809 self._MakeFileDir = path.join(self.BuildDir, self.Arch)
1810 return self._MakeFileDir
1811
1812 ## Return build command string
1813 #
1814 # @retval string Build command string
1815 #
1816 def _GetBuildCommand(self):
1817 if self._BuildCommand == None:
1818 self._BuildCommand = []
1819 if "MAKE" in self.ToolDefinition and "PATH" in self.ToolDefinition["MAKE"]:
1820 self._BuildCommand += SplitOption(self.ToolDefinition["MAKE"]["PATH"])
1821 if "FLAGS" in self.ToolDefinition["MAKE"]:
1822 NewOption = self.ToolDefinition["MAKE"]["FLAGS"].strip()
1823 if NewOption != '':
1824 self._BuildCommand += SplitOption(NewOption)
1825 return self._BuildCommand
1826
1827 ## Get tool chain definition
1828 #
1829 # Get each tool defition for given tool chain from tools_def.txt and platform
1830 #
1831 def _GetToolDefinition(self):
1832 if self._ToolDefinitions == None:
1833 ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDictionary
1834 if TAB_TOD_DEFINES_COMMAND_TYPE not in self.Workspace.ToolDef.ToolsDefTxtDatabase:
1835 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "No tools found in configuration",
1836 ExtraData="[%s]" % self.MetaFile)
1837 self._ToolDefinitions = {}
1838 DllPathList = set()
1839 for Def in ToolDefinition:
1840 Target, Tag, Arch, Tool, Attr = Def.split("_")
1841 if Target != self.BuildTarget or Tag != self.ToolChain or Arch != self.Arch:
1842 continue
1843
1844 Value = ToolDefinition[Def]
1845 # don't record the DLL
1846 if Attr == "DLL":
1847 DllPathList.add(Value)
1848 continue
1849
1850 if Tool not in self._ToolDefinitions:
1851 self._ToolDefinitions[Tool] = {}
1852 self._ToolDefinitions[Tool][Attr] = Value
1853
1854 ToolsDef = ''
1855 MakePath = ''
1856 if GlobalData.gOptions.SilentMode and "MAKE" in self._ToolDefinitions:
1857 if "FLAGS" not in self._ToolDefinitions["MAKE"]:
1858 self._ToolDefinitions["MAKE"]["FLAGS"] = ""
1859 self._ToolDefinitions["MAKE"]["FLAGS"] += " -s"
1860 MakeFlags = ''
1861 for Tool in self._ToolDefinitions:
1862 for Attr in self._ToolDefinitions[Tool]:
1863 Value = self._ToolDefinitions[Tool][Attr]
1864 if Tool in self.BuildOption and Attr in self.BuildOption[Tool]:
1865 # check if override is indicated
1866 if self.BuildOption[Tool][Attr].startswith('='):
1867 Value = self.BuildOption[Tool][Attr][1:]
1868 else:
1869 if Attr != 'PATH':
1870 Value += " " + self.BuildOption[Tool][Attr]
1871 else:
1872 Value = self.BuildOption[Tool][Attr]
1873
1874 if Attr == "PATH":
1875 # Don't put MAKE definition in the file
1876 if Tool == "MAKE":
1877 MakePath = Value
1878 else:
1879 ToolsDef += "%s = %s\n" % (Tool, Value)
1880 elif Attr != "DLL":
1881 # Don't put MAKE definition in the file
1882 if Tool == "MAKE":
1883 if Attr == "FLAGS":
1884 MakeFlags = Value
1885 else:
1886 ToolsDef += "%s_%s = %s\n" % (Tool, Attr, Value)
1887 ToolsDef += "\n"
1888
1889 SaveFileOnChange(self.ToolDefinitionFile, ToolsDef)
1890 for DllPath in DllPathList:
1891 os.environ["PATH"] = DllPath + os.pathsep + os.environ["PATH"]
1892 os.environ["MAKE_FLAGS"] = MakeFlags
1893
1894 return self._ToolDefinitions
1895
1896 ## Return the paths of tools
1897 def _GetToolDefFile(self):
1898 if self._ToolDefFile == None:
1899 self._ToolDefFile = os.path.join(self.MakeFileDir, "TOOLS_DEF." + self.Arch)
1900 return self._ToolDefFile
1901
1902 ## Retrieve the toolchain family of given toolchain tag. Default to 'MSFT'.
1903 def _GetToolChainFamily(self):
1904 if self._ToolChainFamily == None:
1905 ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDatabase
1906 if TAB_TOD_DEFINES_FAMILY not in ToolDefinition \
1907 or self.ToolChain not in ToolDefinition[TAB_TOD_DEFINES_FAMILY] \
1908 or not ToolDefinition[TAB_TOD_DEFINES_FAMILY][self.ToolChain]:
1909 EdkLogger.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
1910 % self.ToolChain)
1911 self._ToolChainFamily = "MSFT"
1912 else:
1913 self._ToolChainFamily = ToolDefinition[TAB_TOD_DEFINES_FAMILY][self.ToolChain]
1914 return self._ToolChainFamily
1915
1916 def _GetBuildRuleFamily(self):
1917 if self._BuildRuleFamily == None:
1918 ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDatabase
1919 if TAB_TOD_DEFINES_BUILDRULEFAMILY not in ToolDefinition \
1920 or self.ToolChain not in ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY] \
1921 or not ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY][self.ToolChain]:
1922 EdkLogger.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
1923 % self.ToolChain)
1924 self._BuildRuleFamily = "MSFT"
1925 else:
1926 self._BuildRuleFamily = ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY][self.ToolChain]
1927 return self._BuildRuleFamily
1928
1929 ## Return the build options specific for all modules in this platform
1930 def _GetBuildOptions(self):
1931 if self._BuildOption == None:
1932 self._BuildOption = self._ExpandBuildOption(self.Platform.BuildOptions)
1933 return self._BuildOption
1934
1935 ## Return the build options specific for EDK modules in this platform
1936 def _GetEdkBuildOptions(self):
1937 if self._EdkBuildOption == None:
1938 self._EdkBuildOption = self._ExpandBuildOption(self.Platform.BuildOptions, EDK_NAME)
1939 return self._EdkBuildOption
1940
1941 ## Return the build options specific for EDKII modules in this platform
1942 def _GetEdkIIBuildOptions(self):
1943 if self._EdkIIBuildOption == None:
1944 self._EdkIIBuildOption = self._ExpandBuildOption(self.Platform.BuildOptions, EDKII_NAME)
1945 return self._EdkIIBuildOption
1946
1947 ## Parse build_rule.txt in Conf Directory.
1948 #
1949 # @retval BuildRule object
1950 #
1951 def _GetBuildRule(self):
1952 if self._BuildRule == None:
1953 BuildRuleFile = None
1954 if TAB_TAT_DEFINES_BUILD_RULE_CONF in self.Workspace.TargetTxt.TargetTxtDictionary:
1955 BuildRuleFile = self.Workspace.TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_BUILD_RULE_CONF]
1956 if BuildRuleFile in [None, '']:
1957 BuildRuleFile = gDefaultBuildRuleFile
1958 self._BuildRule = BuildRule(BuildRuleFile)
1959 if self._BuildRule._FileVersion == "":
1960 self._BuildRule._FileVersion = AutoGenReqBuildRuleVerNum
1961 else:
1962 if self._BuildRule._FileVersion < AutoGenReqBuildRuleVerNum :
1963 # If Build Rule's version is less than the version number required by the tools, halting the build.
1964 EdkLogger.error("build", AUTOGEN_ERROR,
1965 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])"\
1966 % (self._BuildRule._FileVersion, AutoGenReqBuildRuleVerNum))
1967
1968 return self._BuildRule
1969
1970 ## Summarize the packages used by modules in this platform
1971 def _GetPackageList(self):
1972 if self._PackageList == None:
1973 self._PackageList = set()
1974 for La in self.LibraryAutoGenList:
1975 self._PackageList.update(La.DependentPackageList)
1976 for Ma in self.ModuleAutoGenList:
1977 self._PackageList.update(Ma.DependentPackageList)
1978 #Collect package set information from INF of FDF
1979 PkgSet = set()
1980 for ModuleFile in self._AsBuildModuleList:
1981 if ModuleFile in self.Platform.Modules:
1982 continue
1983 ModuleData = self.BuildDatabase[ModuleFile, self.Arch, self.BuildTarget, self.ToolChain]
1984 PkgSet.update(ModuleData.Packages)
1985 self._PackageList = list(self._PackageList) + list (PkgSet)
1986 return self._PackageList
1987
1988 def _GetNonDynamicPcdDict(self):
1989 if self._NonDynamicPcdDict:
1990 return self._NonDynamicPcdDict
1991 for Pcd in self.NonDynamicPcdList:
1992 self._NonDynamicPcdDict[(Pcd.TokenCName,Pcd.TokenSpaceGuidCName)] = Pcd
1993 return self._NonDynamicPcdDict
1994
1995 ## Get list of non-dynamic PCDs
1996 def _GetNonDynamicPcdList(self):
1997 if self._NonDynamicPcdList == None:
1998 self.CollectPlatformDynamicPcds()
1999 return self._NonDynamicPcdList
2000
2001 ## Get list of dynamic PCDs
2002 def _GetDynamicPcdList(self):
2003 if self._DynamicPcdList == None:
2004 self.CollectPlatformDynamicPcds()
2005 return self._DynamicPcdList
2006
2007 ## Generate Token Number for all PCD
2008 def _GetPcdTokenNumbers(self):
2009 if self._PcdTokenNumber == None:
2010 self._PcdTokenNumber = sdict()
2011 TokenNumber = 1
2012 #
2013 # Make the Dynamic and DynamicEx PCD use within different TokenNumber area.
2014 # Such as:
2015 #
2016 # Dynamic PCD:
2017 # TokenNumber 0 ~ 10
2018 # DynamicEx PCD:
2019 # TokeNumber 11 ~ 20
2020 #
2021 for Pcd in self.DynamicPcdList:
2022 if Pcd.Phase == "PEI":
2023 if Pcd.Type in ["Dynamic", "DynamicDefault", "DynamicVpd", "DynamicHii"]:
2024 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))
2025 self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
2026 TokenNumber += 1
2027
2028 for Pcd in self.DynamicPcdList:
2029 if Pcd.Phase == "PEI":
2030 if Pcd.Type in ["DynamicEx", "DynamicExDefault", "DynamicExVpd", "DynamicExHii"]:
2031 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))
2032 self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
2033 TokenNumber += 1
2034
2035 for Pcd in self.DynamicPcdList:
2036 if Pcd.Phase == "DXE":
2037 if Pcd.Type in ["Dynamic", "DynamicDefault", "DynamicVpd", "DynamicHii"]:
2038 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))
2039 self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
2040 TokenNumber += 1
2041
2042 for Pcd in self.DynamicPcdList:
2043 if Pcd.Phase == "DXE":
2044 if Pcd.Type in ["DynamicEx", "DynamicExDefault", "DynamicExVpd", "DynamicExHii"]:
2045 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))
2046 self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
2047 TokenNumber += 1
2048
2049 for Pcd in self.NonDynamicPcdList:
2050 self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
2051 TokenNumber += 1
2052 return self._PcdTokenNumber
2053
2054 ## Summarize ModuleAutoGen objects of all modules/libraries to be built for this platform
2055 def _GetAutoGenObjectList(self):
2056 self._ModuleAutoGenList = []
2057 self._LibraryAutoGenList = []
2058 for ModuleFile in self.Platform.Modules:
2059 Ma = ModuleAutoGen(
2060 self.Workspace,
2061 ModuleFile,
2062 self.BuildTarget,
2063 self.ToolChain,
2064 self.Arch,
2065 self.MetaFile
2066 )
2067 if Ma not in self._ModuleAutoGenList:
2068 self._ModuleAutoGenList.append(Ma)
2069 for La in Ma.LibraryAutoGenList:
2070 if La not in self._LibraryAutoGenList:
2071 self._LibraryAutoGenList.append(La)
2072 if Ma not in La._ReferenceModules:
2073 La._ReferenceModules.append(Ma)
2074
2075 ## Summarize ModuleAutoGen objects of all modules to be built for this platform
2076 def _GetModuleAutoGenList(self):
2077 if self._ModuleAutoGenList == None:
2078 self._GetAutoGenObjectList()
2079 return self._ModuleAutoGenList
2080
2081 ## Summarize ModuleAutoGen objects of all libraries to be built for this platform
2082 def _GetLibraryAutoGenList(self):
2083 if self._LibraryAutoGenList == None:
2084 self._GetAutoGenObjectList()
2085 return self._LibraryAutoGenList
2086
2087 ## Test if a module is supported by the platform
2088 #
2089 # An error will be raised directly if the module or its arch is not supported
2090 # by the platform or current configuration
2091 #
2092 def ValidModule(self, Module):
2093 return Module in self.Platform.Modules or Module in self.Platform.LibraryInstances \
2094 or Module in self._AsBuildModuleList
2095
2096 ## Resolve the library classes in a module to library instances
2097 #
2098 # This method will not only resolve library classes but also sort the library
2099 # instances according to the dependency-ship.
2100 #
2101 # @param Module The module from which the library classes will be resolved
2102 #
2103 # @retval library_list List of library instances sorted
2104 #
2105 def ApplyLibraryInstance(self, Module):
2106 # Cover the case that the binary INF file is list in the FDF file but not DSC file, return empty list directly
2107 if str(Module) not in self.Platform.Modules:
2108 return []
2109
2110 ModuleType = Module.ModuleType
2111
2112 # for overridding library instances with module specific setting
2113 PlatformModule = self.Platform.Modules[str(Module)]
2114
2115 # add forced library instances (specified under LibraryClasses sections)
2116 #
2117 # If a module has a MODULE_TYPE of USER_DEFINED,
2118 # do not link in NULL library class instances from the global [LibraryClasses.*] sections.
2119 #
2120 if Module.ModuleType != SUP_MODULE_USER_DEFINED:
2121 for LibraryClass in self.Platform.LibraryClasses.GetKeys():
2122 if LibraryClass.startswith("NULL") and self.Platform.LibraryClasses[LibraryClass, Module.ModuleType]:
2123 Module.LibraryClasses[LibraryClass] = self.Platform.LibraryClasses[LibraryClass, Module.ModuleType]
2124
2125 # add forced library instances (specified in module overrides)
2126 for LibraryClass in PlatformModule.LibraryClasses:
2127 if LibraryClass.startswith("NULL"):
2128 Module.LibraryClasses[LibraryClass] = PlatformModule.LibraryClasses[LibraryClass]
2129
2130 # EdkII module
2131 LibraryConsumerList = [Module]
2132 Constructor = []
2133 ConsumedByList = sdict()
2134 LibraryInstance = sdict()
2135
2136 EdkLogger.verbose("")
2137 EdkLogger.verbose("Library instances of module [%s] [%s]:" % (str(Module), self.Arch))
2138 while len(LibraryConsumerList) > 0:
2139 M = LibraryConsumerList.pop()
2140 for LibraryClassName in M.LibraryClasses:
2141 if LibraryClassName not in LibraryInstance:
2142 # override library instance for this module
2143 if LibraryClassName in PlatformModule.LibraryClasses:
2144 LibraryPath = PlatformModule.LibraryClasses[LibraryClassName]
2145 else:
2146 LibraryPath = self.Platform.LibraryClasses[LibraryClassName, ModuleType]
2147 if LibraryPath == None or LibraryPath == "":
2148 LibraryPath = M.LibraryClasses[LibraryClassName]
2149 if LibraryPath == None or LibraryPath == "":
2150 EdkLogger.error("build", RESOURCE_NOT_AVAILABLE,
2151 "Instance of library class [%s] is not found" % LibraryClassName,
2152 File=self.MetaFile,
2153 ExtraData="in [%s] [%s]\n\tconsumed by module [%s]" % (str(M), self.Arch, str(Module)))
2154
2155 LibraryModule = self.BuildDatabase[LibraryPath, self.Arch, self.BuildTarget, self.ToolChain]
2156 # for those forced library instance (NULL library), add a fake library class
2157 if LibraryClassName.startswith("NULL"):
2158 LibraryModule.LibraryClass.append(LibraryClassObject(LibraryClassName, [ModuleType]))
2159 elif LibraryModule.LibraryClass == None \
2160 or len(LibraryModule.LibraryClass) == 0 \
2161 or (ModuleType != 'USER_DEFINED'
2162 and ModuleType not in LibraryModule.LibraryClass[0].SupModList):
2163 # only USER_DEFINED can link against any library instance despite of its SupModList
2164 EdkLogger.error("build", OPTION_MISSING,
2165 "Module type [%s] is not supported by library instance [%s]" \
2166 % (ModuleType, LibraryPath), File=self.MetaFile,
2167 ExtraData="consumed by [%s]" % str(Module))
2168
2169 LibraryInstance[LibraryClassName] = LibraryModule
2170 LibraryConsumerList.append(LibraryModule)
2171 EdkLogger.verbose("\t" + str(LibraryClassName) + " : " + str(LibraryModule))
2172 else:
2173 LibraryModule = LibraryInstance[LibraryClassName]
2174
2175 if LibraryModule == None:
2176 continue
2177
2178 if LibraryModule.ConstructorList != [] and LibraryModule not in Constructor:
2179 Constructor.append(LibraryModule)
2180
2181 if LibraryModule not in ConsumedByList:
2182 ConsumedByList[LibraryModule] = []
2183 # don't add current module itself to consumer list
2184 if M != Module:
2185 if M in ConsumedByList[LibraryModule]:
2186 continue
2187 ConsumedByList[LibraryModule].append(M)
2188 #
2189 # Initialize the sorted output list to the empty set
2190 #
2191 SortedLibraryList = []
2192 #
2193 # Q <- Set of all nodes with no incoming edges
2194 #
2195 LibraryList = [] #LibraryInstance.values()
2196 Q = []
2197 for LibraryClassName in LibraryInstance:
2198 M = LibraryInstance[LibraryClassName]
2199 LibraryList.append(M)
2200 if ConsumedByList[M] == []:
2201 Q.append(M)
2202
2203 #
2204 # start the DAG algorithm
2205 #
2206 while True:
2207 EdgeRemoved = True
2208 while Q == [] and EdgeRemoved:
2209 EdgeRemoved = False
2210 # for each node Item with a Constructor
2211 for Item in LibraryList:
2212 if Item not in Constructor:
2213 continue
2214 # for each Node without a constructor with an edge e from Item to Node
2215 for Node in ConsumedByList[Item]:
2216 if Node in Constructor:
2217 continue
2218 # remove edge e from the graph if Node has no constructor
2219 ConsumedByList[Item].remove(Node)
2220 EdgeRemoved = True
2221 if ConsumedByList[Item] == []:
2222 # insert Item into Q
2223 Q.insert(0, Item)
2224 break
2225 if Q != []:
2226 break
2227 # DAG is done if there's no more incoming edge for all nodes
2228 if Q == []:
2229 break
2230
2231 # remove node from Q
2232 Node = Q.pop()
2233 # output Node
2234 SortedLibraryList.append(Node)
2235
2236 # for each node Item with an edge e from Node to Item do
2237 for Item in LibraryList:
2238 if Node not in ConsumedByList[Item]:
2239 continue
2240 # remove edge e from the graph
2241 ConsumedByList[Item].remove(Node)
2242
2243 if ConsumedByList[Item] != []:
2244 continue
2245 # insert Item into Q, if Item has no other incoming edges
2246 Q.insert(0, Item)
2247
2248 #
2249 # if any remaining node Item in the graph has a constructor and an incoming edge, then the graph has a cycle
2250 #
2251 for Item in LibraryList:
2252 if ConsumedByList[Item] != [] and Item in Constructor and len(Constructor) > 1:
2253 ErrorMessage = "\tconsumed by " + "\n\tconsumed by ".join([str(L) for L in ConsumedByList[Item]])
2254 EdkLogger.error("build", BUILD_ERROR, 'Library [%s] with constructors has a cycle' % str(Item),
2255 ExtraData=ErrorMessage, File=self.MetaFile)
2256 if Item not in SortedLibraryList:
2257 SortedLibraryList.append(Item)
2258
2259 #
2260 # Build the list of constructor and destructir names
2261 # The DAG Topo sort produces the destructor order, so the list of constructors must generated in the reverse order
2262 #
2263 SortedLibraryList.reverse()
2264 return SortedLibraryList
2265
2266
2267 ## Override PCD setting (type, value, ...)
2268 #
2269 # @param ToPcd The PCD to be overrided
2270 # @param FromPcd The PCD overrideing from
2271 #
2272 def _OverridePcd(self, ToPcd, FromPcd, Module=""):
2273 #
2274 # in case there's PCDs coming from FDF file, which have no type given.
2275 # at this point, ToPcd.Type has the type found from dependent
2276 # package
2277 #
2278 TokenCName = ToPcd.TokenCName
2279 for PcdItem in GlobalData.MixedPcd:
2280 if (ToPcd.TokenCName, ToPcd.TokenSpaceGuidCName) in GlobalData.MixedPcd[PcdItem]:
2281 TokenCName = PcdItem[0]
2282 break
2283 if FromPcd != None:
2284 if GlobalData.BuildOptionPcd:
2285 for pcd in GlobalData.BuildOptionPcd:
2286 if (FromPcd.TokenSpaceGuidCName, FromPcd.TokenCName) == (pcd[0], pcd[1]):
2287 FromPcd.DefaultValue = pcd[2]
2288 break
2289 if ToPcd.Pending and FromPcd.Type not in [None, '']:
2290 ToPcd.Type = FromPcd.Type
2291 elif (ToPcd.Type not in [None, '']) and (FromPcd.Type not in [None, ''])\
2292 and (ToPcd.Type != FromPcd.Type) and (ToPcd.Type in FromPcd.Type):
2293 if ToPcd.Type.strip() == "DynamicEx":
2294 ToPcd.Type = FromPcd.Type
2295 elif ToPcd.Type not in [None, ''] and FromPcd.Type not in [None, ''] \
2296 and ToPcd.Type != FromPcd.Type:
2297 EdkLogger.error("build", OPTION_CONFLICT, "Mismatched PCD type",
2298 ExtraData="%s.%s is defined as [%s] in module %s, but as [%s] in platform."\
2299 % (ToPcd.TokenSpaceGuidCName, TokenCName,
2300 ToPcd.Type, Module, FromPcd.Type),
2301 File=self.MetaFile)
2302
2303 if FromPcd.MaxDatumSize not in [None, '']:
2304 ToPcd.MaxDatumSize = FromPcd.MaxDatumSize
2305 if FromPcd.DefaultValue not in [None, '']:
2306 ToPcd.DefaultValue = FromPcd.DefaultValue
2307 if FromPcd.TokenValue not in [None, '']:
2308 ToPcd.TokenValue = FromPcd.TokenValue
2309 if FromPcd.MaxDatumSize not in [None, '']:
2310 ToPcd.MaxDatumSize = FromPcd.MaxDatumSize
2311 if FromPcd.DatumType not in [None, '']:
2312 ToPcd.DatumType = FromPcd.DatumType
2313 if FromPcd.SkuInfoList not in [None, '', []]:
2314 ToPcd.SkuInfoList = FromPcd.SkuInfoList
2315
2316 # check the validation of datum
2317 IsValid, Cause = CheckPcdDatum(ToPcd.DatumType, ToPcd.DefaultValue)
2318 if not IsValid:
2319 EdkLogger.error('build', FORMAT_INVALID, Cause, File=self.MetaFile,
2320 ExtraData="%s.%s" % (ToPcd.TokenSpaceGuidCName, TokenCName))
2321 ToPcd.validateranges = FromPcd.validateranges
2322 ToPcd.validlists = FromPcd.validlists
2323 ToPcd.expressions = FromPcd.expressions
2324
2325 if ToPcd.DatumType == "VOID*" and ToPcd.MaxDatumSize in ['', None]:
2326 EdkLogger.debug(EdkLogger.DEBUG_9, "No MaxDatumSize specified for PCD %s.%s" \
2327 % (ToPcd.TokenSpaceGuidCName, TokenCName))
2328 Value = ToPcd.DefaultValue
2329 if Value in [None, '']:
2330 ToPcd.MaxDatumSize = '1'
2331 elif Value[0] == 'L':
2332 ToPcd.MaxDatumSize = str((len(Value) - 2) * 2)
2333 elif Value[0] == '{':
2334 ToPcd.MaxDatumSize = str(len(Value.split(',')))
2335 else:
2336 ToPcd.MaxDatumSize = str(len(Value) - 1)
2337
2338 # apply default SKU for dynamic PCDS if specified one is not available
2339 if (ToPcd.Type in PCD_DYNAMIC_TYPE_LIST or ToPcd.Type in PCD_DYNAMIC_EX_TYPE_LIST) \
2340 and ToPcd.SkuInfoList in [None, {}, '']:
2341 if self.Platform.SkuName in self.Platform.SkuIds:
2342 SkuName = self.Platform.SkuName
2343 else:
2344 SkuName = 'DEFAULT'
2345 ToPcd.SkuInfoList = {
2346 SkuName : SkuInfoClass(SkuName, self.Platform.SkuIds[SkuName], '', '', '', '', '', ToPcd.DefaultValue)
2347 }
2348
2349 ## Apply PCD setting defined platform to a module
2350 #
2351 # @param Module The module from which the PCD setting will be overrided
2352 #
2353 # @retval PCD_list The list PCDs with settings from platform
2354 #
2355 def ApplyPcdSetting(self, Module, Pcds):
2356 # for each PCD in module
2357 for Name, Guid in Pcds:
2358 PcdInModule = Pcds[Name, Guid]
2359 # find out the PCD setting in platform
2360 if (Name, Guid) in self.Platform.Pcds:
2361 PcdInPlatform = self.Platform.Pcds[Name, Guid]
2362 else:
2363 PcdInPlatform = None
2364 # then override the settings if any
2365 self._OverridePcd(PcdInModule, PcdInPlatform, Module)
2366 # resolve the VariableGuid value
2367 for SkuId in PcdInModule.SkuInfoList:
2368 Sku = PcdInModule.SkuInfoList[SkuId]
2369 if Sku.VariableGuid == '': continue
2370 Sku.VariableGuidValue = GuidValue(Sku.VariableGuid, self.PackageList, self.MetaFile.Path)
2371 if Sku.VariableGuidValue == None:
2372 PackageList = "\n\t".join([str(P) for P in self.PackageList])
2373 EdkLogger.error(
2374 'build',
2375 RESOURCE_NOT_AVAILABLE,
2376 "Value of GUID [%s] is not found in" % Sku.VariableGuid,
2377 ExtraData=PackageList + "\n\t(used with %s.%s from module %s)" \
2378 % (Guid, Name, str(Module)),
2379 File=self.MetaFile
2380 )
2381
2382 # override PCD settings with module specific setting
2383 if Module in self.Platform.Modules:
2384 PlatformModule = self.Platform.Modules[str(Module)]
2385 for Key in PlatformModule.Pcds:
2386 Flag = False
2387 if Key in Pcds:
2388 ToPcd = Pcds[Key]
2389 Flag = True
2390 elif Key in GlobalData.MixedPcd:
2391 for PcdItem in GlobalData.MixedPcd[Key]:
2392 if PcdItem in Pcds:
2393 ToPcd = Pcds[PcdItem]
2394 Flag = True
2395 break
2396 if Flag:
2397 self._OverridePcd(ToPcd, PlatformModule.Pcds[Key], Module)
2398 return Pcds.values()
2399
2400 ## Resolve library names to library modules
2401 #
2402 # (for Edk.x modules)
2403 #
2404 # @param Module The module from which the library names will be resolved
2405 #
2406 # @retval library_list The list of library modules
2407 #
2408 def ResolveLibraryReference(self, Module):
2409 EdkLogger.verbose("")
2410 EdkLogger.verbose("Library instances of module [%s] [%s]:" % (str(Module), self.Arch))
2411 LibraryConsumerList = [Module]
2412
2413 # "CompilerStub" is a must for Edk modules
2414 if Module.Libraries:
2415 Module.Libraries.append("CompilerStub")
2416 LibraryList = []
2417 while len(LibraryConsumerList) > 0:
2418 M = LibraryConsumerList.pop()
2419 for LibraryName in M.Libraries:
2420 Library = self.Platform.LibraryClasses[LibraryName, ':dummy:']
2421 if Library == None:
2422 for Key in self.Platform.LibraryClasses.data.keys():
2423 if LibraryName.upper() == Key.upper():
2424 Library = self.Platform.LibraryClasses[Key, ':dummy:']
2425 break
2426 if Library == None:
2427 EdkLogger.warn("build", "Library [%s] is not found" % LibraryName, File=str(M),
2428 ExtraData="\t%s [%s]" % (str(Module), self.Arch))
2429 continue
2430
2431 if Library not in LibraryList:
2432 LibraryList.append(Library)
2433 LibraryConsumerList.append(Library)
2434 EdkLogger.verbose("\t" + LibraryName + " : " + str(Library) + ' ' + str(type(Library)))
2435 return LibraryList
2436
2437 ## Calculate the priority value of the build option
2438 #
2439 # @param Key Build option definition contain: TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
2440 #
2441 # @retval Value Priority value based on the priority list.
2442 #
2443 def CalculatePriorityValue(self, Key):
2444 Target, ToolChain, Arch, CommandType, Attr = Key.split('_')
2445 PriorityValue = 0x11111
2446 if Target == "*":
2447 PriorityValue &= 0x01111
2448 if ToolChain == "*":
2449 PriorityValue &= 0x10111
2450 if Arch == "*":
2451 PriorityValue &= 0x11011
2452 if CommandType == "*":
2453 PriorityValue &= 0x11101
2454 if Attr == "*":
2455 PriorityValue &= 0x11110
2456
2457 return self.PrioList["0x%0.5x" % PriorityValue]
2458
2459
2460 ## Expand * in build option key
2461 #
2462 # @param Options Options to be expanded
2463 #
2464 # @retval options Options expanded
2465 #
2466 def _ExpandBuildOption(self, Options, ModuleStyle=None):
2467 BuildOptions = {}
2468 FamilyMatch = False
2469 FamilyIsNull = True
2470
2471 OverrideList = {}
2472 #
2473 # Construct a list contain the build options which need override.
2474 #
2475 for Key in Options:
2476 #
2477 # Key[0] -- tool family
2478 # Key[1] -- TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
2479 #
2480 if (Key[0] == self.BuildRuleFamily and
2481 (ModuleStyle == None or len(Key) < 3 or (len(Key) > 2 and Key[2] == ModuleStyle))):
2482 Target, ToolChain, Arch, CommandType, Attr = Key[1].split('_')
2483 if Target == self.BuildTarget or Target == "*":
2484 if ToolChain == self.ToolChain or ToolChain == "*":
2485 if Arch == self.Arch or Arch == "*":
2486 if Options[Key].startswith("="):
2487 if OverrideList.get(Key[1]) != None:
2488 OverrideList.pop(Key[1])
2489 OverrideList[Key[1]] = Options[Key]
2490
2491 #
2492 # Use the highest priority value.
2493 #
2494 if (len(OverrideList) >= 2):
2495 KeyList = OverrideList.keys()
2496 for Index in range(len(KeyList)):
2497 NowKey = KeyList[Index]
2498 Target1, ToolChain1, Arch1, CommandType1, Attr1 = NowKey.split("_")
2499 for Index1 in range(len(KeyList) - Index - 1):
2500 NextKey = KeyList[Index1 + Index + 1]
2501 #
2502 # Compare two Key, if one is included by another, choose the higher priority one
2503 #
2504 Target2, ToolChain2, Arch2, CommandType2, Attr2 = NextKey.split("_")
2505 if Target1 == Target2 or Target1 == "*" or Target2 == "*":
2506 if ToolChain1 == ToolChain2 or ToolChain1 == "*" or ToolChain2 == "*":
2507 if Arch1 == Arch2 or Arch1 == "*" or Arch2 == "*":
2508 if CommandType1 == CommandType2 or CommandType1 == "*" or CommandType2 == "*":
2509 if Attr1 == Attr2 or Attr1 == "*" or Attr2 == "*":
2510 if self.CalculatePriorityValue(NowKey) > self.CalculatePriorityValue(NextKey):
2511 if Options.get((self.BuildRuleFamily, NextKey)) != None:
2512 Options.pop((self.BuildRuleFamily, NextKey))
2513 else:
2514 if Options.get((self.BuildRuleFamily, NowKey)) != None:
2515 Options.pop((self.BuildRuleFamily, NowKey))
2516
2517 for Key in Options:
2518 if ModuleStyle != None and len (Key) > 2:
2519 # Check Module style is EDK or EDKII.
2520 # Only append build option for the matched style module.
2521 if ModuleStyle == EDK_NAME and Key[2] != EDK_NAME:
2522 continue
2523 elif ModuleStyle == EDKII_NAME and Key[2] != EDKII_NAME:
2524 continue
2525 Family = Key[0]
2526 Target, Tag, Arch, Tool, Attr = Key[1].split("_")
2527 # if tool chain family doesn't match, skip it
2528 if Tool in self.ToolDefinition and Family != "":
2529 FamilyIsNull = False
2530 if self.ToolDefinition[Tool].get(TAB_TOD_DEFINES_BUILDRULEFAMILY, "") != "":
2531 if Family != self.ToolDefinition[Tool][TAB_TOD_DEFINES_BUILDRULEFAMILY]:
2532 continue
2533 elif Family != self.ToolDefinition[Tool][TAB_TOD_DEFINES_FAMILY]:
2534 continue
2535 FamilyMatch = True
2536 # expand any wildcard
2537 if Target == "*" or Target == self.BuildTarget:
2538 if Tag == "*" or Tag == self.ToolChain:
2539 if Arch == "*" or Arch == self.Arch:
2540 if Tool not in BuildOptions:
2541 BuildOptions[Tool] = {}
2542 if Attr != "FLAGS" or Attr not in BuildOptions[Tool] or Options[Key].startswith('='):
2543 BuildOptions[Tool][Attr] = Options[Key]
2544 else:
2545 # append options for the same tool except PATH
2546 if Attr != 'PATH':
2547 BuildOptions[Tool][Attr] += " " + Options[Key]
2548 else:
2549 BuildOptions[Tool][Attr] = Options[Key]
2550 # Build Option Family has been checked, which need't to be checked again for family.
2551 if FamilyMatch or FamilyIsNull:
2552 return BuildOptions
2553
2554 for Key in Options:
2555 if ModuleStyle != None and len (Key) > 2:
2556 # Check Module style is EDK or EDKII.
2557 # Only append build option for the matched style module.
2558 if ModuleStyle == EDK_NAME and Key[2] != EDK_NAME:
2559 continue
2560 elif ModuleStyle == EDKII_NAME and Key[2] != EDKII_NAME:
2561 continue
2562 Family = Key[0]
2563 Target, Tag, Arch, Tool, Attr = Key[1].split("_")
2564 # if tool chain family doesn't match, skip it
2565 if Tool not in self.ToolDefinition or Family == "":
2566 continue
2567 # option has been added before
2568 if Family != self.ToolDefinition[Tool][TAB_TOD_DEFINES_FAMILY]:
2569 continue
2570
2571 # expand any wildcard
2572 if Target == "*" or Target == self.BuildTarget:
2573 if Tag == "*" or Tag == self.ToolChain:
2574 if Arch == "*" or Arch == self.Arch:
2575 if Tool not in BuildOptions:
2576 BuildOptions[Tool] = {}
2577 if Attr != "FLAGS" or Attr not in BuildOptions[Tool] or Options[Key].startswith('='):
2578 BuildOptions[Tool][Attr] = Options[Key]
2579 else:
2580 # append options for the same tool except PATH
2581 if Attr != 'PATH':
2582 BuildOptions[Tool][Attr] += " " + Options[Key]
2583 else:
2584 BuildOptions[Tool][Attr] = Options[Key]
2585 return BuildOptions
2586
2587 ## Append build options in platform to a module
2588 #
2589 # @param Module The module to which the build options will be appened
2590 #
2591 # @retval options The options appended with build options in platform
2592 #
2593 def ApplyBuildOption(self, Module):
2594 # Get the different options for the different style module
2595 if Module.AutoGenVersion < 0x00010005:
2596 PlatformOptions = self.EdkBuildOption
2597 ModuleTypeOptions = self.Platform.GetBuildOptionsByModuleType(EDK_NAME, Module.ModuleType)
2598 else:
2599 PlatformOptions = self.EdkIIBuildOption
2600 ModuleTypeOptions = self.Platform.GetBuildOptionsByModuleType(EDKII_NAME, Module.ModuleType)
2601 ModuleTypeOptions = self._ExpandBuildOption(ModuleTypeOptions)
2602 ModuleOptions = self._ExpandBuildOption(Module.BuildOptions)
2603 if Module in self.Platform.Modules:
2604 PlatformModule = self.Platform.Modules[str(Module)]
2605 PlatformModuleOptions = self._ExpandBuildOption(PlatformModule.BuildOptions)
2606 else:
2607 PlatformModuleOptions = {}
2608
2609 BuildRuleOrder = None
2610 for Options in [self.ToolDefinition, ModuleOptions, PlatformOptions, ModuleTypeOptions, PlatformModuleOptions]:
2611 for Tool in Options:
2612 for Attr in Options[Tool]:
2613 if Attr == TAB_TOD_DEFINES_BUILDRULEORDER:
2614 BuildRuleOrder = Options[Tool][Attr]
2615
2616 AllTools = set(ModuleOptions.keys() + PlatformOptions.keys() +
2617 PlatformModuleOptions.keys() + ModuleTypeOptions.keys() +
2618 self.ToolDefinition.keys())
2619 BuildOptions = {}
2620 for Tool in AllTools:
2621 if Tool not in BuildOptions:
2622 BuildOptions[Tool] = {}
2623
2624 for Options in [self.ToolDefinition, ModuleOptions, PlatformOptions, ModuleTypeOptions, PlatformModuleOptions]:
2625 if Tool not in Options:
2626 continue
2627 for Attr in Options[Tool]:
2628 Value = Options[Tool][Attr]
2629 #
2630 # Do not generate it in Makefile
2631 #
2632 if Attr == TAB_TOD_DEFINES_BUILDRULEORDER:
2633 continue
2634 if Attr not in BuildOptions[Tool]:
2635 BuildOptions[Tool][Attr] = ""
2636 # check if override is indicated
2637 if Value.startswith('='):
2638 ToolPath = Value[1:]
2639 ToolPath = mws.handleWsMacro(ToolPath)
2640 BuildOptions[Tool][Attr] = ToolPath
2641 else:
2642 Value = mws.handleWsMacro(Value)
2643 if Attr != 'PATH':
2644 BuildOptions[Tool][Attr] += " " + Value
2645 else:
2646 BuildOptions[Tool][Attr] = Value
2647 if Module.AutoGenVersion < 0x00010005 and self.Workspace.UniFlag != None:
2648 #
2649 # Override UNI flag only for EDK module.
2650 #
2651 if 'BUILD' not in BuildOptions:
2652 BuildOptions['BUILD'] = {}
2653 BuildOptions['BUILD']['FLAGS'] = self.Workspace.UniFlag
2654 return BuildOptions, BuildRuleOrder
2655
2656 Platform = property(_GetPlatform)
2657 Name = property(_GetName)
2658 Guid = property(_GetGuid)
2659 Version = property(_GetVersion)
2660
2661 OutputDir = property(_GetOutputDir)
2662 BuildDir = property(_GetBuildDir)
2663 MakeFileDir = property(_GetMakeFileDir)
2664 FdfFile = property(_GetFdfFile)
2665
2666 PcdTokenNumber = property(_GetPcdTokenNumbers) # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber
2667 DynamicPcdList = property(_GetDynamicPcdList) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
2668 NonDynamicPcdList = property(_GetNonDynamicPcdList) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
2669 NonDynamicPcdDict = property(_GetNonDynamicPcdDict)
2670 PackageList = property(_GetPackageList)
2671
2672 ToolDefinition = property(_GetToolDefinition) # toolcode : tool path
2673 ToolDefinitionFile = property(_GetToolDefFile) # toolcode : lib path
2674 ToolChainFamily = property(_GetToolChainFamily)
2675 BuildRuleFamily = property(_GetBuildRuleFamily)
2676 BuildOption = property(_GetBuildOptions) # toolcode : option
2677 EdkBuildOption = property(_GetEdkBuildOptions) # edktoolcode : option
2678 EdkIIBuildOption = property(_GetEdkIIBuildOptions) # edkiitoolcode : option
2679
2680 BuildCommand = property(_GetBuildCommand)
2681 BuildRule = property(_GetBuildRule)
2682 ModuleAutoGenList = property(_GetModuleAutoGenList)
2683 LibraryAutoGenList = property(_GetLibraryAutoGenList)
2684 GenFdsCommand = property(_GenFdsCommand)
2685
2686 ## ModuleAutoGen class
2687 #
2688 # This class encapsules the AutoGen behaviors for the build tools. In addition to
2689 # the generation of AutoGen.h and AutoGen.c, it will generate *.depex file according
2690 # to the [depex] section in module's inf file.
2691 #
2692 class ModuleAutoGen(AutoGen):
2693 ## Cache the timestamps of metafiles of every module in a class variable
2694 #
2695 TimeDict = {}
2696
2697 ## The real constructor of ModuleAutoGen
2698 #
2699 # This method is not supposed to be called by users of ModuleAutoGen. It's
2700 # only used by factory method __new__() to do real initialization work for an
2701 # object of ModuleAutoGen
2702 #
2703 # @param Workspace EdkIIWorkspaceBuild object
2704 # @param ModuleFile The path of module file
2705 # @param Target Build target (DEBUG, RELEASE)
2706 # @param Toolchain Name of tool chain
2707 # @param Arch The arch the module supports
2708 # @param PlatformFile Platform meta-file
2709 #
2710 def _Init(self, Workspace, ModuleFile, Target, Toolchain, Arch, PlatformFile):
2711 EdkLogger.debug(EdkLogger.DEBUG_9, "AutoGen module [%s] [%s]" % (ModuleFile, Arch))
2712 GlobalData.gProcessingFile = "%s [%s, %s, %s]" % (ModuleFile, Arch, Toolchain, Target)
2713
2714 self.Workspace = Workspace
2715 self.WorkspaceDir = Workspace.WorkspaceDir
2716
2717 self.MetaFile = ModuleFile
2718 self.PlatformInfo = PlatformAutoGen(Workspace, PlatformFile, Target, Toolchain, Arch)
2719 # check if this module is employed by active platform
2720 if not self.PlatformInfo.ValidModule(self.MetaFile):
2721 EdkLogger.verbose("Module [%s] for [%s] is not employed by active platform\n" \
2722 % (self.MetaFile, Arch))
2723 return False
2724
2725 self.SourceDir = self.MetaFile.SubDir
2726 self.SourceDir = mws.relpath(self.SourceDir, self.WorkspaceDir)
2727
2728 self.SourceOverrideDir = None
2729 # use overrided path defined in DSC file
2730 if self.MetaFile.Key in GlobalData.gOverrideDir:
2731 self.SourceOverrideDir = GlobalData.gOverrideDir[self.MetaFile.Key]
2732
2733 self.ToolChain = Toolchain
2734 self.BuildTarget = Target
2735 self.Arch = Arch
2736 self.ToolChainFamily = self.PlatformInfo.ToolChainFamily
2737 self.BuildRuleFamily = self.PlatformInfo.BuildRuleFamily
2738
2739 self.IsMakeFileCreated = False
2740 self.IsCodeFileCreated = False
2741 self.IsAsBuiltInfCreated = False
2742 self.DepexGenerated = False
2743
2744 self.BuildDatabase = self.Workspace.BuildDatabase
2745 self.BuildRuleOrder = None
2746 self.BuildTime = 0
2747
2748 self._Module = None
2749 self._Name = None
2750 self._Guid = None
2751 self._Version = None
2752 self._ModuleType = None
2753 self._ComponentType = None
2754 self._PcdIsDriver = None
2755 self._AutoGenVersion = None
2756 self._LibraryFlag = None
2757 self._CustomMakefile = None
2758 self._Macro = None
2759
2760 self._BuildDir = None
2761 self._OutputDir = None
2762 self._DebugDir = None
2763 self._MakeFileDir = None
2764
2765 self._IncludePathList = None
2766 self._IncludePathLength = 0
2767 self._AutoGenFileList = None
2768 self._UnicodeFileList = None
2769 self._VfrFileList = None
2770 self._IdfFileList = None
2771 self._SourceFileList = None
2772 self._ObjectFileList = None
2773 self._BinaryFileList = None
2774
2775 self._DependentPackageList = None
2776 self._DependentLibraryList = None
2777 self._LibraryAutoGenList = None
2778 self._DerivedPackageList = None
2779 self._ModulePcdList = None
2780 self._LibraryPcdList = None
2781 self._PcdComments = sdict()
2782 self._GuidList = None
2783 self._GuidsUsedByPcd = None
2784 self._GuidComments = sdict()
2785 self._ProtocolList = None
2786 self._ProtocolComments = sdict()
2787 self._PpiList = None
2788 self._PpiComments = sdict()
2789 self._DepexList = None
2790 self._DepexExpressionList = None
2791 self._BuildOption = None
2792 self._BuildOptionIncPathList = None
2793 self._BuildTargets = None
2794 self._IntroBuildTargetList = None
2795 self._FinalBuildTargetList = None
2796 self._FileTypes = None
2797 self._BuildRules = None
2798
2799 self._TimeStampPath = None
2800
2801 self.AutoGenDepSet = set()
2802
2803
2804 ## The Modules referenced to this Library
2805 # Only Library has this attribute
2806 self._ReferenceModules = []
2807
2808 ## Store the FixedAtBuild Pcds
2809 #
2810 self._FixedAtBuildPcds = []
2811 self.ConstPcd = {}
2812 return True
2813
2814 def __repr__(self):
2815 return "%s [%s]" % (self.MetaFile, self.Arch)
2816
2817 # Get FixedAtBuild Pcds of this Module
2818 def _GetFixedAtBuildPcds(self):
2819 if self._FixedAtBuildPcds:
2820 return self._FixedAtBuildPcds
2821 for Pcd in self.ModulePcdList:
2822 if Pcd.Type != "FixedAtBuild":
2823 continue
2824 if Pcd not in self._FixedAtBuildPcds:
2825 self._FixedAtBuildPcds.append(Pcd)
2826
2827 return self._FixedAtBuildPcds
2828
2829 def _GetUniqueBaseName(self):
2830 BaseName = self.Name
2831 for Module in self.PlatformInfo.ModuleAutoGenList:
2832 if Module.MetaFile == self.MetaFile:
2833 continue
2834 if Module.Name == self.Name:
2835 if uuid.UUID(Module.Guid) == uuid.UUID(self.Guid):
2836 EdkLogger.error("build", FILE_DUPLICATED, 'Modules have same BaseName and FILE_GUID:\n'
2837 ' %s\n %s' % (Module.MetaFile, self.MetaFile))
2838 BaseName = '%s_%s' % (self.Name, self.Guid)
2839 return BaseName
2840
2841 # Macros could be used in build_rule.txt (also Makefile)
2842 def _GetMacros(self):
2843 if self._Macro == None:
2844 self._Macro = sdict()
2845 self._Macro["WORKSPACE" ] = self.WorkspaceDir
2846 self._Macro["MODULE_NAME" ] = self.Name
2847 self._Macro["MODULE_NAME_GUID" ] = self._GetUniqueBaseName()
2848 self._Macro["MODULE_GUID" ] = self.Guid
2849 self._Macro["MODULE_VERSION" ] = self.Version
2850 self._Macro["MODULE_TYPE" ] = self.ModuleType
2851 self._Macro["MODULE_FILE" ] = str(self.MetaFile)
2852 self._Macro["MODULE_FILE_BASE_NAME" ] = self.MetaFile.BaseName
2853 self._Macro["MODULE_RELATIVE_DIR" ] = self.SourceDir
2854 self._Macro["MODULE_DIR" ] = self.SourceDir
2855
2856 self._Macro["BASE_NAME" ] = self.Name
2857
2858 self._Macro["ARCH" ] = self.Arch
2859 self._Macro["TOOLCHAIN" ] = self.ToolChain
2860 self._Macro["TOOLCHAIN_TAG" ] = self.ToolChain
2861 self._Macro["TOOL_CHAIN_TAG" ] = self.ToolChain
2862 self._Macro["TARGET" ] = self.BuildTarget
2863
2864 self._Macro["BUILD_DIR" ] = self.PlatformInfo.BuildDir
2865 self._Macro["BIN_DIR" ] = os.path.join(self.PlatformInfo.BuildDir, self.Arch)
2866 self._Macro["LIB_DIR" ] = os.path.join(self.PlatformInfo.BuildDir, self.Arch)
2867 self._Macro["MODULE_BUILD_DIR" ] = self.BuildDir
2868 self._Macro["OUTPUT_DIR" ] = self.OutputDir
2869 self._Macro["DEBUG_DIR" ] = self.DebugDir
2870 self._Macro["DEST_DIR_OUTPUT" ] = self.OutputDir
2871 self._Macro["DEST_DIR_DEBUG" ] = self.DebugDir
2872 self._Macro["PLATFORM_NAME" ] = self.PlatformInfo.Name
2873 self._Macro["PLATFORM_GUID" ] = self.PlatformInfo.Guid
2874 self._Macro["PLATFORM_VERSION" ] = self.PlatformInfo.Version
2875 self._Macro["PLATFORM_RELATIVE_DIR" ] = self.PlatformInfo.SourceDir
2876 self._Macro["PLATFORM_DIR" ] = mws.join(self.WorkspaceDir, self.PlatformInfo.SourceDir)
2877 self._Macro["PLATFORM_OUTPUT_DIR" ] = self.PlatformInfo.OutputDir
2878 return self._Macro
2879
2880 ## Return the module build data object
2881 def _GetModule(self):
2882 if self._Module == None:
2883 self._Module = self.Workspace.BuildDatabase[self.MetaFile, self.Arch, self.BuildTarget, self.ToolChain]
2884 return self._Module
2885
2886 ## Return the module name
2887 def _GetBaseName(self):
2888 return self.Module.BaseName
2889
2890 ## Return the module DxsFile if exist
2891 def _GetDxsFile(self):
2892 return self.Module.DxsFile
2893
2894 ## Return the module SourceOverridePath
2895 def _GetSourceOverridePath(self):
2896 return self.Module.SourceOverridePath
2897
2898 ## Return the module meta-file GUID
2899 def _GetGuid(self):
2900 #
2901 # To build same module more than once, the module path with FILE_GUID overridden has
2902 # the file name FILE_GUIDmodule.inf, but the relative path (self.MetaFile.File) is the realy path
2903 # in DSC. The overridden GUID can be retrieved from file name
2904 #
2905 if os.path.basename(self.MetaFile.File) != os.path.basename(self.MetaFile.Path):
2906 #
2907 # Length of GUID is 36
2908 #
2909 return os.path.basename(self.MetaFile.Path)[:36]
2910 return self.Module.Guid
2911
2912 ## Return the module version
2913 def _GetVersion(self):
2914 return self.Module.Version
2915
2916 ## Return the module type
2917 def _GetModuleType(self):
2918 return self.Module.ModuleType
2919
2920 ## Return the component type (for Edk.x style of module)
2921 def _GetComponentType(self):
2922 return self.Module.ComponentType
2923
2924 ## Return the build type
2925 def _GetBuildType(self):
2926 return self.Module.BuildType
2927
2928 ## Return the PCD_IS_DRIVER setting
2929 def _GetPcdIsDriver(self):
2930 return self.Module.PcdIsDriver
2931
2932 ## Return the autogen version, i.e. module meta-file version
2933 def _GetAutoGenVersion(self):
2934 return self.Module.AutoGenVersion
2935
2936 ## Check if the module is library or not
2937 def _IsLibrary(self):
2938 if self._LibraryFlag == None:
2939 if self.Module.LibraryClass != None and self.Module.LibraryClass != []:
2940 self._LibraryFlag = True
2941 else:
2942 self._LibraryFlag = False
2943 return self._LibraryFlag
2944
2945 ## Check if the module is binary module or not
2946 def _IsBinaryModule(self):
2947 return self.Module.IsBinaryModule
2948
2949 ## Return the directory to store intermediate files of the module
2950 def _GetBuildDir(self):
2951 if self._BuildDir == None:
2952 self._BuildDir = path.join(
2953 self.PlatformInfo.BuildDir,
2954 self.Arch,
2955 self.SourceDir,
2956 self.MetaFile.BaseName
2957 )
2958 CreateDirectory(self._BuildDir)
2959 return self._BuildDir
2960
2961 ## Return the directory to store the intermediate object files of the mdoule
2962 def _GetOutputDir(self):
2963 if self._OutputDir == None:
2964 self._OutputDir = path.join(self.BuildDir, "OUTPUT")
2965 CreateDirectory(self._OutputDir)
2966 return self._OutputDir
2967
2968 ## Return the directory to store auto-gened source files of the mdoule
2969 def _GetDebugDir(self):
2970 if self._DebugDir == None:
2971 self._DebugDir = path.join(self.BuildDir, "DEBUG")
2972 CreateDirectory(self._DebugDir)
2973 return self._DebugDir
2974
2975 ## Return the path of custom file
2976 def _GetCustomMakefile(self):
2977 if self._CustomMakefile == None:
2978 self._CustomMakefile = {}
2979 for Type in self.Module.CustomMakefile:
2980 if Type in gMakeTypeMap:
2981 MakeType = gMakeTypeMap[Type]
2982 else:
2983 MakeType = 'nmake'
2984 if self.SourceOverrideDir != None:
2985 File = os.path.join(self.SourceOverrideDir, self.Module.CustomMakefile[Type])
2986 if not os.path.exists(File):
2987 File = os.path.join(self.SourceDir, self.Module.CustomMakefile[Type])
2988 else:
2989 File = os.path.join(self.SourceDir, self.Module.CustomMakefile[Type])
2990 self._CustomMakefile[MakeType] = File
2991 return self._CustomMakefile
2992
2993 ## Return the directory of the makefile
2994 #
2995 # @retval string The directory string of module's makefile
2996 #
2997 def _GetMakeFileDir(self):
2998 return self.BuildDir
2999
3000 ## Return build command string
3001 #
3002 # @retval string Build command string
3003 #
3004 def _GetBuildCommand(self):
3005 return self.PlatformInfo.BuildCommand
3006
3007 ## Get object list of all packages the module and its dependent libraries belong to
3008 #
3009 # @retval list The list of package object
3010 #
3011 def _GetDerivedPackageList(self):
3012 PackageList = []
3013 for M in [self.Module] + self.DependentLibraryList:
3014 for Package in M.Packages:
3015 if Package in PackageList:
3016 continue
3017 PackageList.append(Package)
3018 return PackageList
3019
3020 ## Get the depex string
3021 #
3022 # @return : a string contain all depex expresion.
3023 def _GetDepexExpresionString(self):
3024 DepexStr = ''
3025 DepexList = []
3026 ## DPX_SOURCE IN Define section.
3027 if self.Module.DxsFile:
3028 return DepexStr
3029 for M in [self.Module] + self.DependentLibraryList:
3030 Filename = M.MetaFile.Path
3031 InfObj = InfSectionParser.InfSectionParser(Filename)
3032 DepexExpresionList = InfObj.GetDepexExpresionList()
3033 for DepexExpresion in DepexExpresionList:
3034 for key in DepexExpresion.keys():
3035 Arch, ModuleType = key
3036 DepexExpr = [x for x in DepexExpresion[key] if not str(x).startswith('#')]
3037 # the type of build module is USER_DEFINED.
3038 # All different DEPEX section tags would be copied into the As Built INF file
3039 # and there would be separate DEPEX section tags
3040 if self.ModuleType.upper() == SUP_MODULE_USER_DEFINED:
3041 if (Arch.upper() == self.Arch.upper()) and (ModuleType.upper() != TAB_ARCH_COMMON):
3042 DepexList.append({(Arch, ModuleType): DepexExpr})
3043 else:
3044 if Arch.upper() == TAB_ARCH_COMMON or \
3045 (Arch.upper() == self.Arch.upper() and \
3046 ModuleType.upper() in [TAB_ARCH_COMMON, self.ModuleType.upper()]):
3047 DepexList.append({(Arch, ModuleType): DepexExpr})
3048
3049 #the type of build module is USER_DEFINED.
3050 if self.ModuleType.upper() == SUP_MODULE_USER_DEFINED:
3051 for Depex in DepexList:
3052 for key in Depex.keys():
3053 DepexStr += '[Depex.%s.%s]\n' % key
3054 DepexStr += '\n'.join(['# '+ val for val in Depex[key]])
3055 DepexStr += '\n\n'
3056 if not DepexStr:
3057 return '[Depex.%s]\n' % self.Arch
3058 return DepexStr
3059
3060 #the type of build module not is USER_DEFINED.
3061 Count = 0
3062 for Depex in DepexList:
3063 Count += 1
3064 if DepexStr != '':
3065 DepexStr += ' AND '
3066 DepexStr += '('
3067 for D in Depex.values():
3068 DepexStr += ' '.join([val for val in D])
3069 Index = DepexStr.find('END')
3070 if Index > -1 and Index == len(DepexStr) - 3:
3071 DepexStr = DepexStr[:-3]
3072 DepexStr = DepexStr.strip()
3073 DepexStr += ')'
3074 if Count == 1:
3075 DepexStr = DepexStr.lstrip('(').rstrip(')').strip()
3076 if not DepexStr:
3077 return '[Depex.%s]\n' % self.Arch
3078 return '[Depex.%s]\n# ' % self.Arch + DepexStr
3079
3080 ## Merge dependency expression
3081 #
3082 # @retval list The token list of the dependency expression after parsed
3083 #
3084 def _GetDepexTokenList(self):
3085 if self._DepexList == None:
3086 self._DepexList = {}
3087 if self.DxsFile or self.IsLibrary or TAB_DEPENDENCY_EXPRESSION_FILE in self.FileTypes:
3088 return self._DepexList
3089
3090 self._DepexList[self.ModuleType] = []
3091
3092 for ModuleType in self._DepexList:
3093 DepexList = self._DepexList[ModuleType]
3094 #
3095 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
3096 #
3097 for M in [self.Module] + self.DependentLibraryList:
3098 Inherited = False
3099 for D in M.Depex[self.Arch, ModuleType]:
3100 if DepexList != []:
3101 DepexList.append('AND')
3102 DepexList.append('(')
3103 DepexList.extend(D)
3104 if DepexList[-1] == 'END': # no need of a END at this time
3105 DepexList.pop()
3106 DepexList.append(')')
3107 Inherited = True
3108 if Inherited:
3109 EdkLogger.verbose("DEPEX[%s] (+%s) = %s" % (self.Name, M.BaseName, DepexList))
3110 if 'BEFORE' in DepexList or 'AFTER' in DepexList:
3111 break
3112 if len(DepexList) > 0:
3113 EdkLogger.verbose('')
3114 return self._DepexList
3115
3116 ## Merge dependency expression
3117 #
3118 # @retval list The token list of the dependency expression after parsed
3119 #
3120 def _GetDepexExpressionTokenList(self):
3121 if self._DepexExpressionList == None:
3122 self._DepexExpressionList = {}
3123 if self.DxsFile or self.IsLibrary or TAB_DEPENDENCY_EXPRESSION_FILE in self.FileTypes:
3124 return self._DepexExpressionList
3125
3126 self._DepexExpressionList[self.ModuleType] = ''
3127
3128 for ModuleType in self._DepexExpressionList:
3129 DepexExpressionList = self._DepexExpressionList[ModuleType]
3130 #
3131 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
3132 #
3133 for M in [self.Module] + self.DependentLibraryList:
3134 Inherited = False
3135 for D in M.DepexExpression[self.Arch, ModuleType]:
3136 if DepexExpressionList != '':
3137 DepexExpressionList += ' AND '
3138 DepexExpressionList += '('
3139 DepexExpressionList += D
3140 DepexExpressionList = DepexExpressionList.rstrip('END').strip()
3141 DepexExpressionList += ')'
3142 Inherited = True
3143 if Inherited:
3144 EdkLogger.verbose("DEPEX[%s] (+%s) = %s" % (self.Name, M.BaseName, DepexExpressionList))
3145 if 'BEFORE' in DepexExpressionList or 'AFTER' in DepexExpressionList:
3146 break
3147 if len(DepexExpressionList) > 0:
3148 EdkLogger.verbose('')
3149 self._DepexExpressionList[ModuleType] = DepexExpressionList
3150 return self._DepexExpressionList
3151
3152 # Get the tiano core user extension, it is contain dependent library.
3153 # @retval: a list contain tiano core userextension.
3154 #
3155 def _GetTianoCoreUserExtensionList(self):
3156 TianoCoreUserExtentionList = []
3157 for M in [self.Module] + self.DependentLibraryList:
3158 Filename = M.MetaFile.Path
3159 InfObj = InfSectionParser.InfSectionParser(Filename)
3160 TianoCoreUserExtenList = InfObj.GetUserExtensionTianoCore()
3161 for TianoCoreUserExtent in TianoCoreUserExtenList:
3162 for Section in TianoCoreUserExtent.keys():
3163 ItemList = Section.split(TAB_SPLIT)
3164 Arch = self.Arch
3165 if len(ItemList) == 4:
3166 Arch = ItemList[3]
3167 if Arch.upper() == TAB_ARCH_COMMON or Arch.upper() == self.Arch.upper():
3168 TianoCoreList = []
3169 TianoCoreList.extend([TAB_SECTION_START + Section + TAB_SECTION_END])
3170 TianoCoreList.extend(TianoCoreUserExtent[Section][:])
3171 TianoCoreList.append('\n')
3172 TianoCoreUserExtentionList.append(TianoCoreList)
3173
3174 return TianoCoreUserExtentionList
3175
3176 ## Return the list of specification version required for the module
3177 #
3178 # @retval list The list of specification defined in module file
3179 #
3180 def _GetSpecification(self):
3181 return self.Module.Specification
3182
3183 ## Tool option for the module build
3184 #
3185 # @param PlatformInfo The object of PlatformBuildInfo
3186 # @retval dict The dict containing valid options
3187 #
3188 def _GetModuleBuildOption(self):
3189 if self._BuildOption == None:
3190 self._BuildOption, self.BuildRuleOrder = self.PlatformInfo.ApplyBuildOption(self.Module)
3191 if self.BuildRuleOrder:
3192 self.BuildRuleOrder = ['.%s' % Ext for Ext in self.BuildRuleOrder.split()]
3193 return self._BuildOption
3194
3195 ## Get include path list from tool option for the module build
3196 #
3197 # @retval list The include path list
3198 #
3199 def _GetBuildOptionIncPathList(self):
3200 if self._BuildOptionIncPathList == None:
3201 #
3202 # Regular expression for finding Include Directories, the difference between MSFT and INTEL/GCC/RVCT
3203 # is the former use /I , the Latter used -I to specify include directories
3204 #
3205 if self.PlatformInfo.ToolChainFamily in ('MSFT'):
3206 gBuildOptIncludePattern = re.compile(r"(?:.*?)/I[ \t]*([^ ]*)", re.MULTILINE | re.DOTALL)
3207 elif self.PlatformInfo.ToolChainFamily in ('INTEL', 'GCC', 'RVCT'):
3208 gBuildOptIncludePattern = re.compile(r"(?:.*?)-I[ \t]*([^ ]*)", re.MULTILINE | re.DOTALL)
3209 else:
3210 #
3211 # New ToolChainFamily, don't known whether there is option to specify include directories
3212 #
3213 self._BuildOptionIncPathList = []
3214 return self._BuildOptionIncPathList
3215
3216 BuildOptionIncPathList = []
3217 for Tool in ('CC', 'PP', 'VFRPP', 'ASLPP', 'ASLCC', 'APP', 'ASM'):
3218 Attr = 'FLAGS'
3219 try:
3220 FlagOption = self.BuildOption[Tool][Attr]
3221 except KeyError:
3222 FlagOption = ''
3223
3224 if self.PlatformInfo.ToolChainFamily != 'RVCT':
3225 IncPathList = [NormPath(Path, self.Macros) for Path in gBuildOptIncludePattern.findall(FlagOption)]
3226 else:
3227 #
3228 # RVCT may specify a list of directory seperated by commas
3229 #
3230 IncPathList = []
3231 for Path in gBuildOptIncludePattern.findall(FlagOption):
3232 PathList = GetSplitList(Path, TAB_COMMA_SPLIT)
3233 IncPathList += [NormPath(PathEntry, self.Macros) for PathEntry in PathList]
3234
3235 #
3236 # EDK II modules must not reference header files outside of the packages they depend on or
3237 # within the module's directory tree. Report error if violation.
3238 #
3239 if self.AutoGenVersion >= 0x00010005 and len(IncPathList) > 0:
3240 for Path in IncPathList:
3241 if (Path not in self.IncludePathList) and (CommonPath([Path, self.MetaFile.Dir]) != self.MetaFile.Dir):
3242 ErrMsg = "The include directory for the EDK II module in this line is invalid %s specified in %s FLAGS '%s'" % (Path, Tool, FlagOption)
3243 EdkLogger.error("build",
3244 PARAMETER_INVALID,
3245 ExtraData=ErrMsg,
3246 File=str(self.MetaFile))
3247
3248
3249 BuildOptionIncPathList += IncPathList
3250
3251 self._BuildOptionIncPathList = BuildOptionIncPathList
3252
3253 return self._BuildOptionIncPathList
3254
3255 ## Return a list of files which can be built from source
3256 #
3257 # What kind of files can be built is determined by build rules in
3258 # $(CONF_DIRECTORY)/build_rule.txt and toolchain family.
3259 #
3260 def _GetSourceFileList(self):
3261 if self._SourceFileList == None:
3262 self._SourceFileList = []
3263 for F in self.Module.Sources:
3264 # match tool chain
3265 if F.TagName not in ("", "*", self.ToolChain):
3266 EdkLogger.debug(EdkLogger.DEBUG_9, "The toolchain [%s] for processing file [%s] is found, "
3267 "but [%s] is needed" % (F.TagName, str(F), self.ToolChain))
3268 continue
3269 # match tool chain family
3270 if F.ToolChainFamily not in ("", "*", self.ToolChainFamily):
3271 EdkLogger.debug(
3272 EdkLogger.DEBUG_0,
3273 "The file [%s] must be built by tools of [%s], " \
3274 "but current toolchain family is [%s]" \
3275 % (str(F), F.ToolChainFamily, self.ToolChainFamily))
3276 continue
3277
3278 # add the file path into search path list for file including
3279 if F.Dir not in self.IncludePathList and self.AutoGenVersion >= 0x00010005:
3280 self.IncludePathList.insert(0, F.Dir)
3281 self._SourceFileList.append(F)
3282
3283 self._MatchBuildRuleOrder(self._SourceFileList)
3284
3285 for F in self._SourceFileList:
3286 self._ApplyBuildRule(F, TAB_UNKNOWN_FILE)
3287 return self._SourceFileList
3288
3289 def _MatchBuildRuleOrder(self, FileList):
3290 Order_Dict = {}
3291 self._GetModuleBuildOption()
3292 for SingleFile in FileList:
3293 if self.BuildRuleOrder and SingleFile.Ext in self.BuildRuleOrder and SingleFile.Ext in self.BuildRules:
3294 key = SingleFile.Path.split(SingleFile.Ext)[0]
3295 if key in Order_Dict:
3296 Order_Dict[key].append(SingleFile.Ext)
3297 else:
3298 Order_Dict[key] = [SingleFile.Ext]
3299
3300 RemoveList = []
3301 for F in Order_Dict:
3302 if len(Order_Dict[F]) > 1:
3303 Order_Dict[F].sort(key=lambda i: self.BuildRuleOrder.index(i))
3304 for Ext in Order_Dict[F][1:]:
3305 RemoveList.append(F + Ext)
3306
3307 for item in RemoveList:
3308 FileList.remove(item)
3309
3310 return FileList
3311
3312 ## Return the list of unicode files
3313 def _GetUnicodeFileList(self):
3314 if self._UnicodeFileList == None:
3315 if TAB_UNICODE_FILE in self.FileTypes:
3316 self._UnicodeFileList = self.FileTypes[TAB_UNICODE_FILE]
3317 else:
3318 self._UnicodeFileList = []
3319 return self._UnicodeFileList
3320
3321 ## Return the list of vfr files
3322 def _GetVfrFileList(self):
3323 if self._VfrFileList == None:
3324 if TAB_VFR_FILE in self.FileTypes:
3325 self._VfrFileList = self.FileTypes[TAB_VFR_FILE]
3326 else:
3327 self._VfrFileList = []
3328 return self._VfrFileList
3329
3330 ## Return the list of Image Definition files
3331 def _GetIdfFileList(self):
3332 if self._IdfFileList == None:
3333 if TAB_IMAGE_FILE in self.FileTypes:
3334 self._IdfFileList = self.FileTypes[TAB_IMAGE_FILE]
3335 else:
3336 self._IdfFileList = []
3337 return self._IdfFileList
3338
3339 ## Return a list of files which can be built from binary
3340 #
3341 # "Build" binary files are just to copy them to build directory.
3342 #
3343 # @retval list The list of files which can be built later
3344 #
3345 def _GetBinaryFiles(self):
3346 if self._BinaryFileList == None:
3347 self._BinaryFileList = []
3348 for F in self.Module.Binaries:
3349 if F.Target not in ['COMMON', '*'] and F.Target != self.BuildTarget:
3350 continue
3351 self._BinaryFileList.append(F)
3352 self._ApplyBuildRule(F, F.Type)
3353 return self._BinaryFileList
3354
3355 def _GetBuildRules(self):
3356 if self._BuildRules == None:
3357 BuildRules = {}
3358 BuildRuleDatabase = self.PlatformInfo.BuildRule
3359 for Type in BuildRuleDatabase.FileTypeList:
3360 #first try getting build rule by BuildRuleFamily
3361 RuleObject = BuildRuleDatabase[Type, self.BuildType, self.Arch, self.BuildRuleFamily]
3362 if not RuleObject:
3363 # build type is always module type, but ...
3364 if self.ModuleType != self.BuildType:
3365 RuleObject = BuildRuleDatabase[Type, self.ModuleType, self.Arch, self.BuildRuleFamily]
3366 #second try getting build rule by ToolChainFamily
3367 if not RuleObject:
3368 RuleObject = BuildRuleDatabase[Type, self.BuildType, self.Arch, self.ToolChainFamily]
3369 if not RuleObject:
3370 # build type is always module type, but ...
3371 if self.ModuleType != self.BuildType:
3372 RuleObject = BuildRuleDatabase[Type, self.ModuleType, self.Arch, self.ToolChainFamily]
3373 if not RuleObject:
3374 continue
3375 RuleObject = RuleObject.Instantiate(self.Macros)
3376 BuildRules[Type] = RuleObject
3377 for Ext in RuleObject.SourceFileExtList:
3378 BuildRules[Ext] = RuleObject
3379 self._BuildRules = BuildRules
3380 return self._BuildRules
3381
3382 def _ApplyBuildRule(self, File, FileType):
3383 if self._BuildTargets == None:
3384 self._IntroBuildTargetList = set()
3385 self._FinalBuildTargetList = set()
3386 self._BuildTargets = {}
3387 self._FileTypes = {}
3388
3389 SubDirectory = os.path.join(self.OutputDir, File.SubDir)
3390 if not os.path.exists(SubDirectory):
3391 CreateDirectory(SubDirectory)
3392 LastTarget = None
3393 RuleChain = []
3394 SourceList = [File]
3395 Index = 0
3396 #
3397 # Make sure to get build rule order value
3398 #
3399 self._GetModuleBuildOption()
3400
3401 while Index < len(SourceList):
3402 Source = SourceList[Index]
3403 Index = Index + 1
3404
3405 if Source != File:
3406 CreateDirectory(Source.Dir)
3407
3408 if File.IsBinary and File == Source and self._BinaryFileList != None and File in self._BinaryFileList:
3409 # Skip all files that are not binary libraries
3410 if not self.IsLibrary:
3411 continue
3412 RuleObject = self.BuildRules[TAB_DEFAULT_BINARY_FILE]
3413 elif FileType in self.BuildRules:
3414 RuleObject = self.BuildRules[FileType]
3415 elif Source.Ext in self.BuildRules:
3416 RuleObject = self.BuildRules[Source.Ext]
3417 else:
3418 # stop at no more rules
3419 if LastTarget:
3420 self._FinalBuildTargetList.add(LastTarget)
3421 break
3422
3423 FileType = RuleObject.SourceFileType
3424 if FileType not in self._FileTypes:
3425 self._FileTypes[FileType] = set()
3426 self._FileTypes[FileType].add(Source)
3427
3428 # stop at STATIC_LIBRARY for library
3429 if self.IsLibrary and FileType == TAB_STATIC_LIBRARY:
3430 if LastTarget:
3431 self._FinalBuildTargetList.add(LastTarget)
3432 break
3433
3434 Target = RuleObject.Apply(Source, self.BuildRuleOrder)
3435 if not Target:
3436 if LastTarget:
3437 self._FinalBuildTargetList.add(LastTarget)
3438 break
3439 elif not Target.Outputs:
3440 # Only do build for target with outputs
3441 self._FinalBuildTargetList.add(Target)
3442
3443 if FileType not in self._BuildTargets:
3444 self._BuildTargets[FileType] = set()
3445 self._BuildTargets[FileType].add(Target)
3446
3447 if not Source.IsBinary and Source == File:
3448 self._IntroBuildTargetList.add(Target)
3449
3450 # to avoid cyclic rule
3451 if FileType in RuleChain:
3452 break
3453
3454 RuleChain.append(FileType)
3455 SourceList.extend(Target.Outputs)
3456 LastTarget = Target
3457 FileType = TAB_UNKNOWN_FILE
3458
3459 def _GetTargets(self):
3460 if self._BuildTargets == None:
3461 self._IntroBuildTargetList = set()
3462 self._FinalBuildTargetList = set()
3463 self._BuildTargets = {}
3464 self._FileTypes = {}
3465
3466 #TRICK: call _GetSourceFileList to apply build rule for source files
3467 if self.SourceFileList:
3468 pass
3469
3470 #TRICK: call _GetBinaryFileList to apply build rule for binary files
3471 if self.BinaryFileList:
3472 pass
3473
3474 return self._BuildTargets
3475
3476 def _GetIntroTargetList(self):
3477 self._GetTargets()
3478 return self._IntroBuildTargetList
3479
3480 def _GetFinalTargetList(self):
3481 self._GetTargets()
3482 return self._FinalBuildTargetList
3483
3484 def _GetFileTypes(self):
3485 self._GetTargets()
3486 return self._FileTypes
3487
3488 ## Get the list of package object the module depends on
3489 #
3490 # @retval list The package object list
3491 #
3492 def _GetDependentPackageList(self):
3493 return self.Module.Packages
3494
3495 ## Return the list of auto-generated code file
3496 #
3497 # @retval list The list of auto-generated file
3498 #
3499 def _GetAutoGenFileList(self):
3500 UniStringAutoGenC = True
3501 IdfStringAutoGenC = True
3502 UniStringBinBuffer = StringIO()
3503 IdfGenBinBuffer = StringIO()
3504 if self.BuildType == 'UEFI_HII':
3505 UniStringAutoGenC = False
3506 IdfStringAutoGenC = False
3507 if self._AutoGenFileList == None:
3508 self._AutoGenFileList = {}
3509 AutoGenC = TemplateString()
3510 AutoGenH = TemplateString()
3511 StringH = TemplateString()
3512 StringIdf = TemplateString()
3513 GenC.CreateCode(self, AutoGenC, AutoGenH, StringH, UniStringAutoGenC, UniStringBinBuffer, StringIdf, IdfStringAutoGenC, IdfGenBinBuffer)
3514 #
3515 # AutoGen.c is generated if there are library classes in inf, or there are object files
3516 #
3517 if str(AutoGenC) != "" and (len(self.Module.LibraryClasses) > 0
3518 or TAB_OBJECT_FILE in self.FileTypes):
3519 AutoFile = PathClass(gAutoGenCodeFileName, self.DebugDir)
3520 self._AutoGenFileList[AutoFile] = str(AutoGenC)
3521 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
3522 if str(AutoGenH) != "":
3523 AutoFile = PathClass(gAutoGenHeaderFileName, self.DebugDir)
3524 self._AutoGenFileList[AutoFile] = str(AutoGenH)
3525 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
3526 if str(StringH) != "":
3527 AutoFile = PathClass(gAutoGenStringFileName % {"module_name":self.Name}, self.DebugDir)
3528 self._AutoGenFileList[AutoFile] = str(StringH)
3529 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
3530 if UniStringBinBuffer != None and UniStringBinBuffer.getvalue() != "":
3531 AutoFile = PathClass(gAutoGenStringFormFileName % {"module_name":self.Name}, self.OutputDir)
3532 self._AutoGenFileList[AutoFile] = UniStringBinBuffer.getvalue()
3533 AutoFile.IsBinary = True
3534 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
3535 if UniStringBinBuffer != None:
3536 UniStringBinBuffer.close()
3537 if str(StringIdf) != "":
3538 AutoFile = PathClass(gAutoGenImageDefFileName % {"module_name":self.Name}, self.DebugDir)
3539 self._AutoGenFileList[AutoFile] = str(StringIdf)
3540 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
3541 if IdfGenBinBuffer != None and IdfGenBinBuffer.getvalue() != "":
3542 AutoFile = PathClass(gAutoGenIdfFileName % {"module_name":self.Name}, self.OutputDir)
3543 self._AutoGenFileList[AutoFile] = IdfGenBinBuffer.getvalue()
3544 AutoFile.IsBinary = True
3545 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
3546 if IdfGenBinBuffer != None:
3547 IdfGenBinBuffer.close()
3548 return self._AutoGenFileList
3549
3550 ## Return the list of library modules explicitly or implicityly used by this module
3551 def _GetLibraryList(self):
3552 if self._DependentLibraryList == None:
3553 # only merge library classes and PCD for non-library module
3554 if self.IsLibrary:
3555 self._DependentLibraryList = []
3556 else:
3557 if self.AutoGenVersion < 0x00010005:
3558 self._DependentLibraryList = self.PlatformInfo.ResolveLibraryReference(self.Module)
3559 else:
3560 self._DependentLibraryList = self.PlatformInfo.ApplyLibraryInstance(self.Module)
3561 return self._DependentLibraryList
3562
3563 @staticmethod
3564 def UpdateComments(Recver, Src):
3565 for Key in Src:
3566 if Key not in Recver:
3567 Recver[Key] = []
3568 Recver[Key].extend(Src[Key])
3569 ## Get the list of PCDs from current module
3570 #
3571 # @retval list The list of PCD
3572 #
3573 def _GetModulePcdList(self):
3574 if self._ModulePcdList == None:
3575 # apply PCD settings from platform
3576 self._ModulePcdList = self.PlatformInfo.ApplyPcdSetting(self.Module, self.Module.Pcds)
3577 self.UpdateComments(self._PcdComments, self.Module.PcdComments)
3578 return self._ModulePcdList
3579
3580 ## Get the list of PCDs from dependent libraries
3581 #
3582 # @retval list The list of PCD
3583 #
3584 def _GetLibraryPcdList(self):
3585 if self._LibraryPcdList == None:
3586 Pcds = sdict()
3587 if not self.IsLibrary:
3588 # get PCDs from dependent libraries
3589 for Library in self.DependentLibraryList:
3590 self.UpdateComments(self._PcdComments, Library.PcdComments)
3591 for Key in Library.Pcds:
3592 # skip duplicated PCDs
3593 if Key in self.Module.Pcds or Key in Pcds:
3594 continue
3595 Pcds[Key] = copy.copy(Library.Pcds[Key])
3596 # apply PCD settings from platform
3597 self._LibraryPcdList = self.PlatformInfo.ApplyPcdSetting(self.Module, Pcds)
3598 else:
3599 self._LibraryPcdList = []
3600 return self._LibraryPcdList
3601
3602 ## Get the GUID value mapping
3603 #
3604 # @retval dict The mapping between GUID cname and its value
3605 #
3606 def _GetGuidList(self):
3607 if self._GuidList == None:
3608 self._GuidList = sdict()
3609 self._GuidList.update(self.Module.Guids)
3610 for Library in self.DependentLibraryList:
3611 self._GuidList.update(Library.Guids)
3612 self.UpdateComments(self._GuidComments, Library.GuidComments)
3613 self.UpdateComments(self._GuidComments, self.Module.GuidComments)
3614 return self._GuidList
3615
3616 def GetGuidsUsedByPcd(self):
3617 if self._GuidsUsedByPcd == None:
3618 self._GuidsUsedByPcd = sdict()
3619 self._GuidsUsedByPcd.update(self.Module.GetGuidsUsedByPcd())
3620 for Library in self.DependentLibraryList:
3621 self._GuidsUsedByPcd.update(Library.GetGuidsUsedByPcd())
3622 return self._GuidsUsedByPcd
3623 ## Get the protocol value mapping
3624 #
3625 # @retval dict The mapping between protocol cname and its value
3626 #
3627 def _GetProtocolList(self):
3628 if self._ProtocolList == None:
3629 self._ProtocolList = sdict()
3630 self._ProtocolList.update(self.Module.Protocols)
3631 for Library in self.DependentLibraryList:
3632 self._ProtocolList.update(Library.Protocols)
3633 self.UpdateComments(self._ProtocolComments, Library.ProtocolComments)
3634 self.UpdateComments(self._ProtocolComments, self.Module.ProtocolComments)
3635 return self._ProtocolList
3636
3637 ## Get the PPI value mapping
3638 #
3639 # @retval dict The mapping between PPI cname and its value
3640 #
3641 def _GetPpiList(self):
3642 if self._PpiList == None:
3643 self._PpiList = sdict()
3644 self._PpiList.update(self.Module.Ppis)
3645 for Library in self.DependentLibraryList:
3646 self._PpiList.update(Library.Ppis)
3647 self.UpdateComments(self._PpiComments, Library.PpiComments)
3648 self.UpdateComments(self._PpiComments, self.Module.PpiComments)
3649 return self._PpiList
3650
3651 ## Get the list of include search path
3652 #
3653 # @retval list The list path
3654 #
3655 def _GetIncludePathList(self):
3656 if self._IncludePathList == None:
3657 self._IncludePathList = []
3658 if self.AutoGenVersion < 0x00010005:
3659 for Inc in self.Module.Includes:
3660 if Inc not in self._IncludePathList:
3661 self._IncludePathList.append(Inc)
3662 # for Edk modules
3663 Inc = path.join(Inc, self.Arch.capitalize())
3664 if os.path.exists(Inc) and Inc not in self._IncludePathList:
3665 self._IncludePathList.append(Inc)
3666 # Edk module needs to put DEBUG_DIR at the end of search path and not to use SOURCE_DIR all the time
3667 self._IncludePathList.append(self.DebugDir)
3668 else:
3669 self._IncludePathList.append(self.MetaFile.Dir)
3670 self._IncludePathList.append(self.DebugDir)
3671
3672 for Package in self.Module.Packages:
3673 PackageDir = mws.join(self.WorkspaceDir, Package.MetaFile.Dir)
3674 if PackageDir not in self._IncludePathList:
3675 self._IncludePathList.append(PackageDir)
3676 IncludesList = Package.Includes
3677 if Package._PrivateIncludes:
3678 if not self.MetaFile.Path.startswith(PackageDir):
3679 IncludesList = list(set(Package.Includes).difference(set(Package._PrivateIncludes)))
3680 for Inc in IncludesList:
3681 if Inc not in self._IncludePathList:
3682 self._IncludePathList.append(str(Inc))
3683 return self._IncludePathList
3684
3685 def _GetIncludePathLength(self):
3686 self._IncludePathLength = 0
3687 if self._IncludePathList:
3688 for inc in self._IncludePathList:
3689 self._IncludePathLength += len(' ' + inc)
3690 return self._IncludePathLength
3691
3692 ## Get HII EX PCDs which maybe used by VFR
3693 #
3694 # efivarstore used by VFR may relate with HII EX PCDs
3695 # Get the variable name and GUID from efivarstore and HII EX PCD
3696 # List the HII EX PCDs in As Built INF if both name and GUID match.
3697 #
3698 # @retval list HII EX PCDs
3699 #
3700 def _GetPcdsMaybeUsedByVfr(self):
3701 if not self.SourceFileList:
3702 return []
3703
3704 NameGuids = []
3705 for SrcFile in self.SourceFileList:
3706 if SrcFile.Ext.lower() != '.vfr':
3707 continue
3708 Vfri = os.path.join(self.OutputDir, SrcFile.BaseName + '.i')
3709 if not os.path.exists(Vfri):
3710 continue
3711 VfriFile = open(Vfri, 'r')
3712 Content = VfriFile.read()
3713 VfriFile.close()
3714 Pos = Content.find('efivarstore')
3715 while Pos != -1:
3716 #
3717 # Make sure 'efivarstore' is the start of efivarstore statement
3718 # In case of the value of 'name' (name = efivarstore) is equal to 'efivarstore'
3719 #
3720 Index = Pos - 1
3721 while Index >= 0 and Content[Index] in ' \t\r\n':
3722 Index -= 1
3723 if Index >= 0 and Content[Index] != ';':
3724 Pos = Content.find('efivarstore', Pos + len('efivarstore'))
3725 continue
3726 #
3727 # 'efivarstore' must be followed by name and guid
3728 #
3729 Name = gEfiVarStoreNamePattern.search(Content, Pos)
3730 if not Name:
3731 break
3732 Guid = gEfiVarStoreGuidPattern.search(Content, Pos)
3733 if not Guid:
3734 break
3735 NameArray = ConvertStringToByteArray('L"' + Name.group(1) + '"')
3736 NameGuids.append((NameArray, GuidStructureStringToGuidString(Guid.group(1))))
3737 Pos = Content.find('efivarstore', Name.end())
3738 if not NameGuids:
3739 return []
3740 HiiExPcds = []
3741 for Pcd in self.PlatformInfo.Platform.Pcds.values():
3742 if Pcd.Type != TAB_PCDS_DYNAMIC_EX_HII:
3743 continue
3744 for SkuName in Pcd.SkuInfoList:
3745 SkuInfo = Pcd.SkuInfoList[SkuName]
3746 Name = ConvertStringToByteArray(SkuInfo.VariableName)
3747 Value = GuidValue(SkuInfo.VariableGuid, self.PlatformInfo.PackageList, self.MetaFile.Path)
3748 if not Value:
3749 continue
3750 Guid = GuidStructureStringToGuidString(Value)
3751 if (Name, Guid) in NameGuids and Pcd not in HiiExPcds:
3752 HiiExPcds.append(Pcd)
3753 break
3754
3755 return HiiExPcds
3756
3757 def _GenOffsetBin(self):
3758 VfrUniBaseName = {}
3759 for SourceFile in self.Module.Sources:
3760 if SourceFile.Type.upper() == ".VFR" :
3761 #
3762 # search the .map file to find the offset of vfr binary in the PE32+/TE file.
3763 #
3764 VfrUniBaseName[SourceFile.BaseName] = (SourceFile.BaseName + "Bin")
3765 if SourceFile.Type.upper() == ".UNI" :
3766 #
3767 # search the .map file to find the offset of Uni strings binary in the PE32+/TE file.
3768 #
3769 VfrUniBaseName["UniOffsetName"] = (self.Name + "Strings")
3770
3771 if len(VfrUniBaseName) == 0:
3772 return None
3773 MapFileName = os.path.join(self.OutputDir, self.Name + ".map")
3774 EfiFileName = os.path.join(self.OutputDir, self.Name + ".efi")
3775 VfrUniOffsetList = GetVariableOffset(MapFileName, EfiFileName, VfrUniBaseName.values())
3776 if not VfrUniOffsetList:
3777 return None
3778
3779 OutputName = '%sOffset.bin' % self.Name
3780 UniVfrOffsetFileName = os.path.join( self.OutputDir, OutputName)
3781
3782 try:
3783 fInputfile = open(UniVfrOffsetFileName, "wb+", 0)
3784 except:
3785 EdkLogger.error("build", FILE_OPEN_FAILURE, "File open failed for %s" % UniVfrOffsetFileName,None)
3786
3787 # Use a instance of StringIO to cache data
3788 fStringIO = StringIO('')
3789
3790 for Item in VfrUniOffsetList:
3791 if (Item[0].find("Strings") != -1):
3792 #
3793 # UNI offset in image.
3794 # GUID + Offset
3795 # { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } }
3796 #
3797 UniGuid = [0xe0, 0xc5, 0x13, 0x89, 0xf6, 0x33, 0x86, 0x4d, 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66]
3798 UniGuid = [chr(ItemGuid) for ItemGuid in UniGuid]
3799 fStringIO.write(''.join(UniGuid))
3800 UniValue = pack ('Q', int (Item[1], 16))
3801 fStringIO.write (UniValue)
3802 else:
3803 #
3804 # VFR binary offset in image.
3805 # GUID + Offset
3806 # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } };
3807 #
3808 VfrGuid = [0xb4, 0x7c, 0xbc, 0xd0, 0x47, 0x6a, 0x5f, 0x49, 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2]
3809 VfrGuid = [chr(ItemGuid) for ItemGuid in VfrGuid]
3810 fStringIO.write(''.join(VfrGuid))
3811 type (Item[1])
3812 VfrValue = pack ('Q', int (Item[1], 16))
3813 fStringIO.write (VfrValue)
3814 #
3815 # write data into file.
3816 #
3817 try :
3818 fInputfile.write (fStringIO.getvalue())
3819 except:
3820 EdkLogger.error("build", FILE_WRITE_FAILURE, "Write data to file %s failed, please check whether the "
3821 "file been locked or using by other applications." %UniVfrOffsetFileName,None)
3822
3823 fStringIO.close ()
3824 fInputfile.close ()
3825 return OutputName
3826
3827 ## Create AsBuilt INF file the module
3828 #
3829 def CreateAsBuiltInf(self):
3830 if self.IsAsBuiltInfCreated:
3831 return
3832
3833 # Skip the following code for EDK I inf
3834 if self.AutoGenVersion < 0x00010005:
3835 return
3836
3837 # Skip the following code for libraries
3838 if self.IsLibrary:
3839 return
3840
3841 # Skip the following code for modules with no source files
3842 if self.SourceFileList == None or self.SourceFileList == []:
3843 return
3844
3845 # Skip the following code for modules without any binary files
3846 if self.BinaryFileList <> None and self.BinaryFileList <> []:
3847 return
3848
3849 ### TODO: How to handles mixed source and binary modules
3850
3851 # Find all DynamicEx and PatchableInModule PCDs used by this module and dependent libraries
3852 # Also find all packages that the DynamicEx PCDs depend on
3853 Pcds = []
3854 PatchablePcds = []
3855 Packages = []
3856 PcdCheckList = []
3857 PcdTokenSpaceList = []
3858 for Pcd in self.ModulePcdList + self.LibraryPcdList:
3859 if Pcd.Type == TAB_PCDS_PATCHABLE_IN_MODULE:
3860 PatchablePcds += [Pcd]
3861 PcdCheckList.append((Pcd.TokenCName, Pcd.TokenSpaceGuidCName, 'PatchableInModule'))
3862 elif Pcd.Type in GenC.gDynamicExPcd:
3863 if Pcd not in Pcds:
3864 Pcds += [Pcd]
3865 PcdCheckList.append((Pcd.TokenCName, Pcd.TokenSpaceGuidCName, 'DynamicEx'))
3866 PcdCheckList.append((Pcd.TokenCName, Pcd.TokenSpaceGuidCName, 'Dynamic'))
3867 PcdTokenSpaceList.append(Pcd.TokenSpaceGuidCName)
3868 GuidList = sdict()
3869 GuidList.update(self.GuidList)
3870 for TokenSpace in self.GetGuidsUsedByPcd():
3871 # If token space is not referred by patch PCD or Ex PCD, remove the GUID from GUID list
3872 # The GUIDs in GUIDs section should really be the GUIDs in source INF or referred by Ex an patch PCDs
3873 if TokenSpace not in PcdTokenSpaceList and TokenSpace in GuidList:
3874 GuidList.pop(TokenSpace)
3875 CheckList = (GuidList, self.PpiList, self.ProtocolList, PcdCheckList)
3876 for Package in self.DerivedPackageList:
3877 if Package in Packages:
3878 continue
3879 BeChecked = (Package.Guids, Package.Ppis, Package.Protocols, Package.Pcds)
3880 Found = False
3881 for Index in range(len(BeChecked)):
3882 for Item in CheckList[Index]:
3883 if Item in BeChecked[Index]:
3884 Packages += [Package]
3885 Found = True
3886 break
3887 if Found: break
3888
3889 VfrPcds = self._GetPcdsMaybeUsedByVfr()
3890 for Pkg in self.PlatformInfo.PackageList:
3891 if Pkg in Packages:
3892 continue
3893 for VfrPcd in VfrPcds:
3894 if ((VfrPcd.TokenCName, VfrPcd.TokenSpaceGuidCName, 'DynamicEx') in Pkg.Pcds or
3895 (VfrPcd.TokenCName, VfrPcd.TokenSpaceGuidCName, 'Dynamic') in Pkg.Pcds):
3896 Packages += [Pkg]
3897 break
3898
3899 ModuleType = self.ModuleType
3900 if ModuleType == 'UEFI_DRIVER' and self.DepexGenerated:
3901 ModuleType = 'DXE_DRIVER'
3902
3903 DriverType = ''
3904 if self.PcdIsDriver != '':
3905 DriverType = self.PcdIsDriver
3906
3907 Guid = self.Guid
3908 MDefs = self.Module.Defines
3909
3910 AsBuiltInfDict = {
3911 'module_name' : self.Name,
3912 'module_guid' : Guid,
3913 'module_module_type' : ModuleType,
3914 'module_version_string' : [MDefs['VERSION_STRING']] if 'VERSION_STRING' in MDefs else [],
3915 'pcd_is_driver_string' : [],
3916 'module_uefi_specification_version' : [],
3917 'module_pi_specification_version' : [],
3918 'module_entry_point' : self.Module.ModuleEntryPointList,
3919 'module_unload_image' : self.Module.ModuleUnloadImageList,
3920 'module_constructor' : self.Module.ConstructorList,
3921 'module_destructor' : self.Module.DestructorList,
3922 'module_shadow' : [MDefs['SHADOW']] if 'SHADOW' in MDefs else [],
3923 'module_pci_vendor_id' : [MDefs['PCI_VENDOR_ID']] if 'PCI_VENDOR_ID' in MDefs else [],
3924 'module_pci_device_id' : [MDefs['PCI_DEVICE_ID']] if 'PCI_DEVICE_ID' in MDefs else [],
3925 'module_pci_class_code' : [MDefs['PCI_CLASS_CODE']] if 'PCI_CLASS_CODE' in MDefs else [],
3926 'module_pci_revision' : [MDefs['PCI_REVISION']] if 'PCI_REVISION' in MDefs else [],
3927 'module_build_number' : [MDefs['BUILD_NUMBER']] if 'BUILD_NUMBER' in MDefs else [],
3928 'module_spec' : [MDefs['SPEC']] if 'SPEC' in MDefs else [],
3929 'module_uefi_hii_resource_section' : [MDefs['UEFI_HII_RESOURCE_SECTION']] if 'UEFI_HII_RESOURCE_SECTION' in MDefs else [],
3930 'module_uni_file' : [MDefs['MODULE_UNI_FILE']] if 'MODULE_UNI_FILE' in MDefs else [],
3931 'module_arch' : self.Arch,
3932 'package_item' : ['%s' % (Package.MetaFile.File.replace('\\', '/')) for Package in Packages],
3933 'binary_item' : [],
3934 'patchablepcd_item' : [],
3935 'pcd_item' : [],
3936 'protocol_item' : [],
3937 'ppi_item' : [],
3938 'guid_item' : [],
3939 'flags_item' : [],
3940 'libraryclasses_item' : []
3941 }
3942
3943 if 'MODULE_UNI_FILE' in MDefs:
3944 UNIFile = os.path.join(self.MetaFile.Dir, MDefs['MODULE_UNI_FILE'])
3945 if os.path.isfile(UNIFile):
3946 shutil.copy2(UNIFile, self.OutputDir)
3947
3948 if self.AutoGenVersion > int(gInfSpecVersion, 0):
3949 AsBuiltInfDict['module_inf_version'] = '0x%08x' % self.AutoGenVersion
3950 else:
3951 AsBuiltInfDict['module_inf_version'] = gInfSpecVersion
3952
3953 if DriverType:
3954 AsBuiltInfDict['pcd_is_driver_string'] += [DriverType]
3955
3956 if 'UEFI_SPECIFICATION_VERSION' in self.Specification:
3957 AsBuiltInfDict['module_uefi_specification_version'] += [self.Specification['UEFI_SPECIFICATION_VERSION']]
3958 if 'PI_SPECIFICATION_VERSION' in self.Specification:
3959 AsBuiltInfDict['module_pi_specification_version'] += [self.Specification['PI_SPECIFICATION_VERSION']]
3960
3961 OutputDir = self.OutputDir.replace('\\', '/').strip('/')
3962 self.OutputFile = []
3963 for Item in self.CodaTargetList:
3964 File = Item.Target.Path.replace('\\', '/').strip('/').replace(OutputDir, '').strip('/')
3965 if File not in self.OutputFile:
3966 self.OutputFile.append(File)
3967 if Item.Target.Ext.lower() == '.aml':
3968 AsBuiltInfDict['binary_item'] += ['ASL|' + File]
3969 elif Item.Target.Ext.lower() == '.acpi':
3970 AsBuiltInfDict['binary_item'] += ['ACPI|' + File]
3971 elif Item.Target.Ext.lower() == '.efi':
3972 AsBuiltInfDict['binary_item'] += ['PE32|' + self.Name + '.efi']
3973 else:
3974 AsBuiltInfDict['binary_item'] += ['BIN|' + File]
3975 if self.DepexGenerated:
3976 if self.Name + '.depex' not in self.OutputFile:
3977 self.OutputFile.append(self.Name + '.depex')
3978 if self.ModuleType in ['PEIM']:
3979 AsBuiltInfDict['binary_item'] += ['PEI_DEPEX|' + self.Name + '.depex']
3980 if self.ModuleType in ['DXE_DRIVER', 'DXE_RUNTIME_DRIVER', 'DXE_SAL_DRIVER', 'UEFI_DRIVER']:
3981 AsBuiltInfDict['binary_item'] += ['DXE_DEPEX|' + self.Name + '.depex']
3982 if self.ModuleType in ['DXE_SMM_DRIVER']:
3983 AsBuiltInfDict['binary_item'] += ['SMM_DEPEX|' + self.Name + '.depex']
3984
3985 Bin = self._GenOffsetBin()
3986 if Bin:
3987 AsBuiltInfDict['binary_item'] += ['BIN|%s' % Bin]
3988 if Bin not in self.OutputFile:
3989 self.OutputFile.append(Bin)
3990
3991 for Root, Dirs, Files in os.walk(OutputDir):
3992 for File in Files:
3993 if File.lower().endswith('.pdb'):
3994 AsBuiltInfDict['binary_item'] += ['DISPOSABLE|' + File]
3995 if File not in self.OutputFile:
3996 self.OutputFile.append(File)
3997 HeaderComments = self.Module.HeaderComments
3998 StartPos = 0
3999 for Index in range(len(HeaderComments)):
4000 if HeaderComments[Index].find('@BinaryHeader') != -1:
4001 HeaderComments[Index] = HeaderComments[Index].replace('@BinaryHeader', '@file')
4002 StartPos = Index
4003 break
4004 AsBuiltInfDict['header_comments'] = '\n'.join(HeaderComments[StartPos:]).replace(':#', '://')
4005 AsBuiltInfDict['tail_comments'] = '\n'.join(self.Module.TailComments)
4006
4007 GenList = [
4008 (self.ProtocolList, self._ProtocolComments, 'protocol_item'),
4009 (self.PpiList, self._PpiComments, 'ppi_item'),
4010 (GuidList, self._GuidComments, 'guid_item')
4011 ]
4012 for Item in GenList:
4013 for CName in Item[0]:
4014 Comments = ''
4015 if CName in Item[1]:
4016 Comments = '\n '.join(Item[1][CName])
4017 Entry = CName
4018 if Comments:
4019 Entry = Comments + '\n ' + CName
4020 AsBuiltInfDict[Item[2]].append(Entry)
4021 PatchList = parsePcdInfoFromMapFile(
4022 os.path.join(self.OutputDir, self.Name + '.map'),
4023 os.path.join(self.OutputDir, self.Name + '.efi')
4024 )
4025 if PatchList:
4026 for Pcd in PatchablePcds:
4027 TokenCName = Pcd.TokenCName
4028 for PcdItem in GlobalData.MixedPcd:
4029 if (Pcd.TokenCName, Pcd.TokenSpaceGuidCName) in GlobalData.MixedPcd[PcdItem]:
4030 TokenCName = PcdItem[0]
4031 break
4032 for PatchPcd in PatchList:
4033 if TokenCName == PatchPcd[0]:
4034 break
4035 else:
4036 continue
4037 PcdValue = ''
4038 if Pcd.DatumType == 'BOOLEAN':
4039 BoolValue = Pcd.DefaultValue.upper()
4040 if BoolValue == 'TRUE':
4041 Pcd.DefaultValue = '1'
4042 elif BoolValue == 'FALSE':
4043 Pcd.DefaultValue = '0'
4044
4045 if Pcd.DatumType != 'VOID*':
4046 HexFormat = '0x%02x'
4047 if Pcd.DatumType == 'UINT16':
4048 HexFormat = '0x%04x'
4049 elif Pcd.DatumType == 'UINT32':
4050 HexFormat = '0x%08x'
4051 elif Pcd.DatumType == 'UINT64':
4052 HexFormat = '0x%016x'
4053 PcdValue = HexFormat % int(Pcd.DefaultValue, 0)
4054 else:
4055 if Pcd.MaxDatumSize == None or Pcd.MaxDatumSize == '':
4056 EdkLogger.error("build", AUTOGEN_ERROR,
4057 "Unknown [MaxDatumSize] of PCD [%s.%s]" % (Pcd.TokenSpaceGuidCName, TokenCName)
4058 )
4059 ArraySize = int(Pcd.MaxDatumSize, 0)
4060 PcdValue = Pcd.DefaultValue
4061 if PcdValue[0] != '{':
4062 Unicode = False
4063 if PcdValue[0] == 'L':
4064 Unicode = True
4065 PcdValue = PcdValue.lstrip('L')
4066 PcdValue = eval(PcdValue)
4067 NewValue = '{'
4068 for Index in range(0, len(PcdValue)):
4069 if Unicode:
4070 CharVal = ord(PcdValue[Index])
4071 NewValue = NewValue + '0x%02x' % (CharVal & 0x00FF) + ', ' \
4072 + '0x%02x' % (CharVal >> 8) + ', '
4073 else:
4074 NewValue = NewValue + '0x%02x' % (ord(PcdValue[Index]) % 0x100) + ', '
4075 Padding = '0x00, '
4076 if Unicode:
4077 Padding = Padding * 2
4078 ArraySize = ArraySize / 2
4079 if ArraySize < (len(PcdValue) + 1):
4080 EdkLogger.error("build", AUTOGEN_ERROR,
4081 "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd.TokenSpaceGuidCName, TokenCName)
4082 )
4083 if ArraySize > len(PcdValue) + 1:
4084 NewValue = NewValue + Padding * (ArraySize - len(PcdValue) - 1)
4085 PcdValue = NewValue + Padding.strip().rstrip(',') + '}'
4086 elif len(PcdValue.split(',')) <= ArraySize:
4087 PcdValue = PcdValue.rstrip('}') + ', 0x00' * (ArraySize - len(PcdValue.split(',')))
4088 PcdValue += '}'
4089 else:
4090 EdkLogger.error("build", AUTOGEN_ERROR,
4091 "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd.TokenSpaceGuidCName, TokenCName)
4092 )
4093 PcdItem = '%s.%s|%s|0x%X' % \
4094 (Pcd.TokenSpaceGuidCName, TokenCName, PcdValue, PatchPcd[1])
4095 PcdComments = ''
4096 if (Pcd.TokenSpaceGuidCName, Pcd.TokenCName) in self._PcdComments:
4097 PcdComments = '\n '.join(self._PcdComments[Pcd.TokenSpaceGuidCName, Pcd.TokenCName])
4098 if PcdComments:
4099 PcdItem = PcdComments + '\n ' + PcdItem
4100 AsBuiltInfDict['patchablepcd_item'].append(PcdItem)
4101
4102 HiiPcds = []
4103 for Pcd in Pcds + VfrPcds:
4104 PcdComments = ''
4105 PcdCommentList = []
4106 HiiInfo = ''
4107 SkuId = ''
4108 TokenCName = Pcd.TokenCName
4109 for PcdItem in GlobalData.MixedPcd:
4110 if (Pcd.TokenCName, Pcd.TokenSpaceGuidCName) in GlobalData.MixedPcd[PcdItem]:
4111 TokenCName = PcdItem[0]
4112 break
4113 if Pcd.Type == TAB_PCDS_DYNAMIC_EX_HII:
4114 for SkuName in Pcd.SkuInfoList:
4115 SkuInfo = Pcd.SkuInfoList[SkuName]
4116 SkuId = SkuInfo.SkuId
4117 HiiInfo = '## %s|%s|%s' % (SkuInfo.VariableName, SkuInfo.VariableGuid, SkuInfo.VariableOffset)
4118 break
4119 if SkuId:
4120 #
4121 # Don't generate duplicated HII PCD
4122 #
4123 if (SkuId, Pcd.TokenSpaceGuidCName, Pcd.TokenCName) in HiiPcds:
4124 continue
4125 else:
4126 HiiPcds.append((SkuId, Pcd.TokenSpaceGuidCName, Pcd.TokenCName))
4127 if (Pcd.TokenSpaceGuidCName, Pcd.TokenCName) in self._PcdComments:
4128 PcdCommentList = self._PcdComments[Pcd.TokenSpaceGuidCName, Pcd.TokenCName][:]
4129 if HiiInfo:
4130 UsageIndex = -1
4131 UsageStr = ''
4132 for Index, Comment in enumerate(PcdCommentList):
4133 for Usage in UsageList:
4134 if Comment.find(Usage) != -1:
4135 UsageStr = Usage
4136 UsageIndex = Index
4137 break
4138 if UsageIndex != -1:
4139 PcdCommentList[UsageIndex] = '## %s %s %s' % (UsageStr, HiiInfo, PcdCommentList[UsageIndex].replace(UsageStr, ''))
4140 else:
4141 PcdCommentList.append('## UNDEFINED ' + HiiInfo)
4142 PcdComments = '\n '.join(PcdCommentList)
4143 PcdEntry = Pcd.TokenSpaceGuidCName + '.' + TokenCName
4144 if PcdComments:
4145 PcdEntry = PcdComments + '\n ' + PcdEntry
4146 AsBuiltInfDict['pcd_item'] += [PcdEntry]
4147 for Item in self.BuildOption:
4148 if 'FLAGS' in self.BuildOption[Item]:
4149 AsBuiltInfDict['flags_item'] += ['%s:%s_%s_%s_%s_FLAGS = %s' % (self.ToolChainFamily, self.BuildTarget, self.ToolChain, self.Arch, Item, self.BuildOption[Item]['FLAGS'].strip())]
4150
4151 # Generated LibraryClasses section in comments.
4152 for Library in self.LibraryAutoGenList:
4153 AsBuiltInfDict['libraryclasses_item'] += [Library.MetaFile.File.replace('\\', '/')]
4154
4155 # Generated UserExtensions TianoCore section.
4156 # All tianocore user extensions are copied.
4157 UserExtStr = ''
4158 for TianoCore in self._GetTianoCoreUserExtensionList():
4159 UserExtStr += '\n'.join(TianoCore)
4160 ExtensionFile = os.path.join(self.MetaFile.Dir, TianoCore[1])
4161 if os.path.isfile(ExtensionFile):
4162 shutil.copy2(ExtensionFile, self.OutputDir)
4163 AsBuiltInfDict['userextension_tianocore_item'] = UserExtStr
4164
4165 # Generated depex expression section in comments.
4166 AsBuiltInfDict['depexsection_item'] = ''
4167 DepexExpresion = self._GetDepexExpresionString()
4168 if DepexExpresion:
4169 AsBuiltInfDict['depexsection_item'] = DepexExpresion
4170
4171 AsBuiltInf = TemplateString()
4172 AsBuiltInf.Append(gAsBuiltInfHeaderString.Replace(AsBuiltInfDict))
4173
4174 SaveFileOnChange(os.path.join(self.OutputDir, self.Name + '.inf'), str(AsBuiltInf), False)
4175
4176 self.IsAsBuiltInfCreated = True
4177 if GlobalData.gBinCacheDest:
4178 self.CopyModuleToCache()
4179
4180 def CopyModuleToCache(self):
4181 FileDir = path.join(GlobalData.gBinCacheDest, self.Arch, self.SourceDir, self.MetaFile.BaseName)
4182 CreateDirectory (FileDir)
4183 HashFile = path.join(self.BuildDir, self.Name + '.hash')
4184 ModuleFile = path.join(self.OutputDir, self.Name + '.inf')
4185 if os.path.exists(HashFile):
4186 shutil.copy2(HashFile, FileDir)
4187 if os.path.exists(ModuleFile):
4188 shutil.copy2(ModuleFile, FileDir)
4189 if self.OutputFile:
4190 for File in self.OutputFile:
4191 if not os.path.isabs(File):
4192 File = os.path.join(self.OutputDir, File)
4193 if os.path.exists(File):
4194 shutil.copy2(File, FileDir)
4195
4196 def AttemptModuleCacheCopy(self):
4197 if self.IsBinaryModule:
4198 return False
4199 FileDir = path.join(GlobalData.gBinCacheSource, self.Arch, self.SourceDir, self.MetaFile.BaseName)
4200 HashFile = path.join(FileDir, self.Name + '.hash')
4201 if os.path.exists(HashFile):
4202 f = open(HashFile, 'r')
4203 CacheHash = f.read()
4204 f.close()
4205 if GlobalData.gModuleHash[self.Arch][self.Name]:
4206 if CacheHash == GlobalData.gModuleHash[self.Arch][self.Name]:
4207 for root, dir, files in os.walk(FileDir):
4208 for f in files:
4209 if self.Name + '.hash' in f:
4210 shutil.copy2(HashFile, self.BuildDir)
4211 else:
4212 File = path.join(root, f)
4213 shutil.copy2(File, self.OutputDir)
4214 if self.Name == "PcdPeim" or self.Name == "PcdDxe":
4215 CreatePcdDatabaseCode(self, TemplateString(), TemplateString())
4216 return True
4217 return False
4218
4219 ## Create makefile for the module and its dependent libraries
4220 #
4221 # @param CreateLibraryMakeFile Flag indicating if or not the makefiles of
4222 # dependent libraries will be created
4223 #
4224 def CreateMakeFile(self, CreateLibraryMakeFile=True):
4225 # Ignore generating makefile when it is a binary module
4226 if self.IsBinaryModule:
4227 return
4228
4229 if self.IsMakeFileCreated:
4230 return
4231 if self.CanSkip():
4232 return
4233
4234 if not self.IsLibrary and CreateLibraryMakeFile:
4235 for LibraryAutoGen in self.LibraryAutoGenList:
4236 LibraryAutoGen.CreateMakeFile()
4237
4238 if len(self.CustomMakefile) == 0:
4239 Makefile = GenMake.ModuleMakefile(self)
4240 else:
4241 Makefile = GenMake.CustomMakefile(self)
4242 if Makefile.Generate():
4243 EdkLogger.debug(EdkLogger.DEBUG_9, "Generated makefile for module %s [%s]" %
4244 (self.Name, self.Arch))
4245 else:
4246 EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of makefile for module %s [%s]" %
4247 (self.Name, self.Arch))
4248
4249 self.CreateTimeStamp(Makefile)
4250 self.IsMakeFileCreated = True
4251
4252 def CopyBinaryFiles(self):
4253 for File in self.Module.Binaries:
4254 SrcPath = File.Path
4255 DstPath = os.path.join(self.OutputDir , os.path.basename(SrcPath))
4256 CopyLongFilePath(SrcPath, DstPath)
4257 ## Create autogen code for the module and its dependent libraries
4258 #
4259 # @param CreateLibraryCodeFile Flag indicating if or not the code of
4260 # dependent libraries will be created
4261 #
4262 def CreateCodeFile(self, CreateLibraryCodeFile=True):
4263 if self.IsCodeFileCreated:
4264 return
4265 if self.CanSkip():
4266 return
4267
4268 # Need to generate PcdDatabase even PcdDriver is binarymodule
4269 if self.IsBinaryModule and self.PcdIsDriver != '':
4270 CreatePcdDatabaseCode(self, TemplateString(), TemplateString())
4271 return
4272 if self.IsBinaryModule:
4273 if self.IsLibrary:
4274 self.CopyBinaryFiles()
4275 return
4276
4277 if not self.IsLibrary and CreateLibraryCodeFile:
4278 for LibraryAutoGen in self.LibraryAutoGenList:
4279 LibraryAutoGen.CreateCodeFile()
4280
4281 AutoGenList = []
4282 IgoredAutoGenList = []
4283
4284 for File in self.AutoGenFileList:
4285 if GenC.Generate(File.Path, self.AutoGenFileList[File], File.IsBinary):
4286 #Ignore Edk AutoGen.c
4287 if self.AutoGenVersion < 0x00010005 and File.Name == 'AutoGen.c':
4288 continue
4289
4290 AutoGenList.append(str(File))
4291 else:
4292 IgoredAutoGenList.append(str(File))
4293
4294 # Skip the following code for EDK I inf
4295 if self.AutoGenVersion < 0x00010005:
4296 return
4297
4298 for ModuleType in self.DepexList:
4299 # Ignore empty [depex] section or [depex] section for "USER_DEFINED" module
4300 if len(self.DepexList[ModuleType]) == 0 or ModuleType == "USER_DEFINED":
4301 continue
4302
4303 Dpx = GenDepex.DependencyExpression(self.DepexList[ModuleType], ModuleType, True)
4304 DpxFile = gAutoGenDepexFileName % {"module_name" : self.Name}
4305
4306 if len(Dpx.PostfixNotation) <> 0:
4307 self.DepexGenerated = True
4308
4309 if Dpx.Generate(path.join(self.OutputDir, DpxFile)):
4310 AutoGenList.append(str(DpxFile))
4311 else:
4312 IgoredAutoGenList.append(str(DpxFile))
4313
4314 if IgoredAutoGenList == []:
4315 EdkLogger.debug(EdkLogger.DEBUG_9, "Generated [%s] files for module %s [%s]" %
4316 (" ".join(AutoGenList), self.Name, self.Arch))
4317 elif AutoGenList == []:
4318 EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of [%s] files for module %s [%s]" %
4319 (" ".join(IgoredAutoGenList), self.Name, self.Arch))
4320 else:
4321 EdkLogger.debug(EdkLogger.DEBUG_9, "Generated [%s] (skipped %s) files for module %s [%s]" %
4322 (" ".join(AutoGenList), " ".join(IgoredAutoGenList), self.Name, self.Arch))
4323
4324 self.IsCodeFileCreated = True
4325 return AutoGenList
4326
4327 ## Summarize the ModuleAutoGen objects of all libraries used by this module
4328 def _GetLibraryAutoGenList(self):
4329 if self._LibraryAutoGenList == None:
4330 self._LibraryAutoGenList = []
4331 for Library in self.DependentLibraryList:
4332 La = ModuleAutoGen(
4333 self.Workspace,
4334 Library.MetaFile,
4335 self.BuildTarget,
4336 self.ToolChain,
4337 self.Arch,
4338 self.PlatformInfo.MetaFile
4339 )
4340 if La not in self._LibraryAutoGenList:
4341 self._LibraryAutoGenList.append(La)
4342 for Lib in La.CodaTargetList:
4343 self._ApplyBuildRule(Lib.Target, TAB_UNKNOWN_FILE)
4344 return self._LibraryAutoGenList
4345
4346 def GenModuleHash(self):
4347 if self.Arch not in GlobalData.gModuleHash:
4348 GlobalData.gModuleHash[self.Arch] = {}
4349 m = hashlib.md5()
4350 # Add Platform level hash
4351 m.update(GlobalData.gPlatformHash)
4352 # Add Package level hash
4353 if self.DependentPackageList:
4354 for Pkg in self.DependentPackageList:
4355 if Pkg.PackageName in GlobalData.gPackageHash[self.Arch]:
4356 m.update(GlobalData.gPackageHash[self.Arch][Pkg.PackageName])
4357
4358 # Add Library hash
4359 if self.LibraryAutoGenList:
4360 for Lib in self.LibraryAutoGenList:
4361 if Lib.Name not in GlobalData.gModuleHash[self.Arch]:
4362 Lib.GenModuleHash()
4363 m.update(GlobalData.gModuleHash[self.Arch][Lib.Name])
4364
4365 # Add Module self
4366 f = open(str(self.MetaFile), 'r')
4367 Content = f.read()
4368 f.close()
4369 m.update(Content)
4370 # Add Module's source files
4371 if self.SourceFileList:
4372 for File in self.SourceFileList:
4373 f = open(str(File), 'r')
4374 Content = f.read()
4375 f.close()
4376 m.update(Content)
4377
4378 ModuleHashFile = path.join(self.BuildDir, self.Name + ".hash")
4379 if self.Name not in GlobalData.gModuleHash[self.Arch]:
4380 GlobalData.gModuleHash[self.Arch][self.Name] = m.hexdigest()
4381 if GlobalData.gBinCacheSource:
4382 CacheValid = self.AttemptModuleCacheCopy()
4383 if CacheValid:
4384 return False
4385 return SaveFileOnChange(ModuleHashFile, m.hexdigest(), True)
4386
4387 ## Decide whether we can skip the ModuleAutoGen process
4388 def CanSkipbyHash(self):
4389 if GlobalData.gUseHashCache:
4390 return not self.GenModuleHash()
4391
4392 ## Decide whether we can skip the ModuleAutoGen process
4393 # If any source file is newer than the module than we cannot skip
4394 #
4395 def CanSkip(self):
4396 if not os.path.exists(self.GetTimeStampPath()):
4397 return False
4398 #last creation time of the module
4399 DstTimeStamp = os.stat(self.GetTimeStampPath())[8]
4400
4401 SrcTimeStamp = self.Workspace._SrcTimeStamp
4402 if SrcTimeStamp > DstTimeStamp:
4403 return False
4404
4405 with open(self.GetTimeStampPath(),'r') as f:
4406 for source in f:
4407 source = source.rstrip('\n')
4408 if not os.path.exists(source):
4409 return False
4410 if source not in ModuleAutoGen.TimeDict :
4411 ModuleAutoGen.TimeDict[source] = os.stat(source)[8]
4412 if ModuleAutoGen.TimeDict[source] > DstTimeStamp:
4413 return False
4414 return True
4415
4416 def GetTimeStampPath(self):
4417 if self._TimeStampPath == None:
4418 self._TimeStampPath = os.path.join(self.MakeFileDir, 'AutoGenTimeStamp')
4419 return self._TimeStampPath
4420 def CreateTimeStamp(self, Makefile):
4421
4422 FileSet = set()
4423
4424 FileSet.add (self.MetaFile.Path)
4425
4426 for SourceFile in self.Module.Sources:
4427 FileSet.add (SourceFile.Path)
4428
4429 for Lib in self.DependentLibraryList:
4430 FileSet.add (Lib.MetaFile.Path)
4431
4432 for f in self.AutoGenDepSet:
4433 FileSet.add (f.Path)
4434
4435 if os.path.exists (self.GetTimeStampPath()):
4436 os.remove (self.GetTimeStampPath())
4437 with open(self.GetTimeStampPath(), 'w+') as file:
4438 for f in FileSet:
4439 print >> file, f
4440
4441 Module = property(_GetModule)
4442 Name = property(_GetBaseName)
4443 Guid = property(_GetGuid)
4444 Version = property(_GetVersion)
4445 ModuleType = property(_GetModuleType)
4446 ComponentType = property(_GetComponentType)
4447 BuildType = property(_GetBuildType)
4448 PcdIsDriver = property(_GetPcdIsDriver)
4449 AutoGenVersion = property(_GetAutoGenVersion)
4450 Macros = property(_GetMacros)
4451 Specification = property(_GetSpecification)
4452
4453 IsLibrary = property(_IsLibrary)
4454 IsBinaryModule = property(_IsBinaryModule)
4455 BuildDir = property(_GetBuildDir)
4456 OutputDir = property(_GetOutputDir)
4457 DebugDir = property(_GetDebugDir)
4458 MakeFileDir = property(_GetMakeFileDir)
4459 CustomMakefile = property(_GetCustomMakefile)
4460
4461 IncludePathList = property(_GetIncludePathList)
4462 IncludePathLength = property(_GetIncludePathLength)
4463 AutoGenFileList = property(_GetAutoGenFileList)
4464 UnicodeFileList = property(_GetUnicodeFileList)
4465 VfrFileList = property(_GetVfrFileList)
4466 SourceFileList = property(_GetSourceFileList)
4467 BinaryFileList = property(_GetBinaryFiles) # FileType : [File List]
4468 Targets = property(_GetTargets)
4469 IntroTargetList = property(_GetIntroTargetList)
4470 CodaTargetList = property(_GetFinalTargetList)
4471 FileTypes = property(_GetFileTypes)
4472 BuildRules = property(_GetBuildRules)
4473 IdfFileList = property(_GetIdfFileList)
4474
4475 DependentPackageList = property(_GetDependentPackageList)
4476 DependentLibraryList = property(_GetLibraryList)
4477 LibraryAutoGenList = property(_GetLibraryAutoGenList)
4478 DerivedPackageList = property(_GetDerivedPackageList)
4479
4480 ModulePcdList = property(_GetModulePcdList)
4481 LibraryPcdList = property(_GetLibraryPcdList)
4482 GuidList = property(_GetGuidList)
4483 ProtocolList = property(_GetProtocolList)
4484 PpiList = property(_GetPpiList)
4485 DepexList = property(_GetDepexTokenList)
4486 DxsFile = property(_GetDxsFile)
4487 DepexExpressionList = property(_GetDepexExpressionTokenList)
4488 BuildOption = property(_GetModuleBuildOption)
4489 BuildOptionIncPathList = property(_GetBuildOptionIncPathList)
4490 BuildCommand = property(_GetBuildCommand)
4491
4492 FixedAtBuildPcds = property(_GetFixedAtBuildPcds)
4493
4494 # This acts like the main() function for the script, unless it is 'import'ed into another script.
4495 if __name__ == '__main__':
4496 pass
4497