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