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