]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/AutoGen/AutoGen.py
BaseTools: Fix the bug to re-build uni file for Library
[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 GlobalData.gBuildDirectory = self._BuildDir
1802 return self._BuildDir
1803
1804 ## Return directory of platform makefile
1805 #
1806 # @retval string Makefile directory
1807 #
1808 def _GetMakeFileDir(self):
1809 if self._MakeFileDir == None:
1810 self._MakeFileDir = path.join(self.BuildDir, self.Arch)
1811 return self._MakeFileDir
1812
1813 ## Return build command string
1814 #
1815 # @retval string Build command string
1816 #
1817 def _GetBuildCommand(self):
1818 if self._BuildCommand == None:
1819 self._BuildCommand = []
1820 if "MAKE" in self.ToolDefinition and "PATH" in self.ToolDefinition["MAKE"]:
1821 self._BuildCommand += SplitOption(self.ToolDefinition["MAKE"]["PATH"])
1822 if "FLAGS" in self.ToolDefinition["MAKE"]:
1823 NewOption = self.ToolDefinition["MAKE"]["FLAGS"].strip()
1824 if NewOption != '':
1825 self._BuildCommand += SplitOption(NewOption)
1826 return self._BuildCommand
1827
1828 ## Get tool chain definition
1829 #
1830 # Get each tool defition for given tool chain from tools_def.txt and platform
1831 #
1832 def _GetToolDefinition(self):
1833 if self._ToolDefinitions == None:
1834 ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDictionary
1835 if TAB_TOD_DEFINES_COMMAND_TYPE not in self.Workspace.ToolDef.ToolsDefTxtDatabase:
1836 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "No tools found in configuration",
1837 ExtraData="[%s]" % self.MetaFile)
1838 self._ToolDefinitions = {}
1839 DllPathList = set()
1840 for Def in ToolDefinition:
1841 Target, Tag, Arch, Tool, Attr = Def.split("_")
1842 if Target != self.BuildTarget or Tag != self.ToolChain or Arch != self.Arch:
1843 continue
1844
1845 Value = ToolDefinition[Def]
1846 # don't record the DLL
1847 if Attr == "DLL":
1848 DllPathList.add(Value)
1849 continue
1850
1851 if Tool not in self._ToolDefinitions:
1852 self._ToolDefinitions[Tool] = {}
1853 self._ToolDefinitions[Tool][Attr] = Value
1854
1855 ToolsDef = ''
1856 MakePath = ''
1857 if GlobalData.gOptions.SilentMode and "MAKE" in self._ToolDefinitions:
1858 if "FLAGS" not in self._ToolDefinitions["MAKE"]:
1859 self._ToolDefinitions["MAKE"]["FLAGS"] = ""
1860 self._ToolDefinitions["MAKE"]["FLAGS"] += " -s"
1861 MakeFlags = ''
1862 for Tool in self._ToolDefinitions:
1863 for Attr in self._ToolDefinitions[Tool]:
1864 Value = self._ToolDefinitions[Tool][Attr]
1865 if Tool in self.BuildOption and Attr in self.BuildOption[Tool]:
1866 # check if override is indicated
1867 if self.BuildOption[Tool][Attr].startswith('='):
1868 Value = self.BuildOption[Tool][Attr][1:]
1869 else:
1870 if Attr != 'PATH':
1871 Value += " " + self.BuildOption[Tool][Attr]
1872 else:
1873 Value = self.BuildOption[Tool][Attr]
1874
1875 if Attr == "PATH":
1876 # Don't put MAKE definition in the file
1877 if Tool == "MAKE":
1878 MakePath = Value
1879 else:
1880 ToolsDef += "%s = %s\n" % (Tool, Value)
1881 elif Attr != "DLL":
1882 # Don't put MAKE definition in the file
1883 if Tool == "MAKE":
1884 if Attr == "FLAGS":
1885 MakeFlags = Value
1886 else:
1887 ToolsDef += "%s_%s = %s\n" % (Tool, Attr, Value)
1888 ToolsDef += "\n"
1889
1890 SaveFileOnChange(self.ToolDefinitionFile, ToolsDef)
1891 for DllPath in DllPathList:
1892 os.environ["PATH"] = DllPath + os.pathsep + os.environ["PATH"]
1893 os.environ["MAKE_FLAGS"] = MakeFlags
1894
1895 return self._ToolDefinitions
1896
1897 ## Return the paths of tools
1898 def _GetToolDefFile(self):
1899 if self._ToolDefFile == None:
1900 self._ToolDefFile = os.path.join(self.MakeFileDir, "TOOLS_DEF." + self.Arch)
1901 return self._ToolDefFile
1902
1903 ## Retrieve the toolchain family of given toolchain tag. Default to 'MSFT'.
1904 def _GetToolChainFamily(self):
1905 if self._ToolChainFamily == None:
1906 ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDatabase
1907 if TAB_TOD_DEFINES_FAMILY not in ToolDefinition \
1908 or self.ToolChain not in ToolDefinition[TAB_TOD_DEFINES_FAMILY] \
1909 or not ToolDefinition[TAB_TOD_DEFINES_FAMILY][self.ToolChain]:
1910 EdkLogger.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
1911 % self.ToolChain)
1912 self._ToolChainFamily = "MSFT"
1913 else:
1914 self._ToolChainFamily = ToolDefinition[TAB_TOD_DEFINES_FAMILY][self.ToolChain]
1915 return self._ToolChainFamily
1916
1917 def _GetBuildRuleFamily(self):
1918 if self._BuildRuleFamily == None:
1919 ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDatabase
1920 if TAB_TOD_DEFINES_BUILDRULEFAMILY not in ToolDefinition \
1921 or self.ToolChain not in ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY] \
1922 or not ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY][self.ToolChain]:
1923 EdkLogger.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
1924 % self.ToolChain)
1925 self._BuildRuleFamily = "MSFT"
1926 else:
1927 self._BuildRuleFamily = ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY][self.ToolChain]
1928 return self._BuildRuleFamily
1929
1930 ## Return the build options specific for all modules in this platform
1931 def _GetBuildOptions(self):
1932 if self._BuildOption == None:
1933 self._BuildOption = self._ExpandBuildOption(self.Platform.BuildOptions)
1934 return self._BuildOption
1935
1936 ## Return the build options specific for EDK modules in this platform
1937 def _GetEdkBuildOptions(self):
1938 if self._EdkBuildOption == None:
1939 self._EdkBuildOption = self._ExpandBuildOption(self.Platform.BuildOptions, EDK_NAME)
1940 return self._EdkBuildOption
1941
1942 ## Return the build options specific for EDKII modules in this platform
1943 def _GetEdkIIBuildOptions(self):
1944 if self._EdkIIBuildOption == None:
1945 self._EdkIIBuildOption = self._ExpandBuildOption(self.Platform.BuildOptions, EDKII_NAME)
1946 return self._EdkIIBuildOption
1947
1948 ## Parse build_rule.txt in Conf Directory.
1949 #
1950 # @retval BuildRule object
1951 #
1952 def _GetBuildRule(self):
1953 if self._BuildRule == None:
1954 BuildRuleFile = None
1955 if TAB_TAT_DEFINES_BUILD_RULE_CONF in self.Workspace.TargetTxt.TargetTxtDictionary:
1956 BuildRuleFile = self.Workspace.TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_BUILD_RULE_CONF]
1957 if BuildRuleFile in [None, '']:
1958 BuildRuleFile = gDefaultBuildRuleFile
1959 self._BuildRule = BuildRule(BuildRuleFile)
1960 if self._BuildRule._FileVersion == "":
1961 self._BuildRule._FileVersion = AutoGenReqBuildRuleVerNum
1962 else:
1963 if self._BuildRule._FileVersion < AutoGenReqBuildRuleVerNum :
1964 # If Build Rule's version is less than the version number required by the tools, halting the build.
1965 EdkLogger.error("build", AUTOGEN_ERROR,
1966 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])"\
1967 % (self._BuildRule._FileVersion, AutoGenReqBuildRuleVerNum))
1968
1969 return self._BuildRule
1970
1971 ## Summarize the packages used by modules in this platform
1972 def _GetPackageList(self):
1973 if self._PackageList == None:
1974 self._PackageList = set()
1975 for La in self.LibraryAutoGenList:
1976 self._PackageList.update(La.DependentPackageList)
1977 for Ma in self.ModuleAutoGenList:
1978 self._PackageList.update(Ma.DependentPackageList)
1979 #Collect package set information from INF of FDF
1980 PkgSet = set()
1981 for ModuleFile in self._AsBuildModuleList:
1982 if ModuleFile in self.Platform.Modules:
1983 continue
1984 ModuleData = self.BuildDatabase[ModuleFile, self.Arch, self.BuildTarget, self.ToolChain]
1985 PkgSet.update(ModuleData.Packages)
1986 self._PackageList = list(self._PackageList) + list (PkgSet)
1987 return self._PackageList
1988
1989 def _GetNonDynamicPcdDict(self):
1990 if self._NonDynamicPcdDict:
1991 return self._NonDynamicPcdDict
1992 for Pcd in self.NonDynamicPcdList:
1993 self._NonDynamicPcdDict[(Pcd.TokenCName,Pcd.TokenSpaceGuidCName)] = Pcd
1994 return self._NonDynamicPcdDict
1995
1996 ## Get list of non-dynamic PCDs
1997 def _GetNonDynamicPcdList(self):
1998 if self._NonDynamicPcdList == None:
1999 self.CollectPlatformDynamicPcds()
2000 return self._NonDynamicPcdList
2001
2002 ## Get list of dynamic PCDs
2003 def _GetDynamicPcdList(self):
2004 if self._DynamicPcdList == None:
2005 self.CollectPlatformDynamicPcds()
2006 return self._DynamicPcdList
2007
2008 ## Generate Token Number for all PCD
2009 def _GetPcdTokenNumbers(self):
2010 if self._PcdTokenNumber == None:
2011 self._PcdTokenNumber = sdict()
2012 TokenNumber = 1
2013 #
2014 # Make the Dynamic and DynamicEx PCD use within different TokenNumber area.
2015 # Such as:
2016 #
2017 # Dynamic PCD:
2018 # TokenNumber 0 ~ 10
2019 # DynamicEx PCD:
2020 # TokeNumber 11 ~ 20
2021 #
2022 for Pcd in self.DynamicPcdList:
2023 if Pcd.Phase == "PEI":
2024 if Pcd.Type in ["Dynamic", "DynamicDefault", "DynamicVpd", "DynamicHii"]:
2025 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))
2026 self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
2027 TokenNumber += 1
2028
2029 for Pcd in self.DynamicPcdList:
2030 if Pcd.Phase == "PEI":
2031 if Pcd.Type in ["DynamicEx", "DynamicExDefault", "DynamicExVpd", "DynamicExHii"]:
2032 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))
2033 self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
2034 TokenNumber += 1
2035
2036 for Pcd in self.DynamicPcdList:
2037 if Pcd.Phase == "DXE":
2038 if Pcd.Type in ["Dynamic", "DynamicDefault", "DynamicVpd", "DynamicHii"]:
2039 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))
2040 self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
2041 TokenNumber += 1
2042
2043 for Pcd in self.DynamicPcdList:
2044 if Pcd.Phase == "DXE":
2045 if Pcd.Type in ["DynamicEx", "DynamicExDefault", "DynamicExVpd", "DynamicExHii"]:
2046 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))
2047 self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
2048 TokenNumber += 1
2049
2050 for Pcd in self.NonDynamicPcdList:
2051 self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
2052 TokenNumber += 1
2053 return self._PcdTokenNumber
2054
2055 ## Summarize ModuleAutoGen objects of all modules/libraries to be built for this platform
2056 def _GetAutoGenObjectList(self):
2057 self._ModuleAutoGenList = []
2058 self._LibraryAutoGenList = []
2059 for ModuleFile in self.Platform.Modules:
2060 Ma = ModuleAutoGen(
2061 self.Workspace,
2062 ModuleFile,
2063 self.BuildTarget,
2064 self.ToolChain,
2065 self.Arch,
2066 self.MetaFile
2067 )
2068 if Ma not in self._ModuleAutoGenList:
2069 self._ModuleAutoGenList.append(Ma)
2070 for La in Ma.LibraryAutoGenList:
2071 if La not in self._LibraryAutoGenList:
2072 self._LibraryAutoGenList.append(La)
2073 if Ma not in La._ReferenceModules:
2074 La._ReferenceModules.append(Ma)
2075
2076 ## Summarize ModuleAutoGen objects of all modules to be built for this platform
2077 def _GetModuleAutoGenList(self):
2078 if self._ModuleAutoGenList == None:
2079 self._GetAutoGenObjectList()
2080 return self._ModuleAutoGenList
2081
2082 ## Summarize ModuleAutoGen objects of all libraries to be built for this platform
2083 def _GetLibraryAutoGenList(self):
2084 if self._LibraryAutoGenList == None:
2085 self._GetAutoGenObjectList()
2086 return self._LibraryAutoGenList
2087
2088 ## Test if a module is supported by the platform
2089 #
2090 # An error will be raised directly if the module or its arch is not supported
2091 # by the platform or current configuration
2092 #
2093 def ValidModule(self, Module):
2094 return Module in self.Platform.Modules or Module in self.Platform.LibraryInstances \
2095 or Module in self._AsBuildModuleList
2096
2097 ## Resolve the library classes in a module to library instances
2098 #
2099 # This method will not only resolve library classes but also sort the library
2100 # instances according to the dependency-ship.
2101 #
2102 # @param Module The module from which the library classes will be resolved
2103 #
2104 # @retval library_list List of library instances sorted
2105 #
2106 def ApplyLibraryInstance(self, Module):
2107 # Cover the case that the binary INF file is list in the FDF file but not DSC file, return empty list directly
2108 if str(Module) not in self.Platform.Modules:
2109 return []
2110
2111 ModuleType = Module.ModuleType
2112
2113 # for overridding library instances with module specific setting
2114 PlatformModule = self.Platform.Modules[str(Module)]
2115
2116 # add forced library instances (specified under LibraryClasses sections)
2117 #
2118 # If a module has a MODULE_TYPE of USER_DEFINED,
2119 # do not link in NULL library class instances from the global [LibraryClasses.*] sections.
2120 #
2121 if Module.ModuleType != SUP_MODULE_USER_DEFINED:
2122 for LibraryClass in self.Platform.LibraryClasses.GetKeys():
2123 if LibraryClass.startswith("NULL") and self.Platform.LibraryClasses[LibraryClass, Module.ModuleType]:
2124 Module.LibraryClasses[LibraryClass] = self.Platform.LibraryClasses[LibraryClass, Module.ModuleType]
2125
2126 # add forced library instances (specified in module overrides)
2127 for LibraryClass in PlatformModule.LibraryClasses:
2128 if LibraryClass.startswith("NULL"):
2129 Module.LibraryClasses[LibraryClass] = PlatformModule.LibraryClasses[LibraryClass]
2130
2131 # EdkII module
2132 LibraryConsumerList = [Module]
2133 Constructor = []
2134 ConsumedByList = sdict()
2135 LibraryInstance = sdict()
2136
2137 EdkLogger.verbose("")
2138 EdkLogger.verbose("Library instances of module [%s] [%s]:" % (str(Module), self.Arch))
2139 while len(LibraryConsumerList) > 0:
2140 M = LibraryConsumerList.pop()
2141 for LibraryClassName in M.LibraryClasses:
2142 if LibraryClassName not in LibraryInstance:
2143 # override library instance for this module
2144 if LibraryClassName in PlatformModule.LibraryClasses:
2145 LibraryPath = PlatformModule.LibraryClasses[LibraryClassName]
2146 else:
2147 LibraryPath = self.Platform.LibraryClasses[LibraryClassName, ModuleType]
2148 if LibraryPath == None or LibraryPath == "":
2149 LibraryPath = M.LibraryClasses[LibraryClassName]
2150 if LibraryPath == None or LibraryPath == "":
2151 EdkLogger.error("build", RESOURCE_NOT_AVAILABLE,
2152 "Instance of library class [%s] is not found" % LibraryClassName,
2153 File=self.MetaFile,
2154 ExtraData="in [%s] [%s]\n\tconsumed by module [%s]" % (str(M), self.Arch, str(Module)))
2155
2156 LibraryModule = self.BuildDatabase[LibraryPath, self.Arch, self.BuildTarget, self.ToolChain]
2157 # for those forced library instance (NULL library), add a fake library class
2158 if LibraryClassName.startswith("NULL"):
2159 LibraryModule.LibraryClass.append(LibraryClassObject(LibraryClassName, [ModuleType]))
2160 elif LibraryModule.LibraryClass == None \
2161 or len(LibraryModule.LibraryClass) == 0 \
2162 or (ModuleType != 'USER_DEFINED'
2163 and ModuleType not in LibraryModule.LibraryClass[0].SupModList):
2164 # only USER_DEFINED can link against any library instance despite of its SupModList
2165 EdkLogger.error("build", OPTION_MISSING,
2166 "Module type [%s] is not supported by library instance [%s]" \
2167 % (ModuleType, LibraryPath), File=self.MetaFile,
2168 ExtraData="consumed by [%s]" % str(Module))
2169
2170 LibraryInstance[LibraryClassName] = LibraryModule
2171 LibraryConsumerList.append(LibraryModule)
2172 EdkLogger.verbose("\t" + str(LibraryClassName) + " : " + str(LibraryModule))
2173 else:
2174 LibraryModule = LibraryInstance[LibraryClassName]
2175
2176 if LibraryModule == None:
2177 continue
2178
2179 if LibraryModule.ConstructorList != [] and LibraryModule not in Constructor:
2180 Constructor.append(LibraryModule)
2181
2182 if LibraryModule not in ConsumedByList:
2183 ConsumedByList[LibraryModule] = []
2184 # don't add current module itself to consumer list
2185 if M != Module:
2186 if M in ConsumedByList[LibraryModule]:
2187 continue
2188 ConsumedByList[LibraryModule].append(M)
2189 #
2190 # Initialize the sorted output list to the empty set
2191 #
2192 SortedLibraryList = []
2193 #
2194 # Q <- Set of all nodes with no incoming edges
2195 #
2196 LibraryList = [] #LibraryInstance.values()
2197 Q = []
2198 for LibraryClassName in LibraryInstance:
2199 M = LibraryInstance[LibraryClassName]
2200 LibraryList.append(M)
2201 if ConsumedByList[M] == []:
2202 Q.append(M)
2203
2204 #
2205 # start the DAG algorithm
2206 #
2207 while True:
2208 EdgeRemoved = True
2209 while Q == [] and EdgeRemoved:
2210 EdgeRemoved = False
2211 # for each node Item with a Constructor
2212 for Item in LibraryList:
2213 if Item not in Constructor:
2214 continue
2215 # for each Node without a constructor with an edge e from Item to Node
2216 for Node in ConsumedByList[Item]:
2217 if Node in Constructor:
2218 continue
2219 # remove edge e from the graph if Node has no constructor
2220 ConsumedByList[Item].remove(Node)
2221 EdgeRemoved = True
2222 if ConsumedByList[Item] == []:
2223 # insert Item into Q
2224 Q.insert(0, Item)
2225 break
2226 if Q != []:
2227 break
2228 # DAG is done if there's no more incoming edge for all nodes
2229 if Q == []:
2230 break
2231
2232 # remove node from Q
2233 Node = Q.pop()
2234 # output Node
2235 SortedLibraryList.append(Node)
2236
2237 # for each node Item with an edge e from Node to Item do
2238 for Item in LibraryList:
2239 if Node not in ConsumedByList[Item]:
2240 continue
2241 # remove edge e from the graph
2242 ConsumedByList[Item].remove(Node)
2243
2244 if ConsumedByList[Item] != []:
2245 continue
2246 # insert Item into Q, if Item has no other incoming edges
2247 Q.insert(0, Item)
2248
2249 #
2250 # if any remaining node Item in the graph has a constructor and an incoming edge, then the graph has a cycle
2251 #
2252 for Item in LibraryList:
2253 if ConsumedByList[Item] != [] and Item in Constructor and len(Constructor) > 1:
2254 ErrorMessage = "\tconsumed by " + "\n\tconsumed by ".join([str(L) for L in ConsumedByList[Item]])
2255 EdkLogger.error("build", BUILD_ERROR, 'Library [%s] with constructors has a cycle' % str(Item),
2256 ExtraData=ErrorMessage, File=self.MetaFile)
2257 if Item not in SortedLibraryList:
2258 SortedLibraryList.append(Item)
2259
2260 #
2261 # Build the list of constructor and destructir names
2262 # The DAG Topo sort produces the destructor order, so the list of constructors must generated in the reverse order
2263 #
2264 SortedLibraryList.reverse()
2265 return SortedLibraryList
2266
2267
2268 ## Override PCD setting (type, value, ...)
2269 #
2270 # @param ToPcd The PCD to be overrided
2271 # @param FromPcd The PCD overrideing from
2272 #
2273 def _OverridePcd(self, ToPcd, FromPcd, Module=""):
2274 #
2275 # in case there's PCDs coming from FDF file, which have no type given.
2276 # at this point, ToPcd.Type has the type found from dependent
2277 # package
2278 #
2279 TokenCName = ToPcd.TokenCName
2280 for PcdItem in GlobalData.MixedPcd:
2281 if (ToPcd.TokenCName, ToPcd.TokenSpaceGuidCName) in GlobalData.MixedPcd[PcdItem]:
2282 TokenCName = PcdItem[0]
2283 break
2284 if FromPcd != None:
2285 if GlobalData.BuildOptionPcd:
2286 for pcd in GlobalData.BuildOptionPcd:
2287 if (FromPcd.TokenSpaceGuidCName, FromPcd.TokenCName) == (pcd[0], pcd[1]):
2288 FromPcd.DefaultValue = pcd[2]
2289 break
2290 if ToPcd.Pending and FromPcd.Type not in [None, '']:
2291 ToPcd.Type = FromPcd.Type
2292 elif (ToPcd.Type not in [None, '']) and (FromPcd.Type not in [None, ''])\
2293 and (ToPcd.Type != FromPcd.Type) and (ToPcd.Type in FromPcd.Type):
2294 if ToPcd.Type.strip() == "DynamicEx":
2295 ToPcd.Type = FromPcd.Type
2296 elif ToPcd.Type not in [None, ''] and FromPcd.Type not in [None, ''] \
2297 and ToPcd.Type != FromPcd.Type:
2298 EdkLogger.error("build", OPTION_CONFLICT, "Mismatched PCD type",
2299 ExtraData="%s.%s is defined as [%s] in module %s, but as [%s] in platform."\
2300 % (ToPcd.TokenSpaceGuidCName, TokenCName,
2301 ToPcd.Type, Module, FromPcd.Type),
2302 File=self.MetaFile)
2303
2304 if FromPcd.MaxDatumSize not in [None, '']:
2305 ToPcd.MaxDatumSize = FromPcd.MaxDatumSize
2306 if FromPcd.DefaultValue not in [None, '']:
2307 ToPcd.DefaultValue = FromPcd.DefaultValue
2308 if FromPcd.TokenValue not in [None, '']:
2309 ToPcd.TokenValue = FromPcd.TokenValue
2310 if FromPcd.MaxDatumSize not in [None, '']:
2311 ToPcd.MaxDatumSize = FromPcd.MaxDatumSize
2312 if FromPcd.DatumType not in [None, '']:
2313 ToPcd.DatumType = FromPcd.DatumType
2314 if FromPcd.SkuInfoList not in [None, '', []]:
2315 ToPcd.SkuInfoList = FromPcd.SkuInfoList
2316
2317 # check the validation of datum
2318 IsValid, Cause = CheckPcdDatum(ToPcd.DatumType, ToPcd.DefaultValue)
2319 if not IsValid:
2320 EdkLogger.error('build', FORMAT_INVALID, Cause, File=self.MetaFile,
2321 ExtraData="%s.%s" % (ToPcd.TokenSpaceGuidCName, TokenCName))
2322 ToPcd.validateranges = FromPcd.validateranges
2323 ToPcd.validlists = FromPcd.validlists
2324 ToPcd.expressions = FromPcd.expressions
2325
2326 if ToPcd.DatumType == "VOID*" and ToPcd.MaxDatumSize in ['', None]:
2327 EdkLogger.debug(EdkLogger.DEBUG_9, "No MaxDatumSize specified for PCD %s.%s" \
2328 % (ToPcd.TokenSpaceGuidCName, TokenCName))
2329 Value = ToPcd.DefaultValue
2330 if Value in [None, '']:
2331 ToPcd.MaxDatumSize = '1'
2332 elif Value[0] == 'L':
2333 ToPcd.MaxDatumSize = str((len(Value) - 2) * 2)
2334 elif Value[0] == '{':
2335 ToPcd.MaxDatumSize = str(len(Value.split(',')))
2336 else:
2337 ToPcd.MaxDatumSize = str(len(Value) - 1)
2338
2339 # apply default SKU for dynamic PCDS if specified one is not available
2340 if (ToPcd.Type in PCD_DYNAMIC_TYPE_LIST or ToPcd.Type in PCD_DYNAMIC_EX_TYPE_LIST) \
2341 and ToPcd.SkuInfoList in [None, {}, '']:
2342 if self.Platform.SkuName in self.Platform.SkuIds:
2343 SkuName = self.Platform.SkuName
2344 else:
2345 SkuName = 'DEFAULT'
2346 ToPcd.SkuInfoList = {
2347 SkuName : SkuInfoClass(SkuName, self.Platform.SkuIds[SkuName], '', '', '', '', '', ToPcd.DefaultValue)
2348 }
2349
2350 ## Apply PCD setting defined platform to a module
2351 #
2352 # @param Module The module from which the PCD setting will be overrided
2353 #
2354 # @retval PCD_list The list PCDs with settings from platform
2355 #
2356 def ApplyPcdSetting(self, Module, Pcds):
2357 # for each PCD in module
2358 for Name, Guid in Pcds:
2359 PcdInModule = Pcds[Name, Guid]
2360 # find out the PCD setting in platform
2361 if (Name, Guid) in self.Platform.Pcds:
2362 PcdInPlatform = self.Platform.Pcds[Name, Guid]
2363 else:
2364 PcdInPlatform = None
2365 # then override the settings if any
2366 self._OverridePcd(PcdInModule, PcdInPlatform, Module)
2367 # resolve the VariableGuid value
2368 for SkuId in PcdInModule.SkuInfoList:
2369 Sku = PcdInModule.SkuInfoList[SkuId]
2370 if Sku.VariableGuid == '': continue
2371 Sku.VariableGuidValue = GuidValue(Sku.VariableGuid, self.PackageList, self.MetaFile.Path)
2372 if Sku.VariableGuidValue == None:
2373 PackageList = "\n\t".join([str(P) for P in self.PackageList])
2374 EdkLogger.error(
2375 'build',
2376 RESOURCE_NOT_AVAILABLE,
2377 "Value of GUID [%s] is not found in" % Sku.VariableGuid,
2378 ExtraData=PackageList + "\n\t(used with %s.%s from module %s)" \
2379 % (Guid, Name, str(Module)),
2380 File=self.MetaFile
2381 )
2382
2383 # override PCD settings with module specific setting
2384 if Module in self.Platform.Modules:
2385 PlatformModule = self.Platform.Modules[str(Module)]
2386 for Key in PlatformModule.Pcds:
2387 Flag = False
2388 if Key in Pcds:
2389 ToPcd = Pcds[Key]
2390 Flag = True
2391 elif Key in GlobalData.MixedPcd:
2392 for PcdItem in GlobalData.MixedPcd[Key]:
2393 if PcdItem in Pcds:
2394 ToPcd = Pcds[PcdItem]
2395 Flag = True
2396 break
2397 if Flag:
2398 self._OverridePcd(ToPcd, PlatformModule.Pcds[Key], Module)
2399 return Pcds.values()
2400
2401 ## Resolve library names to library modules
2402 #
2403 # (for Edk.x modules)
2404 #
2405 # @param Module The module from which the library names will be resolved
2406 #
2407 # @retval library_list The list of library modules
2408 #
2409 def ResolveLibraryReference(self, Module):
2410 EdkLogger.verbose("")
2411 EdkLogger.verbose("Library instances of module [%s] [%s]:" % (str(Module), self.Arch))
2412 LibraryConsumerList = [Module]
2413
2414 # "CompilerStub" is a must for Edk modules
2415 if Module.Libraries:
2416 Module.Libraries.append("CompilerStub")
2417 LibraryList = []
2418 while len(LibraryConsumerList) > 0:
2419 M = LibraryConsumerList.pop()
2420 for LibraryName in M.Libraries:
2421 Library = self.Platform.LibraryClasses[LibraryName, ':dummy:']
2422 if Library == None:
2423 for Key in self.Platform.LibraryClasses.data.keys():
2424 if LibraryName.upper() == Key.upper():
2425 Library = self.Platform.LibraryClasses[Key, ':dummy:']
2426 break
2427 if Library == None:
2428 EdkLogger.warn("build", "Library [%s] is not found" % LibraryName, File=str(M),
2429 ExtraData="\t%s [%s]" % (str(Module), self.Arch))
2430 continue
2431
2432 if Library not in LibraryList:
2433 LibraryList.append(Library)
2434 LibraryConsumerList.append(Library)
2435 EdkLogger.verbose("\t" + LibraryName + " : " + str(Library) + ' ' + str(type(Library)))
2436 return LibraryList
2437
2438 ## Calculate the priority value of the build option
2439 #
2440 # @param Key Build option definition contain: TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
2441 #
2442 # @retval Value Priority value based on the priority list.
2443 #
2444 def CalculatePriorityValue(self, Key):
2445 Target, ToolChain, Arch, CommandType, Attr = Key.split('_')
2446 PriorityValue = 0x11111
2447 if Target == "*":
2448 PriorityValue &= 0x01111
2449 if ToolChain == "*":
2450 PriorityValue &= 0x10111
2451 if Arch == "*":
2452 PriorityValue &= 0x11011
2453 if CommandType == "*":
2454 PriorityValue &= 0x11101
2455 if Attr == "*":
2456 PriorityValue &= 0x11110
2457
2458 return self.PrioList["0x%0.5x" % PriorityValue]
2459
2460
2461 ## Expand * in build option key
2462 #
2463 # @param Options Options to be expanded
2464 #
2465 # @retval options Options expanded
2466 #
2467 def _ExpandBuildOption(self, Options, ModuleStyle=None):
2468 BuildOptions = {}
2469 FamilyMatch = False
2470 FamilyIsNull = True
2471
2472 OverrideList = {}
2473 #
2474 # Construct a list contain the build options which need override.
2475 #
2476 for Key in Options:
2477 #
2478 # Key[0] -- tool family
2479 # Key[1] -- TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
2480 #
2481 if (Key[0] == self.BuildRuleFamily and
2482 (ModuleStyle == None or len(Key) < 3 or (len(Key) > 2 and Key[2] == ModuleStyle))):
2483 Target, ToolChain, Arch, CommandType, Attr = Key[1].split('_')
2484 if Target == self.BuildTarget or Target == "*":
2485 if ToolChain == self.ToolChain or ToolChain == "*":
2486 if Arch == self.Arch or Arch == "*":
2487 if Options[Key].startswith("="):
2488 if OverrideList.get(Key[1]) != None:
2489 OverrideList.pop(Key[1])
2490 OverrideList[Key[1]] = Options[Key]
2491
2492 #
2493 # Use the highest priority value.
2494 #
2495 if (len(OverrideList) >= 2):
2496 KeyList = OverrideList.keys()
2497 for Index in range(len(KeyList)):
2498 NowKey = KeyList[Index]
2499 Target1, ToolChain1, Arch1, CommandType1, Attr1 = NowKey.split("_")
2500 for Index1 in range(len(KeyList) - Index - 1):
2501 NextKey = KeyList[Index1 + Index + 1]
2502 #
2503 # Compare two Key, if one is included by another, choose the higher priority one
2504 #
2505 Target2, ToolChain2, Arch2, CommandType2, Attr2 = NextKey.split("_")
2506 if Target1 == Target2 or Target1 == "*" or Target2 == "*":
2507 if ToolChain1 == ToolChain2 or ToolChain1 == "*" or ToolChain2 == "*":
2508 if Arch1 == Arch2 or Arch1 == "*" or Arch2 == "*":
2509 if CommandType1 == CommandType2 or CommandType1 == "*" or CommandType2 == "*":
2510 if Attr1 == Attr2 or Attr1 == "*" or Attr2 == "*":
2511 if self.CalculatePriorityValue(NowKey) > self.CalculatePriorityValue(NextKey):
2512 if Options.get((self.BuildRuleFamily, NextKey)) != None:
2513 Options.pop((self.BuildRuleFamily, NextKey))
2514 else:
2515 if Options.get((self.BuildRuleFamily, NowKey)) != None:
2516 Options.pop((self.BuildRuleFamily, NowKey))
2517
2518 for Key in Options:
2519 if ModuleStyle != None and len (Key) > 2:
2520 # Check Module style is EDK or EDKII.
2521 # Only append build option for the matched style module.
2522 if ModuleStyle == EDK_NAME and Key[2] != EDK_NAME:
2523 continue
2524 elif ModuleStyle == EDKII_NAME and Key[2] != EDKII_NAME:
2525 continue
2526 Family = Key[0]
2527 Target, Tag, Arch, Tool, Attr = Key[1].split("_")
2528 # if tool chain family doesn't match, skip it
2529 if Tool in self.ToolDefinition and Family != "":
2530 FamilyIsNull = False
2531 if self.ToolDefinition[Tool].get(TAB_TOD_DEFINES_BUILDRULEFAMILY, "") != "":
2532 if Family != self.ToolDefinition[Tool][TAB_TOD_DEFINES_BUILDRULEFAMILY]:
2533 continue
2534 elif Family != self.ToolDefinition[Tool][TAB_TOD_DEFINES_FAMILY]:
2535 continue
2536 FamilyMatch = True
2537 # expand any wildcard
2538 if Target == "*" or Target == self.BuildTarget:
2539 if Tag == "*" or Tag == self.ToolChain:
2540 if Arch == "*" or Arch == self.Arch:
2541 if Tool not in BuildOptions:
2542 BuildOptions[Tool] = {}
2543 if Attr != "FLAGS" or Attr not in BuildOptions[Tool] or Options[Key].startswith('='):
2544 BuildOptions[Tool][Attr] = Options[Key]
2545 else:
2546 # append options for the same tool except PATH
2547 if Attr != 'PATH':
2548 BuildOptions[Tool][Attr] += " " + Options[Key]
2549 else:
2550 BuildOptions[Tool][Attr] = Options[Key]
2551 # Build Option Family has been checked, which need't to be checked again for family.
2552 if FamilyMatch or FamilyIsNull:
2553 return BuildOptions
2554
2555 for Key in Options:
2556 if ModuleStyle != None and len (Key) > 2:
2557 # Check Module style is EDK or EDKII.
2558 # Only append build option for the matched style module.
2559 if ModuleStyle == EDK_NAME and Key[2] != EDK_NAME:
2560 continue
2561 elif ModuleStyle == EDKII_NAME and Key[2] != EDKII_NAME:
2562 continue
2563 Family = Key[0]
2564 Target, Tag, Arch, Tool, Attr = Key[1].split("_")
2565 # if tool chain family doesn't match, skip it
2566 if Tool not in self.ToolDefinition or Family == "":
2567 continue
2568 # option has been added before
2569 if Family != self.ToolDefinition[Tool][TAB_TOD_DEFINES_FAMILY]:
2570 continue
2571
2572 # expand any wildcard
2573 if Target == "*" or Target == self.BuildTarget:
2574 if Tag == "*" or Tag == self.ToolChain:
2575 if Arch == "*" or Arch == self.Arch:
2576 if Tool not in BuildOptions:
2577 BuildOptions[Tool] = {}
2578 if Attr != "FLAGS" or Attr not in BuildOptions[Tool] or Options[Key].startswith('='):
2579 BuildOptions[Tool][Attr] = Options[Key]
2580 else:
2581 # append options for the same tool except PATH
2582 if Attr != 'PATH':
2583 BuildOptions[Tool][Attr] += " " + Options[Key]
2584 else:
2585 BuildOptions[Tool][Attr] = Options[Key]
2586 return BuildOptions
2587
2588 ## Append build options in platform to a module
2589 #
2590 # @param Module The module to which the build options will be appened
2591 #
2592 # @retval options The options appended with build options in platform
2593 #
2594 def ApplyBuildOption(self, Module):
2595 # Get the different options for the different style module
2596 if Module.AutoGenVersion < 0x00010005:
2597 PlatformOptions = self.EdkBuildOption
2598 ModuleTypeOptions = self.Platform.GetBuildOptionsByModuleType(EDK_NAME, Module.ModuleType)
2599 else:
2600 PlatformOptions = self.EdkIIBuildOption
2601 ModuleTypeOptions = self.Platform.GetBuildOptionsByModuleType(EDKII_NAME, Module.ModuleType)
2602 ModuleTypeOptions = self._ExpandBuildOption(ModuleTypeOptions)
2603 ModuleOptions = self._ExpandBuildOption(Module.BuildOptions)
2604 if Module in self.Platform.Modules:
2605 PlatformModule = self.Platform.Modules[str(Module)]
2606 PlatformModuleOptions = self._ExpandBuildOption(PlatformModule.BuildOptions)
2607 else:
2608 PlatformModuleOptions = {}
2609
2610 BuildRuleOrder = None
2611 for Options in [self.ToolDefinition, ModuleOptions, PlatformOptions, ModuleTypeOptions, PlatformModuleOptions]:
2612 for Tool in Options:
2613 for Attr in Options[Tool]:
2614 if Attr == TAB_TOD_DEFINES_BUILDRULEORDER:
2615 BuildRuleOrder = Options[Tool][Attr]
2616
2617 AllTools = set(ModuleOptions.keys() + PlatformOptions.keys() +
2618 PlatformModuleOptions.keys() + ModuleTypeOptions.keys() +
2619 self.ToolDefinition.keys())
2620 BuildOptions = {}
2621 for Tool in AllTools:
2622 if Tool not in BuildOptions:
2623 BuildOptions[Tool] = {}
2624
2625 for Options in [self.ToolDefinition, ModuleOptions, PlatformOptions, ModuleTypeOptions, PlatformModuleOptions]:
2626 if Tool not in Options:
2627 continue
2628 for Attr in Options[Tool]:
2629 Value = Options[Tool][Attr]
2630 #
2631 # Do not generate it in Makefile
2632 #
2633 if Attr == TAB_TOD_DEFINES_BUILDRULEORDER:
2634 continue
2635 if Attr not in BuildOptions[Tool]:
2636 BuildOptions[Tool][Attr] = ""
2637 # check if override is indicated
2638 if Value.startswith('='):
2639 ToolPath = Value[1:]
2640 ToolPath = mws.handleWsMacro(ToolPath)
2641 BuildOptions[Tool][Attr] = ToolPath
2642 else:
2643 Value = mws.handleWsMacro(Value)
2644 if Attr != 'PATH':
2645 BuildOptions[Tool][Attr] += " " + Value
2646 else:
2647 BuildOptions[Tool][Attr] = Value
2648 if Module.AutoGenVersion < 0x00010005 and self.Workspace.UniFlag != None:
2649 #
2650 # Override UNI flag only for EDK module.
2651 #
2652 if 'BUILD' not in BuildOptions:
2653 BuildOptions['BUILD'] = {}
2654 BuildOptions['BUILD']['FLAGS'] = self.Workspace.UniFlag
2655 return BuildOptions, BuildRuleOrder
2656
2657 Platform = property(_GetPlatform)
2658 Name = property(_GetName)
2659 Guid = property(_GetGuid)
2660 Version = property(_GetVersion)
2661
2662 OutputDir = property(_GetOutputDir)
2663 BuildDir = property(_GetBuildDir)
2664 MakeFileDir = property(_GetMakeFileDir)
2665 FdfFile = property(_GetFdfFile)
2666
2667 PcdTokenNumber = property(_GetPcdTokenNumbers) # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber
2668 DynamicPcdList = property(_GetDynamicPcdList) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
2669 NonDynamicPcdList = property(_GetNonDynamicPcdList) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
2670 NonDynamicPcdDict = property(_GetNonDynamicPcdDict)
2671 PackageList = property(_GetPackageList)
2672
2673 ToolDefinition = property(_GetToolDefinition) # toolcode : tool path
2674 ToolDefinitionFile = property(_GetToolDefFile) # toolcode : lib path
2675 ToolChainFamily = property(_GetToolChainFamily)
2676 BuildRuleFamily = property(_GetBuildRuleFamily)
2677 BuildOption = property(_GetBuildOptions) # toolcode : option
2678 EdkBuildOption = property(_GetEdkBuildOptions) # edktoolcode : option
2679 EdkIIBuildOption = property(_GetEdkIIBuildOptions) # edkiitoolcode : option
2680
2681 BuildCommand = property(_GetBuildCommand)
2682 BuildRule = property(_GetBuildRule)
2683 ModuleAutoGenList = property(_GetModuleAutoGenList)
2684 LibraryAutoGenList = property(_GetLibraryAutoGenList)
2685 GenFdsCommand = property(_GenFdsCommand)
2686
2687 ## ModuleAutoGen class
2688 #
2689 # This class encapsules the AutoGen behaviors for the build tools. In addition to
2690 # the generation of AutoGen.h and AutoGen.c, it will generate *.depex file according
2691 # to the [depex] section in module's inf file.
2692 #
2693 class ModuleAutoGen(AutoGen):
2694 ## Cache the timestamps of metafiles of every module in a class variable
2695 #
2696 TimeDict = {}
2697
2698 ## The real constructor of ModuleAutoGen
2699 #
2700 # This method is not supposed to be called by users of ModuleAutoGen. It's
2701 # only used by factory method __new__() to do real initialization work for an
2702 # object of ModuleAutoGen
2703 #
2704 # @param Workspace EdkIIWorkspaceBuild object
2705 # @param ModuleFile The path of module file
2706 # @param Target Build target (DEBUG, RELEASE)
2707 # @param Toolchain Name of tool chain
2708 # @param Arch The arch the module supports
2709 # @param PlatformFile Platform meta-file
2710 #
2711 def _Init(self, Workspace, ModuleFile, Target, Toolchain, Arch, PlatformFile):
2712 EdkLogger.debug(EdkLogger.DEBUG_9, "AutoGen module [%s] [%s]" % (ModuleFile, Arch))
2713 GlobalData.gProcessingFile = "%s [%s, %s, %s]" % (ModuleFile, Arch, Toolchain, Target)
2714
2715 self.Workspace = Workspace
2716 self.WorkspaceDir = Workspace.WorkspaceDir
2717
2718 self.MetaFile = ModuleFile
2719 self.PlatformInfo = PlatformAutoGen(Workspace, PlatformFile, Target, Toolchain, Arch)
2720 # check if this module is employed by active platform
2721 if not self.PlatformInfo.ValidModule(self.MetaFile):
2722 EdkLogger.verbose("Module [%s] for [%s] is not employed by active platform\n" \
2723 % (self.MetaFile, Arch))
2724 return False
2725
2726 self.SourceDir = self.MetaFile.SubDir
2727 self.SourceDir = mws.relpath(self.SourceDir, self.WorkspaceDir)
2728
2729 self.SourceOverrideDir = None
2730 # use overrided path defined in DSC file
2731 if self.MetaFile.Key in GlobalData.gOverrideDir:
2732 self.SourceOverrideDir = GlobalData.gOverrideDir[self.MetaFile.Key]
2733
2734 self.ToolChain = Toolchain
2735 self.BuildTarget = Target
2736 self.Arch = Arch
2737 self.ToolChainFamily = self.PlatformInfo.ToolChainFamily
2738 self.BuildRuleFamily = self.PlatformInfo.BuildRuleFamily
2739
2740 self.IsMakeFileCreated = False
2741 self.IsCodeFileCreated = False
2742 self.IsAsBuiltInfCreated = False
2743 self.DepexGenerated = False
2744
2745 self.BuildDatabase = self.Workspace.BuildDatabase
2746 self.BuildRuleOrder = None
2747 self.BuildTime = 0
2748
2749 self._Module = None
2750 self._Name = None
2751 self._Guid = None
2752 self._Version = None
2753 self._ModuleType = None
2754 self._ComponentType = None
2755 self._PcdIsDriver = None
2756 self._AutoGenVersion = None
2757 self._LibraryFlag = None
2758 self._CustomMakefile = None
2759 self._Macro = None
2760
2761 self._BuildDir = None
2762 self._OutputDir = None
2763 self._DebugDir = None
2764 self._MakeFileDir = None
2765
2766 self._IncludePathList = None
2767 self._IncludePathLength = 0
2768 self._AutoGenFileList = None
2769 self._UnicodeFileList = None
2770 self._VfrFileList = None
2771 self._IdfFileList = None
2772 self._SourceFileList = None
2773 self._ObjectFileList = None
2774 self._BinaryFileList = None
2775
2776 self._DependentPackageList = None
2777 self._DependentLibraryList = None
2778 self._LibraryAutoGenList = None
2779 self._DerivedPackageList = None
2780 self._ModulePcdList = None
2781 self._LibraryPcdList = None
2782 self._PcdComments = sdict()
2783 self._GuidList = None
2784 self._GuidsUsedByPcd = None
2785 self._GuidComments = sdict()
2786 self._ProtocolList = None
2787 self._ProtocolComments = sdict()
2788 self._PpiList = None
2789 self._PpiComments = sdict()
2790 self._DepexList = None
2791 self._DepexExpressionList = None
2792 self._BuildOption = None
2793 self._BuildOptionIncPathList = None
2794 self._BuildTargets = None
2795 self._IntroBuildTargetList = None
2796 self._FinalBuildTargetList = None
2797 self._FileTypes = None
2798 self._BuildRules = None
2799
2800 self._TimeStampPath = None
2801
2802 self.AutoGenDepSet = set()
2803
2804
2805 ## The Modules referenced to this Library
2806 # Only Library has this attribute
2807 self._ReferenceModules = []
2808
2809 ## Store the FixedAtBuild Pcds
2810 #
2811 self._FixedAtBuildPcds = []
2812 self.ConstPcd = {}
2813 return True
2814
2815 def __repr__(self):
2816 return "%s [%s]" % (self.MetaFile, self.Arch)
2817
2818 # Get FixedAtBuild Pcds of this Module
2819 def _GetFixedAtBuildPcds(self):
2820 if self._FixedAtBuildPcds:
2821 return self._FixedAtBuildPcds
2822 for Pcd in self.ModulePcdList:
2823 if Pcd.Type != "FixedAtBuild":
2824 continue
2825 if Pcd not in self._FixedAtBuildPcds:
2826 self._FixedAtBuildPcds.append(Pcd)
2827
2828 return self._FixedAtBuildPcds
2829
2830 def _GetUniqueBaseName(self):
2831 BaseName = self.Name
2832 for Module in self.PlatformInfo.ModuleAutoGenList:
2833 if Module.MetaFile == self.MetaFile:
2834 continue
2835 if Module.Name == self.Name:
2836 if uuid.UUID(Module.Guid) == uuid.UUID(self.Guid):
2837 EdkLogger.error("build", FILE_DUPLICATED, 'Modules have same BaseName and FILE_GUID:\n'
2838 ' %s\n %s' % (Module.MetaFile, self.MetaFile))
2839 BaseName = '%s_%s' % (self.Name, self.Guid)
2840 return BaseName
2841
2842 # Macros could be used in build_rule.txt (also Makefile)
2843 def _GetMacros(self):
2844 if self._Macro == None:
2845 self._Macro = sdict()
2846 self._Macro["WORKSPACE" ] = self.WorkspaceDir
2847 self._Macro["MODULE_NAME" ] = self.Name
2848 self._Macro["MODULE_NAME_GUID" ] = self._GetUniqueBaseName()
2849 self._Macro["MODULE_GUID" ] = self.Guid
2850 self._Macro["MODULE_VERSION" ] = self.Version
2851 self._Macro["MODULE_TYPE" ] = self.ModuleType
2852 self._Macro["MODULE_FILE" ] = str(self.MetaFile)
2853 self._Macro["MODULE_FILE_BASE_NAME" ] = self.MetaFile.BaseName
2854 self._Macro["MODULE_RELATIVE_DIR" ] = self.SourceDir
2855 self._Macro["MODULE_DIR" ] = self.SourceDir
2856
2857 self._Macro["BASE_NAME" ] = self.Name
2858
2859 self._Macro["ARCH" ] = self.Arch
2860 self._Macro["TOOLCHAIN" ] = self.ToolChain
2861 self._Macro["TOOLCHAIN_TAG" ] = self.ToolChain
2862 self._Macro["TOOL_CHAIN_TAG" ] = self.ToolChain
2863 self._Macro["TARGET" ] = self.BuildTarget
2864
2865 self._Macro["BUILD_DIR" ] = self.PlatformInfo.BuildDir
2866 self._Macro["BIN_DIR" ] = os.path.join(self.PlatformInfo.BuildDir, self.Arch)
2867 self._Macro["LIB_DIR" ] = os.path.join(self.PlatformInfo.BuildDir, self.Arch)
2868 self._Macro["MODULE_BUILD_DIR" ] = self.BuildDir
2869 self._Macro["OUTPUT_DIR" ] = self.OutputDir
2870 self._Macro["DEBUG_DIR" ] = self.DebugDir
2871 self._Macro["DEST_DIR_OUTPUT" ] = self.OutputDir
2872 self._Macro["DEST_DIR_DEBUG" ] = self.DebugDir
2873 self._Macro["PLATFORM_NAME" ] = self.PlatformInfo.Name
2874 self._Macro["PLATFORM_GUID" ] = self.PlatformInfo.Guid
2875 self._Macro["PLATFORM_VERSION" ] = self.PlatformInfo.Version
2876 self._Macro["PLATFORM_RELATIVE_DIR" ] = self.PlatformInfo.SourceDir
2877 self._Macro["PLATFORM_DIR" ] = mws.join(self.WorkspaceDir, self.PlatformInfo.SourceDir)
2878 self._Macro["PLATFORM_OUTPUT_DIR" ] = self.PlatformInfo.OutputDir
2879 return self._Macro
2880
2881 ## Return the module build data object
2882 def _GetModule(self):
2883 if self._Module == None:
2884 self._Module = self.Workspace.BuildDatabase[self.MetaFile, self.Arch, self.BuildTarget, self.ToolChain]
2885 return self._Module
2886
2887 ## Return the module name
2888 def _GetBaseName(self):
2889 return self.Module.BaseName
2890
2891 ## Return the module DxsFile if exist
2892 def _GetDxsFile(self):
2893 return self.Module.DxsFile
2894
2895 ## Return the module SourceOverridePath
2896 def _GetSourceOverridePath(self):
2897 return self.Module.SourceOverridePath
2898
2899 ## Return the module meta-file GUID
2900 def _GetGuid(self):
2901 #
2902 # To build same module more than once, the module path with FILE_GUID overridden has
2903 # the file name FILE_GUIDmodule.inf, but the relative path (self.MetaFile.File) is the realy path
2904 # in DSC. The overridden GUID can be retrieved from file name
2905 #
2906 if os.path.basename(self.MetaFile.File) != os.path.basename(self.MetaFile.Path):
2907 #
2908 # Length of GUID is 36
2909 #
2910 return os.path.basename(self.MetaFile.Path)[:36]
2911 return self.Module.Guid
2912
2913 ## Return the module version
2914 def _GetVersion(self):
2915 return self.Module.Version
2916
2917 ## Return the module type
2918 def _GetModuleType(self):
2919 return self.Module.ModuleType
2920
2921 ## Return the component type (for Edk.x style of module)
2922 def _GetComponentType(self):
2923 return self.Module.ComponentType
2924
2925 ## Return the build type
2926 def _GetBuildType(self):
2927 return self.Module.BuildType
2928
2929 ## Return the PCD_IS_DRIVER setting
2930 def _GetPcdIsDriver(self):
2931 return self.Module.PcdIsDriver
2932
2933 ## Return the autogen version, i.e. module meta-file version
2934 def _GetAutoGenVersion(self):
2935 return self.Module.AutoGenVersion
2936
2937 ## Check if the module is library or not
2938 def _IsLibrary(self):
2939 if self._LibraryFlag == None:
2940 if self.Module.LibraryClass != None and self.Module.LibraryClass != []:
2941 self._LibraryFlag = True
2942 else:
2943 self._LibraryFlag = False
2944 return self._LibraryFlag
2945
2946 ## Check if the module is binary module or not
2947 def _IsBinaryModule(self):
2948 return self.Module.IsBinaryModule
2949
2950 ## Return the directory to store intermediate files of the module
2951 def _GetBuildDir(self):
2952 if self._BuildDir == None:
2953 self._BuildDir = path.join(
2954 self.PlatformInfo.BuildDir,
2955 self.Arch,
2956 self.SourceDir,
2957 self.MetaFile.BaseName
2958 )
2959 CreateDirectory(self._BuildDir)
2960 return self._BuildDir
2961
2962 ## Return the directory to store the intermediate object files of the mdoule
2963 def _GetOutputDir(self):
2964 if self._OutputDir == None:
2965 self._OutputDir = path.join(self.BuildDir, "OUTPUT")
2966 CreateDirectory(self._OutputDir)
2967 return self._OutputDir
2968
2969 ## Return the directory to store auto-gened source files of the mdoule
2970 def _GetDebugDir(self):
2971 if self._DebugDir == None:
2972 self._DebugDir = path.join(self.BuildDir, "DEBUG")
2973 CreateDirectory(self._DebugDir)
2974 return self._DebugDir
2975
2976 ## Return the path of custom file
2977 def _GetCustomMakefile(self):
2978 if self._CustomMakefile == None:
2979 self._CustomMakefile = {}
2980 for Type in self.Module.CustomMakefile:
2981 if Type in gMakeTypeMap:
2982 MakeType = gMakeTypeMap[Type]
2983 else:
2984 MakeType = 'nmake'
2985 if self.SourceOverrideDir != None:
2986 File = os.path.join(self.SourceOverrideDir, self.Module.CustomMakefile[Type])
2987 if not os.path.exists(File):
2988 File = os.path.join(self.SourceDir, self.Module.CustomMakefile[Type])
2989 else:
2990 File = os.path.join(self.SourceDir, self.Module.CustomMakefile[Type])
2991 self._CustomMakefile[MakeType] = File
2992 return self._CustomMakefile
2993
2994 ## Return the directory of the makefile
2995 #
2996 # @retval string The directory string of module's makefile
2997 #
2998 def _GetMakeFileDir(self):
2999 return self.BuildDir
3000
3001 ## Return build command string
3002 #
3003 # @retval string Build command string
3004 #
3005 def _GetBuildCommand(self):
3006 return self.PlatformInfo.BuildCommand
3007
3008 ## Get object list of all packages the module and its dependent libraries belong to
3009 #
3010 # @retval list The list of package object
3011 #
3012 def _GetDerivedPackageList(self):
3013 PackageList = []
3014 for M in [self.Module] + self.DependentLibraryList:
3015 for Package in M.Packages:
3016 if Package in PackageList:
3017 continue
3018 PackageList.append(Package)
3019 return PackageList
3020
3021 ## Get the depex string
3022 #
3023 # @return : a string contain all depex expresion.
3024 def _GetDepexExpresionString(self):
3025 DepexStr = ''
3026 DepexList = []
3027 ## DPX_SOURCE IN Define section.
3028 if self.Module.DxsFile:
3029 return DepexStr
3030 for M in [self.Module] + self.DependentLibraryList:
3031 Filename = M.MetaFile.Path
3032 InfObj = InfSectionParser.InfSectionParser(Filename)
3033 DepexExpresionList = InfObj.GetDepexExpresionList()
3034 for DepexExpresion in DepexExpresionList:
3035 for key in DepexExpresion.keys():
3036 Arch, ModuleType = key
3037 DepexExpr = [x for x in DepexExpresion[key] if not str(x).startswith('#')]
3038 # the type of build module is USER_DEFINED.
3039 # All different DEPEX section tags would be copied into the As Built INF file
3040 # and there would be separate DEPEX section tags
3041 if self.ModuleType.upper() == SUP_MODULE_USER_DEFINED:
3042 if (Arch.upper() == self.Arch.upper()) and (ModuleType.upper() != TAB_ARCH_COMMON):
3043 DepexList.append({(Arch, ModuleType): DepexExpr})
3044 else:
3045 if Arch.upper() == TAB_ARCH_COMMON or \
3046 (Arch.upper() == self.Arch.upper() and \
3047 ModuleType.upper() in [TAB_ARCH_COMMON, self.ModuleType.upper()]):
3048 DepexList.append({(Arch, ModuleType): DepexExpr})
3049
3050 #the type of build module is USER_DEFINED.
3051 if self.ModuleType.upper() == SUP_MODULE_USER_DEFINED:
3052 for Depex in DepexList:
3053 for key in Depex.keys():
3054 DepexStr += '[Depex.%s.%s]\n' % key
3055 DepexStr += '\n'.join(['# '+ val for val in Depex[key]])
3056 DepexStr += '\n\n'
3057 if not DepexStr:
3058 return '[Depex.%s]\n' % self.Arch
3059 return DepexStr
3060
3061 #the type of build module not is USER_DEFINED.
3062 Count = 0
3063 for Depex in DepexList:
3064 Count += 1
3065 if DepexStr != '':
3066 DepexStr += ' AND '
3067 DepexStr += '('
3068 for D in Depex.values():
3069 DepexStr += ' '.join([val for val in D])
3070 Index = DepexStr.find('END')
3071 if Index > -1 and Index == len(DepexStr) - 3:
3072 DepexStr = DepexStr[:-3]
3073 DepexStr = DepexStr.strip()
3074 DepexStr += ')'
3075 if Count == 1:
3076 DepexStr = DepexStr.lstrip('(').rstrip(')').strip()
3077 if not DepexStr:
3078 return '[Depex.%s]\n' % self.Arch
3079 return '[Depex.%s]\n# ' % self.Arch + DepexStr
3080
3081 ## Merge dependency expression
3082 #
3083 # @retval list The token list of the dependency expression after parsed
3084 #
3085 def _GetDepexTokenList(self):
3086 if self._DepexList == None:
3087 self._DepexList = {}
3088 if self.DxsFile or self.IsLibrary or TAB_DEPENDENCY_EXPRESSION_FILE in self.FileTypes:
3089 return self._DepexList
3090
3091 self._DepexList[self.ModuleType] = []
3092
3093 for ModuleType in self._DepexList:
3094 DepexList = self._DepexList[ModuleType]
3095 #
3096 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
3097 #
3098 for M in [self.Module] + self.DependentLibraryList:
3099 Inherited = False
3100 for D in M.Depex[self.Arch, ModuleType]:
3101 if DepexList != []:
3102 DepexList.append('AND')
3103 DepexList.append('(')
3104 DepexList.extend(D)
3105 if DepexList[-1] == 'END': # no need of a END at this time
3106 DepexList.pop()
3107 DepexList.append(')')
3108 Inherited = True
3109 if Inherited:
3110 EdkLogger.verbose("DEPEX[%s] (+%s) = %s" % (self.Name, M.BaseName, DepexList))
3111 if 'BEFORE' in DepexList or 'AFTER' in DepexList:
3112 break
3113 if len(DepexList) > 0:
3114 EdkLogger.verbose('')
3115 return self._DepexList
3116
3117 ## Merge dependency expression
3118 #
3119 # @retval list The token list of the dependency expression after parsed
3120 #
3121 def _GetDepexExpressionTokenList(self):
3122 if self._DepexExpressionList == None:
3123 self._DepexExpressionList = {}
3124 if self.DxsFile or self.IsLibrary or TAB_DEPENDENCY_EXPRESSION_FILE in self.FileTypes:
3125 return self._DepexExpressionList
3126
3127 self._DepexExpressionList[self.ModuleType] = ''
3128
3129 for ModuleType in self._DepexExpressionList:
3130 DepexExpressionList = self._DepexExpressionList[ModuleType]
3131 #
3132 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
3133 #
3134 for M in [self.Module] + self.DependentLibraryList:
3135 Inherited = False
3136 for D in M.DepexExpression[self.Arch, ModuleType]:
3137 if DepexExpressionList != '':
3138 DepexExpressionList += ' AND '
3139 DepexExpressionList += '('
3140 DepexExpressionList += D
3141 DepexExpressionList = DepexExpressionList.rstrip('END').strip()
3142 DepexExpressionList += ')'
3143 Inherited = True
3144 if Inherited:
3145 EdkLogger.verbose("DEPEX[%s] (+%s) = %s" % (self.Name, M.BaseName, DepexExpressionList))
3146 if 'BEFORE' in DepexExpressionList or 'AFTER' in DepexExpressionList:
3147 break
3148 if len(DepexExpressionList) > 0:
3149 EdkLogger.verbose('')
3150 self._DepexExpressionList[ModuleType] = DepexExpressionList
3151 return self._DepexExpressionList
3152
3153 # Get the tiano core user extension, it is contain dependent library.
3154 # @retval: a list contain tiano core userextension.
3155 #
3156 def _GetTianoCoreUserExtensionList(self):
3157 TianoCoreUserExtentionList = []
3158 for M in [self.Module] + self.DependentLibraryList:
3159 Filename = M.MetaFile.Path
3160 InfObj = InfSectionParser.InfSectionParser(Filename)
3161 TianoCoreUserExtenList = InfObj.GetUserExtensionTianoCore()
3162 for TianoCoreUserExtent in TianoCoreUserExtenList:
3163 for Section in TianoCoreUserExtent.keys():
3164 ItemList = Section.split(TAB_SPLIT)
3165 Arch = self.Arch
3166 if len(ItemList) == 4:
3167 Arch = ItemList[3]
3168 if Arch.upper() == TAB_ARCH_COMMON or Arch.upper() == self.Arch.upper():
3169 TianoCoreList = []
3170 TianoCoreList.extend([TAB_SECTION_START + Section + TAB_SECTION_END])
3171 TianoCoreList.extend(TianoCoreUserExtent[Section][:])
3172 TianoCoreList.append('\n')
3173 TianoCoreUserExtentionList.append(TianoCoreList)
3174
3175 return TianoCoreUserExtentionList
3176
3177 ## Return the list of specification version required for the module
3178 #
3179 # @retval list The list of specification defined in module file
3180 #
3181 def _GetSpecification(self):
3182 return self.Module.Specification
3183
3184 ## Tool option for the module build
3185 #
3186 # @param PlatformInfo The object of PlatformBuildInfo
3187 # @retval dict The dict containing valid options
3188 #
3189 def _GetModuleBuildOption(self):
3190 if self._BuildOption == None:
3191 self._BuildOption, self.BuildRuleOrder = self.PlatformInfo.ApplyBuildOption(self.Module)
3192 if self.BuildRuleOrder:
3193 self.BuildRuleOrder = ['.%s' % Ext for Ext in self.BuildRuleOrder.split()]
3194 return self._BuildOption
3195
3196 ## Get include path list from tool option for the module build
3197 #
3198 # @retval list The include path list
3199 #
3200 def _GetBuildOptionIncPathList(self):
3201 if self._BuildOptionIncPathList == None:
3202 #
3203 # Regular expression for finding Include Directories, the difference between MSFT and INTEL/GCC/RVCT
3204 # is the former use /I , the Latter used -I to specify include directories
3205 #
3206 if self.PlatformInfo.ToolChainFamily in ('MSFT'):
3207 gBuildOptIncludePattern = re.compile(r"(?:.*?)/I[ \t]*([^ ]*)", re.MULTILINE | re.DOTALL)
3208 elif self.PlatformInfo.ToolChainFamily in ('INTEL', 'GCC', 'RVCT'):
3209 gBuildOptIncludePattern = re.compile(r"(?:.*?)-I[ \t]*([^ ]*)", re.MULTILINE | re.DOTALL)
3210 else:
3211 #
3212 # New ToolChainFamily, don't known whether there is option to specify include directories
3213 #
3214 self._BuildOptionIncPathList = []
3215 return self._BuildOptionIncPathList
3216
3217 BuildOptionIncPathList = []
3218 for Tool in ('CC', 'PP', 'VFRPP', 'ASLPP', 'ASLCC', 'APP', 'ASM'):
3219 Attr = 'FLAGS'
3220 try:
3221 FlagOption = self.BuildOption[Tool][Attr]
3222 except KeyError:
3223 FlagOption = ''
3224
3225 if self.PlatformInfo.ToolChainFamily != 'RVCT':
3226 IncPathList = [NormPath(Path, self.Macros) for Path in gBuildOptIncludePattern.findall(FlagOption)]
3227 else:
3228 #
3229 # RVCT may specify a list of directory seperated by commas
3230 #
3231 IncPathList = []
3232 for Path in gBuildOptIncludePattern.findall(FlagOption):
3233 PathList = GetSplitList(Path, TAB_COMMA_SPLIT)
3234 IncPathList += [NormPath(PathEntry, self.Macros) for PathEntry in PathList]
3235
3236 #
3237 # EDK II modules must not reference header files outside of the packages they depend on or
3238 # within the module's directory tree. Report error if violation.
3239 #
3240 if self.AutoGenVersion >= 0x00010005 and len(IncPathList) > 0:
3241 for Path in IncPathList:
3242 if (Path not in self.IncludePathList) and (CommonPath([Path, self.MetaFile.Dir]) != self.MetaFile.Dir):
3243 ErrMsg = "The include directory for the EDK II module in this line is invalid %s specified in %s FLAGS '%s'" % (Path, Tool, FlagOption)
3244 EdkLogger.error("build",
3245 PARAMETER_INVALID,
3246 ExtraData=ErrMsg,
3247 File=str(self.MetaFile))
3248
3249
3250 BuildOptionIncPathList += IncPathList
3251
3252 self._BuildOptionIncPathList = BuildOptionIncPathList
3253
3254 return self._BuildOptionIncPathList
3255
3256 ## Return a list of files which can be built from source
3257 #
3258 # What kind of files can be built is determined by build rules in
3259 # $(CONF_DIRECTORY)/build_rule.txt and toolchain family.
3260 #
3261 def _GetSourceFileList(self):
3262 if self._SourceFileList == None:
3263 self._SourceFileList = []
3264 for F in self.Module.Sources:
3265 # match tool chain
3266 if F.TagName not in ("", "*", self.ToolChain):
3267 EdkLogger.debug(EdkLogger.DEBUG_9, "The toolchain [%s] for processing file [%s] is found, "
3268 "but [%s] is needed" % (F.TagName, str(F), self.ToolChain))
3269 continue
3270 # match tool chain family
3271 if F.ToolChainFamily not in ("", "*", self.ToolChainFamily):
3272 EdkLogger.debug(
3273 EdkLogger.DEBUG_0,
3274 "The file [%s] must be built by tools of [%s], " \
3275 "but current toolchain family is [%s]" \
3276 % (str(F), F.ToolChainFamily, self.ToolChainFamily))
3277 continue
3278
3279 # add the file path into search path list for file including
3280 if F.Dir not in self.IncludePathList and self.AutoGenVersion >= 0x00010005:
3281 self.IncludePathList.insert(0, F.Dir)
3282 self._SourceFileList.append(F)
3283
3284 self._MatchBuildRuleOrder(self._SourceFileList)
3285
3286 for F in self._SourceFileList:
3287 self._ApplyBuildRule(F, TAB_UNKNOWN_FILE)
3288 return self._SourceFileList
3289
3290 def _MatchBuildRuleOrder(self, FileList):
3291 Order_Dict = {}
3292 self._GetModuleBuildOption()
3293 for SingleFile in FileList:
3294 if self.BuildRuleOrder and SingleFile.Ext in self.BuildRuleOrder and SingleFile.Ext in self.BuildRules:
3295 key = SingleFile.Path.split(SingleFile.Ext)[0]
3296 if key in Order_Dict:
3297 Order_Dict[key].append(SingleFile.Ext)
3298 else:
3299 Order_Dict[key] = [SingleFile.Ext]
3300
3301 RemoveList = []
3302 for F in Order_Dict:
3303 if len(Order_Dict[F]) > 1:
3304 Order_Dict[F].sort(key=lambda i: self.BuildRuleOrder.index(i))
3305 for Ext in Order_Dict[F][1:]:
3306 RemoveList.append(F + Ext)
3307
3308 for item in RemoveList:
3309 FileList.remove(item)
3310
3311 return FileList
3312
3313 ## Return the list of unicode files
3314 def _GetUnicodeFileList(self):
3315 if self._UnicodeFileList == None:
3316 if TAB_UNICODE_FILE in self.FileTypes:
3317 self._UnicodeFileList = self.FileTypes[TAB_UNICODE_FILE]
3318 else:
3319 self._UnicodeFileList = []
3320 return self._UnicodeFileList
3321
3322 ## Return the list of vfr files
3323 def _GetVfrFileList(self):
3324 if self._VfrFileList == None:
3325 if TAB_VFR_FILE in self.FileTypes:
3326 self._VfrFileList = self.FileTypes[TAB_VFR_FILE]
3327 else:
3328 self._VfrFileList = []
3329 return self._VfrFileList
3330
3331 ## Return the list of Image Definition files
3332 def _GetIdfFileList(self):
3333 if self._IdfFileList == None:
3334 if TAB_IMAGE_FILE in self.FileTypes:
3335 self._IdfFileList = self.FileTypes[TAB_IMAGE_FILE]
3336 else:
3337 self._IdfFileList = []
3338 return self._IdfFileList
3339
3340 ## Return a list of files which can be built from binary
3341 #
3342 # "Build" binary files are just to copy them to build directory.
3343 #
3344 # @retval list The list of files which can be built later
3345 #
3346 def _GetBinaryFiles(self):
3347 if self._BinaryFileList == None:
3348 self._BinaryFileList = []
3349 for F in self.Module.Binaries:
3350 if F.Target not in ['COMMON', '*'] and F.Target != self.BuildTarget:
3351 continue
3352 self._BinaryFileList.append(F)
3353 self._ApplyBuildRule(F, F.Type)
3354 return self._BinaryFileList
3355
3356 def _GetBuildRules(self):
3357 if self._BuildRules == None:
3358 BuildRules = {}
3359 BuildRuleDatabase = self.PlatformInfo.BuildRule
3360 for Type in BuildRuleDatabase.FileTypeList:
3361 #first try getting build rule by BuildRuleFamily
3362 RuleObject = BuildRuleDatabase[Type, self.BuildType, self.Arch, self.BuildRuleFamily]
3363 if not RuleObject:
3364 # build type is always module type, but ...
3365 if self.ModuleType != self.BuildType:
3366 RuleObject = BuildRuleDatabase[Type, self.ModuleType, self.Arch, self.BuildRuleFamily]
3367 #second try getting build rule by ToolChainFamily
3368 if not RuleObject:
3369 RuleObject = BuildRuleDatabase[Type, self.BuildType, self.Arch, self.ToolChainFamily]
3370 if not RuleObject:
3371 # build type is always module type, but ...
3372 if self.ModuleType != self.BuildType:
3373 RuleObject = BuildRuleDatabase[Type, self.ModuleType, self.Arch, self.ToolChainFamily]
3374 if not RuleObject:
3375 continue
3376 RuleObject = RuleObject.Instantiate(self.Macros)
3377 BuildRules[Type] = RuleObject
3378 for Ext in RuleObject.SourceFileExtList:
3379 BuildRules[Ext] = RuleObject
3380 self._BuildRules = BuildRules
3381 return self._BuildRules
3382
3383 def _ApplyBuildRule(self, File, FileType):
3384 if self._BuildTargets == None:
3385 self._IntroBuildTargetList = set()
3386 self._FinalBuildTargetList = set()
3387 self._BuildTargets = {}
3388 self._FileTypes = {}
3389
3390 SubDirectory = os.path.join(self.OutputDir, File.SubDir)
3391 if not os.path.exists(SubDirectory):
3392 CreateDirectory(SubDirectory)
3393 LastTarget = None
3394 RuleChain = []
3395 SourceList = [File]
3396 Index = 0
3397 #
3398 # Make sure to get build rule order value
3399 #
3400 self._GetModuleBuildOption()
3401
3402 while Index < len(SourceList):
3403 Source = SourceList[Index]
3404 Index = Index + 1
3405
3406 if Source != File:
3407 CreateDirectory(Source.Dir)
3408
3409 if File.IsBinary and File == Source and self._BinaryFileList != None and File in self._BinaryFileList:
3410 # Skip all files that are not binary libraries
3411 if not self.IsLibrary:
3412 continue
3413 RuleObject = self.BuildRules[TAB_DEFAULT_BINARY_FILE]
3414 elif FileType in self.BuildRules:
3415 RuleObject = self.BuildRules[FileType]
3416 elif Source.Ext in self.BuildRules:
3417 RuleObject = self.BuildRules[Source.Ext]
3418 else:
3419 # stop at no more rules
3420 if LastTarget:
3421 self._FinalBuildTargetList.add(LastTarget)
3422 break
3423
3424 FileType = RuleObject.SourceFileType
3425 if FileType not in self._FileTypes:
3426 self._FileTypes[FileType] = set()
3427 self._FileTypes[FileType].add(Source)
3428
3429 # stop at STATIC_LIBRARY for library
3430 if self.IsLibrary and FileType == TAB_STATIC_LIBRARY:
3431 if LastTarget:
3432 self._FinalBuildTargetList.add(LastTarget)
3433 break
3434
3435 Target = RuleObject.Apply(Source, self.BuildRuleOrder)
3436 if not Target:
3437 if LastTarget:
3438 self._FinalBuildTargetList.add(LastTarget)
3439 break
3440 elif not Target.Outputs:
3441 # Only do build for target with outputs
3442 self._FinalBuildTargetList.add(Target)
3443
3444 if FileType not in self._BuildTargets:
3445 self._BuildTargets[FileType] = set()
3446 self._BuildTargets[FileType].add(Target)
3447
3448 if not Source.IsBinary and Source == File:
3449 self._IntroBuildTargetList.add(Target)
3450
3451 # to avoid cyclic rule
3452 if FileType in RuleChain:
3453 break
3454
3455 RuleChain.append(FileType)
3456 SourceList.extend(Target.Outputs)
3457 LastTarget = Target
3458 FileType = TAB_UNKNOWN_FILE
3459
3460 def _GetTargets(self):
3461 if self._BuildTargets == None:
3462 self._IntroBuildTargetList = set()
3463 self._FinalBuildTargetList = set()
3464 self._BuildTargets = {}
3465 self._FileTypes = {}
3466
3467 #TRICK: call _GetSourceFileList to apply build rule for source files
3468 if self.SourceFileList:
3469 pass
3470
3471 #TRICK: call _GetBinaryFileList to apply build rule for binary files
3472 if self.BinaryFileList:
3473 pass
3474
3475 return self._BuildTargets
3476
3477 def _GetIntroTargetList(self):
3478 self._GetTargets()
3479 return self._IntroBuildTargetList
3480
3481 def _GetFinalTargetList(self):
3482 self._GetTargets()
3483 return self._FinalBuildTargetList
3484
3485 def _GetFileTypes(self):
3486 self._GetTargets()
3487 return self._FileTypes
3488
3489 ## Get the list of package object the module depends on
3490 #
3491 # @retval list The package object list
3492 #
3493 def _GetDependentPackageList(self):
3494 return self.Module.Packages
3495
3496 ## Return the list of auto-generated code file
3497 #
3498 # @retval list The list of auto-generated file
3499 #
3500 def _GetAutoGenFileList(self):
3501 UniStringAutoGenC = True
3502 IdfStringAutoGenC = True
3503 UniStringBinBuffer = StringIO()
3504 IdfGenBinBuffer = StringIO()
3505 if self.BuildType == 'UEFI_HII':
3506 UniStringAutoGenC = False
3507 IdfStringAutoGenC = False
3508 if self._AutoGenFileList == None:
3509 self._AutoGenFileList = {}
3510 AutoGenC = TemplateString()
3511 AutoGenH = TemplateString()
3512 StringH = TemplateString()
3513 StringIdf = TemplateString()
3514 GenC.CreateCode(self, AutoGenC, AutoGenH, StringH, UniStringAutoGenC, UniStringBinBuffer, StringIdf, IdfStringAutoGenC, IdfGenBinBuffer)
3515 #
3516 # AutoGen.c is generated if there are library classes in inf, or there are object files
3517 #
3518 if str(AutoGenC) != "" and (len(self.Module.LibraryClasses) > 0
3519 or TAB_OBJECT_FILE in self.FileTypes):
3520 AutoFile = PathClass(gAutoGenCodeFileName, self.DebugDir)
3521 self._AutoGenFileList[AutoFile] = str(AutoGenC)
3522 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
3523 if str(AutoGenH) != "":
3524 AutoFile = PathClass(gAutoGenHeaderFileName, self.DebugDir)
3525 self._AutoGenFileList[AutoFile] = str(AutoGenH)
3526 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
3527 if str(StringH) != "":
3528 AutoFile = PathClass(gAutoGenStringFileName % {"module_name":self.Name}, self.DebugDir)
3529 self._AutoGenFileList[AutoFile] = str(StringH)
3530 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
3531 if UniStringBinBuffer != None and UniStringBinBuffer.getvalue() != "":
3532 AutoFile = PathClass(gAutoGenStringFormFileName % {"module_name":self.Name}, self.OutputDir)
3533 self._AutoGenFileList[AutoFile] = UniStringBinBuffer.getvalue()
3534 AutoFile.IsBinary = True
3535 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
3536 if UniStringBinBuffer != None:
3537 UniStringBinBuffer.close()
3538 if str(StringIdf) != "":
3539 AutoFile = PathClass(gAutoGenImageDefFileName % {"module_name":self.Name}, self.DebugDir)
3540 self._AutoGenFileList[AutoFile] = str(StringIdf)
3541 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
3542 if IdfGenBinBuffer != None and IdfGenBinBuffer.getvalue() != "":
3543 AutoFile = PathClass(gAutoGenIdfFileName % {"module_name":self.Name}, self.OutputDir)
3544 self._AutoGenFileList[AutoFile] = IdfGenBinBuffer.getvalue()
3545 AutoFile.IsBinary = True
3546 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
3547 if IdfGenBinBuffer != None:
3548 IdfGenBinBuffer.close()
3549 return self._AutoGenFileList
3550
3551 ## Return the list of library modules explicitly or implicityly used by this module
3552 def _GetLibraryList(self):
3553 if self._DependentLibraryList == None:
3554 # only merge library classes and PCD for non-library module
3555 if self.IsLibrary:
3556 self._DependentLibraryList = []
3557 else:
3558 if self.AutoGenVersion < 0x00010005:
3559 self._DependentLibraryList = self.PlatformInfo.ResolveLibraryReference(self.Module)
3560 else:
3561 self._DependentLibraryList = self.PlatformInfo.ApplyLibraryInstance(self.Module)
3562 return self._DependentLibraryList
3563
3564 @staticmethod
3565 def UpdateComments(Recver, Src):
3566 for Key in Src:
3567 if Key not in Recver:
3568 Recver[Key] = []
3569 Recver[Key].extend(Src[Key])
3570 ## Get the list of PCDs from current module
3571 #
3572 # @retval list The list of PCD
3573 #
3574 def _GetModulePcdList(self):
3575 if self._ModulePcdList == None:
3576 # apply PCD settings from platform
3577 self._ModulePcdList = self.PlatformInfo.ApplyPcdSetting(self.Module, self.Module.Pcds)
3578 self.UpdateComments(self._PcdComments, self.Module.PcdComments)
3579 return self._ModulePcdList
3580
3581 ## Get the list of PCDs from dependent libraries
3582 #
3583 # @retval list The list of PCD
3584 #
3585 def _GetLibraryPcdList(self):
3586 if self._LibraryPcdList == None:
3587 Pcds = sdict()
3588 if not self.IsLibrary:
3589 # get PCDs from dependent libraries
3590 for Library in self.DependentLibraryList:
3591 self.UpdateComments(self._PcdComments, Library.PcdComments)
3592 for Key in Library.Pcds:
3593 # skip duplicated PCDs
3594 if Key in self.Module.Pcds or Key in Pcds:
3595 continue
3596 Pcds[Key] = copy.copy(Library.Pcds[Key])
3597 # apply PCD settings from platform
3598 self._LibraryPcdList = self.PlatformInfo.ApplyPcdSetting(self.Module, Pcds)
3599 else:
3600 self._LibraryPcdList = []
3601 return self._LibraryPcdList
3602
3603 ## Get the GUID value mapping
3604 #
3605 # @retval dict The mapping between GUID cname and its value
3606 #
3607 def _GetGuidList(self):
3608 if self._GuidList == None:
3609 self._GuidList = sdict()
3610 self._GuidList.update(self.Module.Guids)
3611 for Library in self.DependentLibraryList:
3612 self._GuidList.update(Library.Guids)
3613 self.UpdateComments(self._GuidComments, Library.GuidComments)
3614 self.UpdateComments(self._GuidComments, self.Module.GuidComments)
3615 return self._GuidList
3616
3617 def GetGuidsUsedByPcd(self):
3618 if self._GuidsUsedByPcd == None:
3619 self._GuidsUsedByPcd = sdict()
3620 self._GuidsUsedByPcd.update(self.Module.GetGuidsUsedByPcd())
3621 for Library in self.DependentLibraryList:
3622 self._GuidsUsedByPcd.update(Library.GetGuidsUsedByPcd())
3623 return self._GuidsUsedByPcd
3624 ## Get the protocol value mapping
3625 #
3626 # @retval dict The mapping between protocol cname and its value
3627 #
3628 def _GetProtocolList(self):
3629 if self._ProtocolList == None:
3630 self._ProtocolList = sdict()
3631 self._ProtocolList.update(self.Module.Protocols)
3632 for Library in self.DependentLibraryList:
3633 self._ProtocolList.update(Library.Protocols)
3634 self.UpdateComments(self._ProtocolComments, Library.ProtocolComments)
3635 self.UpdateComments(self._ProtocolComments, self.Module.ProtocolComments)
3636 return self._ProtocolList
3637
3638 ## Get the PPI value mapping
3639 #
3640 # @retval dict The mapping between PPI cname and its value
3641 #
3642 def _GetPpiList(self):
3643 if self._PpiList == None:
3644 self._PpiList = sdict()
3645 self._PpiList.update(self.Module.Ppis)
3646 for Library in self.DependentLibraryList:
3647 self._PpiList.update(Library.Ppis)
3648 self.UpdateComments(self._PpiComments, Library.PpiComments)
3649 self.UpdateComments(self._PpiComments, self.Module.PpiComments)
3650 return self._PpiList
3651
3652 ## Get the list of include search path
3653 #
3654 # @retval list The list path
3655 #
3656 def _GetIncludePathList(self):
3657 if self._IncludePathList == None:
3658 self._IncludePathList = []
3659 if self.AutoGenVersion < 0x00010005:
3660 for Inc in self.Module.Includes:
3661 if Inc not in self._IncludePathList:
3662 self._IncludePathList.append(Inc)
3663 # for Edk modules
3664 Inc = path.join(Inc, self.Arch.capitalize())
3665 if os.path.exists(Inc) and Inc not in self._IncludePathList:
3666 self._IncludePathList.append(Inc)
3667 # Edk module needs to put DEBUG_DIR at the end of search path and not to use SOURCE_DIR all the time
3668 self._IncludePathList.append(self.DebugDir)
3669 else:
3670 self._IncludePathList.append(self.MetaFile.Dir)
3671 self._IncludePathList.append(self.DebugDir)
3672
3673 for Package in self.Module.Packages:
3674 PackageDir = mws.join(self.WorkspaceDir, Package.MetaFile.Dir)
3675 if PackageDir not in self._IncludePathList:
3676 self._IncludePathList.append(PackageDir)
3677 IncludesList = Package.Includes
3678 if Package._PrivateIncludes:
3679 if not self.MetaFile.Path.startswith(PackageDir):
3680 IncludesList = list(set(Package.Includes).difference(set(Package._PrivateIncludes)))
3681 for Inc in IncludesList:
3682 if Inc not in self._IncludePathList:
3683 self._IncludePathList.append(str(Inc))
3684 return self._IncludePathList
3685
3686 def _GetIncludePathLength(self):
3687 self._IncludePathLength = 0
3688 if self._IncludePathList:
3689 for inc in self._IncludePathList:
3690 self._IncludePathLength += len(' ' + inc)
3691 return self._IncludePathLength
3692
3693 ## Get HII EX PCDs which maybe used by VFR
3694 #
3695 # efivarstore used by VFR may relate with HII EX PCDs
3696 # Get the variable name and GUID from efivarstore and HII EX PCD
3697 # List the HII EX PCDs in As Built INF if both name and GUID match.
3698 #
3699 # @retval list HII EX PCDs
3700 #
3701 def _GetPcdsMaybeUsedByVfr(self):
3702 if not self.SourceFileList:
3703 return []
3704
3705 NameGuids = []
3706 for SrcFile in self.SourceFileList:
3707 if SrcFile.Ext.lower() != '.vfr':
3708 continue
3709 Vfri = os.path.join(self.OutputDir, SrcFile.BaseName + '.i')
3710 if not os.path.exists(Vfri):
3711 continue
3712 VfriFile = open(Vfri, 'r')
3713 Content = VfriFile.read()
3714 VfriFile.close()
3715 Pos = Content.find('efivarstore')
3716 while Pos != -1:
3717 #
3718 # Make sure 'efivarstore' is the start of efivarstore statement
3719 # In case of the value of 'name' (name = efivarstore) is equal to 'efivarstore'
3720 #
3721 Index = Pos - 1
3722 while Index >= 0 and Content[Index] in ' \t\r\n':
3723 Index -= 1
3724 if Index >= 0 and Content[Index] != ';':
3725 Pos = Content.find('efivarstore', Pos + len('efivarstore'))
3726 continue
3727 #
3728 # 'efivarstore' must be followed by name and guid
3729 #
3730 Name = gEfiVarStoreNamePattern.search(Content, Pos)
3731 if not Name:
3732 break
3733 Guid = gEfiVarStoreGuidPattern.search(Content, Pos)
3734 if not Guid:
3735 break
3736 NameArray = ConvertStringToByteArray('L"' + Name.group(1) + '"')
3737 NameGuids.append((NameArray, GuidStructureStringToGuidString(Guid.group(1))))
3738 Pos = Content.find('efivarstore', Name.end())
3739 if not NameGuids:
3740 return []
3741 HiiExPcds = []
3742 for Pcd in self.PlatformInfo.Platform.Pcds.values():
3743 if Pcd.Type != TAB_PCDS_DYNAMIC_EX_HII:
3744 continue
3745 for SkuName in Pcd.SkuInfoList:
3746 SkuInfo = Pcd.SkuInfoList[SkuName]
3747 Name = ConvertStringToByteArray(SkuInfo.VariableName)
3748 Value = GuidValue(SkuInfo.VariableGuid, self.PlatformInfo.PackageList, self.MetaFile.Path)
3749 if not Value:
3750 continue
3751 Guid = GuidStructureStringToGuidString(Value)
3752 if (Name, Guid) in NameGuids and Pcd not in HiiExPcds:
3753 HiiExPcds.append(Pcd)
3754 break
3755
3756 return HiiExPcds
3757
3758 def _GenOffsetBin(self):
3759 VfrUniBaseName = {}
3760 for SourceFile in self.Module.Sources:
3761 if SourceFile.Type.upper() == ".VFR" :
3762 #
3763 # search the .map file to find the offset of vfr binary in the PE32+/TE file.
3764 #
3765 VfrUniBaseName[SourceFile.BaseName] = (SourceFile.BaseName + "Bin")
3766 if SourceFile.Type.upper() == ".UNI" :
3767 #
3768 # search the .map file to find the offset of Uni strings binary in the PE32+/TE file.
3769 #
3770 VfrUniBaseName["UniOffsetName"] = (self.Name + "Strings")
3771
3772 if len(VfrUniBaseName) == 0:
3773 return None
3774 MapFileName = os.path.join(self.OutputDir, self.Name + ".map")
3775 EfiFileName = os.path.join(self.OutputDir, self.Name + ".efi")
3776 VfrUniOffsetList = GetVariableOffset(MapFileName, EfiFileName, VfrUniBaseName.values())
3777 if not VfrUniOffsetList:
3778 return None
3779
3780 OutputName = '%sOffset.bin' % self.Name
3781 UniVfrOffsetFileName = os.path.join( self.OutputDir, OutputName)
3782
3783 try:
3784 fInputfile = open(UniVfrOffsetFileName, "wb+", 0)
3785 except:
3786 EdkLogger.error("build", FILE_OPEN_FAILURE, "File open failed for %s" % UniVfrOffsetFileName,None)
3787
3788 # Use a instance of StringIO to cache data
3789 fStringIO = StringIO('')
3790
3791 for Item in VfrUniOffsetList:
3792 if (Item[0].find("Strings") != -1):
3793 #
3794 # UNI offset in image.
3795 # GUID + Offset
3796 # { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } }
3797 #
3798 UniGuid = [0xe0, 0xc5, 0x13, 0x89, 0xf6, 0x33, 0x86, 0x4d, 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66]
3799 UniGuid = [chr(ItemGuid) for ItemGuid in UniGuid]
3800 fStringIO.write(''.join(UniGuid))
3801 UniValue = pack ('Q', int (Item[1], 16))
3802 fStringIO.write (UniValue)
3803 else:
3804 #
3805 # VFR binary offset in image.
3806 # GUID + Offset
3807 # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } };
3808 #
3809 VfrGuid = [0xb4, 0x7c, 0xbc, 0xd0, 0x47, 0x6a, 0x5f, 0x49, 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2]
3810 VfrGuid = [chr(ItemGuid) for ItemGuid in VfrGuid]
3811 fStringIO.write(''.join(VfrGuid))
3812 type (Item[1])
3813 VfrValue = pack ('Q', int (Item[1], 16))
3814 fStringIO.write (VfrValue)
3815 #
3816 # write data into file.
3817 #
3818 try :
3819 fInputfile.write (fStringIO.getvalue())
3820 except:
3821 EdkLogger.error("build", FILE_WRITE_FAILURE, "Write data to file %s failed, please check whether the "
3822 "file been locked or using by other applications." %UniVfrOffsetFileName,None)
3823
3824 fStringIO.close ()
3825 fInputfile.close ()
3826 return OutputName
3827
3828 ## Create AsBuilt INF file the module
3829 #
3830 def CreateAsBuiltInf(self):
3831 if self.IsAsBuiltInfCreated:
3832 return
3833
3834 # Skip the following code for EDK I inf
3835 if self.AutoGenVersion < 0x00010005:
3836 return
3837
3838 # Skip the following code for libraries
3839 if self.IsLibrary:
3840 return
3841
3842 # Skip the following code for modules with no source files
3843 if self.SourceFileList == None or self.SourceFileList == []:
3844 return
3845
3846 # Skip the following code for modules without any binary files
3847 if self.BinaryFileList <> None and self.BinaryFileList <> []:
3848 return
3849
3850 ### TODO: How to handles mixed source and binary modules
3851
3852 # Find all DynamicEx and PatchableInModule PCDs used by this module and dependent libraries
3853 # Also find all packages that the DynamicEx PCDs depend on
3854 Pcds = []
3855 PatchablePcds = []
3856 Packages = []
3857 PcdCheckList = []
3858 PcdTokenSpaceList = []
3859 for Pcd in self.ModulePcdList + self.LibraryPcdList:
3860 if Pcd.Type == TAB_PCDS_PATCHABLE_IN_MODULE:
3861 PatchablePcds += [Pcd]
3862 PcdCheckList.append((Pcd.TokenCName, Pcd.TokenSpaceGuidCName, 'PatchableInModule'))
3863 elif Pcd.Type in GenC.gDynamicExPcd:
3864 if Pcd not in Pcds:
3865 Pcds += [Pcd]
3866 PcdCheckList.append((Pcd.TokenCName, Pcd.TokenSpaceGuidCName, 'DynamicEx'))
3867 PcdCheckList.append((Pcd.TokenCName, Pcd.TokenSpaceGuidCName, 'Dynamic'))
3868 PcdTokenSpaceList.append(Pcd.TokenSpaceGuidCName)
3869 GuidList = sdict()
3870 GuidList.update(self.GuidList)
3871 for TokenSpace in self.GetGuidsUsedByPcd():
3872 # If token space is not referred by patch PCD or Ex PCD, remove the GUID from GUID list
3873 # The GUIDs in GUIDs section should really be the GUIDs in source INF or referred by Ex an patch PCDs
3874 if TokenSpace not in PcdTokenSpaceList and TokenSpace in GuidList:
3875 GuidList.pop(TokenSpace)
3876 CheckList = (GuidList, self.PpiList, self.ProtocolList, PcdCheckList)
3877 for Package in self.DerivedPackageList:
3878 if Package in Packages:
3879 continue
3880 BeChecked = (Package.Guids, Package.Ppis, Package.Protocols, Package.Pcds)
3881 Found = False
3882 for Index in range(len(BeChecked)):
3883 for Item in CheckList[Index]:
3884 if Item in BeChecked[Index]:
3885 Packages += [Package]
3886 Found = True
3887 break
3888 if Found: break
3889
3890 VfrPcds = self._GetPcdsMaybeUsedByVfr()
3891 for Pkg in self.PlatformInfo.PackageList:
3892 if Pkg in Packages:
3893 continue
3894 for VfrPcd in VfrPcds:
3895 if ((VfrPcd.TokenCName, VfrPcd.TokenSpaceGuidCName, 'DynamicEx') in Pkg.Pcds or
3896 (VfrPcd.TokenCName, VfrPcd.TokenSpaceGuidCName, 'Dynamic') in Pkg.Pcds):
3897 Packages += [Pkg]
3898 break
3899
3900 ModuleType = self.ModuleType
3901 if ModuleType == 'UEFI_DRIVER' and self.DepexGenerated:
3902 ModuleType = 'DXE_DRIVER'
3903
3904 DriverType = ''
3905 if self.PcdIsDriver != '':
3906 DriverType = self.PcdIsDriver
3907
3908 Guid = self.Guid
3909 MDefs = self.Module.Defines
3910
3911 AsBuiltInfDict = {
3912 'module_name' : self.Name,
3913 'module_guid' : Guid,
3914 'module_module_type' : ModuleType,
3915 'module_version_string' : [MDefs['VERSION_STRING']] if 'VERSION_STRING' in MDefs else [],
3916 'pcd_is_driver_string' : [],
3917 'module_uefi_specification_version' : [],
3918 'module_pi_specification_version' : [],
3919 'module_entry_point' : self.Module.ModuleEntryPointList,
3920 'module_unload_image' : self.Module.ModuleUnloadImageList,
3921 'module_constructor' : self.Module.ConstructorList,
3922 'module_destructor' : self.Module.DestructorList,
3923 'module_shadow' : [MDefs['SHADOW']] if 'SHADOW' in MDefs else [],
3924 'module_pci_vendor_id' : [MDefs['PCI_VENDOR_ID']] if 'PCI_VENDOR_ID' in MDefs else [],
3925 'module_pci_device_id' : [MDefs['PCI_DEVICE_ID']] if 'PCI_DEVICE_ID' in MDefs else [],
3926 'module_pci_class_code' : [MDefs['PCI_CLASS_CODE']] if 'PCI_CLASS_CODE' in MDefs else [],
3927 'module_pci_revision' : [MDefs['PCI_REVISION']] if 'PCI_REVISION' in MDefs else [],
3928 'module_build_number' : [MDefs['BUILD_NUMBER']] if 'BUILD_NUMBER' in MDefs else [],
3929 'module_spec' : [MDefs['SPEC']] if 'SPEC' in MDefs else [],
3930 'module_uefi_hii_resource_section' : [MDefs['UEFI_HII_RESOURCE_SECTION']] if 'UEFI_HII_RESOURCE_SECTION' in MDefs else [],
3931 'module_uni_file' : [MDefs['MODULE_UNI_FILE']] if 'MODULE_UNI_FILE' in MDefs else [],
3932 'module_arch' : self.Arch,
3933 'package_item' : ['%s' % (Package.MetaFile.File.replace('\\', '/')) for Package in Packages],
3934 'binary_item' : [],
3935 'patchablepcd_item' : [],
3936 'pcd_item' : [],
3937 'protocol_item' : [],
3938 'ppi_item' : [],
3939 'guid_item' : [],
3940 'flags_item' : [],
3941 'libraryclasses_item' : []
3942 }
3943
3944 if 'MODULE_UNI_FILE' in MDefs:
3945 UNIFile = os.path.join(self.MetaFile.Dir, MDefs['MODULE_UNI_FILE'])
3946 if os.path.isfile(UNIFile):
3947 shutil.copy2(UNIFile, self.OutputDir)
3948
3949 if self.AutoGenVersion > int(gInfSpecVersion, 0):
3950 AsBuiltInfDict['module_inf_version'] = '0x%08x' % self.AutoGenVersion
3951 else:
3952 AsBuiltInfDict['module_inf_version'] = gInfSpecVersion
3953
3954 if DriverType:
3955 AsBuiltInfDict['pcd_is_driver_string'] += [DriverType]
3956
3957 if 'UEFI_SPECIFICATION_VERSION' in self.Specification:
3958 AsBuiltInfDict['module_uefi_specification_version'] += [self.Specification['UEFI_SPECIFICATION_VERSION']]
3959 if 'PI_SPECIFICATION_VERSION' in self.Specification:
3960 AsBuiltInfDict['module_pi_specification_version'] += [self.Specification['PI_SPECIFICATION_VERSION']]
3961
3962 OutputDir = self.OutputDir.replace('\\', '/').strip('/')
3963 self.OutputFile = []
3964 for Item in self.CodaTargetList:
3965 File = Item.Target.Path.replace('\\', '/').strip('/').replace(OutputDir, '').strip('/')
3966 if File not in self.OutputFile:
3967 self.OutputFile.append(File)
3968 if Item.Target.Ext.lower() == '.aml':
3969 AsBuiltInfDict['binary_item'] += ['ASL|' + File]
3970 elif Item.Target.Ext.lower() == '.acpi':
3971 AsBuiltInfDict['binary_item'] += ['ACPI|' + File]
3972 elif Item.Target.Ext.lower() == '.efi':
3973 AsBuiltInfDict['binary_item'] += ['PE32|' + self.Name + '.efi']
3974 else:
3975 AsBuiltInfDict['binary_item'] += ['BIN|' + File]
3976 if self.DepexGenerated:
3977 if self.Name + '.depex' not in self.OutputFile:
3978 self.OutputFile.append(self.Name + '.depex')
3979 if self.ModuleType in ['PEIM']:
3980 AsBuiltInfDict['binary_item'] += ['PEI_DEPEX|' + self.Name + '.depex']
3981 if self.ModuleType in ['DXE_DRIVER', 'DXE_RUNTIME_DRIVER', 'DXE_SAL_DRIVER', 'UEFI_DRIVER']:
3982 AsBuiltInfDict['binary_item'] += ['DXE_DEPEX|' + self.Name + '.depex']
3983 if self.ModuleType in ['DXE_SMM_DRIVER']:
3984 AsBuiltInfDict['binary_item'] += ['SMM_DEPEX|' + self.Name + '.depex']
3985
3986 Bin = self._GenOffsetBin()
3987 if Bin:
3988 AsBuiltInfDict['binary_item'] += ['BIN|%s' % Bin]
3989 if Bin not in self.OutputFile:
3990 self.OutputFile.append(Bin)
3991
3992 for Root, Dirs, Files in os.walk(OutputDir):
3993 for File in Files:
3994 if File.lower().endswith('.pdb'):
3995 AsBuiltInfDict['binary_item'] += ['DISPOSABLE|' + File]
3996 if File not in self.OutputFile:
3997 self.OutputFile.append(File)
3998 HeaderComments = self.Module.HeaderComments
3999 StartPos = 0
4000 for Index in range(len(HeaderComments)):
4001 if HeaderComments[Index].find('@BinaryHeader') != -1:
4002 HeaderComments[Index] = HeaderComments[Index].replace('@BinaryHeader', '@file')
4003 StartPos = Index
4004 break
4005 AsBuiltInfDict['header_comments'] = '\n'.join(HeaderComments[StartPos:]).replace(':#', '://')
4006 AsBuiltInfDict['tail_comments'] = '\n'.join(self.Module.TailComments)
4007
4008 GenList = [
4009 (self.ProtocolList, self._ProtocolComments, 'protocol_item'),
4010 (self.PpiList, self._PpiComments, 'ppi_item'),
4011 (GuidList, self._GuidComments, 'guid_item')
4012 ]
4013 for Item in GenList:
4014 for CName in Item[0]:
4015 Comments = ''
4016 if CName in Item[1]:
4017 Comments = '\n '.join(Item[1][CName])
4018 Entry = CName
4019 if Comments:
4020 Entry = Comments + '\n ' + CName
4021 AsBuiltInfDict[Item[2]].append(Entry)
4022 PatchList = parsePcdInfoFromMapFile(
4023 os.path.join(self.OutputDir, self.Name + '.map'),
4024 os.path.join(self.OutputDir, self.Name + '.efi')
4025 )
4026 if PatchList:
4027 for Pcd in PatchablePcds:
4028 TokenCName = Pcd.TokenCName
4029 for PcdItem in GlobalData.MixedPcd:
4030 if (Pcd.TokenCName, Pcd.TokenSpaceGuidCName) in GlobalData.MixedPcd[PcdItem]:
4031 TokenCName = PcdItem[0]
4032 break
4033 for PatchPcd in PatchList:
4034 if TokenCName == PatchPcd[0]:
4035 break
4036 else:
4037 continue
4038 PcdValue = ''
4039 if Pcd.DatumType == 'BOOLEAN':
4040 BoolValue = Pcd.DefaultValue.upper()
4041 if BoolValue == 'TRUE':
4042 Pcd.DefaultValue = '1'
4043 elif BoolValue == 'FALSE':
4044 Pcd.DefaultValue = '0'
4045
4046 if Pcd.DatumType != 'VOID*':
4047 HexFormat = '0x%02x'
4048 if Pcd.DatumType == 'UINT16':
4049 HexFormat = '0x%04x'
4050 elif Pcd.DatumType == 'UINT32':
4051 HexFormat = '0x%08x'
4052 elif Pcd.DatumType == 'UINT64':
4053 HexFormat = '0x%016x'
4054 PcdValue = HexFormat % int(Pcd.DefaultValue, 0)
4055 else:
4056 if Pcd.MaxDatumSize == None or Pcd.MaxDatumSize == '':
4057 EdkLogger.error("build", AUTOGEN_ERROR,
4058 "Unknown [MaxDatumSize] of PCD [%s.%s]" % (Pcd.TokenSpaceGuidCName, TokenCName)
4059 )
4060 ArraySize = int(Pcd.MaxDatumSize, 0)
4061 PcdValue = Pcd.DefaultValue
4062 if PcdValue[0] != '{':
4063 Unicode = False
4064 if PcdValue[0] == 'L':
4065 Unicode = True
4066 PcdValue = PcdValue.lstrip('L')
4067 PcdValue = eval(PcdValue)
4068 NewValue = '{'
4069 for Index in range(0, len(PcdValue)):
4070 if Unicode:
4071 CharVal = ord(PcdValue[Index])
4072 NewValue = NewValue + '0x%02x' % (CharVal & 0x00FF) + ', ' \
4073 + '0x%02x' % (CharVal >> 8) + ', '
4074 else:
4075 NewValue = NewValue + '0x%02x' % (ord(PcdValue[Index]) % 0x100) + ', '
4076 Padding = '0x00, '
4077 if Unicode:
4078 Padding = Padding * 2
4079 ArraySize = ArraySize / 2
4080 if ArraySize < (len(PcdValue) + 1):
4081 EdkLogger.error("build", AUTOGEN_ERROR,
4082 "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd.TokenSpaceGuidCName, TokenCName)
4083 )
4084 if ArraySize > len(PcdValue) + 1:
4085 NewValue = NewValue + Padding * (ArraySize - len(PcdValue) - 1)
4086 PcdValue = NewValue + Padding.strip().rstrip(',') + '}'
4087 elif len(PcdValue.split(',')) <= ArraySize:
4088 PcdValue = PcdValue.rstrip('}') + ', 0x00' * (ArraySize - len(PcdValue.split(',')))
4089 PcdValue += '}'
4090 else:
4091 EdkLogger.error("build", AUTOGEN_ERROR,
4092 "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd.TokenSpaceGuidCName, TokenCName)
4093 )
4094 PcdItem = '%s.%s|%s|0x%X' % \
4095 (Pcd.TokenSpaceGuidCName, TokenCName, PcdValue, PatchPcd[1])
4096 PcdComments = ''
4097 if (Pcd.TokenSpaceGuidCName, Pcd.TokenCName) in self._PcdComments:
4098 PcdComments = '\n '.join(self._PcdComments[Pcd.TokenSpaceGuidCName, Pcd.TokenCName])
4099 if PcdComments:
4100 PcdItem = PcdComments + '\n ' + PcdItem
4101 AsBuiltInfDict['patchablepcd_item'].append(PcdItem)
4102
4103 HiiPcds = []
4104 for Pcd in Pcds + VfrPcds:
4105 PcdComments = ''
4106 PcdCommentList = []
4107 HiiInfo = ''
4108 SkuId = ''
4109 TokenCName = Pcd.TokenCName
4110 for PcdItem in GlobalData.MixedPcd:
4111 if (Pcd.TokenCName, Pcd.TokenSpaceGuidCName) in GlobalData.MixedPcd[PcdItem]:
4112 TokenCName = PcdItem[0]
4113 break
4114 if Pcd.Type == TAB_PCDS_DYNAMIC_EX_HII:
4115 for SkuName in Pcd.SkuInfoList:
4116 SkuInfo = Pcd.SkuInfoList[SkuName]
4117 SkuId = SkuInfo.SkuId
4118 HiiInfo = '## %s|%s|%s' % (SkuInfo.VariableName, SkuInfo.VariableGuid, SkuInfo.VariableOffset)
4119 break
4120 if SkuId:
4121 #
4122 # Don't generate duplicated HII PCD
4123 #
4124 if (SkuId, Pcd.TokenSpaceGuidCName, Pcd.TokenCName) in HiiPcds:
4125 continue
4126 else:
4127 HiiPcds.append((SkuId, Pcd.TokenSpaceGuidCName, Pcd.TokenCName))
4128 if (Pcd.TokenSpaceGuidCName, Pcd.TokenCName) in self._PcdComments:
4129 PcdCommentList = self._PcdComments[Pcd.TokenSpaceGuidCName, Pcd.TokenCName][:]
4130 if HiiInfo:
4131 UsageIndex = -1
4132 UsageStr = ''
4133 for Index, Comment in enumerate(PcdCommentList):
4134 for Usage in UsageList:
4135 if Comment.find(Usage) != -1:
4136 UsageStr = Usage
4137 UsageIndex = Index
4138 break
4139 if UsageIndex != -1:
4140 PcdCommentList[UsageIndex] = '## %s %s %s' % (UsageStr, HiiInfo, PcdCommentList[UsageIndex].replace(UsageStr, ''))
4141 else:
4142 PcdCommentList.append('## UNDEFINED ' + HiiInfo)
4143 PcdComments = '\n '.join(PcdCommentList)
4144 PcdEntry = Pcd.TokenSpaceGuidCName + '.' + TokenCName
4145 if PcdComments:
4146 PcdEntry = PcdComments + '\n ' + PcdEntry
4147 AsBuiltInfDict['pcd_item'] += [PcdEntry]
4148 for Item in self.BuildOption:
4149 if 'FLAGS' in self.BuildOption[Item]:
4150 AsBuiltInfDict['flags_item'] += ['%s:%s_%s_%s_%s_FLAGS = %s' % (self.ToolChainFamily, self.BuildTarget, self.ToolChain, self.Arch, Item, self.BuildOption[Item]['FLAGS'].strip())]
4151
4152 # Generated LibraryClasses section in comments.
4153 for Library in self.LibraryAutoGenList:
4154 AsBuiltInfDict['libraryclasses_item'] += [Library.MetaFile.File.replace('\\', '/')]
4155
4156 # Generated UserExtensions TianoCore section.
4157 # All tianocore user extensions are copied.
4158 UserExtStr = ''
4159 for TianoCore in self._GetTianoCoreUserExtensionList():
4160 UserExtStr += '\n'.join(TianoCore)
4161 ExtensionFile = os.path.join(self.MetaFile.Dir, TianoCore[1])
4162 if os.path.isfile(ExtensionFile):
4163 shutil.copy2(ExtensionFile, self.OutputDir)
4164 AsBuiltInfDict['userextension_tianocore_item'] = UserExtStr
4165
4166 # Generated depex expression section in comments.
4167 AsBuiltInfDict['depexsection_item'] = ''
4168 DepexExpresion = self._GetDepexExpresionString()
4169 if DepexExpresion:
4170 AsBuiltInfDict['depexsection_item'] = DepexExpresion
4171
4172 AsBuiltInf = TemplateString()
4173 AsBuiltInf.Append(gAsBuiltInfHeaderString.Replace(AsBuiltInfDict))
4174
4175 SaveFileOnChange(os.path.join(self.OutputDir, self.Name + '.inf'), str(AsBuiltInf), False)
4176
4177 self.IsAsBuiltInfCreated = True
4178 if GlobalData.gBinCacheDest:
4179 self.CopyModuleToCache()
4180
4181 def CopyModuleToCache(self):
4182 FileDir = path.join(GlobalData.gBinCacheDest, self.Arch, self.SourceDir, self.MetaFile.BaseName)
4183 CreateDirectory (FileDir)
4184 HashFile = path.join(self.BuildDir, self.Name + '.hash')
4185 ModuleFile = path.join(self.OutputDir, self.Name + '.inf')
4186 if os.path.exists(HashFile):
4187 shutil.copy2(HashFile, FileDir)
4188 if os.path.exists(ModuleFile):
4189 shutil.copy2(ModuleFile, FileDir)
4190 if self.OutputFile:
4191 for File in self.OutputFile:
4192 if not os.path.isabs(File):
4193 File = os.path.join(self.OutputDir, File)
4194 if os.path.exists(File):
4195 shutil.copy2(File, FileDir)
4196
4197 def AttemptModuleCacheCopy(self):
4198 if self.IsBinaryModule:
4199 return False
4200 FileDir = path.join(GlobalData.gBinCacheSource, self.Arch, self.SourceDir, self.MetaFile.BaseName)
4201 HashFile = path.join(FileDir, self.Name + '.hash')
4202 if os.path.exists(HashFile):
4203 f = open(HashFile, 'r')
4204 CacheHash = f.read()
4205 f.close()
4206 if GlobalData.gModuleHash[self.Arch][self.Name]:
4207 if CacheHash == GlobalData.gModuleHash[self.Arch][self.Name]:
4208 for root, dir, files in os.walk(FileDir):
4209 for f in files:
4210 if self.Name + '.hash' in f:
4211 shutil.copy2(HashFile, self.BuildDir)
4212 else:
4213 File = path.join(root, f)
4214 shutil.copy2(File, self.OutputDir)
4215 if self.Name == "PcdPeim" or self.Name == "PcdDxe":
4216 CreatePcdDatabaseCode(self, TemplateString(), TemplateString())
4217 return True
4218 return False
4219
4220 ## Create makefile for the module and its dependent libraries
4221 #
4222 # @param CreateLibraryMakeFile Flag indicating if or not the makefiles of
4223 # dependent libraries will be created
4224 #
4225 def CreateMakeFile(self, CreateLibraryMakeFile=True):
4226 # Ignore generating makefile when it is a binary module
4227 if self.IsBinaryModule:
4228 return
4229
4230 if self.IsMakeFileCreated:
4231 return
4232
4233 if not self.IsLibrary and CreateLibraryMakeFile:
4234 for LibraryAutoGen in self.LibraryAutoGenList:
4235 LibraryAutoGen.CreateMakeFile()
4236
4237 if self.CanSkip():
4238 return
4239
4240 if len(self.CustomMakefile) == 0:
4241 Makefile = GenMake.ModuleMakefile(self)
4242 else:
4243 Makefile = GenMake.CustomMakefile(self)
4244 if Makefile.Generate():
4245 EdkLogger.debug(EdkLogger.DEBUG_9, "Generated makefile for module %s [%s]" %
4246 (self.Name, self.Arch))
4247 else:
4248 EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of makefile for module %s [%s]" %
4249 (self.Name, self.Arch))
4250
4251 self.CreateTimeStamp(Makefile)
4252 self.IsMakeFileCreated = True
4253
4254 def CopyBinaryFiles(self):
4255 for File in self.Module.Binaries:
4256 SrcPath = File.Path
4257 DstPath = os.path.join(self.OutputDir , os.path.basename(SrcPath))
4258 CopyLongFilePath(SrcPath, DstPath)
4259 ## Create autogen code for the module and its dependent libraries
4260 #
4261 # @param CreateLibraryCodeFile Flag indicating if or not the code of
4262 # dependent libraries will be created
4263 #
4264 def CreateCodeFile(self, CreateLibraryCodeFile=True):
4265 if self.IsCodeFileCreated:
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 if self.CanSkip():
4282 return
4283
4284 AutoGenList = []
4285 IgoredAutoGenList = []
4286
4287 for File in self.AutoGenFileList:
4288 if GenC.Generate(File.Path, self.AutoGenFileList[File], File.IsBinary):
4289 #Ignore Edk AutoGen.c
4290 if self.AutoGenVersion < 0x00010005 and File.Name == 'AutoGen.c':
4291 continue
4292
4293 AutoGenList.append(str(File))
4294 else:
4295 IgoredAutoGenList.append(str(File))
4296
4297 # Skip the following code for EDK I inf
4298 if self.AutoGenVersion < 0x00010005:
4299 return
4300
4301 for ModuleType in self.DepexList:
4302 # Ignore empty [depex] section or [depex] section for "USER_DEFINED" module
4303 if len(self.DepexList[ModuleType]) == 0 or ModuleType == "USER_DEFINED":
4304 continue
4305
4306 Dpx = GenDepex.DependencyExpression(self.DepexList[ModuleType], ModuleType, True)
4307 DpxFile = gAutoGenDepexFileName % {"module_name" : self.Name}
4308
4309 if len(Dpx.PostfixNotation) <> 0:
4310 self.DepexGenerated = True
4311
4312 if Dpx.Generate(path.join(self.OutputDir, DpxFile)):
4313 AutoGenList.append(str(DpxFile))
4314 else:
4315 IgoredAutoGenList.append(str(DpxFile))
4316
4317 if IgoredAutoGenList == []:
4318 EdkLogger.debug(EdkLogger.DEBUG_9, "Generated [%s] files for module %s [%s]" %
4319 (" ".join(AutoGenList), self.Name, self.Arch))
4320 elif AutoGenList == []:
4321 EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of [%s] files for module %s [%s]" %
4322 (" ".join(IgoredAutoGenList), self.Name, self.Arch))
4323 else:
4324 EdkLogger.debug(EdkLogger.DEBUG_9, "Generated [%s] (skipped %s) files for module %s [%s]" %
4325 (" ".join(AutoGenList), " ".join(IgoredAutoGenList), self.Name, self.Arch))
4326
4327 self.IsCodeFileCreated = True
4328 return AutoGenList
4329
4330 ## Summarize the ModuleAutoGen objects of all libraries used by this module
4331 def _GetLibraryAutoGenList(self):
4332 if self._LibraryAutoGenList == None:
4333 self._LibraryAutoGenList = []
4334 for Library in self.DependentLibraryList:
4335 La = ModuleAutoGen(
4336 self.Workspace,
4337 Library.MetaFile,
4338 self.BuildTarget,
4339 self.ToolChain,
4340 self.Arch,
4341 self.PlatformInfo.MetaFile
4342 )
4343 if La not in self._LibraryAutoGenList:
4344 self._LibraryAutoGenList.append(La)
4345 for Lib in La.CodaTargetList:
4346 self._ApplyBuildRule(Lib.Target, TAB_UNKNOWN_FILE)
4347 return self._LibraryAutoGenList
4348
4349 def GenModuleHash(self):
4350 if self.Arch not in GlobalData.gModuleHash:
4351 GlobalData.gModuleHash[self.Arch] = {}
4352 m = hashlib.md5()
4353 # Add Platform level hash
4354 m.update(GlobalData.gPlatformHash)
4355 # Add Package level hash
4356 if self.DependentPackageList:
4357 for Pkg in self.DependentPackageList:
4358 if Pkg.PackageName in GlobalData.gPackageHash[self.Arch]:
4359 m.update(GlobalData.gPackageHash[self.Arch][Pkg.PackageName])
4360
4361 # Add Library hash
4362 if self.LibraryAutoGenList:
4363 for Lib in self.LibraryAutoGenList:
4364 if Lib.Name not in GlobalData.gModuleHash[self.Arch]:
4365 Lib.GenModuleHash()
4366 m.update(GlobalData.gModuleHash[self.Arch][Lib.Name])
4367
4368 # Add Module self
4369 f = open(str(self.MetaFile), 'r')
4370 Content = f.read()
4371 f.close()
4372 m.update(Content)
4373 # Add Module's source files
4374 if self.SourceFileList:
4375 for File in self.SourceFileList:
4376 f = open(str(File), 'r')
4377 Content = f.read()
4378 f.close()
4379 m.update(Content)
4380
4381 ModuleHashFile = path.join(self.BuildDir, self.Name + ".hash")
4382 if self.Name not in GlobalData.gModuleHash[self.Arch]:
4383 GlobalData.gModuleHash[self.Arch][self.Name] = m.hexdigest()
4384 if GlobalData.gBinCacheSource:
4385 CacheValid = self.AttemptModuleCacheCopy()
4386 if CacheValid:
4387 return False
4388 return SaveFileOnChange(ModuleHashFile, m.hexdigest(), True)
4389
4390 ## Decide whether we can skip the ModuleAutoGen process
4391 def CanSkipbyHash(self):
4392 if GlobalData.gUseHashCache:
4393 return not self.GenModuleHash()
4394
4395 ## Decide whether we can skip the ModuleAutoGen process
4396 # If any source file is newer than the module than we cannot skip
4397 #
4398 def CanSkip(self):
4399 if not os.path.exists(self.GetTimeStampPath()):
4400 return False
4401 #last creation time of the module
4402 DstTimeStamp = os.stat(self.GetTimeStampPath())[8]
4403
4404 SrcTimeStamp = self.Workspace._SrcTimeStamp
4405 if SrcTimeStamp > DstTimeStamp:
4406 return False
4407
4408 with open(self.GetTimeStampPath(),'r') as f:
4409 for source in f:
4410 source = source.rstrip('\n')
4411 if not os.path.exists(source):
4412 return False
4413 if source not in ModuleAutoGen.TimeDict :
4414 ModuleAutoGen.TimeDict[source] = os.stat(source)[8]
4415 if ModuleAutoGen.TimeDict[source] > DstTimeStamp:
4416 return False
4417 return True
4418
4419 def GetTimeStampPath(self):
4420 if self._TimeStampPath == None:
4421 self._TimeStampPath = os.path.join(self.MakeFileDir, 'AutoGenTimeStamp')
4422 return self._TimeStampPath
4423 def CreateTimeStamp(self, Makefile):
4424
4425 FileSet = set()
4426
4427 FileSet.add (self.MetaFile.Path)
4428
4429 for SourceFile in self.Module.Sources:
4430 FileSet.add (SourceFile.Path)
4431
4432 for Lib in self.DependentLibraryList:
4433 FileSet.add (Lib.MetaFile.Path)
4434
4435 for f in self.AutoGenDepSet:
4436 FileSet.add (f.Path)
4437
4438 if os.path.exists (self.GetTimeStampPath()):
4439 os.remove (self.GetTimeStampPath())
4440 with open(self.GetTimeStampPath(), 'w+') as file:
4441 for f in FileSet:
4442 print >> file, f
4443
4444 Module = property(_GetModule)
4445 Name = property(_GetBaseName)
4446 Guid = property(_GetGuid)
4447 Version = property(_GetVersion)
4448 ModuleType = property(_GetModuleType)
4449 ComponentType = property(_GetComponentType)
4450 BuildType = property(_GetBuildType)
4451 PcdIsDriver = property(_GetPcdIsDriver)
4452 AutoGenVersion = property(_GetAutoGenVersion)
4453 Macros = property(_GetMacros)
4454 Specification = property(_GetSpecification)
4455
4456 IsLibrary = property(_IsLibrary)
4457 IsBinaryModule = property(_IsBinaryModule)
4458 BuildDir = property(_GetBuildDir)
4459 OutputDir = property(_GetOutputDir)
4460 DebugDir = property(_GetDebugDir)
4461 MakeFileDir = property(_GetMakeFileDir)
4462 CustomMakefile = property(_GetCustomMakefile)
4463
4464 IncludePathList = property(_GetIncludePathList)
4465 IncludePathLength = property(_GetIncludePathLength)
4466 AutoGenFileList = property(_GetAutoGenFileList)
4467 UnicodeFileList = property(_GetUnicodeFileList)
4468 VfrFileList = property(_GetVfrFileList)
4469 SourceFileList = property(_GetSourceFileList)
4470 BinaryFileList = property(_GetBinaryFiles) # FileType : [File List]
4471 Targets = property(_GetTargets)
4472 IntroTargetList = property(_GetIntroTargetList)
4473 CodaTargetList = property(_GetFinalTargetList)
4474 FileTypes = property(_GetFileTypes)
4475 BuildRules = property(_GetBuildRules)
4476 IdfFileList = property(_GetIdfFileList)
4477
4478 DependentPackageList = property(_GetDependentPackageList)
4479 DependentLibraryList = property(_GetLibraryList)
4480 LibraryAutoGenList = property(_GetLibraryAutoGenList)
4481 DerivedPackageList = property(_GetDerivedPackageList)
4482
4483 ModulePcdList = property(_GetModulePcdList)
4484 LibraryPcdList = property(_GetLibraryPcdList)
4485 GuidList = property(_GetGuidList)
4486 ProtocolList = property(_GetProtocolList)
4487 PpiList = property(_GetPpiList)
4488 DepexList = property(_GetDepexTokenList)
4489 DxsFile = property(_GetDxsFile)
4490 DepexExpressionList = property(_GetDepexExpressionTokenList)
4491 BuildOption = property(_GetModuleBuildOption)
4492 BuildOptionIncPathList = property(_GetBuildOptionIncPathList)
4493 BuildCommand = property(_GetBuildCommand)
4494
4495 FixedAtBuildPcds = property(_GetFixedAtBuildPcds)
4496
4497 # This acts like the main() function for the script, unless it is 'import'ed into another script.
4498 if __name__ == '__main__':
4499 pass
4500