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