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