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