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