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