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