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