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