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