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