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