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