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