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