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