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