]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/Python/AutoGen/AutoGen.py
BaseTools: PCD can only use single access method by source build
[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
2762 if self.IsLibrary:\r
2763 if not (Pcd.Pending == False and Pcd.Type == "FixedAtBuild"):\r
2764 continue\r
2765 elif Pcd.Type != "FixedAtBuild":\r
2766 continue\r
2767 if Pcd not in self._FixedAtBuildPcds:\r
2768 self._FixedAtBuildPcds.append(Pcd)\r
2769 \r
2770 return self._FixedAtBuildPcds \r
2771\r
867d1cd4
YL
2772 def _GetUniqueBaseName(self):\r
2773 BaseName = self.Name\r
2774 for Module in self.PlatformInfo.ModuleAutoGenList:\r
2775 if Module.MetaFile == self.MetaFile:\r
2776 continue\r
2777 if Module.Name == self.Name:\r
867d1cd4
YL
2778 if uuid.UUID(Module.Guid) == uuid.UUID(self.Guid):\r
2779 EdkLogger.error("build", FILE_DUPLICATED, 'Modules have same BaseName and FILE_GUID:\n'\r
2780 ' %s\n %s' % (Module.MetaFile, self.MetaFile))\r
2781 BaseName = '%s_%s' % (self.Name, self.Guid)\r
2782 return BaseName\r
2783\r
52302d4d
LG
2784 # Macros could be used in build_rule.txt (also Makefile)\r
2785 def _GetMacros(self):\r
2786 if self._Macro == None:\r
2787 self._Macro = sdict()\r
2788 self._Macro["WORKSPACE" ] = self.WorkspaceDir\r
2789 self._Macro["MODULE_NAME" ] = self.Name\r
867d1cd4 2790 self._Macro["MODULE_NAME_GUID" ] = self._GetUniqueBaseName()\r
52302d4d
LG
2791 self._Macro["MODULE_GUID" ] = self.Guid\r
2792 self._Macro["MODULE_VERSION" ] = self.Version\r
2793 self._Macro["MODULE_TYPE" ] = self.ModuleType\r
2794 self._Macro["MODULE_FILE" ] = str(self.MetaFile)\r
2795 self._Macro["MODULE_FILE_BASE_NAME" ] = self.MetaFile.BaseName\r
2796 self._Macro["MODULE_RELATIVE_DIR" ] = self.SourceDir\r
2797 self._Macro["MODULE_DIR" ] = self.SourceDir\r
2798\r
2799 self._Macro["BASE_NAME" ] = self.Name\r
2800\r
2801 self._Macro["ARCH" ] = self.Arch\r
2802 self._Macro["TOOLCHAIN" ] = self.ToolChain\r
2803 self._Macro["TOOLCHAIN_TAG" ] = self.ToolChain\r
0d2711a6 2804 self._Macro["TOOL_CHAIN_TAG" ] = self.ToolChain\r
52302d4d
LG
2805 self._Macro["TARGET" ] = self.BuildTarget\r
2806\r
2807 self._Macro["BUILD_DIR" ] = self.PlatformInfo.BuildDir\r
2808 self._Macro["BIN_DIR" ] = os.path.join(self.PlatformInfo.BuildDir, self.Arch)\r
2809 self._Macro["LIB_DIR" ] = os.path.join(self.PlatformInfo.BuildDir, self.Arch)\r
2810 self._Macro["MODULE_BUILD_DIR" ] = self.BuildDir\r
2811 self._Macro["OUTPUT_DIR" ] = self.OutputDir\r
2812 self._Macro["DEBUG_DIR" ] = self.DebugDir\r
df1e1b63
YZ
2813 self._Macro["DEST_DIR_OUTPUT" ] = self.OutputDir\r
2814 self._Macro["DEST_DIR_DEBUG" ] = self.DebugDir\r
3570e332
YZ
2815 self._Macro["PLATFORM_NAME" ] = self.PlatformInfo.Name\r
2816 self._Macro["PLATFORM_GUID" ] = self.PlatformInfo.Guid\r
2817 self._Macro["PLATFORM_VERSION" ] = self.PlatformInfo.Version\r
2818 self._Macro["PLATFORM_RELATIVE_DIR" ] = self.PlatformInfo.SourceDir\r
2819 self._Macro["PLATFORM_DIR" ] = mws.join(self.WorkspaceDir, self.PlatformInfo.SourceDir)\r
2820 self._Macro["PLATFORM_OUTPUT_DIR" ] = self.PlatformInfo.OutputDir\r
52302d4d
LG
2821 return self._Macro\r
2822\r
2823 ## Return the module build data object\r
2824 def _GetModule(self):\r
2825 if self._Module == None:\r
0d2711a6 2826 self._Module = self.Workspace.BuildDatabase[self.MetaFile, self.Arch, self.BuildTarget, self.ToolChain]\r
52302d4d
LG
2827 return self._Module\r
2828\r
2829 ## Return the module name\r
2830 def _GetBaseName(self):\r
2831 return self.Module.BaseName\r
2832\r
b36d134f
LG
2833 ## Return the module DxsFile if exist\r
2834 def _GetDxsFile(self):\r
2835 return self.Module.DxsFile\r
2836\r
52302d4d
LG
2837 ## Return the module SourceOverridePath\r
2838 def _GetSourceOverridePath(self):\r
2839 return self.Module.SourceOverridePath\r
2840\r
2841 ## Return the module meta-file GUID\r
2842 def _GetGuid(self):\r
97fa0ee9
YL
2843 #\r
2844 # To build same module more than once, the module path with FILE_GUID overridden has\r
2845 # the file name FILE_GUIDmodule.inf, but the relative path (self.MetaFile.File) is the realy path\r
2846 # in DSC. The overridden GUID can be retrieved from file name\r
2847 #\r
2848 if os.path.basename(self.MetaFile.File) != os.path.basename(self.MetaFile.Path):\r
2849 #\r
2850 # Length of GUID is 36\r
2851 #\r
2852 return os.path.basename(self.MetaFile.Path)[:36]\r
52302d4d
LG
2853 return self.Module.Guid\r
2854\r
2855 ## Return the module version\r
2856 def _GetVersion(self):\r
2857 return self.Module.Version\r
2858\r
2859 ## Return the module type\r
2860 def _GetModuleType(self):\r
2861 return self.Module.ModuleType\r
2862\r
b36d134f 2863 ## Return the component type (for Edk.x style of module)\r
52302d4d
LG
2864 def _GetComponentType(self):\r
2865 return self.Module.ComponentType\r
2866\r
2867 ## Return the build type\r
2868 def _GetBuildType(self):\r
2869 return self.Module.BuildType\r
2870\r
2871 ## Return the PCD_IS_DRIVER setting\r
2872 def _GetPcdIsDriver(self):\r
2873 return self.Module.PcdIsDriver\r
2874\r
2875 ## Return the autogen version, i.e. module meta-file version\r
2876 def _GetAutoGenVersion(self):\r
2877 return self.Module.AutoGenVersion\r
2878\r
2879 ## Check if the module is library or not\r
2880 def _IsLibrary(self):\r
2881 if self._LibraryFlag == None:\r
2882 if self.Module.LibraryClass != None and self.Module.LibraryClass != []:\r
2883 self._LibraryFlag = True\r
2884 else:\r
2885 self._LibraryFlag = False\r
2886 return self._LibraryFlag\r
2887\r
e8a47801
LG
2888 ## Check if the module is binary module or not\r
2889 def _IsBinaryModule(self):\r
2890 return self.Module.IsBinaryModule\r
2891\r
52302d4d
LG
2892 ## Return the directory to store intermediate files of the module\r
2893 def _GetBuildDir(self):\r
2894 if self._BuildDir == None:\r
2895 self._BuildDir = path.join(\r
2896 self.PlatformInfo.BuildDir,\r
2897 self.Arch,\r
2898 self.SourceDir,\r
2899 self.MetaFile.BaseName\r
2900 )\r
2901 CreateDirectory(self._BuildDir)\r
2902 return self._BuildDir\r
2903\r
2904 ## Return the directory to store the intermediate object files of the mdoule\r
2905 def _GetOutputDir(self):\r
2906 if self._OutputDir == None:\r
2907 self._OutputDir = path.join(self.BuildDir, "OUTPUT")\r
2908 CreateDirectory(self._OutputDir)\r
2909 return self._OutputDir\r
2910\r
2911 ## Return the directory to store auto-gened source files of the mdoule\r
2912 def _GetDebugDir(self):\r
2913 if self._DebugDir == None:\r
2914 self._DebugDir = path.join(self.BuildDir, "DEBUG")\r
2915 CreateDirectory(self._DebugDir)\r
2916 return self._DebugDir\r
2917\r
2918 ## Return the path of custom file\r
2919 def _GetCustomMakefile(self):\r
2920 if self._CustomMakefile == None:\r
2921 self._CustomMakefile = {}\r
2922 for Type in self.Module.CustomMakefile:\r
2923 if Type in gMakeTypeMap:\r
2924 MakeType = gMakeTypeMap[Type]\r
2925 else:\r
2926 MakeType = 'nmake'\r
2927 if self.SourceOverrideDir != None:\r
2928 File = os.path.join(self.SourceOverrideDir, self.Module.CustomMakefile[Type])\r
2929 if not os.path.exists(File):\r
2930 File = os.path.join(self.SourceDir, self.Module.CustomMakefile[Type])\r
2931 else:\r
2932 File = os.path.join(self.SourceDir, self.Module.CustomMakefile[Type])\r
2933 self._CustomMakefile[MakeType] = File\r
2934 return self._CustomMakefile\r
2935\r
2936 ## Return the directory of the makefile\r
2937 #\r
2938 # @retval string The directory string of module's makefile\r
2939 #\r
2940 def _GetMakeFileDir(self):\r
2941 return self.BuildDir\r
2942\r
2943 ## Return build command string\r
2944 #\r
2945 # @retval string Build command string\r
2946 #\r
2947 def _GetBuildCommand(self):\r
2948 return self.PlatformInfo.BuildCommand\r
2949\r
2950 ## Get object list of all packages the module and its dependent libraries belong to\r
2951 #\r
2952 # @retval list The list of package object\r
2953 #\r
2954 def _GetDerivedPackageList(self):\r
2955 PackageList = []\r
2956 for M in [self.Module] + self.DependentLibraryList:\r
2957 for Package in M.Packages:\r
2958 if Package in PackageList:\r
2959 continue\r
2960 PackageList.append(Package)\r
2961 return PackageList\r
97fa0ee9
YL
2962 \r
2963 ## Get the depex string\r
2964 #\r
2965 # @return : a string contain all depex expresion.\r
2966 def _GetDepexExpresionString(self):\r
2967 DepexStr = ''\r
2968 DepexList = []\r
2969 ## DPX_SOURCE IN Define section.\r
2970 if self.Module.DxsFile:\r
2971 return DepexStr\r
2972 for M in [self.Module] + self.DependentLibraryList:\r
2973 Filename = M.MetaFile.Path\r
2974 InfObj = InfSectionParser.InfSectionParser(Filename)\r
2975 DepexExpresionList = InfObj.GetDepexExpresionList()\r
2976 for DepexExpresion in DepexExpresionList:\r
2977 for key in DepexExpresion.keys():\r
2978 Arch, ModuleType = key\r
518aebe2 2979 DepexExpr = [x for x in DepexExpresion[key] if not str(x).startswith('#')]\r
97fa0ee9
YL
2980 # the type of build module is USER_DEFINED.\r
2981 # All different DEPEX section tags would be copied into the As Built INF file\r
2982 # and there would be separate DEPEX section tags\r
2983 if self.ModuleType.upper() == SUP_MODULE_USER_DEFINED:\r
2984 if (Arch.upper() == self.Arch.upper()) and (ModuleType.upper() != TAB_ARCH_COMMON):\r
518aebe2 2985 DepexList.append({(Arch, ModuleType): DepexExpr})\r
97fa0ee9
YL
2986 else:\r
2987 if Arch.upper() == TAB_ARCH_COMMON or \\r
2988 (Arch.upper() == self.Arch.upper() and \\r
2989 ModuleType.upper() in [TAB_ARCH_COMMON, self.ModuleType.upper()]):\r
518aebe2 2990 DepexList.append({(Arch, ModuleType): DepexExpr})\r
97fa0ee9
YL
2991 \r
2992 #the type of build module is USER_DEFINED.\r
2993 if self.ModuleType.upper() == SUP_MODULE_USER_DEFINED:\r
2994 for Depex in DepexList:\r
2995 for key in Depex.keys():\r
2996 DepexStr += '[Depex.%s.%s]\n' % key\r
2997 DepexStr += '\n'.join(['# '+ val for val in Depex[key]])\r
2998 DepexStr += '\n\n'\r
2999 if not DepexStr:\r
3000 return '[Depex.%s]\n' % self.Arch\r
3001 return DepexStr\r
3002 \r
3003 #the type of build module not is USER_DEFINED.\r
3004 Count = 0\r
3005 for Depex in DepexList:\r
3006 Count += 1\r
3007 if DepexStr != '':\r
3008 DepexStr += ' AND '\r
3009 DepexStr += '('\r
3010 for D in Depex.values():\r
3011 DepexStr += ' '.join([val for val in D])\r
3012 Index = DepexStr.find('END')\r
3013 if Index > -1 and Index == len(DepexStr) - 3:\r
3014 DepexStr = DepexStr[:-3]\r
3015 DepexStr = DepexStr.strip()\r
3016 DepexStr += ')'\r
3017 if Count == 1:\r
3018 DepexStr = DepexStr.lstrip('(').rstrip(')').strip()\r
3019 if not DepexStr:\r
3020 return '[Depex.%s]\n' % self.Arch\r
3021 return '[Depex.%s]\n# ' % self.Arch + DepexStr\r
3022 \r
52302d4d
LG
3023 ## Merge dependency expression\r
3024 #\r
3025 # @retval list The token list of the dependency expression after parsed\r
3026 #\r
3027 def _GetDepexTokenList(self):\r
3028 if self._DepexList == None:\r
3029 self._DepexList = {}\r
b36d134f 3030 if self.DxsFile or self.IsLibrary or TAB_DEPENDENCY_EXPRESSION_FILE in self.FileTypes:\r
52302d4d
LG
3031 return self._DepexList\r
3032\r
3033 self._DepexList[self.ModuleType] = []\r
3034\r
3035 for ModuleType in self._DepexList:\r
3036 DepexList = self._DepexList[ModuleType]\r
3037 #\r
3038 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion\r
3039 #\r
3040 for M in [self.Module] + self.DependentLibraryList:\r
3041 Inherited = False\r
3042 for D in M.Depex[self.Arch, ModuleType]:\r
3043 if DepexList != []:\r
3044 DepexList.append('AND')\r
3045 DepexList.append('(')\r
3046 DepexList.extend(D)\r
3047 if DepexList[-1] == 'END': # no need of a END at this time\r
3048 DepexList.pop()\r
3049 DepexList.append(')')\r
3050 Inherited = True\r
3051 if Inherited:\r
3052 EdkLogger.verbose("DEPEX[%s] (+%s) = %s" % (self.Name, M.BaseName, DepexList))\r
3053 if 'BEFORE' in DepexList or 'AFTER' in DepexList:\r
3054 break\r
3055 if len(DepexList) > 0:\r
3056 EdkLogger.verbose('')\r
3057 return self._DepexList\r
3058\r
3059 ## Merge dependency expression\r
3060 #\r
3061 # @retval list The token list of the dependency expression after parsed\r
3062 #\r
3063 def _GetDepexExpressionTokenList(self):\r
3064 if self._DepexExpressionList == None:\r
3065 self._DepexExpressionList = {}\r
b36d134f 3066 if self.DxsFile or self.IsLibrary or TAB_DEPENDENCY_EXPRESSION_FILE in self.FileTypes:\r
52302d4d
LG
3067 return self._DepexExpressionList\r
3068\r
3069 self._DepexExpressionList[self.ModuleType] = ''\r
3070\r
3071 for ModuleType in self._DepexExpressionList:\r
3072 DepexExpressionList = self._DepexExpressionList[ModuleType]\r
3073 #\r
3074 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion\r
3075 #\r
3076 for M in [self.Module] + self.DependentLibraryList:\r
3077 Inherited = False\r
3078 for D in M.DepexExpression[self.Arch, ModuleType]:\r
3079 if DepexExpressionList != '':\r
3080 DepexExpressionList += ' AND '\r
3081 DepexExpressionList += '('\r
3082 DepexExpressionList += D\r
3083 DepexExpressionList = DepexExpressionList.rstrip('END').strip()\r
3084 DepexExpressionList += ')'\r
3085 Inherited = True\r
3086 if Inherited:\r
3087 EdkLogger.verbose("DEPEX[%s] (+%s) = %s" % (self.Name, M.BaseName, DepexExpressionList))\r
3088 if 'BEFORE' in DepexExpressionList or 'AFTER' in DepexExpressionList:\r
3089 break\r
3090 if len(DepexExpressionList) > 0:\r
3091 EdkLogger.verbose('')\r
3092 self._DepexExpressionList[ModuleType] = DepexExpressionList\r
3093 return self._DepexExpressionList\r
3094\r
3095 ## Return the list of specification version required for the module\r
3096 #\r
3097 # @retval list The list of specification defined in module file\r
3098 #\r
3099 def _GetSpecification(self):\r
3100 return self.Module.Specification\r
3101\r
3102 ## Tool option for the module build\r
3103 #\r
3104 # @param PlatformInfo The object of PlatformBuildInfo\r
3105 # @retval dict The dict containing valid options\r
3106 #\r
3107 def _GetModuleBuildOption(self):\r
3108 if self._BuildOption == None:\r
fe4bf2f9
YL
3109 self._BuildOption, self.BuildRuleOrder = self.PlatformInfo.ApplyBuildOption(self.Module)\r
3110 if self.BuildRuleOrder:\r
3111 self.BuildRuleOrder = ['.%s' % Ext for Ext in self.BuildRuleOrder.split()]\r
52302d4d
LG
3112 return self._BuildOption\r
3113\r
79b74a03
LG
3114 ## Get include path list from tool option for the module build\r
3115 #\r
3116 # @retval list The include path list\r
3117 #\r
3118 def _GetBuildOptionIncPathList(self):\r
3119 if self._BuildOptionIncPathList == None:\r
3120 #\r
d40b2ee6 3121 # Regular expression for finding Include Directories, the difference between MSFT and INTEL/GCC/RVCT\r
79b74a03
LG
3122 # is the former use /I , the Latter used -I to specify include directories\r
3123 #\r
3124 if self.PlatformInfo.ToolChainFamily in ('MSFT'):\r
47fea6af 3125 gBuildOptIncludePattern = re.compile(r"(?:.*?)/I[ \t]*([^ ]*)", re.MULTILINE | re.DOTALL)\r
d40b2ee6 3126 elif self.PlatformInfo.ToolChainFamily in ('INTEL', 'GCC', 'RVCT'):\r
47fea6af 3127 gBuildOptIncludePattern = re.compile(r"(?:.*?)-I[ \t]*([^ ]*)", re.MULTILINE | re.DOTALL)\r
d40b2ee6
LG
3128 else:\r
3129 #\r
3130 # New ToolChainFamily, don't known whether there is option to specify include directories\r
3131 #\r
3132 self._BuildOptionIncPathList = []\r
3133 return self._BuildOptionIncPathList\r
79b74a03
LG
3134 \r
3135 BuildOptionIncPathList = []\r
3136 for Tool in ('CC', 'PP', 'VFRPP', 'ASLPP', 'ASLCC', 'APP', 'ASM'):\r
3137 Attr = 'FLAGS'\r
3138 try:\r
3139 FlagOption = self.BuildOption[Tool][Attr]\r
3140 except KeyError:\r
3141 FlagOption = ''\r
3142 \r
d40b2ee6
LG
3143 if self.PlatformInfo.ToolChainFamily != 'RVCT':\r
3144 IncPathList = [NormPath(Path, self.Macros) for Path in gBuildOptIncludePattern.findall(FlagOption)]\r
3145 else:\r
3146 #\r
3147 # RVCT may specify a list of directory seperated by commas\r
3148 #\r
3149 IncPathList = []\r
3150 for Path in gBuildOptIncludePattern.findall(FlagOption):\r
3151 PathList = GetSplitList(Path, TAB_COMMA_SPLIT)\r
3152 IncPathList += [NormPath(PathEntry, self.Macros) for PathEntry in PathList]\r
3153\r
79b74a03
LG
3154 #\r
3155 # EDK II modules must not reference header files outside of the packages they depend on or \r
3156 # within the module's directory tree. Report error if violation.\r
3157 #\r
3158 if self.AutoGenVersion >= 0x00010005 and len(IncPathList) > 0:\r
3159 for Path in IncPathList:\r
3160 if (Path not in self.IncludePathList) and (CommonPath([Path, self.MetaFile.Dir]) != self.MetaFile.Dir):\r
47fea6af
YZ
3161 ErrMsg = "The include directory for the EDK II module in this line is invalid %s specified in %s FLAGS '%s'" % (Path, Tool, FlagOption)\r
3162 EdkLogger.error("build",\r
79b74a03 3163 PARAMETER_INVALID,\r
47fea6af
YZ
3164 ExtraData=ErrMsg,\r
3165 File=str(self.MetaFile))\r
79b74a03
LG
3166\r
3167 \r
3168 BuildOptionIncPathList += IncPathList\r
3169 \r
3170 self._BuildOptionIncPathList = BuildOptionIncPathList\r
3171 \r
3172 return self._BuildOptionIncPathList\r
3173 \r
52302d4d
LG
3174 ## Return a list of files which can be built from source\r
3175 #\r
3176 # What kind of files can be built is determined by build rules in\r
97fa0ee9 3177 # $(CONF_DIRECTORY)/build_rule.txt and toolchain family.\r
52302d4d
LG
3178 #\r
3179 def _GetSourceFileList(self):\r
3180 if self._SourceFileList == None:\r
3181 self._SourceFileList = []\r
3182 for F in self.Module.Sources:\r
3183 # match tool chain\r
08dd311f 3184 if F.TagName not in ("", "*", self.ToolChain):\r
52302d4d
LG
3185 EdkLogger.debug(EdkLogger.DEBUG_9, "The toolchain [%s] for processing file [%s] is found, "\r
3186 "but [%s] is needed" % (F.TagName, str(F), self.ToolChain))\r
3187 continue\r
3188 # match tool chain family\r
08dd311f 3189 if F.ToolChainFamily not in ("", "*", self.ToolChainFamily):\r
52302d4d
LG
3190 EdkLogger.debug(\r
3191 EdkLogger.DEBUG_0,\r
3192 "The file [%s] must be built by tools of [%s], " \\r
3193 "but current toolchain family is [%s]" \\r
3194 % (str(F), F.ToolChainFamily, self.ToolChainFamily))\r
3195 continue\r
3196\r
3197 # add the file path into search path list for file including\r
3198 if F.Dir not in self.IncludePathList and self.AutoGenVersion >= 0x00010005:\r
3199 self.IncludePathList.insert(0, F.Dir)\r
3200 self._SourceFileList.append(F)\r
4cb7bade
YZ
3201\r
3202 self._MatchBuildRuleOrder(self._SourceFileList)\r
3203\r
3204 for F in self._SourceFileList:\r
52302d4d
LG
3205 self._ApplyBuildRule(F, TAB_UNKNOWN_FILE)\r
3206 return self._SourceFileList\r
3207\r
4cb7bade
YZ
3208 def _MatchBuildRuleOrder(self, FileList):\r
3209 Order_Dict = {}\r
3210 self._GetModuleBuildOption()\r
3211 for SingleFile in FileList:\r
3212 if self.BuildRuleOrder and SingleFile.Ext in self.BuildRuleOrder and SingleFile.Ext in self.BuildRules:\r
3213 key = SingleFile.Path.split(SingleFile.Ext)[0]\r
3214 if key in Order_Dict:\r
3215 Order_Dict[key].append(SingleFile.Ext)\r
3216 else:\r
3217 Order_Dict[key] = [SingleFile.Ext]\r
3218\r
3219 RemoveList = []\r
3220 for F in Order_Dict:\r
3221 if len(Order_Dict[F]) > 1:\r
3222 Order_Dict[F].sort(key=lambda i: self.BuildRuleOrder.index(i))\r
3223 for Ext in Order_Dict[F][1:]:\r
3224 RemoveList.append(F + Ext)\r
3225 \r
3226 for item in RemoveList:\r
3227 FileList.remove(item)\r
3228\r
3229 return FileList\r
3230\r
52302d4d
LG
3231 ## Return the list of unicode files\r
3232 def _GetUnicodeFileList(self):\r
3233 if self._UnicodeFileList == None:\r
3234 if TAB_UNICODE_FILE in self.FileTypes:\r
3235 self._UnicodeFileList = self.FileTypes[TAB_UNICODE_FILE]\r
3236 else:\r
3237 self._UnicodeFileList = []\r
3238 return self._UnicodeFileList\r
3239\r
5b97eb4c
YZ
3240 ## Return the list of vfr files\r
3241 def _GetVfrFileList(self):\r
3242 if self._VfrFileList == None:\r
3243 if TAB_VFR_FILE in self.FileTypes:\r
3244 self._VfrFileList = self.FileTypes[TAB_VFR_FILE]\r
3245 else:\r
3246 self._VfrFileList = []\r
3247 return self._VfrFileList\r
3248\r
333ba578
YZ
3249 ## Return the list of Image Definition files\r
3250 def _GetIdfFileList(self):\r
3251 if self._IdfFileList == None:\r
3252 if TAB_IMAGE_FILE in self.FileTypes:\r
3253 self._IdfFileList = self.FileTypes[TAB_IMAGE_FILE]\r
3254 else:\r
3255 self._IdfFileList = []\r
3256 return self._IdfFileList\r
3257\r
52302d4d
LG
3258 ## Return a list of files which can be built from binary\r
3259 #\r
3260 # "Build" binary files are just to copy them to build directory.\r
3261 #\r
3262 # @retval list The list of files which can be built later\r
3263 #\r
3264 def _GetBinaryFiles(self):\r
3265 if self._BinaryFileList == None:\r
3266 self._BinaryFileList = []\r
3267 for F in self.Module.Binaries:\r
3268 if F.Target not in ['COMMON', '*'] and F.Target != self.BuildTarget:\r
3269 continue\r
3270 self._BinaryFileList.append(F)\r
3271 self._ApplyBuildRule(F, F.Type)\r
3272 return self._BinaryFileList\r
3273\r
3274 def _GetBuildRules(self):\r
3275 if self._BuildRules == None:\r
3276 BuildRules = {}\r
3277 BuildRuleDatabase = self.PlatformInfo.BuildRule\r
3278 for Type in BuildRuleDatabase.FileTypeList:\r
3279 #first try getting build rule by BuildRuleFamily\r
3280 RuleObject = BuildRuleDatabase[Type, self.BuildType, self.Arch, self.BuildRuleFamily]\r
3281 if not RuleObject:\r
3282 # build type is always module type, but ...\r
3283 if self.ModuleType != self.BuildType:\r
3284 RuleObject = BuildRuleDatabase[Type, self.ModuleType, self.Arch, self.BuildRuleFamily]\r
3285 #second try getting build rule by ToolChainFamily\r
3286 if not RuleObject:\r
3287 RuleObject = BuildRuleDatabase[Type, self.BuildType, self.Arch, self.ToolChainFamily]\r
3288 if not RuleObject:\r
3289 # build type is always module type, but ...\r
3290 if self.ModuleType != self.BuildType:\r
3291 RuleObject = BuildRuleDatabase[Type, self.ModuleType, self.Arch, self.ToolChainFamily]\r
3292 if not RuleObject:\r
3293 continue\r
3294 RuleObject = RuleObject.Instantiate(self.Macros)\r
3295 BuildRules[Type] = RuleObject\r
3296 for Ext in RuleObject.SourceFileExtList:\r
3297 BuildRules[Ext] = RuleObject\r
3298 self._BuildRules = BuildRules\r
3299 return self._BuildRules\r
3300\r
3301 def _ApplyBuildRule(self, File, FileType):\r
3302 if self._BuildTargets == None:\r
3303 self._IntroBuildTargetList = set()\r
3304 self._FinalBuildTargetList = set()\r
3305 self._BuildTargets = {}\r
3306 self._FileTypes = {}\r
3307\r
fcd4fbf3
YL
3308 SubDirectory = os.path.join(self.OutputDir, File.SubDir)\r
3309 if not os.path.exists(SubDirectory):\r
3310 CreateDirectory(SubDirectory)\r
52302d4d
LG
3311 LastTarget = None\r
3312 RuleChain = []\r
3313 SourceList = [File]\r
3314 Index = 0\r
fe4bf2f9
YL
3315 #\r
3316 # Make sure to get build rule order value\r
3317 #\r
3318 self._GetModuleBuildOption()\r
3319\r
52302d4d
LG
3320 while Index < len(SourceList):\r
3321 Source = SourceList[Index]\r
3322 Index = Index + 1\r
3323\r
3324 if Source != File:\r
3325 CreateDirectory(Source.Dir)\r
3326\r
3327 if File.IsBinary and File == Source and self._BinaryFileList != None and File in self._BinaryFileList:\r
da92f276
LG
3328 # Skip all files that are not binary libraries\r
3329 if not self.IsLibrary:\r
47fea6af 3330 continue\r
52302d4d
LG
3331 RuleObject = self.BuildRules[TAB_DEFAULT_BINARY_FILE]\r
3332 elif FileType in self.BuildRules:\r
3333 RuleObject = self.BuildRules[FileType]\r
3334 elif Source.Ext in self.BuildRules:\r
3335 RuleObject = self.BuildRules[Source.Ext]\r
3336 else:\r
3337 # stop at no more rules\r
3338 if LastTarget:\r
3339 self._FinalBuildTargetList.add(LastTarget)\r
3340 break\r
3341\r
3342 FileType = RuleObject.SourceFileType\r
3343 if FileType not in self._FileTypes:\r
3344 self._FileTypes[FileType] = set()\r
3345 self._FileTypes[FileType].add(Source)\r
3346\r
3347 # stop at STATIC_LIBRARY for library\r
3348 if self.IsLibrary and FileType == TAB_STATIC_LIBRARY:\r
3349 if LastTarget:\r
3350 self._FinalBuildTargetList.add(LastTarget)\r
3351 break\r
3352\r
fe4bf2f9 3353 Target = RuleObject.Apply(Source, self.BuildRuleOrder)\r
52302d4d
LG
3354 if not Target:\r
3355 if LastTarget:\r
3356 self._FinalBuildTargetList.add(LastTarget)\r
3357 break\r
3358 elif not Target.Outputs:\r
3359 # Only do build for target with outputs\r
3360 self._FinalBuildTargetList.add(Target)\r
3361\r
3362 if FileType not in self._BuildTargets:\r
3363 self._BuildTargets[FileType] = set()\r
3364 self._BuildTargets[FileType].add(Target)\r
3365\r
3366 if not Source.IsBinary and Source == File:\r
3367 self._IntroBuildTargetList.add(Target)\r
3368\r
3369 # to avoid cyclic rule\r
3370 if FileType in RuleChain:\r
3371 break\r
3372\r
3373 RuleChain.append(FileType)\r
3374 SourceList.extend(Target.Outputs)\r
3375 LastTarget = Target\r
3376 FileType = TAB_UNKNOWN_FILE\r
3377\r
3378 def _GetTargets(self):\r
3379 if self._BuildTargets == None:\r
3380 self._IntroBuildTargetList = set()\r
3381 self._FinalBuildTargetList = set()\r
3382 self._BuildTargets = {}\r
3383 self._FileTypes = {}\r
3384\r
b36d134f 3385 #TRICK: call _GetSourceFileList to apply build rule for source files\r
52302d4d
LG
3386 if self.SourceFileList:\r
3387 pass\r
3388\r
3389 #TRICK: call _GetBinaryFileList to apply build rule for binary files\r
3390 if self.BinaryFileList:\r
3391 pass\r
3392\r
3393 return self._BuildTargets\r
3394\r
3395 def _GetIntroTargetList(self):\r
3396 self._GetTargets()\r
3397 return self._IntroBuildTargetList\r
3398\r
3399 def _GetFinalTargetList(self):\r
3400 self._GetTargets()\r
3401 return self._FinalBuildTargetList\r
3402\r
3403 def _GetFileTypes(self):\r
3404 self._GetTargets()\r
3405 return self._FileTypes\r
3406\r
3407 ## Get the list of package object the module depends on\r
3408 #\r
3409 # @retval list The package object list\r
3410 #\r
3411 def _GetDependentPackageList(self):\r
3412 return self.Module.Packages\r
3413\r
3414 ## Return the list of auto-generated code file\r
3415 #\r
3416 # @retval list The list of auto-generated file\r
3417 #\r
3418 def _GetAutoGenFileList(self):\r
3419 UniStringAutoGenC = True\r
333ba578 3420 IdfStringAutoGenC = True\r
4234283c 3421 UniStringBinBuffer = StringIO()\r
333ba578 3422 IdfGenBinBuffer = StringIO()\r
52302d4d 3423 if self.BuildType == 'UEFI_HII':\r
52302d4d 3424 UniStringAutoGenC = False\r
333ba578 3425 IdfStringAutoGenC = False\r
52302d4d
LG
3426 if self._AutoGenFileList == None:\r
3427 self._AutoGenFileList = {}\r
3428 AutoGenC = TemplateString()\r
3429 AutoGenH = TemplateString()\r
3430 StringH = TemplateString()\r
333ba578
YZ
3431 StringIdf = TemplateString()\r
3432 GenC.CreateCode(self, AutoGenC, AutoGenH, StringH, UniStringAutoGenC, UniStringBinBuffer, StringIdf, IdfStringAutoGenC, IdfGenBinBuffer)\r
07b8564b
YL
3433 #\r
3434 # AutoGen.c is generated if there are library classes in inf, or there are object files\r
3435 #\r
3436 if str(AutoGenC) != "" and (len(self.Module.LibraryClasses) > 0\r
3437 or TAB_OBJECT_FILE in self.FileTypes):\r
52302d4d
LG
3438 AutoFile = PathClass(gAutoGenCodeFileName, self.DebugDir)\r
3439 self._AutoGenFileList[AutoFile] = str(AutoGenC)\r
3440 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)\r
3441 if str(AutoGenH) != "":\r
3442 AutoFile = PathClass(gAutoGenHeaderFileName, self.DebugDir)\r
3443 self._AutoGenFileList[AutoFile] = str(AutoGenH)\r
3444 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)\r
3445 if str(StringH) != "":\r
3446 AutoFile = PathClass(gAutoGenStringFileName % {"module_name":self.Name}, self.DebugDir)\r
3447 self._AutoGenFileList[AutoFile] = str(StringH)\r
3448 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)\r
3449 if UniStringBinBuffer != None and UniStringBinBuffer.getvalue() != "":\r
3450 AutoFile = PathClass(gAutoGenStringFormFileName % {"module_name":self.Name}, self.OutputDir)\r
3451 self._AutoGenFileList[AutoFile] = UniStringBinBuffer.getvalue()\r
3452 AutoFile.IsBinary = True\r
3453 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)\r
3454 if UniStringBinBuffer != None:\r
3455 UniStringBinBuffer.close()\r
333ba578
YZ
3456 if str(StringIdf) != "":\r
3457 AutoFile = PathClass(gAutoGenImageDefFileName % {"module_name":self.Name}, self.DebugDir)\r
3458 self._AutoGenFileList[AutoFile] = str(StringIdf)\r
3459 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)\r
3460 if IdfGenBinBuffer != None and IdfGenBinBuffer.getvalue() != "":\r
3461 AutoFile = PathClass(gAutoGenIdfFileName % {"module_name":self.Name}, self.OutputDir)\r
3462 self._AutoGenFileList[AutoFile] = IdfGenBinBuffer.getvalue()\r
3463 AutoFile.IsBinary = True\r
3464 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)\r
3465 if IdfGenBinBuffer != None:\r
3466 IdfGenBinBuffer.close()\r
52302d4d
LG
3467 return self._AutoGenFileList\r
3468\r
3469 ## Return the list of library modules explicitly or implicityly used by this module\r
3470 def _GetLibraryList(self):\r
3471 if self._DependentLibraryList == None:\r
3472 # only merge library classes and PCD for non-library module\r
3473 if self.IsLibrary:\r
3474 self._DependentLibraryList = []\r
3475 else:\r
3476 if self.AutoGenVersion < 0x00010005:\r
3477 self._DependentLibraryList = self.PlatformInfo.ResolveLibraryReference(self.Module)\r
3478 else:\r
3479 self._DependentLibraryList = self.PlatformInfo.ApplyLibraryInstance(self.Module)\r
3480 return self._DependentLibraryList\r
3481\r
e8a47801
LG
3482 @staticmethod\r
3483 def UpdateComments(Recver, Src):\r
3484 for Key in Src:\r
3485 if Key not in Recver:\r
3486 Recver[Key] = []\r
3487 Recver[Key].extend(Src[Key])\r
52302d4d
LG
3488 ## Get the list of PCDs from current module\r
3489 #\r
3490 # @retval list The list of PCD\r
3491 #\r
3492 def _GetModulePcdList(self):\r
3493 if self._ModulePcdList == None:\r
3494 # apply PCD settings from platform\r
3495 self._ModulePcdList = self.PlatformInfo.ApplyPcdSetting(self.Module, self.Module.Pcds)\r
e8a47801 3496 self.UpdateComments(self._PcdComments, self.Module.PcdComments)\r
52302d4d
LG
3497 return self._ModulePcdList\r
3498\r
3499 ## Get the list of PCDs from dependent libraries\r
3500 #\r
3501 # @retval list The list of PCD\r
3502 #\r
3503 def _GetLibraryPcdList(self):\r
3504 if self._LibraryPcdList == None:\r
79b74a03 3505 Pcds = sdict()\r
52302d4d
LG
3506 if not self.IsLibrary:\r
3507 # get PCDs from dependent libraries\r
3508 for Library in self.DependentLibraryList:\r
e8a47801 3509 self.UpdateComments(self._PcdComments, Library.PcdComments)\r
52302d4d
LG
3510 for Key in Library.Pcds:\r
3511 # skip duplicated PCDs\r
3512 if Key in self.Module.Pcds or Key in Pcds:\r
3513 continue\r
3514 Pcds[Key] = copy.copy(Library.Pcds[Key])\r
3515 # apply PCD settings from platform\r
3516 self._LibraryPcdList = self.PlatformInfo.ApplyPcdSetting(self.Module, Pcds)\r
3517 else:\r
3518 self._LibraryPcdList = []\r
3519 return self._LibraryPcdList\r
3520\r
3521 ## Get the GUID value mapping\r
3522 #\r
3523 # @retval dict The mapping between GUID cname and its value\r
3524 #\r
3525 def _GetGuidList(self):\r
3526 if self._GuidList == None:\r
8200fcfe
YL
3527 self._GuidList = sdict()\r
3528 self._GuidList.update(self.Module.Guids)\r
52302d4d
LG
3529 for Library in self.DependentLibraryList:\r
3530 self._GuidList.update(Library.Guids)\r
e8a47801
LG
3531 self.UpdateComments(self._GuidComments, Library.GuidComments)\r
3532 self.UpdateComments(self._GuidComments, self.Module.GuidComments)\r
52302d4d
LG
3533 return self._GuidList\r
3534\r
e8a47801
LG
3535 def GetGuidsUsedByPcd(self):\r
3536 if self._GuidsUsedByPcd == None:\r
3537 self._GuidsUsedByPcd = sdict()\r
3538 self._GuidsUsedByPcd.update(self.Module.GetGuidsUsedByPcd())\r
3539 for Library in self.DependentLibraryList:\r
3540 self._GuidsUsedByPcd.update(Library.GetGuidsUsedByPcd())\r
3541 return self._GuidsUsedByPcd\r
52302d4d
LG
3542 ## Get the protocol value mapping\r
3543 #\r
3544 # @retval dict The mapping between protocol cname and its value\r
3545 #\r
3546 def _GetProtocolList(self):\r
3547 if self._ProtocolList == None:\r
8200fcfe
YL
3548 self._ProtocolList = sdict()\r
3549 self._ProtocolList.update(self.Module.Protocols)\r
52302d4d
LG
3550 for Library in self.DependentLibraryList:\r
3551 self._ProtocolList.update(Library.Protocols)\r
e8a47801
LG
3552 self.UpdateComments(self._ProtocolComments, Library.ProtocolComments)\r
3553 self.UpdateComments(self._ProtocolComments, self.Module.ProtocolComments)\r
52302d4d
LG
3554 return self._ProtocolList\r
3555\r
3556 ## Get the PPI value mapping\r
3557 #\r
3558 # @retval dict The mapping between PPI cname and its value\r
3559 #\r
3560 def _GetPpiList(self):\r
3561 if self._PpiList == None:\r
8200fcfe
YL
3562 self._PpiList = sdict()\r
3563 self._PpiList.update(self.Module.Ppis)\r
52302d4d
LG
3564 for Library in self.DependentLibraryList:\r
3565 self._PpiList.update(Library.Ppis)\r
e8a47801
LG
3566 self.UpdateComments(self._PpiComments, Library.PpiComments)\r
3567 self.UpdateComments(self._PpiComments, self.Module.PpiComments)\r
52302d4d
LG
3568 return self._PpiList\r
3569\r
3570 ## Get the list of include search path\r
3571 #\r
3572 # @retval list The list path\r
3573 #\r
3574 def _GetIncludePathList(self):\r
3575 if self._IncludePathList == None:\r
3576 self._IncludePathList = []\r
3577 if self.AutoGenVersion < 0x00010005:\r
3578 for Inc in self.Module.Includes:\r
3579 if Inc not in self._IncludePathList:\r
3580 self._IncludePathList.append(Inc)\r
b36d134f 3581 # for Edk modules\r
52302d4d
LG
3582 Inc = path.join(Inc, self.Arch.capitalize())\r
3583 if os.path.exists(Inc) and Inc not in self._IncludePathList:\r
3584 self._IncludePathList.append(Inc)\r
b36d134f 3585 # 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
3586 self._IncludePathList.append(self.DebugDir)\r
3587 else:\r
3588 self._IncludePathList.append(self.MetaFile.Dir)\r
3589 self._IncludePathList.append(self.DebugDir)\r
3590\r
3591 for Package in self.Module.Packages:\r
05cc51ad 3592 PackageDir = mws.join(self.WorkspaceDir, Package.MetaFile.Dir)\r
52302d4d
LG
3593 if PackageDir not in self._IncludePathList:\r
3594 self._IncludePathList.append(PackageDir)\r
c28d2e10
YZ
3595 IncludesList = Package.Includes\r
3596 if Package._PrivateIncludes:\r
3597 if not self.MetaFile.Path.startswith(PackageDir):\r
3598 IncludesList = list(set(Package.Includes).difference(set(Package._PrivateIncludes)))\r
3599 for Inc in IncludesList:\r
52302d4d
LG
3600 if Inc not in self._IncludePathList:\r
3601 self._IncludePathList.append(str(Inc))\r
3602 return self._IncludePathList\r
3603\r
725cdb8f
YZ
3604 def _GetIncludePathLength(self):\r
3605 self._IncludePathLength = 0\r
3606 if self._IncludePathList:\r
3607 for inc in self._IncludePathList:\r
3608 self._IncludePathLength += len(' ' + inc)\r
3609 return self._IncludePathLength\r
3610\r
97fa0ee9
YL
3611 ## Get HII EX PCDs which maybe used by VFR\r
3612 #\r
3613 # efivarstore used by VFR may relate with HII EX PCDs\r
3614 # Get the variable name and GUID from efivarstore and HII EX PCD\r
3615 # List the HII EX PCDs in As Built INF if both name and GUID match.\r
3616 #\r
3617 # @retval list HII EX PCDs\r
3618 #\r
3619 def _GetPcdsMaybeUsedByVfr(self):\r
3620 if not self.SourceFileList:\r
3621 return []\r
3622\r
3623 NameGuids = []\r
3624 for SrcFile in self.SourceFileList:\r
3625 if SrcFile.Ext.lower() != '.vfr':\r
3626 continue\r
3627 Vfri = os.path.join(self.OutputDir, SrcFile.BaseName + '.i')\r
3628 if not os.path.exists(Vfri):\r
3629 continue\r
3630 VfriFile = open(Vfri, 'r')\r
3631 Content = VfriFile.read()\r
3632 VfriFile.close()\r
3633 Pos = Content.find('efivarstore')\r
3634 while Pos != -1:\r
3635 #\r
3636 # Make sure 'efivarstore' is the start of efivarstore statement\r
3637 # In case of the value of 'name' (name = efivarstore) is equal to 'efivarstore'\r
3638 #\r
3639 Index = Pos - 1\r
3640 while Index >= 0 and Content[Index] in ' \t\r\n':\r
3641 Index -= 1\r
3642 if Index >= 0 and Content[Index] != ';':\r
3643 Pos = Content.find('efivarstore', Pos + len('efivarstore'))\r
3644 continue\r
3645 #\r
3646 # 'efivarstore' must be followed by name and guid\r
3647 #\r
3648 Name = gEfiVarStoreNamePattern.search(Content, Pos)\r
3649 if not Name:\r
3650 break\r
3651 Guid = gEfiVarStoreGuidPattern.search(Content, Pos)\r
3652 if not Guid:\r
3653 break\r
3654 NameArray = ConvertStringToByteArray('L"' + Name.group(1) + '"')\r
3655 NameGuids.append((NameArray, GuidStructureStringToGuidString(Guid.group(1))))\r
3656 Pos = Content.find('efivarstore', Name.end())\r
3657 if not NameGuids:\r
3658 return []\r
3659 HiiExPcds = []\r
3660 for Pcd in self.PlatformInfo.Platform.Pcds.values():\r
3661 if Pcd.Type != TAB_PCDS_DYNAMIC_EX_HII:\r
3662 continue\r
3663 for SkuName in Pcd.SkuInfoList:\r
3664 SkuInfo = Pcd.SkuInfoList[SkuName]\r
3665 Name = ConvertStringToByteArray(SkuInfo.VariableName)\r
c28d2e10 3666 Value = GuidValue(SkuInfo.VariableGuid, self.PlatformInfo.PackageList, self.MetaFile.Path)\r
97fa0ee9
YL
3667 if not Value:\r
3668 continue\r
3669 Guid = GuidStructureStringToGuidString(Value)\r
3670 if (Name, Guid) in NameGuids and Pcd not in HiiExPcds:\r
3671 HiiExPcds.append(Pcd)\r
3672 break\r
3673\r
3674 return HiiExPcds\r
3675\r
aeaaf754
YL
3676 def _GenOffsetBin(self):\r
3677 VfrUniBaseName = {}\r
3678 for SourceFile in self.Module.Sources:\r
3679 if SourceFile.Type.upper() == ".VFR" :\r
3680 #\r
3681 # search the .map file to find the offset of vfr binary in the PE32+/TE file. \r
3682 #\r
3683 VfrUniBaseName[SourceFile.BaseName] = (SourceFile.BaseName + "Bin")\r
3684 if SourceFile.Type.upper() == ".UNI" :\r
3685 #\r
3686 # search the .map file to find the offset of Uni strings binary in the PE32+/TE file. \r
3687 #\r
3688 VfrUniBaseName["UniOffsetName"] = (self.Name + "Strings")\r
3689\r
3690 if len(VfrUniBaseName) == 0:\r
3691 return None\r
3692 MapFileName = os.path.join(self.OutputDir, self.Name + ".map")\r
3693 EfiFileName = os.path.join(self.OutputDir, self.Name + ".efi")\r
3694 VfrUniOffsetList = GetVariableOffset(MapFileName, EfiFileName, VfrUniBaseName.values())\r
3695 if not VfrUniOffsetList:\r
3696 return None\r
3697\r
3698 OutputName = '%sOffset.bin' % self.Name\r
3699 UniVfrOffsetFileName = os.path.join( self.OutputDir, OutputName)\r
3700\r
3701 try:\r
3702 fInputfile = open(UniVfrOffsetFileName, "wb+", 0)\r
3703 except:\r
3704 EdkLogger.error("build", FILE_OPEN_FAILURE, "File open failed for %s" % UniVfrOffsetFileName,None)\r
3705\r
3706 # Use a instance of StringIO to cache data\r
3707 fStringIO = StringIO('') \r
3708\r
3709 for Item in VfrUniOffsetList:\r
3710 if (Item[0].find("Strings") != -1):\r
3711 #\r
3712 # UNI offset in image.\r
3713 # GUID + Offset\r
3714 # { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } }\r
3715 #\r
3716 UniGuid = [0xe0, 0xc5, 0x13, 0x89, 0xf6, 0x33, 0x86, 0x4d, 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66]\r
3717 UniGuid = [chr(ItemGuid) for ItemGuid in UniGuid]\r
3718 fStringIO.write(''.join(UniGuid)) \r
3719 UniValue = pack ('Q', int (Item[1], 16))\r
3720 fStringIO.write (UniValue)\r
3721 else:\r
3722 #\r
3723 # VFR binary offset in image.\r
3724 # GUID + Offset\r
3725 # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } };\r
3726 #\r
3727 VfrGuid = [0xb4, 0x7c, 0xbc, 0xd0, 0x47, 0x6a, 0x5f, 0x49, 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2]\r
3728 VfrGuid = [chr(ItemGuid) for ItemGuid in VfrGuid]\r
3729 fStringIO.write(''.join(VfrGuid)) \r
3730 type (Item[1]) \r
3731 VfrValue = pack ('Q', int (Item[1], 16))\r
3732 fStringIO.write (VfrValue)\r
3733 #\r
3734 # write data into file.\r
3735 #\r
3736 try : \r
3737 fInputfile.write (fStringIO.getvalue())\r
3738 except:\r
3739 EdkLogger.error("build", FILE_WRITE_FAILURE, "Write data to file %s failed, please check whether the "\r
3740 "file been locked or using by other applications." %UniVfrOffsetFileName,None)\r
3741\r
3742 fStringIO.close ()\r
3743 fInputfile.close ()\r
3744 return OutputName\r
3745\r
da92f276
LG
3746 ## Create AsBuilt INF file the module\r
3747 #\r
3748 def CreateAsBuiltInf(self):\r
3749 if self.IsAsBuiltInfCreated:\r
3750 return\r
3751 \r
3752 # Skip the following code for EDK I inf\r
3753 if self.AutoGenVersion < 0x00010005:\r
3754 return\r
3755 \r
3756 # Skip the following code for libraries\r
3757 if self.IsLibrary:\r
3758 return\r
3759 \r
3760 # Skip the following code for modules with no source files\r
3761 if self.SourceFileList == None or self.SourceFileList == []:\r
3762 return\r
3763\r
3764 # Skip the following code for modules without any binary files\r
3765 if self.BinaryFileList <> None and self.BinaryFileList <> []:\r
3766 return\r
3767 \r
3768 ### TODO: How to handles mixed source and binary modules\r
3769\r
e8a47801 3770 # Find all DynamicEx and PatchableInModule PCDs used by this module and dependent libraries\r
da92f276
LG
3771 # Also find all packages that the DynamicEx PCDs depend on\r
3772 Pcds = []\r
e5cf9198 3773 PatchablePcds = []\r
47fea6af 3774 Packages = []\r
e8a47801
LG
3775 PcdCheckList = []\r
3776 PcdTokenSpaceList = []\r
da92f276 3777 for Pcd in self.ModulePcdList + self.LibraryPcdList:\r
e8a47801 3778 if Pcd.Type == TAB_PCDS_PATCHABLE_IN_MODULE:\r
e5cf9198 3779 PatchablePcds += [Pcd]\r
e8a47801
LG
3780 PcdCheckList.append((Pcd.TokenCName, Pcd.TokenSpaceGuidCName, 'PatchableInModule'))\r
3781 elif Pcd.Type in GenC.gDynamicExPcd:\r
3782 if Pcd not in Pcds:\r
3783 Pcds += [Pcd]\r
3784 PcdCheckList.append((Pcd.TokenCName, Pcd.TokenSpaceGuidCName, 'DynamicEx'))\r
3785 PcdCheckList.append((Pcd.TokenCName, Pcd.TokenSpaceGuidCName, 'Dynamic'))\r
3786 PcdTokenSpaceList.append(Pcd.TokenSpaceGuidCName)\r
3787 GuidList = sdict()\r
3788 GuidList.update(self.GuidList)\r
3789 for TokenSpace in self.GetGuidsUsedByPcd():\r
3790 # If token space is not referred by patch PCD or Ex PCD, remove the GUID from GUID list\r
3791 # The GUIDs in GUIDs section should really be the GUIDs in source INF or referred by Ex an patch PCDs\r
3792 if TokenSpace not in PcdTokenSpaceList and TokenSpace in GuidList:\r
3793 GuidList.pop(TokenSpace)\r
3794 CheckList = (GuidList, self.PpiList, self.ProtocolList, PcdCheckList)\r
3795 for Package in self.DerivedPackageList:\r
3796 if Package in Packages:\r
3797 continue\r
3798 BeChecked = (Package.Guids, Package.Ppis, Package.Protocols, Package.Pcds)\r
3799 Found = False\r
3800 for Index in range(len(BeChecked)):\r
3801 for Item in CheckList[Index]:\r
3802 if Item in BeChecked[Index]:\r
3803 Packages += [Package]\r
3804 Found = True\r
3805 break\r
3806 if Found: break\r
da92f276 3807\r
97fa0ee9
YL
3808 VfrPcds = self._GetPcdsMaybeUsedByVfr()\r
3809 for Pkg in self.PlatformInfo.PackageList:\r
3810 if Pkg in Packages:\r
3811 continue\r
3812 for VfrPcd in VfrPcds:\r
3813 if ((VfrPcd.TokenCName, VfrPcd.TokenSpaceGuidCName, 'DynamicEx') in Pkg.Pcds or\r
3814 (VfrPcd.TokenCName, VfrPcd.TokenSpaceGuidCName, 'Dynamic') in Pkg.Pcds):\r
3815 Packages += [Pkg]\r
3816 break\r
3817\r
da92f276
LG
3818 ModuleType = self.ModuleType\r
3819 if ModuleType == 'UEFI_DRIVER' and self.DepexGenerated:\r
e8a47801
LG
3820 ModuleType = 'DXE_DRIVER'\r
3821\r
3822 DriverType = ''\r
3823 if self.PcdIsDriver != '':\r
3824 DriverType = self.PcdIsDriver\r
da92f276 3825\r
97fa0ee9
YL
3826 Guid = self.Guid\r
3827 MDefs = self.Module.Defines\r
3828\r
da92f276
LG
3829 AsBuiltInfDict = {\r
3830 'module_name' : self.Name,\r
97fa0ee9 3831 'module_guid' : Guid,\r
da92f276 3832 'module_module_type' : ModuleType,\r
97fa0ee9 3833 'module_version_string' : [MDefs['VERSION_STRING']] if 'VERSION_STRING' in MDefs else [],\r
e8a47801 3834 'pcd_is_driver_string' : [],\r
da92f276
LG
3835 'module_uefi_specification_version' : [],\r
3836 'module_pi_specification_version' : [],\r
97fa0ee9
YL
3837 'module_entry_point' : self.Module.ModuleEntryPointList,\r
3838 'module_unload_image' : self.Module.ModuleUnloadImageList,\r
3839 'module_constructor' : self.Module.ConstructorList,\r
3840 'module_destructor' : self.Module.DestructorList,\r
3841 'module_shadow' : [MDefs['SHADOW']] if 'SHADOW' in MDefs else [],\r
3842 'module_pci_vendor_id' : [MDefs['PCI_VENDOR_ID']] if 'PCI_VENDOR_ID' in MDefs else [],\r
3843 'module_pci_device_id' : [MDefs['PCI_DEVICE_ID']] if 'PCI_DEVICE_ID' in MDefs else [],\r
3844 'module_pci_class_code' : [MDefs['PCI_CLASS_CODE']] if 'PCI_CLASS_CODE' in MDefs else [],\r
3845 'module_pci_revision' : [MDefs['PCI_REVISION']] if 'PCI_REVISION' in MDefs else [],\r
3846 'module_build_number' : [MDefs['BUILD_NUMBER']] if 'BUILD_NUMBER' in MDefs else [],\r
3847 'module_spec' : [MDefs['SPEC']] if 'SPEC' in MDefs else [],\r
3848 'module_uefi_hii_resource_section' : [MDefs['UEFI_HII_RESOURCE_SECTION']] if 'UEFI_HII_RESOURCE_SECTION' in MDefs else [],\r
3849 'module_uni_file' : [MDefs['MODULE_UNI_FILE']] if 'MODULE_UNI_FILE' in MDefs else [],\r
da92f276 3850 'module_arch' : self.Arch,\r
47fea6af 3851 'package_item' : ['%s' % (Package.MetaFile.File.replace('\\', '/')) for Package in Packages],\r
da92f276 3852 'binary_item' : [],\r
e8a47801 3853 'patchablepcd_item' : [],\r
da92f276 3854 'pcd_item' : [],\r
e8a47801
LG
3855 'protocol_item' : [],\r
3856 'ppi_item' : [],\r
3857 'guid_item' : [],\r
3858 'flags_item' : [],\r
3859 'libraryclasses_item' : []\r
da92f276 3860 }\r
97fa0ee9
YL
3861\r
3862 if self.AutoGenVersion > int(gInfSpecVersion, 0):\r
3863 AsBuiltInfDict['module_inf_version'] = '0x%08x' % self.AutoGenVersion\r
3864 else:\r
3865 AsBuiltInfDict['module_inf_version'] = gInfSpecVersion\r
3866\r
e8a47801
LG
3867 if DriverType:\r
3868 AsBuiltInfDict['pcd_is_driver_string'] += [DriverType]\r
da92f276
LG
3869\r
3870 if 'UEFI_SPECIFICATION_VERSION' in self.Specification:\r
481252bb 3871 AsBuiltInfDict['module_uefi_specification_version'] += [self.Specification['UEFI_SPECIFICATION_VERSION']]\r
da92f276 3872 if 'PI_SPECIFICATION_VERSION' in self.Specification:\r
481252bb 3873 AsBuiltInfDict['module_pi_specification_version'] += [self.Specification['PI_SPECIFICATION_VERSION']]\r
da92f276 3874\r
47fea6af 3875 OutputDir = self.OutputDir.replace('\\', '/').strip('/')\r
481252bb
YZ
3876\r
3877 for Item in self.CodaTargetList:\r
47fea6af
YZ
3878 File = Item.Target.Path.replace('\\', '/').strip('/').replace(OutputDir, '').strip('/')\r
3879 if Item.Target.Ext.lower() == '.aml':\r
481252bb 3880 AsBuiltInfDict['binary_item'] += ['ASL|' + File]\r
47fea6af 3881 elif Item.Target.Ext.lower() == '.acpi':\r
481252bb
YZ
3882 AsBuiltInfDict['binary_item'] += ['ACPI|' + File]\r
3883 elif Item.Target.Ext.lower() == '.efi':\r
3884 AsBuiltInfDict['binary_item'] += ['PE32|' + self.Name + '.efi']\r
da92f276 3885 else:\r
481252bb
YZ
3886 AsBuiltInfDict['binary_item'] += ['BIN|' + File]\r
3887 if self.DepexGenerated:\r
da92f276 3888 if self.ModuleType in ['PEIM']:\r
481252bb 3889 AsBuiltInfDict['binary_item'] += ['PEI_DEPEX|' + self.Name + '.depex']\r
47fea6af 3890 if self.ModuleType in ['DXE_DRIVER', 'DXE_RUNTIME_DRIVER', 'DXE_SAL_DRIVER', 'UEFI_DRIVER']:\r
481252bb 3891 AsBuiltInfDict['binary_item'] += ['DXE_DEPEX|' + self.Name + '.depex']\r
da92f276 3892 if self.ModuleType in ['DXE_SMM_DRIVER']:\r
481252bb 3893 AsBuiltInfDict['binary_item'] += ['SMM_DEPEX|' + self.Name + '.depex']\r
da92f276 3894\r
aeaaf754
YL
3895 Bin = self._GenOffsetBin()\r
3896 if Bin:\r
3897 AsBuiltInfDict['binary_item'] += ['BIN|%s' % Bin]\r
3898\r
e8a47801
LG
3899 for Root, Dirs, Files in os.walk(OutputDir):\r
3900 for File in Files:\r
3901 if File.lower().endswith('.pdb'):\r
3902 AsBuiltInfDict['binary_item'] += ['DISPOSABLE|' + File]\r
3903 HeaderComments = self.Module.HeaderComments\r
3904 StartPos = 0\r
3905 for Index in range(len(HeaderComments)):\r
3906 if HeaderComments[Index].find('@BinaryHeader') != -1:\r
3907 HeaderComments[Index] = HeaderComments[Index].replace('@BinaryHeader', '@file')\r
3908 StartPos = Index\r
3909 break\r
3910 AsBuiltInfDict['header_comments'] = '\n'.join(HeaderComments[StartPos:]).replace(':#', '://')\r
97fa0ee9
YL
3911 AsBuiltInfDict['tail_comments'] = '\n'.join(self.Module.TailComments)\r
3912\r
e8a47801
LG
3913 GenList = [\r
3914 (self.ProtocolList, self._ProtocolComments, 'protocol_item'),\r
3915 (self.PpiList, self._PpiComments, 'ppi_item'),\r
3916 (GuidList, self._GuidComments, 'guid_item')\r
3917 ]\r
3918 for Item in GenList:\r
3919 for CName in Item[0]:\r
3920 Comments = ''\r
3921 if CName in Item[1]:\r
3922 Comments = '\n '.join(Item[1][CName])\r
3923 Entry = CName\r
3924 if Comments:\r
3925 Entry = Comments + '\n ' + CName\r
3926 AsBuiltInfDict[Item[2]].append(Entry)\r
3927 PatchList = parsePcdInfoFromMapFile(\r
3928 os.path.join(self.OutputDir, self.Name + '.map'),\r
3929 os.path.join(self.OutputDir, self.Name + '.efi')\r
3930 )\r
3931 if PatchList:\r
e5cf9198
YZ
3932 for Pcd in PatchablePcds:\r
3933 TokenCName = Pcd.TokenCName\r
3934 for PcdItem in GlobalData.MixedPcd:\r
3935 if (Pcd.TokenCName, Pcd.TokenSpaceGuidCName) in GlobalData.MixedPcd[PcdItem]:\r
3936 TokenCName = PcdItem[0]\r
3937 break\r
3938 for PatchPcd in PatchList:\r
3939 if TokenCName == PatchPcd[0]:\r
3940 break\r
2a29017e 3941 else:\r
e8a47801 3942 continue\r
e8a47801 3943 PcdValue = ''\r
7ced8bb4
YZ
3944 if Pcd.DatumType == 'BOOLEAN':\r
3945 BoolValue = Pcd.DefaultValue.upper()\r
3946 if BoolValue == 'TRUE':\r
3947 Pcd.DefaultValue = '1'\r
3948 elif BoolValue == 'FALSE':\r
3949 Pcd.DefaultValue = '0'\r
3950\r
e8a47801
LG
3951 if Pcd.DatumType != 'VOID*':\r
3952 HexFormat = '0x%02x'\r
3953 if Pcd.DatumType == 'UINT16':\r
3954 HexFormat = '0x%04x'\r
3955 elif Pcd.DatumType == 'UINT32':\r
3956 HexFormat = '0x%08x'\r
3957 elif Pcd.DatumType == 'UINT64':\r
3958 HexFormat = '0x%016x'\r
3959 PcdValue = HexFormat % int(Pcd.DefaultValue, 0)\r
3960 else:\r
3961 if Pcd.MaxDatumSize == None or Pcd.MaxDatumSize == '':\r
3962 EdkLogger.error("build", AUTOGEN_ERROR,\r
2a29017e 3963 "Unknown [MaxDatumSize] of PCD [%s.%s]" % (Pcd.TokenSpaceGuidCName, TokenCName)\r
e8a47801
LG
3964 )\r
3965 ArraySize = int(Pcd.MaxDatumSize, 0)\r
3966 PcdValue = Pcd.DefaultValue\r
3967 if PcdValue[0] != '{':\r
3968 Unicode = False\r
3969 if PcdValue[0] == 'L':\r
3970 Unicode = True\r
3971 PcdValue = PcdValue.lstrip('L')\r
3972 PcdValue = eval(PcdValue)\r
3973 NewValue = '{'\r
3974 for Index in range(0, len(PcdValue)):\r
3975 if Unicode:\r
3976 CharVal = ord(PcdValue[Index])\r
3977 NewValue = NewValue + '0x%02x' % (CharVal & 0x00FF) + ', ' \\r
3978 + '0x%02x' % (CharVal >> 8) + ', '\r
3979 else:\r
3980 NewValue = NewValue + '0x%02x' % (ord(PcdValue[Index]) % 0x100) + ', '\r
3981 Padding = '0x00, '\r
3982 if Unicode:\r
3983 Padding = Padding * 2\r
3984 ArraySize = ArraySize / 2\r
3985 if ArraySize < (len(PcdValue) + 1):\r
3986 EdkLogger.error("build", AUTOGEN_ERROR,\r
2a29017e 3987 "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd.TokenSpaceGuidCName, TokenCName)\r
e8a47801
LG
3988 )\r
3989 if ArraySize > len(PcdValue) + 1:\r
3990 NewValue = NewValue + Padding * (ArraySize - len(PcdValue) - 1)\r
3991 PcdValue = NewValue + Padding.strip().rstrip(',') + '}'\r
3992 elif len(PcdValue.split(',')) <= ArraySize:\r
3993 PcdValue = PcdValue.rstrip('}') + ', 0x00' * (ArraySize - len(PcdValue.split(',')))\r
3994 PcdValue += '}'\r
3995 else:\r
3996 EdkLogger.error("build", AUTOGEN_ERROR,\r
2a29017e 3997 "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd.TokenSpaceGuidCName, TokenCName)\r
e8a47801
LG
3998 )\r
3999 PcdItem = '%s.%s|%s|0x%X' % \\r
2a29017e 4000 (Pcd.TokenSpaceGuidCName, TokenCName, PcdValue, PatchPcd[1])\r
e8a47801
LG
4001 PcdComments = ''\r
4002 if (Pcd.TokenSpaceGuidCName, Pcd.TokenCName) in self._PcdComments:\r
4003 PcdComments = '\n '.join(self._PcdComments[Pcd.TokenSpaceGuidCName, Pcd.TokenCName])\r
4004 if PcdComments:\r
4005 PcdItem = PcdComments + '\n ' + PcdItem\r
4006 AsBuiltInfDict['patchablepcd_item'].append(PcdItem)\r
97fa0ee9
YL
4007\r
4008 HiiPcds = []\r
4009 for Pcd in Pcds + VfrPcds:\r
e8a47801
LG
4010 PcdComments = ''\r
4011 PcdCommentList = []\r
4012 HiiInfo = ''\r
97fa0ee9 4013 SkuId = ''\r
2a29017e
YZ
4014 TokenCName = Pcd.TokenCName\r
4015 for PcdItem in GlobalData.MixedPcd:\r
4016 if (Pcd.TokenCName, Pcd.TokenSpaceGuidCName) in GlobalData.MixedPcd[PcdItem]:\r
4017 TokenCName = PcdItem[0]\r
4018 break\r
e8a47801
LG
4019 if Pcd.Type == TAB_PCDS_DYNAMIC_EX_HII:\r
4020 for SkuName in Pcd.SkuInfoList:\r
4021 SkuInfo = Pcd.SkuInfoList[SkuName]\r
97fa0ee9 4022 SkuId = SkuInfo.SkuId\r
e8a47801
LG
4023 HiiInfo = '## %s|%s|%s' % (SkuInfo.VariableName, SkuInfo.VariableGuid, SkuInfo.VariableOffset)\r
4024 break\r
97fa0ee9
YL
4025 if SkuId:\r
4026 #\r
4027 # Don't generate duplicated HII PCD\r
4028 #\r
4029 if (SkuId, Pcd.TokenSpaceGuidCName, Pcd.TokenCName) in HiiPcds:\r
4030 continue\r
4031 else:\r
4032 HiiPcds.append((SkuId, Pcd.TokenSpaceGuidCName, Pcd.TokenCName))\r
e8a47801
LG
4033 if (Pcd.TokenSpaceGuidCName, Pcd.TokenCName) in self._PcdComments:\r
4034 PcdCommentList = self._PcdComments[Pcd.TokenSpaceGuidCName, Pcd.TokenCName][:]\r
4035 if HiiInfo:\r
4036 UsageIndex = -1\r
97fa0ee9 4037 UsageStr = ''\r
e8a47801
LG
4038 for Index, Comment in enumerate(PcdCommentList):\r
4039 for Usage in UsageList:\r
4040 if Comment.find(Usage) != -1:\r
97fa0ee9 4041 UsageStr = Usage\r
e8a47801
LG
4042 UsageIndex = Index\r
4043 break\r
4044 if UsageIndex != -1:\r
97fa0ee9 4045 PcdCommentList[UsageIndex] = '## %s %s %s' % (UsageStr, HiiInfo, PcdCommentList[UsageIndex].replace(UsageStr, '')) \r
e8a47801 4046 else:\r
97fa0ee9 4047 PcdCommentList.append('## UNDEFINED ' + HiiInfo)\r
e8a47801 4048 PcdComments = '\n '.join(PcdCommentList)\r
2a29017e 4049 PcdEntry = Pcd.TokenSpaceGuidCName + '.' + TokenCName\r
e8a47801
LG
4050 if PcdComments:\r
4051 PcdEntry = PcdComments + '\n ' + PcdEntry\r
4052 AsBuiltInfDict['pcd_item'] += [PcdEntry]\r
da92f276 4053 for Item in self.BuildOption:\r
481252bb
YZ
4054 if 'FLAGS' in self.BuildOption[Item]:\r
4055 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
4056\r
4057 # Generated LibraryClasses section in comments.\r
4058 for Library in self.LibraryAutoGenList:\r
4059 AsBuiltInfDict['libraryclasses_item'] += [Library.MetaFile.File.replace('\\', '/')]\r
4060 \r
4061 # Generated depex expression section in comments.\r
4062 AsBuiltInfDict['depexsection_item'] = ''\r
4063 DepexExpresion = self._GetDepexExpresionString()\r
4064 if DepexExpresion:\r
4065 AsBuiltInfDict['depexsection_item'] = DepexExpresion\r
da92f276
LG
4066 \r
4067 AsBuiltInf = TemplateString()\r
4068 AsBuiltInf.Append(gAsBuiltInfHeaderString.Replace(AsBuiltInfDict))\r
4069 \r
4070 SaveFileOnChange(os.path.join(self.OutputDir, self.Name + '.inf'), str(AsBuiltInf), False)\r
4071 \r
4072 self.IsAsBuiltInfCreated = True\r
4073 \r
52302d4d
LG
4074 ## Create makefile for the module and its dependent libraries\r
4075 #\r
4076 # @param CreateLibraryMakeFile Flag indicating if or not the makefiles of\r
4077 # dependent libraries will be created\r
4078 #\r
4079 def CreateMakeFile(self, CreateLibraryMakeFile=True):\r
fae62ff2 4080 # Ignore generating makefile when it is a binary module\r
a0a2cd1e
FB
4081 if self.IsBinaryModule:\r
4082 return\r
fae62ff2 4083\r
52302d4d
LG
4084 if self.IsMakeFileCreated:\r
4085 return\r
c17956e0
DL
4086 if self.CanSkip():\r
4087 return\r
52302d4d
LG
4088\r
4089 if not self.IsLibrary and CreateLibraryMakeFile:\r
4090 for LibraryAutoGen in self.LibraryAutoGenList:\r
4091 LibraryAutoGen.CreateMakeFile()\r
4092\r
4093 if len(self.CustomMakefile) == 0:\r
4094 Makefile = GenMake.ModuleMakefile(self)\r
4095 else:\r
4096 Makefile = GenMake.CustomMakefile(self)\r
4097 if Makefile.Generate():\r
4098 EdkLogger.debug(EdkLogger.DEBUG_9, "Generated makefile for module %s [%s]" %\r
4099 (self.Name, self.Arch))\r
4100 else:\r
4101 EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of makefile for module %s [%s]" %\r
4102 (self.Name, self.Arch))\r
4103\r
c17956e0 4104 self.CreateTimeStamp(Makefile)\r
52302d4d
LG
4105 self.IsMakeFileCreated = True\r
4106\r
a0a2cd1e
FB
4107 def CopyBinaryFiles(self):\r
4108 for File in self.Module.Binaries:\r
4109 SrcPath = File.Path\r
4110 DstPath = os.path.join(self.OutputDir , os.path.basename(SrcPath))\r
4111 CopyLongFilePath(SrcPath, DstPath)\r
52302d4d
LG
4112 ## Create autogen code for the module and its dependent libraries\r
4113 #\r
4114 # @param CreateLibraryCodeFile Flag indicating if or not the code of\r
4115 # dependent libraries will be created\r
4116 #\r
4117 def CreateCodeFile(self, CreateLibraryCodeFile=True):\r
4118 if self.IsCodeFileCreated:\r
4119 return\r
c17956e0
DL
4120 if self.CanSkip():\r
4121 return\r
52302d4d 4122\r
e8a47801
LG
4123 # Need to generate PcdDatabase even PcdDriver is binarymodule\r
4124 if self.IsBinaryModule and self.PcdIsDriver != '':\r
4125 CreatePcdDatabaseCode(self, TemplateString(), TemplateString())\r
4126 return\r
a0a2cd1e 4127 if self.IsBinaryModule:\r
49d9b71d
HC
4128 if self.IsLibrary:\r
4129 self.CopyBinaryFiles()\r
a0a2cd1e 4130 return\r
e8a47801 4131\r
52302d4d
LG
4132 if not self.IsLibrary and CreateLibraryCodeFile:\r
4133 for LibraryAutoGen in self.LibraryAutoGenList:\r
4134 LibraryAutoGen.CreateCodeFile()\r
4135\r
4136 AutoGenList = []\r
4137 IgoredAutoGenList = []\r
4138\r
4139 for File in self.AutoGenFileList:\r
4140 if GenC.Generate(File.Path, self.AutoGenFileList[File], File.IsBinary):\r
b36d134f 4141 #Ignore Edk AutoGen.c\r
52302d4d
LG
4142 if self.AutoGenVersion < 0x00010005 and File.Name == 'AutoGen.c':\r
4143 continue\r
4144\r
4145 AutoGenList.append(str(File))\r
4146 else:\r
4147 IgoredAutoGenList.append(str(File))\r
4148\r
4149 # Skip the following code for EDK I inf\r
4150 if self.AutoGenVersion < 0x00010005:\r
4151 return\r
4152\r
4153 for ModuleType in self.DepexList:\r
40d841f6
LG
4154 # Ignore empty [depex] section or [depex] section for "USER_DEFINED" module\r
4155 if len(self.DepexList[ModuleType]) == 0 or ModuleType == "USER_DEFINED":\r
52302d4d 4156 continue\r
40d841f6 4157\r
52302d4d
LG
4158 Dpx = GenDepex.DependencyExpression(self.DepexList[ModuleType], ModuleType, True)\r
4159 DpxFile = gAutoGenDepexFileName % {"module_name" : self.Name}\r
4160\r
da92f276 4161 if len(Dpx.PostfixNotation) <> 0:\r
0d2711a6 4162 self.DepexGenerated = True\r
da92f276 4163\r
52302d4d
LG
4164 if Dpx.Generate(path.join(self.OutputDir, DpxFile)):\r
4165 AutoGenList.append(str(DpxFile))\r
4166 else:\r
4167 IgoredAutoGenList.append(str(DpxFile))\r
4168\r
4169 if IgoredAutoGenList == []:\r
4170 EdkLogger.debug(EdkLogger.DEBUG_9, "Generated [%s] files for module %s [%s]" %\r
4171 (" ".join(AutoGenList), self.Name, self.Arch))\r
4172 elif AutoGenList == []:\r
4173 EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of [%s] files for module %s [%s]" %\r
4174 (" ".join(IgoredAutoGenList), self.Name, self.Arch))\r
4175 else:\r
4176 EdkLogger.debug(EdkLogger.DEBUG_9, "Generated [%s] (skipped %s) files for module %s [%s]" %\r
4177 (" ".join(AutoGenList), " ".join(IgoredAutoGenList), self.Name, self.Arch))\r
4178\r
4179 self.IsCodeFileCreated = True\r
4180 return AutoGenList\r
4181\r
4182 ## Summarize the ModuleAutoGen objects of all libraries used by this module\r
4183 def _GetLibraryAutoGenList(self):\r
4184 if self._LibraryAutoGenList == None:\r
4185 self._LibraryAutoGenList = []\r
4186 for Library in self.DependentLibraryList:\r
4187 La = ModuleAutoGen(\r
4188 self.Workspace,\r
4189 Library.MetaFile,\r
4190 self.BuildTarget,\r
4191 self.ToolChain,\r
4192 self.Arch,\r
4193 self.PlatformInfo.MetaFile\r
4194 )\r
4195 if La not in self._LibraryAutoGenList:\r
4196 self._LibraryAutoGenList.append(La)\r
4197 for Lib in La.CodaTargetList:\r
4198 self._ApplyBuildRule(Lib.Target, TAB_UNKNOWN_FILE)\r
4199 return self._LibraryAutoGenList\r
4200\r
c17956e0
DL
4201 ## Decide whether we can skip the ModuleAutoGen process\r
4202 # If any source file is newer than the modeule than we cannot skip\r
4203 #\r
4204 def CanSkip(self):\r
4205 if not os.path.exists(self.GetTimeStampPath()):\r
4206 return False\r
4207 #last creation time of the module\r
4208 DstTimeStamp = os.stat(self.GetTimeStampPath())[8]\r
4209\r
4210 SrcTimeStamp = self.Workspace._SrcTimeStamp\r
4211 if SrcTimeStamp > DstTimeStamp:\r
4212 return False\r
4213\r
4214 with open(self.GetTimeStampPath(),'r') as f:\r
4215 for source in f:\r
4216 source = source.rstrip('\n')\r
4217 if source not in ModuleAutoGen.TimeDict :\r
4218 ModuleAutoGen.TimeDict[source] = os.stat(source)[8]\r
4219 if ModuleAutoGen.TimeDict[source] > DstTimeStamp:\r
4220 return False\r
4221 return True\r
4222\r
4223 def GetTimeStampPath(self):\r
4224 if self._TimeStampPath == None:\r
4225 self._TimeStampPath = os.path.join(self.MakeFileDir, 'AutoGenTimeStamp')\r
4226 return self._TimeStampPath\r
4227 def CreateTimeStamp(self, Makefile):\r
4228\r
4229 FileSet = set()\r
4230\r
4231 FileSet.add (self.MetaFile.Path)\r
4232\r
4233 for SourceFile in self.Module.Sources:\r
4234 FileSet.add (SourceFile.Path)\r
4235\r
4236 for Lib in self.DependentLibraryList:\r
4237 FileSet.add (Lib.MetaFile.Path)\r
4238\r
4239 for f in self.AutoGenDepSet:\r
4240 FileSet.add (f.Path)\r
4241\r
4242 if os.path.exists (self.GetTimeStampPath()):\r
4243 os.remove (self.GetTimeStampPath())\r
4244 with open(self.GetTimeStampPath(), 'w+') as file:\r
4245 for f in FileSet:\r
4246 print >> file, f\r
4247\r
52302d4d
LG
4248 Module = property(_GetModule)\r
4249 Name = property(_GetBaseName)\r
4250 Guid = property(_GetGuid)\r
4251 Version = property(_GetVersion)\r
4252 ModuleType = property(_GetModuleType)\r
4253 ComponentType = property(_GetComponentType)\r
4254 BuildType = property(_GetBuildType)\r
4255 PcdIsDriver = property(_GetPcdIsDriver)\r
4256 AutoGenVersion = property(_GetAutoGenVersion)\r
4257 Macros = property(_GetMacros)\r
4258 Specification = property(_GetSpecification)\r
4259\r
4260 IsLibrary = property(_IsLibrary)\r
e8a47801 4261 IsBinaryModule = property(_IsBinaryModule)\r
52302d4d
LG
4262 BuildDir = property(_GetBuildDir)\r
4263 OutputDir = property(_GetOutputDir)\r
4264 DebugDir = property(_GetDebugDir)\r
4265 MakeFileDir = property(_GetMakeFileDir)\r
4266 CustomMakefile = property(_GetCustomMakefile)\r
4267\r
4268 IncludePathList = property(_GetIncludePathList)\r
725cdb8f 4269 IncludePathLength = property(_GetIncludePathLength)\r
52302d4d
LG
4270 AutoGenFileList = property(_GetAutoGenFileList)\r
4271 UnicodeFileList = property(_GetUnicodeFileList)\r
5b97eb4c 4272 VfrFileList = property(_GetVfrFileList)\r
52302d4d
LG
4273 SourceFileList = property(_GetSourceFileList)\r
4274 BinaryFileList = property(_GetBinaryFiles) # FileType : [File List]\r
4275 Targets = property(_GetTargets)\r
4276 IntroTargetList = property(_GetIntroTargetList)\r
4277 CodaTargetList = property(_GetFinalTargetList)\r
4278 FileTypes = property(_GetFileTypes)\r
4279 BuildRules = property(_GetBuildRules)\r
333ba578 4280 IdfFileList = property(_GetIdfFileList)\r
52302d4d
LG
4281\r
4282 DependentPackageList = property(_GetDependentPackageList)\r
4283 DependentLibraryList = property(_GetLibraryList)\r
4284 LibraryAutoGenList = property(_GetLibraryAutoGenList)\r
4285 DerivedPackageList = property(_GetDerivedPackageList)\r
4286\r
4287 ModulePcdList = property(_GetModulePcdList)\r
4288 LibraryPcdList = property(_GetLibraryPcdList)\r
4289 GuidList = property(_GetGuidList)\r
4290 ProtocolList = property(_GetProtocolList)\r
4291 PpiList = property(_GetPpiList)\r
4292 DepexList = property(_GetDepexTokenList)\r
b36d134f 4293 DxsFile = property(_GetDxsFile)\r
52302d4d
LG
4294 DepexExpressionList = property(_GetDepexExpressionTokenList)\r
4295 BuildOption = property(_GetModuleBuildOption)\r
79b74a03 4296 BuildOptionIncPathList = property(_GetBuildOptionIncPathList)\r
52302d4d 4297 BuildCommand = property(_GetBuildCommand)\r
2bc3256c
LG
4298 \r
4299 FixedAtBuildPcds = property(_GetFixedAtBuildPcds)\r
52302d4d
LG
4300\r
4301# This acts like the main() function for the script, unless it is 'import'ed into another script.\r
4302if __name__ == '__main__':\r
4303 pass\r
4304\r