OvmfPkg: AcpiPlatformDxe: Don't enable unsupported PCI attributes
[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
763e8edf
YZ
353 if GlobalData.BuildOptionPcd:\r
354 for i, pcd in enumerate(GlobalData.BuildOptionPcd):\r
d7cd3356
YZ
355 if type(pcd) is tuple:\r
356 continue\r
763e8edf
YZ
357 (pcdname, pcdvalue) = pcd.split('=')\r
358 if not pcdvalue:\r
359 EdkLogger.error('build', AUTOGEN_ERROR, "No Value specified for the PCD %s." % (pcdname))\r
360 if '.' in pcdname:\r
361 (TokenSpaceGuidCName, TokenCName) = pcdname.split('.')\r
362 HasTokenSpace = True\r
363 else:\r
364 TokenCName = pcdname\r
365 TokenSpaceGuidCName = ''\r
366 HasTokenSpace = False\r
367 TokenSpaceGuidCNameList = []\r
368 FoundFlag = False\r
369 PcdDatumType = ''\r
370 NewValue = ''\r
371 for package in PGen.PackageList:\r
372 for key in package.Pcds:\r
373 PcdItem = package.Pcds[key]\r
374 if HasTokenSpace:\r
375 if (PcdItem.TokenCName, PcdItem.TokenSpaceGuidCName) == (TokenCName, TokenSpaceGuidCName):\r
376 PcdDatumType = PcdItem.DatumType\r
377 NewValue = self._BuildOptionPcdValueFormat(TokenSpaceGuidCName, TokenCName, PcdDatumType, pcdvalue)\r
378 FoundFlag = True\r
379 else:\r
380 if PcdItem.TokenCName == TokenCName:\r
381 if not PcdItem.TokenSpaceGuidCName in TokenSpaceGuidCNameList:\r
382 if len (TokenSpaceGuidCNameList) < 1:\r
383 TokenSpaceGuidCNameList.append(PcdItem.TokenSpaceGuidCName)\r
384 PcdDatumType = PcdItem.DatumType\r
385 TokenSpaceGuidCName = PcdItem.TokenSpaceGuidCName\r
386 NewValue = self._BuildOptionPcdValueFormat(TokenSpaceGuidCName, TokenCName, PcdDatumType, pcdvalue)\r
387 FoundFlag = True\r
388 else:\r
389 EdkLogger.error(\r
390 'build',\r
391 AUTOGEN_ERROR,\r
392 "The Pcd %s is found under multiple different TokenSpaceGuid: %s and %s." % (TokenCName, PcdItem.TokenSpaceGuidCName, TokenSpaceGuidCNameList[0])\r
393 )\r
394\r
395 GlobalData.BuildOptionPcd[i] = (TokenSpaceGuidCName, TokenCName, NewValue)\r
396\r
397 if not FoundFlag:\r
398 if HasTokenSpace:\r
399 EdkLogger.error('build', AUTOGEN_ERROR, "The Pcd %s.%s is not found in the DEC file." % (TokenSpaceGuidCName, TokenCName))\r
400 else:\r
401 EdkLogger.error('build', AUTOGEN_ERROR, "The Pcd %s is not found in the DEC file." % (TokenCName))\r
402\r
403 for BuildData in PGen.BuildDatabase._CACHE_.values():\r
404 if BuildData.Arch != Arch:\r
405 continue\r
406 if BuildData.MetaFile.Ext == '.dec':\r
407 continue\r
408 for key in BuildData.Pcds:\r
409 PcdItem = BuildData.Pcds[key]\r
410 if (TokenSpaceGuidCName, TokenCName) == (PcdItem.TokenSpaceGuidCName, PcdItem.TokenCName):\r
411 PcdItem.DefaultValue = NewValue\r
412\r
413 if (TokenCName, TokenSpaceGuidCName) in PcdSet:\r
414 PcdSet[(TokenCName, TokenSpaceGuidCName)] = NewValue\r
415\r
97fa0ee9 416 #Collect package set information from INF of FDF\r
a0a2cd1e
FB
417 PkgSet = set()\r
418 for Inf in ModuleList:\r
419 ModuleFile = PathClass(NormPath(Inf), GlobalData.gWorkspace, Arch)\r
420 if ModuleFile in Platform.Modules:\r
421 continue\r
422 ModuleData = self.BuildDatabase[ModuleFile, Arch, Target, Toolchain]\r
423 PkgSet.update(ModuleData.Packages)\r
424 Pkgs = list(PkgSet) + list(PGen.PackageList)\r
64b2609f 425 for Pkg in Pkgs:\r
25918452
LG
426 for Pcd in Pkg.Pcds:\r
427 DecPcds[Pcd[0], Pcd[1]] = Pkg.Pcds[Pcd]\r
4afd3d04 428 DecPcdsKey.add((Pcd[0], Pcd[1], Pcd[2]))\r
64b2609f 429\r
52302d4d
LG
430 Platform.SkuName = self.SkuId\r
431 for Name, Guid in PcdSet:\r
64b2609f
LG
432 if (Name, Guid) not in DecPcds:\r
433 EdkLogger.error(\r
434 'build',\r
435 PARSER_ERROR,\r
436 "PCD (%s.%s) used in FDF is not declared in DEC files." % (Guid, Name),\r
437 File = self.FdfProfile.PcdFileLineDict[Name, Guid][0],\r
438 Line = self.FdfProfile.PcdFileLineDict[Name, Guid][1]\r
439 )\r
4afd3d04
LG
440 else:\r
441 # Check whether Dynamic or DynamicEx PCD used in FDF file. If used, build break and give a error message.\r
442 if (Name, Guid, TAB_PCDS_FIXED_AT_BUILD) in DecPcdsKey \\r
443 or (Name, Guid, TAB_PCDS_PATCHABLE_IN_MODULE) in DecPcdsKey \\r
444 or (Name, Guid, TAB_PCDS_FEATURE_FLAG) in DecPcdsKey:\r
445 Platform.AddPcd(Name, Guid, PcdSet[Name, Guid])\r
446 continue\r
447 elif (Name, Guid, TAB_PCDS_DYNAMIC) in DecPcdsKey or (Name, Guid, TAB_PCDS_DYNAMIC_EX) in DecPcdsKey:\r
448 EdkLogger.error(\r
449 'build',\r
450 PARSER_ERROR,\r
451 "Using Dynamic or DynamicEx type of PCD [%s.%s] in FDF file is not allowed." % (Guid, Name),\r
452 File = self.FdfProfile.PcdFileLineDict[Name, Guid][0],\r
453 Line = self.FdfProfile.PcdFileLineDict[Name, Guid][1]\r
454 )\r
52302d4d
LG
455\r
456 Pa = PlatformAutoGen(self, self.MetaFile, Target, Toolchain, Arch)\r
457 #\r
458 # Explicitly collect platform's dynamic PCDs\r
459 #\r
460 Pa.CollectPlatformDynamicPcds()\r
2bc3256c 461 Pa.CollectFixedAtBuildPcds()\r
52302d4d 462 self.AutoGenObjectList.append(Pa)\r
47fea6af 463\r
6780eef1
LG
464 #\r
465 # Check PCDs token value conflict in each DEC file.\r
466 #\r
467 self._CheckAllPcdsTokenValueConflict()\r
47fea6af 468\r
4234283c
LG
469 #\r
470 # Check PCD type and definition between DSC and DEC\r
471 #\r
472 self._CheckPcdDefineAndType()\r
97fa0ee9
YL
473\r
474# if self.FdfFile:\r
475# self._CheckDuplicateInFV(Fdf)\r
476\r
52302d4d
LG
477 self._BuildDir = None\r
478 self._FvDir = None\r
479 self._MakeFileDir = None\r
480 self._BuildCommand = None\r
481\r
482 return True\r
483\r
763e8edf
YZ
484 def _BuildOptionPcdValueFormat(self, TokenSpaceGuidCName, TokenCName, PcdDatumType, Value):\r
485 if PcdDatumType == 'VOID*':\r
486 if Value.startswith('L'):\r
487 if not Value[1]:\r
488 EdkLogger.error('build', OPTION_VALUE_INVALID, 'For Void* type PCD, when specify the Value in the command line, please use the following format: "string", L"string", B"{...}"')\r
489 Value = Value[0] + '"' + Value[1:] + '"'\r
490 elif Value.startswith('B'):\r
491 if not Value[1]:\r
492 EdkLogger.error('build', OPTION_VALUE_INVALID, 'For Void* type PCD, when specify the Value in the command line, please use the following format: "string", L"string", B"{...}"')\r
493 Value = Value[1:]\r
494 else:\r
495 if not Value[0]:\r
496 EdkLogger.error('build', OPTION_VALUE_INVALID, 'For Void* type PCD, when specify the Value in the command line, please use the following format: "string", L"string", B"{...}"')\r
497 Value = '"' + Value + '"'\r
498\r
499 IsValid, Cause = CheckPcdDatum(PcdDatumType, Value)\r
500 if not IsValid:\r
501 EdkLogger.error('build', FORMAT_INVALID, Cause, ExtraData="%s.%s" % (TokenSpaceGuidCName, TokenCName))\r
502 if PcdDatumType == 'BOOLEAN':\r
503 Value = Value.upper()\r
504 if Value == 'TRUE' or Value == '1':\r
505 Value = '1'\r
506 elif Value == 'FALSE' or Value == '0':\r
507 Value = '0'\r
508 return Value\r
509\r
79b74a03
LG
510 ## _CheckDuplicateInFV() method\r
511 #\r
512 # Check whether there is duplicate modules/files exist in FV section. \r
513 # The check base on the file GUID;\r
514 #\r
515 def _CheckDuplicateInFV(self, Fdf):\r
516 for Fv in Fdf.Profile.FvDict:\r
517 _GuidDict = {}\r
518 for FfsFile in Fdf.Profile.FvDict[Fv].FfsList:\r
519 if FfsFile.InfFileName and FfsFile.NameGuid == None:\r
520 #\r
521 # Get INF file GUID\r
522 #\r
47fea6af 523 InfFoundFlag = False\r
79b74a03 524 for Pa in self.AutoGenObjectList:\r
64b2609f
LG
525 if InfFoundFlag:\r
526 break\r
79b74a03
LG
527 for Module in Pa.ModuleAutoGenList:\r
528 if path.normpath(Module.MetaFile.File) == path.normpath(FfsFile.InfFileName):\r
529 InfFoundFlag = True\r
530 if not Module.Guid.upper() in _GuidDict.keys():\r
531 _GuidDict[Module.Guid.upper()] = FfsFile\r
64b2609f 532 break\r
79b74a03 533 else:\r
47fea6af 534 EdkLogger.error("build",\r
79b74a03 535 FORMAT_INVALID,\r
47fea6af 536 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile.CurrentLineNum,\r
79b74a03
LG
537 FfsFile.CurrentLineContent,\r
538 _GuidDict[Module.Guid.upper()].CurrentLineNum,\r
539 _GuidDict[Module.Guid.upper()].CurrentLineContent,\r
540 Module.Guid.upper()),\r
541 ExtraData=self.FdfFile)\r
542 #\r
543 # Some INF files not have entity in DSC file. \r
544 #\r
545 if not InfFoundFlag:\r
546 if FfsFile.InfFileName.find('$') == -1:\r
547 InfPath = NormPath(FfsFile.InfFileName)\r
548 if not os.path.exists(InfPath):\r
549 EdkLogger.error('build', GENFDS_ERROR, "Non-existant Module %s !" % (FfsFile.InfFileName))\r
47fea6af 550\r
79b74a03
LG
551 PathClassObj = PathClass(FfsFile.InfFileName, self.WorkspaceDir)\r
552 #\r
553 # Here we just need to get FILE_GUID from INF file, use 'COMMON' as ARCH attribute. and use \r
554 # BuildObject from one of AutoGenObjectList is enough.\r
555 #\r
556 InfObj = self.AutoGenObjectList[0].BuildDatabase.WorkspaceDb.BuildObject[PathClassObj, 'COMMON', self.BuildTarget, self.ToolChain]\r
557 if not InfObj.Guid.upper() in _GuidDict.keys():\r
558 _GuidDict[InfObj.Guid.upper()] = FfsFile\r
559 else:\r
47fea6af 560 EdkLogger.error("build",\r
79b74a03 561 FORMAT_INVALID,\r
47fea6af 562 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile.CurrentLineNum,\r
79b74a03
LG
563 FfsFile.CurrentLineContent,\r
564 _GuidDict[InfObj.Guid.upper()].CurrentLineNum,\r
565 _GuidDict[InfObj.Guid.upper()].CurrentLineContent,\r
566 InfObj.Guid.upper()),\r
567 ExtraData=self.FdfFile)\r
568 InfFoundFlag = False\r
47fea6af 569\r
79b74a03
LG
570 if FfsFile.NameGuid != None:\r
571 _CheckPCDAsGuidPattern = re.compile("^PCD\(.+\..+\)$")\r
47fea6af 572\r
79b74a03
LG
573 #\r
574 # If the NameGuid reference a PCD name. \r
575 # The style must match: PCD(xxxx.yyy)\r
576 #\r
577 if _CheckPCDAsGuidPattern.match(FfsFile.NameGuid):\r
578 #\r
579 # Replace the PCD value.\r
580 #\r
581 _PcdName = FfsFile.NameGuid.lstrip("PCD(").rstrip(")")\r
582 PcdFoundFlag = False\r
583 for Pa in self.AutoGenObjectList:\r
584 if not PcdFoundFlag:\r
585 for PcdItem in Pa.AllPcdList:\r
586 if (PcdItem.TokenSpaceGuidCName + "." + PcdItem.TokenCName) == _PcdName:\r
587 #\r
588 # First convert from CFormatGuid to GUID string\r
589 #\r
590 _PcdGuidString = GuidStructureStringToGuidString(PcdItem.DefaultValue)\r
47fea6af 591\r
79b74a03
LG
592 if not _PcdGuidString:\r
593 #\r
594 # Then try Byte array.\r
595 #\r
596 _PcdGuidString = GuidStructureByteArrayToGuidString(PcdItem.DefaultValue)\r
47fea6af 597\r
79b74a03
LG
598 if not _PcdGuidString:\r
599 #\r
600 # Not Byte array or CFormat GUID, raise error.\r
601 #\r
602 EdkLogger.error("build",\r
603 FORMAT_INVALID,\r
47fea6af 604 "The format of PCD value is incorrect. PCD: %s , Value: %s\n" % (_PcdName, PcdItem.DefaultValue),\r
79b74a03 605 ExtraData=self.FdfFile)\r
47fea6af
YZ
606\r
607 if not _PcdGuidString.upper() in _GuidDict.keys():\r
79b74a03
LG
608 _GuidDict[_PcdGuidString.upper()] = FfsFile\r
609 PcdFoundFlag = True\r
610 break\r
611 else:\r
47fea6af 612 EdkLogger.error("build",\r
79b74a03 613 FORMAT_INVALID,\r
47fea6af 614 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile.CurrentLineNum,\r
79b74a03
LG
615 FfsFile.CurrentLineContent,\r
616 _GuidDict[_PcdGuidString.upper()].CurrentLineNum,\r
617 _GuidDict[_PcdGuidString.upper()].CurrentLineContent,\r
618 FfsFile.NameGuid.upper()),\r
47fea6af
YZ
619 ExtraData=self.FdfFile)\r
620\r
79b74a03
LG
621 if not FfsFile.NameGuid.upper() in _GuidDict.keys():\r
622 _GuidDict[FfsFile.NameGuid.upper()] = FfsFile\r
623 else:\r
624 #\r
625 # Two raw file GUID conflict.\r
626 #\r
47fea6af 627 EdkLogger.error("build",\r
79b74a03 628 FORMAT_INVALID,\r
47fea6af 629 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile.CurrentLineNum,\r
79b74a03
LG
630 FfsFile.CurrentLineContent,\r
631 _GuidDict[FfsFile.NameGuid.upper()].CurrentLineNum,\r
632 _GuidDict[FfsFile.NameGuid.upper()].CurrentLineContent,\r
633 FfsFile.NameGuid.upper()),\r
634 ExtraData=self.FdfFile)\r
47fea6af 635\r
79b74a03 636\r
4234283c
LG
637 def _CheckPcdDefineAndType(self):\r
638 PcdTypeList = [\r
639 "FixedAtBuild", "PatchableInModule", "FeatureFlag",\r
640 "Dynamic", #"DynamicHii", "DynamicVpd",\r
641 "DynamicEx", # "DynamicExHii", "DynamicExVpd"\r
642 ]\r
643\r
644 # This dict store PCDs which are not used by any modules with specified arches\r
645 UnusedPcd = sdict()\r
646 for Pa in self.AutoGenObjectList:\r
647 # Key of DSC's Pcds dictionary is PcdCName, TokenSpaceGuid\r
648 for Pcd in Pa.Platform.Pcds:\r
649 PcdType = Pa.Platform.Pcds[Pcd].Type\r
47fea6af 650\r
4234283c
LG
651 # If no PCD type, this PCD comes from FDF \r
652 if not PcdType:\r
653 continue\r
47fea6af 654\r
4234283c
LG
655 # Try to remove Hii and Vpd suffix\r
656 if PcdType.startswith("DynamicEx"):\r
657 PcdType = "DynamicEx"\r
658 elif PcdType.startswith("Dynamic"):\r
659 PcdType = "Dynamic"\r
47fea6af 660\r
4234283c
LG
661 for Package in Pa.PackageList:\r
662 # Key of DEC's Pcds dictionary is PcdCName, TokenSpaceGuid, PcdType\r
663 if (Pcd[0], Pcd[1], PcdType) in Package.Pcds:\r
664 break\r
665 for Type in PcdTypeList:\r
666 if (Pcd[0], Pcd[1], Type) in Package.Pcds:\r
667 EdkLogger.error(\r
668 'build',\r
669 FORMAT_INVALID,\r
670 "Type [%s] of PCD [%s.%s] in DSC file doesn't match the type [%s] defined in DEC file." \\r
671 % (Pa.Platform.Pcds[Pcd].Type, Pcd[1], Pcd[0], Type),\r
672 ExtraData=None\r
673 )\r
674 return\r
675 else:\r
676 UnusedPcd.setdefault(Pcd, []).append(Pa.Arch)\r
677\r
678 for Pcd in UnusedPcd:\r
679 EdkLogger.warn(\r
680 'build',\r
681 "The PCD was not specified by any INF module in the platform for the given architecture.\n"\r
682 "\tPCD: [%s.%s]\n\tPlatform: [%s]\n\tArch: %s"\r
683 % (Pcd[1], Pcd[0], os.path.basename(str(self.MetaFile)), str(UnusedPcd[Pcd])),\r
684 ExtraData=None\r
685 )\r
686\r
52302d4d
LG
687 def __repr__(self):\r
688 return "%s [%s]" % (self.MetaFile, ", ".join(self.ArchList))\r
689\r
690 ## Return the directory to store FV files\r
691 def _GetFvDir(self):\r
692 if self._FvDir == None:\r
693 self._FvDir = path.join(self.BuildDir, 'FV')\r
694 return self._FvDir\r
695\r
696 ## Return the directory to store all intermediate and final files built\r
697 def _GetBuildDir(self):\r
698 return self.AutoGenObjectList[0].BuildDir\r
699\r
700 ## Return the build output directory platform specifies\r
701 def _GetOutputDir(self):\r
702 return self.Platform.OutputDirectory\r
703\r
704 ## Return platform name\r
705 def _GetName(self):\r
706 return self.Platform.PlatformName\r
707\r
708 ## Return meta-file GUID\r
709 def _GetGuid(self):\r
710 return self.Platform.Guid\r
711\r
712 ## Return platform version\r
713 def _GetVersion(self):\r
714 return self.Platform.Version\r
715\r
716 ## Return paths of tools\r
717 def _GetToolDefinition(self):\r
718 return self.AutoGenObjectList[0].ToolDefinition\r
719\r
720 ## Return directory of platform makefile\r
721 #\r
722 # @retval string Makefile directory\r
723 #\r
724 def _GetMakeFileDir(self):\r
725 if self._MakeFileDir == None:\r
726 self._MakeFileDir = self.BuildDir\r
727 return self._MakeFileDir\r
728\r
729 ## Return build command string\r
730 #\r
731 # @retval string Build command string\r
732 #\r
733 def _GetBuildCommand(self):\r
734 if self._BuildCommand == None:\r
735 # BuildCommand should be all the same. So just get one from platform AutoGen\r
736 self._BuildCommand = self.AutoGenObjectList[0].BuildCommand\r
737 return self._BuildCommand\r
47fea6af 738\r
6780eef1
LG
739 ## Check the PCDs token value conflict in each DEC file.\r
740 #\r
741 # Will cause build break and raise error message while two PCDs conflict.\r
742 # \r
743 # @return None\r
744 #\r
745 def _CheckAllPcdsTokenValueConflict(self):\r
b36d134f
LG
746 for Pa in self.AutoGenObjectList:\r
747 for Package in Pa.PackageList:\r
6780eef1 748 PcdList = Package.Pcds.values()\r
f827cd07 749 PcdList.sort(lambda x, y: cmp(int(x.TokenValue, 0), int(y.TokenValue, 0))) \r
6780eef1
LG
750 Count = 0\r
751 while (Count < len(PcdList) - 1) :\r
752 Item = PcdList[Count]\r
753 ItemNext = PcdList[Count + 1]\r
754 #\r
755 # Make sure in the same token space the TokenValue should be unique\r
756 #\r
f827cd07 757 if (int(Item.TokenValue, 0) == int(ItemNext.TokenValue, 0)):\r
6780eef1
LG
758 SameTokenValuePcdList = []\r
759 SameTokenValuePcdList.append(Item)\r
760 SameTokenValuePcdList.append(ItemNext)\r
761 RemainPcdListLength = len(PcdList) - Count - 2\r
762 for ValueSameCount in range(RemainPcdListLength):\r
f827cd07 763 if int(PcdList[len(PcdList) - RemainPcdListLength + ValueSameCount].TokenValue, 0) == int(Item.TokenValue, 0):\r
6780eef1
LG
764 SameTokenValuePcdList.append(PcdList[len(PcdList) - RemainPcdListLength + ValueSameCount])\r
765 else:\r
766 break;\r
767 #\r
768 # Sort same token value PCD list with TokenGuid and TokenCName\r
769 #\r
47fea6af
YZ
770 SameTokenValuePcdList.sort(lambda x, y: cmp("%s.%s" % (x.TokenSpaceGuidCName, x.TokenCName), "%s.%s" % (y.TokenSpaceGuidCName, y.TokenCName)))\r
771 SameTokenValuePcdListCount = 0\r
6780eef1 772 while (SameTokenValuePcdListCount < len(SameTokenValuePcdList) - 1):\r
47fea6af
YZ
773 TemListItem = SameTokenValuePcdList[SameTokenValuePcdListCount]\r
774 TemListItemNext = SameTokenValuePcdList[SameTokenValuePcdListCount + 1]\r
775\r
6780eef1
LG
776 if (TemListItem.TokenSpaceGuidCName == TemListItemNext.TokenSpaceGuidCName) and (TemListItem.TokenCName != TemListItemNext.TokenCName):\r
777 EdkLogger.error(\r
778 'build',\r
779 FORMAT_INVALID,\r
780 "The TokenValue [%s] of PCD [%s.%s] is conflict with: [%s.%s] in %s"\\r
781 % (TemListItem.TokenValue, TemListItem.TokenSpaceGuidCName, TemListItem.TokenCName, TemListItemNext.TokenSpaceGuidCName, TemListItemNext.TokenCName, Package),\r
782 ExtraData=None\r
783 )\r
784 SameTokenValuePcdListCount += 1\r
785 Count += SameTokenValuePcdListCount\r
786 Count += 1\r
47fea6af 787\r
6780eef1 788 PcdList = Package.Pcds.values()\r
47fea6af 789 PcdList.sort(lambda x, y: cmp("%s.%s" % (x.TokenSpaceGuidCName, x.TokenCName), "%s.%s" % (y.TokenSpaceGuidCName, y.TokenCName)))\r
6780eef1
LG
790 Count = 0\r
791 while (Count < len(PcdList) - 1) :\r
792 Item = PcdList[Count]\r
47fea6af 793 ItemNext = PcdList[Count + 1]\r
6780eef1
LG
794 #\r
795 # Check PCDs with same TokenSpaceGuidCName.TokenCName have same token value as well.\r
796 #\r
f827cd07 797 if (Item.TokenSpaceGuidCName == ItemNext.TokenSpaceGuidCName) and (Item.TokenCName == ItemNext.TokenCName) and (int(Item.TokenValue, 0) != int(ItemNext.TokenValue, 0)):\r
6780eef1
LG
798 EdkLogger.error(\r
799 'build',\r
800 FORMAT_INVALID,\r
801 "The TokenValue [%s] of PCD [%s.%s] in %s defined in two places should be same as well."\\r
802 % (Item.TokenValue, Item.TokenSpaceGuidCName, Item.TokenCName, Package),\r
803 ExtraData=None\r
804 )\r
805 Count += 1\r
97fa0ee9 806 ## Generate fds command\r
03af2753
HC
807 def _GenFdsCommand(self):\r
808 return (GenMake.TopLevelMakefile(self)._TEMPLATE_.Replace(GenMake.TopLevelMakefile(self)._TemplateDict)).strip()\r
52302d4d 809\r
e56468c0 810 ## Create makefile for the platform and modules in it\r
52302d4d
LG
811 #\r
812 # @param CreateDepsMakeFile Flag indicating if the makefile for\r
813 # modules will be created as well\r
814 #\r
815 def CreateMakeFile(self, CreateDepsMakeFile=False):\r
52302d4d
LG
816 if CreateDepsMakeFile:\r
817 for Pa in self.AutoGenObjectList:\r
818 Pa.CreateMakeFile(CreateDepsMakeFile)\r
819\r
820 ## Create autogen code for platform and modules\r
821 #\r
822 # Since there's no autogen code for platform, this method will do nothing\r
823 # if CreateModuleCodeFile is set to False.\r
824 #\r
825 # @param CreateDepsCodeFile Flag indicating if creating module's\r
826 # autogen code file or not\r
827 #\r
828 def CreateCodeFile(self, CreateDepsCodeFile=False):\r
829 if not CreateDepsCodeFile:\r
830 return\r
831 for Pa in self.AutoGenObjectList:\r
832 Pa.CreateCodeFile(CreateDepsCodeFile)\r
833\r
7c1fd323
LG
834 ## Create AsBuilt INF file the platform\r
835 #\r
836 def CreateAsBuiltInf(self):\r
837 return\r
838\r
52302d4d
LG
839 Name = property(_GetName)\r
840 Guid = property(_GetGuid)\r
841 Version = property(_GetVersion)\r
842 OutputDir = property(_GetOutputDir)\r
843\r
844 ToolDefinition = property(_GetToolDefinition) # toolcode : tool path\r
845\r
846 BuildDir = property(_GetBuildDir)\r
847 FvDir = property(_GetFvDir)\r
848 MakeFileDir = property(_GetMakeFileDir)\r
849 BuildCommand = property(_GetBuildCommand)\r
03af2753 850 GenFdsCommand = property(_GenFdsCommand)\r
52302d4d
LG
851\r
852## AutoGen class for platform\r
853#\r
854# PlatformAutoGen class will process the original information in platform\r
855# file in order to generate makefile for platform.\r
856#\r
857class PlatformAutoGen(AutoGen):\r
858 #\r
859 # Used to store all PCDs for both PEI and DXE phase, in order to generate \r
860 # correct PCD database\r
861 # \r
862 _DynaPcdList_ = []\r
863 _NonDynaPcdList_ = []\r
61ee1dff 864 _PlatformPcds = {}\r
6780eef1
LG
865 \r
866 #\r
867 # The priority list while override build option \r
868 #\r
869 PrioList = {"0x11111" : 16, # TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE (Highest)\r
870 "0x01111" : 15, # ******_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE\r
871 "0x10111" : 14, # TARGET_*********_ARCH_COMMANDTYPE_ATTRIBUTE\r
872 "0x00111" : 13, # ******_*********_ARCH_COMMANDTYPE_ATTRIBUTE \r
873 "0x11011" : 12, # TARGET_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE\r
874 "0x01011" : 11, # ******_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE\r
875 "0x10011" : 10, # TARGET_*********_****_COMMANDTYPE_ATTRIBUTE\r
876 "0x00011" : 9, # ******_*********_****_COMMANDTYPE_ATTRIBUTE\r
877 "0x11101" : 8, # TARGET_TOOLCHAIN_ARCH_***********_ATTRIBUTE\r
878 "0x01101" : 7, # ******_TOOLCHAIN_ARCH_***********_ATTRIBUTE\r
879 "0x10101" : 6, # TARGET_*********_ARCH_***********_ATTRIBUTE\r
880 "0x00101" : 5, # ******_*********_ARCH_***********_ATTRIBUTE\r
881 "0x11001" : 4, # TARGET_TOOLCHAIN_****_***********_ATTRIBUTE\r
882 "0x01001" : 3, # ******_TOOLCHAIN_****_***********_ATTRIBUTE\r
883 "0x10001" : 2, # TARGET_*********_****_***********_ATTRIBUTE\r
884 "0x00001" : 1} # ******_*********_****_***********_ATTRIBUTE (Lowest)\r
47fea6af 885\r
52302d4d
LG
886 ## The real constructor of PlatformAutoGen\r
887 #\r
888 # This method is not supposed to be called by users of PlatformAutoGen. It's\r
889 # only used by factory method __new__() to do real initialization work for an\r
890 # object of PlatformAutoGen\r
891 #\r
892 # @param Workspace WorkspaceAutoGen object\r
893 # @param PlatformFile Platform file (DSC file)\r
894 # @param Target Build target (DEBUG, RELEASE)\r
895 # @param Toolchain Name of tool chain\r
896 # @param Arch arch of the platform supports\r
897 #\r
898 def _Init(self, Workspace, PlatformFile, Target, Toolchain, Arch):\r
899 EdkLogger.debug(EdkLogger.DEBUG_9, "AutoGen platform [%s] [%s]" % (PlatformFile, Arch))\r
900 GlobalData.gProcessingFile = "%s [%s, %s, %s]" % (PlatformFile, Arch, Toolchain, Target)\r
901\r
902 self.MetaFile = PlatformFile\r
903 self.Workspace = Workspace\r
904 self.WorkspaceDir = Workspace.WorkspaceDir\r
905 self.ToolChain = Toolchain\r
906 self.BuildTarget = Target\r
907 self.Arch = Arch\r
908 self.SourceDir = PlatformFile.SubDir\r
909 self.SourceOverrideDir = None\r
910 self.FdTargetList = self.Workspace.FdTargetList\r
911 self.FvTargetList = self.Workspace.FvTargetList\r
912 self.AllPcdList = []\r
a0a2cd1e
FB
913 # get the original module/package/platform objects\r
914 self.BuildDatabase = Workspace.BuildDatabase\r
52302d4d
LG
915\r
916 # flag indicating if the makefile/C-code file has been created or not\r
917 self.IsMakeFileCreated = False\r
918 self.IsCodeFileCreated = False\r
919\r
920 self._Platform = None\r
921 self._Name = None\r
922 self._Guid = None\r
923 self._Version = None\r
924\r
925 self._BuildRule = None\r
926 self._SourceDir = None\r
927 self._BuildDir = None\r
928 self._OutputDir = None\r
929 self._FvDir = None\r
930 self._MakeFileDir = None\r
931 self._FdfFile = None\r
932\r
933 self._PcdTokenNumber = None # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber\r
934 self._DynamicPcdList = None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]\r
935 self._NonDynamicPcdList = None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]\r
2bc3256c 936 self._NonDynamicPcdDict = {}\r
52302d4d
LG
937\r
938 self._ToolDefinitions = None\r
939 self._ToolDefFile = None # toolcode : tool path\r
940 self._ToolChainFamily = None\r
941 self._BuildRuleFamily = None\r
942 self._BuildOption = None # toolcode : option\r
943 self._EdkBuildOption = None # edktoolcode : option\r
944 self._EdkIIBuildOption = None # edkiitoolcode : option\r
945 self._PackageList = None\r
946 self._ModuleAutoGenList = None\r
947 self._LibraryAutoGenList = None\r
948 self._BuildCommand = None\r
a0a2cd1e
FB
949 self._AsBuildInfList = []\r
950 self._AsBuildModuleList = []\r
951 if GlobalData.gFdfParser != None:\r
952 self._AsBuildInfList = GlobalData.gFdfParser.Profile.InfList\r
953 for Inf in self._AsBuildInfList:\r
954 InfClass = PathClass(NormPath(Inf), GlobalData.gWorkspace, self.Arch)\r
955 M = self.BuildDatabase[InfClass, self.Arch, self.BuildTarget, self.ToolChain]\r
956 if not M.IsSupportedArch:\r
957 continue\r
958 self._AsBuildModuleList.append(InfClass)\r
03af2753
HC
959 # get library/modules for build\r
960 self.LibraryBuildDirectoryList = []\r
961 self.ModuleBuildDirectoryList = []\r
52302d4d
LG
962 return True\r
963\r
964 def __repr__(self):\r
965 return "%s [%s]" % (self.MetaFile, self.Arch)\r
966\r
967 ## Create autogen code for platform and modules\r
968 #\r
969 # Since there's no autogen code for platform, this method will do nothing\r
970 # if CreateModuleCodeFile is set to False.\r
971 #\r
972 # @param CreateModuleCodeFile Flag indicating if creating module's\r
973 # autogen code file or not\r
974 #\r
975 def CreateCodeFile(self, CreateModuleCodeFile=False):\r
976 # only module has code to be greated, so do nothing if CreateModuleCodeFile is False\r
977 if self.IsCodeFileCreated or not CreateModuleCodeFile:\r
978 return\r
979\r
980 for Ma in self.ModuleAutoGenList:\r
981 Ma.CreateCodeFile(True)\r
982\r
983 # don't do this twice\r
984 self.IsCodeFileCreated = True\r
985\r
03af2753
HC
986 ## Generate Fds Command\r
987 def _GenFdsCommand(self):\r
988 return self.Workspace.GenFdsCommand\r
989 \r
52302d4d
LG
990 ## Create makefile for the platform and mdoules in it\r
991 #\r
992 # @param CreateModuleMakeFile Flag indicating if the makefile for\r
993 # modules will be created as well\r
994 #\r
995 def CreateMakeFile(self, CreateModuleMakeFile=False):\r
996 if CreateModuleMakeFile:\r
997 for ModuleFile in self.Platform.Modules:\r
998 Ma = ModuleAutoGen(self.Workspace, ModuleFile, self.BuildTarget,\r
999 self.ToolChain, self.Arch, self.MetaFile)\r
1000 Ma.CreateMakeFile(True)\r
97fa0ee9 1001 #Ma.CreateAsBuiltInf()\r
52302d4d
LG
1002\r
1003 # no need to create makefile for the platform more than once\r
1004 if self.IsMakeFileCreated:\r
1005 return\r
1006\r
03af2753 1007 # create library/module build dirs for platform\r
52302d4d 1008 Makefile = GenMake.PlatformMakefile(self)\r
03af2753
HC
1009 self.LibraryBuildDirectoryList = Makefile.GetLibraryBuildDirectoryList()\r
1010 self.ModuleBuildDirectoryList = Makefile.GetModuleBuildDirectoryList()\r
1011\r
52302d4d
LG
1012 self.IsMakeFileCreated = True\r
1013\r
2bc3256c
LG
1014 ## Deal with Shared FixedAtBuild Pcds\r
1015 #\r
1016 def CollectFixedAtBuildPcds(self):\r
1017 for LibAuto in self.LibraryAutoGenList:\r
1018 FixedAtBuildPcds = {} \r
1019 ShareFixedAtBuildPcdsSameValue = {} \r
1020 for Module in LibAuto._ReferenceModules: \r
1021 for Pcd in Module.FixedAtBuildPcds + LibAuto.FixedAtBuildPcds:\r
1022 key = ".".join((Pcd.TokenSpaceGuidCName,Pcd.TokenCName)) \r
1023 if key not in FixedAtBuildPcds:\r
1024 ShareFixedAtBuildPcdsSameValue[key] = True\r
1025 FixedAtBuildPcds[key] = Pcd.DefaultValue\r
1026 else:\r
1027 if FixedAtBuildPcds[key] != Pcd.DefaultValue:\r
1028 ShareFixedAtBuildPcdsSameValue[key] = False \r
1029 for Pcd in LibAuto.FixedAtBuildPcds:\r
1030 key = ".".join((Pcd.TokenSpaceGuidCName,Pcd.TokenCName))\r
1031 if (Pcd.TokenCName,Pcd.TokenSpaceGuidCName) not in self.NonDynamicPcdDict:\r
1032 continue\r
1033 else:\r
1034 DscPcd = self.NonDynamicPcdDict[(Pcd.TokenCName,Pcd.TokenSpaceGuidCName)]\r
1035 if DscPcd.Type != "FixedAtBuild":\r
1036 continue\r
1037 if key in ShareFixedAtBuildPcdsSameValue and ShareFixedAtBuildPcdsSameValue[key]: \r
1038 LibAuto.ConstPcd[key] = Pcd.DefaultValue\r
1039\r
52302d4d
LG
1040 ## Collect dynamic PCDs\r
1041 #\r
1042 # Gather dynamic PCDs list from each module and their settings from platform\r
1043 # This interface should be invoked explicitly when platform action is created.\r
1044 #\r
1045 def CollectPlatformDynamicPcds(self):\r
763e8edf
YZ
1046 # Override the platform Pcd's value by build option\r
1047 if GlobalData.BuildOptionPcd:\r
1048 for key in self.Platform.Pcds:\r
1049 PlatformPcd = self.Platform.Pcds[key]\r
1050 for PcdItem in GlobalData.BuildOptionPcd:\r
1051 if (PlatformPcd.TokenSpaceGuidCName, PlatformPcd.TokenCName) == (PcdItem[0], PcdItem[1]):\r
1052 PlatformPcd.DefaultValue = PcdItem[2]\r
1053 if PlatformPcd.SkuInfoList:\r
1054 Sku = PlatformPcd.SkuInfoList[PlatformPcd.SkuInfoList.keys()[0]]\r
1055 Sku.DefaultValue = PcdItem[2]\r
1056 break\r
1057\r
52302d4d
LG
1058 # for gathering error information\r
1059 NoDatumTypePcdList = set()\r
a0a2cd1e 1060 PcdNotInDb = []\r
52302d4d 1061 self._GuidValue = {}\r
a0a2cd1e
FB
1062 FdfModuleList = []\r
1063 for InfName in self._AsBuildInfList:\r
05cc51ad 1064 InfName = mws.join(self.WorkspaceDir, InfName)\r
a0a2cd1e 1065 FdfModuleList.append(os.path.normpath(InfName))\r
52302d4d
LG
1066 for F in self.Platform.Modules.keys():\r
1067 M = ModuleAutoGen(self.Workspace, F, self.BuildTarget, self.ToolChain, self.Arch, self.MetaFile)\r
1068 #GuidValue.update(M.Guids)\r
1069 \r
1070 self.Platform.Modules[F].M = M\r
47fea6af
YZ
1071\r
1072 for PcdFromModule in M.ModulePcdList + M.LibraryPcdList:\r
52302d4d 1073 # make sure that the "VOID*" kind of datum has MaxDatumSize set\r
e8a47801 1074 if PcdFromModule.DatumType == "VOID*" and PcdFromModule.MaxDatumSize in [None, '']:\r
52302d4d
LG
1075 NoDatumTypePcdList.add("%s.%s [%s]" % (PcdFromModule.TokenSpaceGuidCName, PcdFromModule.TokenCName, F))\r
1076\r
97fa0ee9 1077 # Check the PCD from Binary INF or Source INF\r
a0a2cd1e
FB
1078 if M.IsBinaryModule == True:\r
1079 PcdFromModule.IsFromBinaryInf = True\r
97fa0ee9
YL
1080\r
1081 # Check the PCD from DSC or not \r
a0a2cd1e
FB
1082 if (PcdFromModule.TokenCName, PcdFromModule.TokenSpaceGuidCName) in self.Platform.Pcds.keys():\r
1083 PcdFromModule.IsFromDsc = True\r
1084 else:\r
1085 PcdFromModule.IsFromDsc = False\r
52302d4d 1086 if PcdFromModule.Type in GenC.gDynamicPcd or PcdFromModule.Type in GenC.gDynamicExPcd:\r
a0a2cd1e
FB
1087 if F.Path not in FdfModuleList:\r
1088 # If one of the Source built modules listed in the DSC is not listed \r
1089 # in FDF modules, and the INF lists a PCD can only use the PcdsDynamic \r
1090 # access method (it is only listed in the DEC file that declares the \r
1091 # PCD as PcdsDynamic), then build tool will report warning message\r
1092 # notify the PI that they are attempting to build a module that must \r
1093 # be included in a flash image in order to be functional. These Dynamic \r
1094 # PCD will not be added into the Database unless it is used by other \r
1095 # modules that are included in the FDF file.\r
1096 if PcdFromModule.Type in GenC.gDynamicPcd and \\r
1097 PcdFromModule.IsFromBinaryInf == False:\r
1098 # Print warning message to let the developer make a determine.\r
1099 if PcdFromModule not in PcdNotInDb:\r
a0a2cd1e
FB
1100 PcdNotInDb.append(PcdFromModule)\r
1101 continue\r
1102 # If one of the Source built modules listed in the DSC is not listed in \r
1103 # FDF modules, and the INF lists a PCD can only use the PcdsDynamicEx \r
1104 # access method (it is only listed in the DEC file that declares the \r
1105 # PCD as PcdsDynamicEx), then DO NOT break the build; DO NOT add the \r
1106 # PCD to the Platform's PCD Database.\r
1107 if PcdFromModule.Type in GenC.gDynamicExPcd:\r
1108 if PcdFromModule not in PcdNotInDb:\r
1109 PcdNotInDb.append(PcdFromModule)\r
1110 continue\r
52302d4d
LG
1111 #\r
1112 # If a dynamic PCD used by a PEM module/PEI module & DXE module,\r
1113 # it should be stored in Pcd PEI database, If a dynamic only\r
1114 # used by DXE module, it should be stored in DXE PCD database.\r
1115 # The default Phase is DXE\r
1116 #\r
1117 if M.ModuleType in ["PEIM", "PEI_CORE"]:\r
1118 PcdFromModule.Phase = "PEI"\r
1119 if PcdFromModule not in self._DynaPcdList_:\r
1120 self._DynaPcdList_.append(PcdFromModule)\r
1121 elif PcdFromModule.Phase == 'PEI':\r
1122 # overwrite any the same PCD existing, if Phase is PEI\r
1123 Index = self._DynaPcdList_.index(PcdFromModule)\r
1124 self._DynaPcdList_[Index] = PcdFromModule\r
1125 elif PcdFromModule not in self._NonDynaPcdList_:\r
1126 self._NonDynaPcdList_.append(PcdFromModule)\r
a0a2cd1e
FB
1127 elif PcdFromModule in self._NonDynaPcdList_ and PcdFromModule.IsFromBinaryInf == True:\r
1128 Index = self._NonDynaPcdList_.index(PcdFromModule)\r
1129 if self._NonDynaPcdList_[Index].IsFromBinaryInf == False:\r
1130 #The PCD from Binary INF will override the same one from source INF\r
1131 self._NonDynaPcdList_.remove (self._NonDynaPcdList_[Index])\r
1132 PcdFromModule.Pending = False\r
1133 self._NonDynaPcdList_.append (PcdFromModule)\r
1134 # Parse the DynamicEx PCD from the AsBuild INF module list of FDF.\r
1135 DscModuleList = []\r
1136 for ModuleInf in self.Platform.Modules.keys():\r
1137 DscModuleList.append (os.path.normpath(ModuleInf.Path))\r
1138 # add the PCD from modules that listed in FDF but not in DSC to Database \r
1139 for InfName in FdfModuleList:\r
1140 if InfName not in DscModuleList:\r
1141 InfClass = PathClass(InfName)\r
1142 M = self.BuildDatabase[InfClass, self.Arch, self.BuildTarget, self.ToolChain]\r
1143 # If a module INF in FDF but not in current arch's DSC module list, it must be module (either binary or source) \r
1144 # for different Arch. PCDs in source module for different Arch is already added before, so skip the source module here. \r
1145 # For binary module, if in current arch, we need to list the PCDs into database. \r
1146 if not M.IsSupportedArch:\r
1147 continue\r
1148 # Override the module PCD setting by platform setting\r
1149 ModulePcdList = self.ApplyPcdSetting(M, M.Pcds)\r
1150 for PcdFromModule in ModulePcdList:\r
1151 PcdFromModule.IsFromBinaryInf = True\r
1152 PcdFromModule.IsFromDsc = False\r
1153 # Only allow the DynamicEx and Patchable PCD in AsBuild INF\r
1154 if PcdFromModule.Type not in GenC.gDynamicExPcd and PcdFromModule.Type not in TAB_PCDS_PATCHABLE_IN_MODULE:\r
1155 EdkLogger.error("build", AUTOGEN_ERROR, "PCD setting error",\r
1156 File=self.MetaFile,\r
1157 ExtraData="\n\tExisted %s PCD %s in:\n\t\t%s\n"\r
1158 % (PcdFromModule.Type, PcdFromModule.TokenCName, InfName))\r
1159 # make sure that the "VOID*" kind of datum has MaxDatumSize set\r
1160 if PcdFromModule.DatumType == "VOID*" and PcdFromModule.MaxDatumSize in [None, '']:\r
1161 NoDatumTypePcdList.add("%s.%s [%s]" % (PcdFromModule.TokenSpaceGuidCName, PcdFromModule.TokenCName, InfName))\r
1162 if M.ModuleType in ["PEIM", "PEI_CORE"]:\r
1163 PcdFromModule.Phase = "PEI"\r
1164 if PcdFromModule not in self._DynaPcdList_ and PcdFromModule.Type in GenC.gDynamicExPcd:\r
1165 self._DynaPcdList_.append(PcdFromModule)\r
1166 elif PcdFromModule not in self._NonDynaPcdList_ and PcdFromModule.Type in TAB_PCDS_PATCHABLE_IN_MODULE:\r
1167 self._NonDynaPcdList_.append(PcdFromModule)\r
1168 if PcdFromModule in self._DynaPcdList_ and PcdFromModule.Phase == 'PEI' and PcdFromModule.Type in GenC.gDynamicExPcd:\r
97fa0ee9
YL
1169 # Overwrite the phase of any the same PCD existing, if Phase is PEI.\r
1170 # It is to solve the case that a dynamic PCD used by a PEM module/PEI \r
1171 # module & DXE module at a same time.\r
1172 # Overwrite the type of the PCDs in source INF by the type of AsBuild\r
1173 # INF file as DynamicEx. \r
a0a2cd1e
FB
1174 Index = self._DynaPcdList_.index(PcdFromModule)\r
1175 self._DynaPcdList_[Index].Phase = PcdFromModule.Phase\r
1176 self._DynaPcdList_[Index].Type = PcdFromModule.Type\r
1177 for PcdFromModule in self._NonDynaPcdList_:\r
1178 # If a PCD is not listed in the DSC file, but binary INF files used by \r
1179 # this platform all (that use this PCD) list the PCD in a [PatchPcds] \r
1180 # section, AND all source INF files used by this platform the build \r
1181 # that use the PCD list the PCD in either a [Pcds] or [PatchPcds] \r
1182 # section, then the tools must NOT add the PCD to the Platform's PCD\r
1183 # Database; the build must assign the access method for this PCD as \r
1184 # PcdsPatchableInModule.\r
1185 if PcdFromModule not in self._DynaPcdList_:\r
1186 continue\r
1187 Index = self._DynaPcdList_.index(PcdFromModule)\r
1188 if PcdFromModule.IsFromDsc == False and \\r
1189 PcdFromModule.Type in TAB_PCDS_PATCHABLE_IN_MODULE and \\r
1190 PcdFromModule.IsFromBinaryInf == True and \\r
1191 self._DynaPcdList_[Index].IsFromBinaryInf == False:\r
1192 Index = self._DynaPcdList_.index(PcdFromModule)\r
1193 self._DynaPcdList_.remove (self._DynaPcdList_[Index])\r
52302d4d
LG
1194\r
1195 # print out error information and break the build, if error found\r
1196 if len(NoDatumTypePcdList) > 0:\r
1197 NoDatumTypePcdListString = "\n\t\t".join(NoDatumTypePcdList)\r
1198 EdkLogger.error("build", AUTOGEN_ERROR, "PCD setting error",\r
1199 File=self.MetaFile,\r
1200 ExtraData="\n\tPCD(s) without MaxDatumSize:\n\t\t%s\n"\r
1201 % NoDatumTypePcdListString)\r
1202 self._NonDynamicPcdList = self._NonDynaPcdList_\r
1203 self._DynamicPcdList = self._DynaPcdList_\r
52302d4d
LG
1204 #\r
1205 # Sort dynamic PCD list to:\r
1206 # 1) If PCD's datum type is VOID* and value is unicode string which starts with L, the PCD item should \r
1207 # try to be put header of dynamicd List\r
1208 # 2) If PCD is HII type, the PCD item should be put after unicode type PCD\r
1209 #\r
1210 # The reason of sorting is make sure the unicode string is in double-byte alignment in string table.\r
1211 #\r
1212 UnicodePcdArray = []\r
1213 HiiPcdArray = []\r
1214 OtherPcdArray = []\r
6780eef1 1215 VpdPcdDict = {}\r
e56468c0 1216 VpdFile = VpdInfoFile.VpdInfoFile()\r
61ee1dff
YZ
1217 NeedProcessVpdMapFile = False\r
1218\r
1219 for pcd in self.Platform.Pcds.keys():\r
1220 if pcd not in self._PlatformPcds.keys():\r
1221 self._PlatformPcds[pcd] = self.Platform.Pcds[pcd]\r
1222\r
e56468c0 1223 if (self.Workspace.ArchList[-1] == self.Arch): \r
1224 for Pcd in self._DynamicPcdList:\r
e56468c0 1225 # just pick the a value to determine whether is unicode string type\r
47fea6af 1226 Sku = Pcd.SkuInfoList[Pcd.SkuInfoList.keys()[0]]\r
e56468c0 1227 Sku.VpdOffset = Sku.VpdOffset.strip()\r
47fea6af 1228\r
e56468c0 1229 PcdValue = Sku.DefaultValue\r
1230 if Pcd.DatumType == 'VOID*' and PcdValue.startswith("L"):\r
1231 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex\r
1232 UnicodePcdArray.append(Pcd)\r
1233 elif len(Sku.VariableName) > 0:\r
1234 # if found HII type PCD then insert to right of UnicodeIndex\r
1235 HiiPcdArray.append(Pcd)\r
1236 else:\r
1237 OtherPcdArray.append(Pcd)\r
e56468c0 1238 if Pcd.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD]:\r
47fea6af
YZ
1239 VpdPcdDict[(Pcd.TokenCName, Pcd.TokenSpaceGuidCName)] = Pcd\r
1240\r
61ee1dff 1241 PlatformPcds = self._PlatformPcds.keys()\r
47fea6af 1242 PlatformPcds.sort()\r
6780eef1
LG
1243 #\r
1244 # Add VPD type PCD into VpdFile and determine whether the VPD PCD need to be fixed up.\r
1245 #\r
1246 for PcdKey in PlatformPcds:\r
61ee1dff 1247 Pcd = self._PlatformPcds[PcdKey]\r
e8a47801
LG
1248 if Pcd.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD] and \\r
1249 PcdKey in VpdPcdDict:\r
1250 Pcd = VpdPcdDict[PcdKey]\r
1251 for (SkuName,Sku) in Pcd.SkuInfoList.items():\r
1252 Sku.VpdOffset = Sku.VpdOffset.strip()\r
5a13737a
YZ
1253 PcdValue = Sku.DefaultValue\r
1254 if PcdValue == "":\r
1255 PcdValue = Pcd.DefaultValue\r
1256 if Sku.VpdOffset != '*':\r
1257 if PcdValue.startswith("{"):\r
1258 Alignment = 8\r
1259 elif PcdValue.startswith("L"):\r
1260 Alignment = 2\r
1261 else:\r
1262 Alignment = 1\r
ca85291f
YZ
1263 try:\r
1264 VpdOffset = int(Sku.VpdOffset)\r
1265 except:\r
1266 try:\r
1267 VpdOffset = int(Sku.VpdOffset, 16)\r
1268 except:\r
1269 EdkLogger.error("build", FORMAT_INVALID, "Invalid offset value %s for PCD %s.%s." % (Sku.VpdOffset, Pcd.TokenSpaceGuidCName, Pcd.TokenCName))\r
1270 if VpdOffset % Alignment != 0:\r
815ada26
YZ
1271 if PcdValue.startswith("{"):\r
1272 EdkLogger.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(Pcd.TokenSpaceGuidCName, Pcd.TokenCName), File=self.MetaFile)\r
1273 else:\r
1274 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
1275 VpdFile.Add(Pcd, Sku.VpdOffset)\r
1276 # if the offset of a VPD is *, then it need to be fixed up by third party tool.\r
1277 if not NeedProcessVpdMapFile and Sku.VpdOffset == "*":\r
1278 NeedProcessVpdMapFile = True\r
1279 if self.Platform.VpdToolGuid == None or self.Platform.VpdToolGuid == '':\r
1280 EdkLogger.error("Build", FILE_NOT_FOUND, \\r
1281 "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
1282\r
1283\r
e56468c0 1284 #\r
1285 # Fix the PCDs define in VPD PCD section that never referenced by module.\r
1286 # An example is PCD for signature usage.\r
6780eef1
LG
1287 # \r
1288 for DscPcd in PlatformPcds:\r
61ee1dff 1289 DscPcdEntry = self._PlatformPcds[DscPcd]\r
e56468c0 1290 if DscPcdEntry.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD]:\r
1291 if not (self.Platform.VpdToolGuid == None or self.Platform.VpdToolGuid == ''):\r
1292 FoundFlag = False\r
1293 for VpdPcd in VpdFile._VpdArray.keys():\r
1294 # This PCD has been referenced by module\r
1295 if (VpdPcd.TokenSpaceGuidCName == DscPcdEntry.TokenSpaceGuidCName) and \\r
1296 (VpdPcd.TokenCName == DscPcdEntry.TokenCName):\r
1297 FoundFlag = True\r
47fea6af 1298\r
e56468c0 1299 # Not found, it should be signature\r
1300 if not FoundFlag :\r
1301 # just pick the a value to determine whether is unicode string type\r
e8a47801
LG
1302 for (SkuName,Sku) in DscPcdEntry.SkuInfoList.items():\r
1303 Sku.VpdOffset = Sku.VpdOffset.strip() \r
1304 \r
1305 # Need to iterate DEC pcd information to get the value & datumtype\r
1306 for eachDec in self.PackageList:\r
1307 for DecPcd in eachDec.Pcds:\r
1308 DecPcdEntry = eachDec.Pcds[DecPcd]\r
1309 if (DecPcdEntry.TokenSpaceGuidCName == DscPcdEntry.TokenSpaceGuidCName) and \\r
1310 (DecPcdEntry.TokenCName == DscPcdEntry.TokenCName):\r
1311 # Print warning message to let the developer make a determine.\r
1312 EdkLogger.warn("build", "Unreferenced vpd pcd used!",\r
1313 File=self.MetaFile, \\r
1314 ExtraData = "PCD: %s.%s used in the DSC file %s is unreferenced." \\r
1315 %(DscPcdEntry.TokenSpaceGuidCName, DscPcdEntry.TokenCName, self.Platform.MetaFile.Path)) \r
1316 \r
1317 DscPcdEntry.DatumType = DecPcdEntry.DatumType\r
1318 DscPcdEntry.DefaultValue = DecPcdEntry.DefaultValue\r
1319 DscPcdEntry.TokenValue = DecPcdEntry.TokenValue\r
1320 DscPcdEntry.TokenSpaceGuidValue = eachDec.Guids[DecPcdEntry.TokenSpaceGuidCName]\r
1321 # Only fix the value while no value provided in DSC file.\r
1322 if (Sku.DefaultValue == "" or Sku.DefaultValue==None):\r
1323 DscPcdEntry.SkuInfoList[DscPcdEntry.SkuInfoList.keys()[0]].DefaultValue = DecPcdEntry.DefaultValue\r
1324 \r
1325 if DscPcdEntry not in self._DynamicPcdList:\r
1326 self._DynamicPcdList.append(DscPcdEntry)\r
1327# Sku = DscPcdEntry.SkuInfoList[DscPcdEntry.SkuInfoList.keys()[0]]\r
1328 Sku.VpdOffset = Sku.VpdOffset.strip()\r
1329 PcdValue = Sku.DefaultValue\r
5a13737a
YZ
1330 if PcdValue == "":\r
1331 PcdValue = DscPcdEntry.DefaultValue\r
1332 if Sku.VpdOffset != '*':\r
1333 if PcdValue.startswith("{"):\r
1334 Alignment = 8\r
1335 elif PcdValue.startswith("L"):\r
1336 Alignment = 2\r
1337 else:\r
1338 Alignment = 1\r
ca85291f
YZ
1339 try:\r
1340 VpdOffset = int(Sku.VpdOffset)\r
1341 except:\r
1342 try:\r
1343 VpdOffset = int(Sku.VpdOffset, 16)\r
1344 except:\r
1345 EdkLogger.error("build", FORMAT_INVALID, "Invalid offset value %s for PCD %s.%s." % (Sku.VpdOffset, DscPcdEntry.TokenSpaceGuidCName, DscPcdEntry.TokenCName))\r
1346 if VpdOffset % Alignment != 0:\r
815ada26
YZ
1347 if PcdValue.startswith("{"):\r
1348 EdkLogger.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(DscPcdEntry.TokenSpaceGuidCName, DscPcdEntry.TokenCName), File=self.MetaFile)\r
1349 else:\r
1350 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
1351 VpdFile.Add(DscPcdEntry, Sku.VpdOffset)\r
1352 if not NeedProcessVpdMapFile and Sku.VpdOffset == "*":\r
1353 NeedProcessVpdMapFile = True \r
1354 if DscPcdEntry.DatumType == 'VOID*' and PcdValue.startswith("L"):\r
1355 UnicodePcdArray.append(DscPcdEntry)\r
1356 elif len(Sku.VariableName) > 0:\r
1357 HiiPcdArray.append(DscPcdEntry)\r
1358 else:\r
1359 OtherPcdArray.append(DscPcdEntry)\r
1360 \r
1361 # if the offset of a VPD is *, then it need to be fixed up by third party tool.\r
e56468c0 1362 \r
e56468c0 1363 \r
1364 \r
1365 if (self.Platform.FlashDefinition == None or self.Platform.FlashDefinition == '') and \\r
1366 VpdFile.GetCount() != 0:\r
1367 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE, \r
1368 "Fail to get FLASH_DEFINITION definition in DSC file %s which is required when DSC contains VPD PCD." % str(self.Platform.MetaFile))\r
47fea6af 1369\r
e56468c0 1370 if VpdFile.GetCount() != 0:\r
e56468c0 1371 FvPath = os.path.join(self.BuildDir, "FV")\r
1372 if not os.path.exists(FvPath):\r
1373 try:\r
1374 os.makedirs(FvPath)\r
1375 except:\r
1376 EdkLogger.error("build", FILE_WRITE_FAILURE, "Fail to create FV folder under %s" % self.BuildDir)\r
47fea6af 1377\r
08dd311f
LG
1378 VpdFilePath = os.path.join(FvPath, "%s.txt" % self.Platform.VpdToolGuid)\r
1379\r
e459de78 1380 if VpdFile.Write(VpdFilePath):\r
e56468c0 1381 # retrieve BPDG tool's path from tool_def.txt according to VPD_TOOL_GUID defined in DSC file.\r
1382 BPDGToolName = None\r
1383 for ToolDef in self.ToolDefinition.values():\r
1384 if ToolDef.has_key("GUID") and ToolDef["GUID"] == self.Platform.VpdToolGuid:\r
1385 if not ToolDef.has_key("PATH"):\r
1386 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE, "PATH attribute was not provided for BPDG guid tool %s in tools_def.txt" % self.Platform.VpdToolGuid)\r
1387 BPDGToolName = ToolDef["PATH"]\r
1388 break\r
1389 # Call third party GUID BPDG tool.\r
1390 if BPDGToolName != None:\r
08dd311f 1391 VpdInfoFile.CallExtenalBPDGTool(BPDGToolName, VpdFilePath)\r
e56468c0 1392 else:\r
1393 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 1394\r
e56468c0 1395 # Process VPD map file generated by third party BPDG tool\r
1396 if NeedProcessVpdMapFile:\r
08dd311f 1397 VpdMapFilePath = os.path.join(self.BuildDir, "FV", "%s.map" % self.Platform.VpdToolGuid)\r
e56468c0 1398 if os.path.exists(VpdMapFilePath):\r
1399 VpdFile.Read(VpdMapFilePath)\r
47fea6af 1400\r
e56468c0 1401 # Fixup "*" offset\r
1402 for Pcd in self._DynamicPcdList:\r
1403 # just pick the a value to determine whether is unicode string type\r
e8a47801
LG
1404 i = 0\r
1405 for (SkuName,Sku) in Pcd.SkuInfoList.items(): \r
1406 if Sku.VpdOffset == "*":\r
1407 Sku.VpdOffset = VpdFile.GetOffset(Pcd)[i].strip()\r
1408 i += 1\r
e56468c0 1409 else:\r
1410 EdkLogger.error("build", FILE_READ_FAILURE, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath)\r
47fea6af 1411\r
e56468c0 1412 # Delete the DynamicPcdList At the last time enter into this function \r
47fea6af 1413 del self._DynamicPcdList[:]\r
52302d4d
LG
1414 self._DynamicPcdList.extend(UnicodePcdArray)\r
1415 self._DynamicPcdList.extend(HiiPcdArray)\r
1416 self._DynamicPcdList.extend(OtherPcdArray)\r
a0a2cd1e 1417 self.AllPcdList = self._NonDynamicPcdList + self._DynamicPcdList\r
52302d4d
LG
1418 \r
1419 ## Return the platform build data object\r
1420 def _GetPlatform(self):\r
1421 if self._Platform == None:\r
0d2711a6 1422 self._Platform = self.BuildDatabase[self.MetaFile, self.Arch, self.BuildTarget, self.ToolChain]\r
52302d4d
LG
1423 return self._Platform\r
1424\r
1425 ## Return platform name\r
1426 def _GetName(self):\r
1427 return self.Platform.PlatformName\r
1428\r
1429 ## Return the meta file GUID\r
1430 def _GetGuid(self):\r
1431 return self.Platform.Guid\r
1432\r
1433 ## Return the platform version\r
1434 def _GetVersion(self):\r
1435 return self.Platform.Version\r
1436\r
1437 ## Return the FDF file name\r
1438 def _GetFdfFile(self):\r
1439 if self._FdfFile == None:\r
1440 if self.Workspace.FdfFile != "":\r
05cc51ad 1441 self._FdfFile= mws.join(self.WorkspaceDir, self.Workspace.FdfFile)\r
52302d4d
LG
1442 else:\r
1443 self._FdfFile = ''\r
1444 return self._FdfFile\r
1445\r
1446 ## Return the build output directory platform specifies\r
1447 def _GetOutputDir(self):\r
1448 return self.Platform.OutputDirectory\r
1449\r
1450 ## Return the directory to store all intermediate and final files built\r
1451 def _GetBuildDir(self):\r
1452 if self._BuildDir == None:\r
1453 if os.path.isabs(self.OutputDir):\r
1454 self._BuildDir = path.join(\r
1455 path.abspath(self.OutputDir),\r
1456 self.BuildTarget + "_" + self.ToolChain,\r
1457 )\r
1458 else:\r
1459 self._BuildDir = path.join(\r
1460 self.WorkspaceDir,\r
1461 self.OutputDir,\r
1462 self.BuildTarget + "_" + self.ToolChain,\r
1463 )\r
1464 return self._BuildDir\r
1465\r
1466 ## Return directory of platform makefile\r
1467 #\r
1468 # @retval string Makefile directory\r
1469 #\r
1470 def _GetMakeFileDir(self):\r
1471 if self._MakeFileDir == None:\r
1472 self._MakeFileDir = path.join(self.BuildDir, self.Arch)\r
1473 return self._MakeFileDir\r
1474\r
1475 ## Return build command string\r
1476 #\r
1477 # @retval string Build command string\r
1478 #\r
1479 def _GetBuildCommand(self):\r
1480 if self._BuildCommand == None:\r
1481 self._BuildCommand = []\r
1482 if "MAKE" in self.ToolDefinition and "PATH" in self.ToolDefinition["MAKE"]:\r
1483 self._BuildCommand += SplitOption(self.ToolDefinition["MAKE"]["PATH"])\r
1484 if "FLAGS" in self.ToolDefinition["MAKE"]:\r
1485 NewOption = self.ToolDefinition["MAKE"]["FLAGS"].strip()\r
1486 if NewOption != '':\r
6780eef1 1487 self._BuildCommand += SplitOption(NewOption)\r
52302d4d
LG
1488 return self._BuildCommand\r
1489\r
1490 ## Get tool chain definition\r
1491 #\r
1492 # Get each tool defition for given tool chain from tools_def.txt and platform\r
1493 #\r
1494 def _GetToolDefinition(self):\r
1495 if self._ToolDefinitions == None:\r
1496 ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDictionary\r
1497 if TAB_TOD_DEFINES_COMMAND_TYPE not in self.Workspace.ToolDef.ToolsDefTxtDatabase:\r
1498 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "No tools found in configuration",\r
1499 ExtraData="[%s]" % self.MetaFile)\r
1500 self._ToolDefinitions = {}\r
1501 DllPathList = set()\r
1502 for Def in ToolDefinition:\r
1503 Target, Tag, Arch, Tool, Attr = Def.split("_")\r
1504 if Target != self.BuildTarget or Tag != self.ToolChain or Arch != self.Arch:\r
1505 continue\r
1506\r
1507 Value = ToolDefinition[Def]\r
1508 # don't record the DLL\r
1509 if Attr == "DLL":\r
1510 DllPathList.add(Value)\r
1511 continue\r
1512\r
1513 if Tool not in self._ToolDefinitions:\r
1514 self._ToolDefinitions[Tool] = {}\r
1515 self._ToolDefinitions[Tool][Attr] = Value\r
1516\r
1517 ToolsDef = ''\r
1518 MakePath = ''\r
1519 if GlobalData.gOptions.SilentMode and "MAKE" in self._ToolDefinitions:\r
1520 if "FLAGS" not in self._ToolDefinitions["MAKE"]:\r
1521 self._ToolDefinitions["MAKE"]["FLAGS"] = ""\r
1522 self._ToolDefinitions["MAKE"]["FLAGS"] += " -s"\r
1523 MakeFlags = ''\r
1524 for Tool in self._ToolDefinitions:\r
1525 for Attr in self._ToolDefinitions[Tool]:\r
1526 Value = self._ToolDefinitions[Tool][Attr]\r
1527 if Tool in self.BuildOption and Attr in self.BuildOption[Tool]:\r
1528 # check if override is indicated\r
1529 if self.BuildOption[Tool][Attr].startswith('='):\r
1530 Value = self.BuildOption[Tool][Attr][1:]\r
1531 else:\r
1532 Value += " " + self.BuildOption[Tool][Attr]\r
1533\r
1534 if Attr == "PATH":\r
1535 # Don't put MAKE definition in the file\r
1536 if Tool == "MAKE":\r
1537 MakePath = Value\r
1538 else:\r
1539 ToolsDef += "%s = %s\n" % (Tool, Value)\r
1540 elif Attr != "DLL":\r
1541 # Don't put MAKE definition in the file\r
1542 if Tool == "MAKE":\r
1543 if Attr == "FLAGS":\r
1544 MakeFlags = Value\r
1545 else:\r
1546 ToolsDef += "%s_%s = %s\n" % (Tool, Attr, Value)\r
1547 ToolsDef += "\n"\r
1548\r
1549 SaveFileOnChange(self.ToolDefinitionFile, ToolsDef)\r
1550 for DllPath in DllPathList:\r
1551 os.environ["PATH"] = DllPath + os.pathsep + os.environ["PATH"]\r
1552 os.environ["MAKE_FLAGS"] = MakeFlags\r
1553\r
1554 return self._ToolDefinitions\r
1555\r
1556 ## Return the paths of tools\r
1557 def _GetToolDefFile(self):\r
1558 if self._ToolDefFile == None:\r
1559 self._ToolDefFile = os.path.join(self.MakeFileDir, "TOOLS_DEF." + self.Arch)\r
1560 return self._ToolDefFile\r
1561\r
1562 ## Retrieve the toolchain family of given toolchain tag. Default to 'MSFT'.\r
1563 def _GetToolChainFamily(self):\r
1564 if self._ToolChainFamily == None:\r
1565 ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDatabase\r
1566 if TAB_TOD_DEFINES_FAMILY not in ToolDefinition \\r
1567 or self.ToolChain not in ToolDefinition[TAB_TOD_DEFINES_FAMILY] \\r
1568 or not ToolDefinition[TAB_TOD_DEFINES_FAMILY][self.ToolChain]:\r
1569 EdkLogger.verbose("No tool chain family found in configuration for %s. Default to MSFT." \\r
1570 % self.ToolChain)\r
1571 self._ToolChainFamily = "MSFT"\r
1572 else:\r
1573 self._ToolChainFamily = ToolDefinition[TAB_TOD_DEFINES_FAMILY][self.ToolChain]\r
1574 return self._ToolChainFamily\r
1575\r
1576 def _GetBuildRuleFamily(self):\r
1577 if self._BuildRuleFamily == None:\r
1578 ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDatabase\r
1579 if TAB_TOD_DEFINES_BUILDRULEFAMILY not in ToolDefinition \\r
1580 or self.ToolChain not in ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY] \\r
1581 or not ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY][self.ToolChain]:\r
1582 EdkLogger.verbose("No tool chain family found in configuration for %s. Default to MSFT." \\r
1583 % self.ToolChain)\r
1584 self._BuildRuleFamily = "MSFT"\r
1585 else:\r
1586 self._BuildRuleFamily = ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY][self.ToolChain]\r
1587 return self._BuildRuleFamily\r
1588\r
1589 ## Return the build options specific for all modules in this platform\r
1590 def _GetBuildOptions(self):\r
1591 if self._BuildOption == None:\r
1592 self._BuildOption = self._ExpandBuildOption(self.Platform.BuildOptions)\r
1593 return self._BuildOption\r
1594\r
1595 ## Return the build options specific for EDK modules in this platform\r
1596 def _GetEdkBuildOptions(self):\r
1597 if self._EdkBuildOption == None:\r
1598 self._EdkBuildOption = self._ExpandBuildOption(self.Platform.BuildOptions, EDK_NAME)\r
1599 return self._EdkBuildOption\r
1600\r
1601 ## Return the build options specific for EDKII modules in this platform\r
1602 def _GetEdkIIBuildOptions(self):\r
1603 if self._EdkIIBuildOption == None:\r
1604 self._EdkIIBuildOption = self._ExpandBuildOption(self.Platform.BuildOptions, EDKII_NAME)\r
1605 return self._EdkIIBuildOption\r
1606\r
97fa0ee9 1607 ## Parse build_rule.txt in Conf Directory.\r
52302d4d
LG
1608 #\r
1609 # @retval BuildRule object\r
1610 #\r
1611 def _GetBuildRule(self):\r
1612 if self._BuildRule == None:\r
1613 BuildRuleFile = None\r
1614 if TAB_TAT_DEFINES_BUILD_RULE_CONF in self.Workspace.TargetTxt.TargetTxtDictionary:\r
1615 BuildRuleFile = self.Workspace.TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_BUILD_RULE_CONF]\r
1616 if BuildRuleFile in [None, '']:\r
97fa0ee9 1617 BuildRuleFile = gDefaultBuildRuleFile\r
52302d4d 1618 self._BuildRule = BuildRule(BuildRuleFile)\r
64b2609f
LG
1619 if self._BuildRule._FileVersion == "":\r
1620 self._BuildRule._FileVersion = AutoGenReqBuildRuleVerNum\r
1621 else:\r
1622 if self._BuildRule._FileVersion < AutoGenReqBuildRuleVerNum :\r
1623 # If Build Rule's version is less than the version number required by the tools, halting the build.\r
47fea6af 1624 EdkLogger.error("build", AUTOGEN_ERROR,\r
64b2609f
LG
1625 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
1626 % (self._BuildRule._FileVersion, AutoGenReqBuildRuleVerNum))\r
47fea6af 1627\r
52302d4d
LG
1628 return self._BuildRule\r
1629\r
1630 ## Summarize the packages used by modules in this platform\r
1631 def _GetPackageList(self):\r
1632 if self._PackageList == None:\r
1633 self._PackageList = set()\r
1634 for La in self.LibraryAutoGenList:\r
1635 self._PackageList.update(La.DependentPackageList)\r
1636 for Ma in self.ModuleAutoGenList:\r
1637 self._PackageList.update(Ma.DependentPackageList)\r
a0a2cd1e
FB
1638 #Collect package set information from INF of FDF\r
1639 PkgSet = set()\r
1640 for ModuleFile in self._AsBuildModuleList:\r
1641 if ModuleFile in self.Platform.Modules:\r
1642 continue\r
1643 ModuleData = self.BuildDatabase[ModuleFile, self.Arch, self.BuildTarget, self.ToolChain]\r
1644 PkgSet.update(ModuleData.Packages)\r
1645 self._PackageList = list(self._PackageList) + list (PkgSet)\r
52302d4d
LG
1646 return self._PackageList\r
1647\r
2bc3256c
LG
1648 def _GetNonDynamicPcdDict(self):\r
1649 if self._NonDynamicPcdDict:\r
1650 return self._NonDynamicPcdDict\r
1651 for Pcd in self.NonDynamicPcdList:\r
1652 self._NonDynamicPcdDict[(Pcd.TokenCName,Pcd.TokenSpaceGuidCName)] = Pcd\r
1653 return self._NonDynamicPcdDict\r
1654\r
52302d4d
LG
1655 ## Get list of non-dynamic PCDs\r
1656 def _GetNonDynamicPcdList(self):\r
e56468c0 1657 if self._NonDynamicPcdList == None:\r
1658 self.CollectPlatformDynamicPcds()\r
52302d4d
LG
1659 return self._NonDynamicPcdList\r
1660\r
1661 ## Get list of dynamic PCDs\r
1662 def _GetDynamicPcdList(self):\r
e56468c0 1663 if self._DynamicPcdList == None:\r
1664 self.CollectPlatformDynamicPcds()\r
52302d4d
LG
1665 return self._DynamicPcdList\r
1666\r
1667 ## Generate Token Number for all PCD\r
1668 def _GetPcdTokenNumbers(self):\r
1669 if self._PcdTokenNumber == None:\r
1670 self._PcdTokenNumber = sdict()\r
1671 TokenNumber = 1\r
d0acc87a
LG
1672 #\r
1673 # Make the Dynamic and DynamicEx PCD use within different TokenNumber area. \r
1674 # Such as:\r
1675 # \r
1676 # Dynamic PCD:\r
1677 # TokenNumber 0 ~ 10\r
1678 # DynamicEx PCD:\r
1679 # TokeNumber 11 ~ 20\r
1680 #\r
52302d4d
LG
1681 for Pcd in self.DynamicPcdList:\r
1682 if Pcd.Phase == "PEI":\r
d0acc87a
LG
1683 if Pcd.Type in ["Dynamic", "DynamicDefault", "DynamicVpd", "DynamicHii"]:\r
1684 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))\r
1685 self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber\r
1686 TokenNumber += 1\r
47fea6af 1687\r
d0acc87a
LG
1688 for Pcd in self.DynamicPcdList:\r
1689 if Pcd.Phase == "PEI":\r
1690 if Pcd.Type in ["DynamicEx", "DynamicExDefault", "DynamicExVpd", "DynamicExHii"]:\r
1691 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))\r
1692 self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber\r
1693 TokenNumber += 1\r
47fea6af 1694\r
52302d4d
LG
1695 for Pcd in self.DynamicPcdList:\r
1696 if Pcd.Phase == "DXE":\r
d0acc87a
LG
1697 if Pcd.Type in ["Dynamic", "DynamicDefault", "DynamicVpd", "DynamicHii"]:\r
1698 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))\r
1699 self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber\r
1700 TokenNumber += 1\r
47fea6af 1701\r
d0acc87a
LG
1702 for Pcd in self.DynamicPcdList:\r
1703 if Pcd.Phase == "DXE":\r
1704 if Pcd.Type in ["DynamicEx", "DynamicExDefault", "DynamicExVpd", "DynamicExHii"]:\r
1705 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))\r
1706 self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber\r
1707 TokenNumber += 1\r
47fea6af 1708\r
52302d4d
LG
1709 for Pcd in self.NonDynamicPcdList:\r
1710 self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber\r
1711 TokenNumber += 1\r
1712 return self._PcdTokenNumber\r
1713\r
1714 ## Summarize ModuleAutoGen objects of all modules/libraries to be built for this platform\r
1715 def _GetAutoGenObjectList(self):\r
1716 self._ModuleAutoGenList = []\r
1717 self._LibraryAutoGenList = []\r
1718 for ModuleFile in self.Platform.Modules:\r
1719 Ma = ModuleAutoGen(\r
1720 self.Workspace,\r
1721 ModuleFile,\r
1722 self.BuildTarget,\r
1723 self.ToolChain,\r
1724 self.Arch,\r
1725 self.MetaFile\r
1726 )\r
1727 if Ma not in self._ModuleAutoGenList:\r
1728 self._ModuleAutoGenList.append(Ma)\r
1729 for La in Ma.LibraryAutoGenList:\r
1730 if La not in self._LibraryAutoGenList:\r
1731 self._LibraryAutoGenList.append(La)\r
2bc3256c
LG
1732 if Ma not in La._ReferenceModules:\r
1733 La._ReferenceModules.append(Ma)\r
52302d4d
LG
1734\r
1735 ## Summarize ModuleAutoGen objects of all modules to be built for this platform\r
1736 def _GetModuleAutoGenList(self):\r
1737 if self._ModuleAutoGenList == None:\r
1738 self._GetAutoGenObjectList()\r
1739 return self._ModuleAutoGenList\r
1740\r
1741 ## Summarize ModuleAutoGen objects of all libraries to be built for this platform\r
1742 def _GetLibraryAutoGenList(self):\r
1743 if self._LibraryAutoGenList == None:\r
1744 self._GetAutoGenObjectList()\r
1745 return self._LibraryAutoGenList\r
1746\r
1747 ## Test if a module is supported by the platform\r
1748 #\r
1749 # An error will be raised directly if the module or its arch is not supported\r
1750 # by the platform or current configuration\r
1751 #\r
1752 def ValidModule(self, Module):\r
a0a2cd1e
FB
1753 return Module in self.Platform.Modules or Module in self.Platform.LibraryInstances \\r
1754 or Module in self._AsBuildModuleList\r
52302d4d
LG
1755\r
1756 ## Resolve the library classes in a module to library instances\r
1757 #\r
1758 # This method will not only resolve library classes but also sort the library\r
1759 # instances according to the dependency-ship.\r
1760 #\r
1761 # @param Module The module from which the library classes will be resolved\r
1762 #\r
1763 # @retval library_list List of library instances sorted\r
1764 #\r
1765 def ApplyLibraryInstance(self, Module):\r
1766 ModuleType = Module.ModuleType\r
1767\r
1768 # for overridding library instances with module specific setting\r
1769 PlatformModule = self.Platform.Modules[str(Module)]\r
1770\r
1771 # add forced library instances (specified under LibraryClasses sections)\r
da92f276
LG
1772 #\r
1773 # If a module has a MODULE_TYPE of USER_DEFINED,\r
1774 # do not link in NULL library class instances from the global [LibraryClasses.*] sections.\r
1775 #\r
1776 if Module.ModuleType != SUP_MODULE_USER_DEFINED:\r
1777 for LibraryClass in self.Platform.LibraryClasses.GetKeys():\r
1778 if LibraryClass.startswith("NULL") and self.Platform.LibraryClasses[LibraryClass, Module.ModuleType]:\r
1779 Module.LibraryClasses[LibraryClass] = self.Platform.LibraryClasses[LibraryClass, Module.ModuleType]\r
52302d4d
LG
1780\r
1781 # add forced library instances (specified in module overrides)\r
1782 for LibraryClass in PlatformModule.LibraryClasses:\r
1783 if LibraryClass.startswith("NULL"):\r
1784 Module.LibraryClasses[LibraryClass] = PlatformModule.LibraryClasses[LibraryClass]\r
1785\r
b36d134f 1786 # EdkII module\r
52302d4d
LG
1787 LibraryConsumerList = [Module]\r
1788 Constructor = []\r
1789 ConsumedByList = sdict()\r
1790 LibraryInstance = sdict()\r
1791\r
1792 EdkLogger.verbose("")\r
1793 EdkLogger.verbose("Library instances of module [%s] [%s]:" % (str(Module), self.Arch))\r
1794 while len(LibraryConsumerList) > 0:\r
1795 M = LibraryConsumerList.pop()\r
1796 for LibraryClassName in M.LibraryClasses:\r
1797 if LibraryClassName not in LibraryInstance:\r
1798 # override library instance for this module\r
1799 if LibraryClassName in PlatformModule.LibraryClasses:\r
1800 LibraryPath = PlatformModule.LibraryClasses[LibraryClassName]\r
1801 else:\r
1802 LibraryPath = self.Platform.LibraryClasses[LibraryClassName, ModuleType]\r
1803 if LibraryPath == None or LibraryPath == "":\r
1804 LibraryPath = M.LibraryClasses[LibraryClassName]\r
1805 if LibraryPath == None or LibraryPath == "":\r
1806 EdkLogger.error("build", RESOURCE_NOT_AVAILABLE,\r
1807 "Instance of library class [%s] is not found" % LibraryClassName,\r
1808 File=self.MetaFile,\r
1809 ExtraData="in [%s] [%s]\n\tconsumed by module [%s]" % (str(M), self.Arch, str(Module)))\r
1810\r
0d2711a6 1811 LibraryModule = self.BuildDatabase[LibraryPath, self.Arch, self.BuildTarget, self.ToolChain]\r
52302d4d
LG
1812 # for those forced library instance (NULL library), add a fake library class\r
1813 if LibraryClassName.startswith("NULL"):\r
1814 LibraryModule.LibraryClass.append(LibraryClassObject(LibraryClassName, [ModuleType]))\r
1815 elif LibraryModule.LibraryClass == None \\r
1816 or len(LibraryModule.LibraryClass) == 0 \\r
1817 or (ModuleType != 'USER_DEFINED'\r
1818 and ModuleType not in LibraryModule.LibraryClass[0].SupModList):\r
1819 # only USER_DEFINED can link against any library instance despite of its SupModList\r
1820 EdkLogger.error("build", OPTION_MISSING,\r
1821 "Module type [%s] is not supported by library instance [%s]" \\r
1822 % (ModuleType, LibraryPath), File=self.MetaFile,\r
1823 ExtraData="consumed by [%s]" % str(Module))\r
1824\r
1825 LibraryInstance[LibraryClassName] = LibraryModule\r
1826 LibraryConsumerList.append(LibraryModule)\r
1827 EdkLogger.verbose("\t" + str(LibraryClassName) + " : " + str(LibraryModule))\r
1828 else:\r
1829 LibraryModule = LibraryInstance[LibraryClassName]\r
1830\r
1831 if LibraryModule == None:\r
1832 continue\r
1833\r
1834 if LibraryModule.ConstructorList != [] and LibraryModule not in Constructor:\r
1835 Constructor.append(LibraryModule)\r
1836\r
1837 if LibraryModule not in ConsumedByList:\r
1838 ConsumedByList[LibraryModule] = []\r
1839 # don't add current module itself to consumer list\r
1840 if M != Module:\r
1841 if M in ConsumedByList[LibraryModule]:\r
1842 continue\r
1843 ConsumedByList[LibraryModule].append(M)\r
1844 #\r
1845 # Initialize the sorted output list to the empty set\r
1846 #\r
1847 SortedLibraryList = []\r
1848 #\r
1849 # Q <- Set of all nodes with no incoming edges\r
1850 #\r
1851 LibraryList = [] #LibraryInstance.values()\r
1852 Q = []\r
1853 for LibraryClassName in LibraryInstance:\r
1854 M = LibraryInstance[LibraryClassName]\r
1855 LibraryList.append(M)\r
1856 if ConsumedByList[M] == []:\r
1857 Q.append(M)\r
1858\r
1859 #\r
1860 # start the DAG algorithm\r
1861 #\r
1862 while True:\r
1863 EdgeRemoved = True\r
1864 while Q == [] and EdgeRemoved:\r
1865 EdgeRemoved = False\r
1866 # for each node Item with a Constructor\r
1867 for Item in LibraryList:\r
1868 if Item not in Constructor:\r
1869 continue\r
1870 # for each Node without a constructor with an edge e from Item to Node\r
1871 for Node in ConsumedByList[Item]:\r
1872 if Node in Constructor:\r
1873 continue\r
1874 # remove edge e from the graph if Node has no constructor\r
1875 ConsumedByList[Item].remove(Node)\r
1876 EdgeRemoved = True\r
1877 if ConsumedByList[Item] == []:\r
1878 # insert Item into Q\r
1879 Q.insert(0, Item)\r
1880 break\r
1881 if Q != []:\r
1882 break\r
1883 # DAG is done if there's no more incoming edge for all nodes\r
1884 if Q == []:\r
1885 break\r
1886\r
1887 # remove node from Q\r
1888 Node = Q.pop()\r
1889 # output Node\r
1890 SortedLibraryList.append(Node)\r
1891\r
1892 # for each node Item with an edge e from Node to Item do\r
1893 for Item in LibraryList:\r
1894 if Node not in ConsumedByList[Item]:\r
1895 continue\r
1896 # remove edge e from the graph\r
1897 ConsumedByList[Item].remove(Node)\r
1898\r
1899 if ConsumedByList[Item] != []:\r
1900 continue\r
1901 # insert Item into Q, if Item has no other incoming edges\r
1902 Q.insert(0, Item)\r
1903\r
1904 #\r
1905 # if any remaining node Item in the graph has a constructor and an incoming edge, then the graph has a cycle\r
1906 #\r
1907 for Item in LibraryList:\r
1908 if ConsumedByList[Item] != [] and Item in Constructor and len(Constructor) > 1:\r
1909 ErrorMessage = "\tconsumed by " + "\n\tconsumed by ".join([str(L) for L in ConsumedByList[Item]])\r
1910 EdkLogger.error("build", BUILD_ERROR, 'Library [%s] with constructors has a cycle' % str(Item),\r
1911 ExtraData=ErrorMessage, File=self.MetaFile)\r
1912 if Item not in SortedLibraryList:\r
1913 SortedLibraryList.append(Item)\r
1914\r
1915 #\r
1916 # Build the list of constructor and destructir names\r
1917 # The DAG Topo sort produces the destructor order, so the list of constructors must generated in the reverse order\r
1918 #\r
1919 SortedLibraryList.reverse()\r
1920 return SortedLibraryList\r
1921\r
1922\r
1923 ## Override PCD setting (type, value, ...)\r
1924 #\r
1925 # @param ToPcd The PCD to be overrided\r
1926 # @param FromPcd The PCD overrideing from\r
1927 #\r
1928 def _OverridePcd(self, ToPcd, FromPcd, Module=""):\r
1929 #\r
1930 # in case there's PCDs coming from FDF file, which have no type given.\r
1931 # at this point, ToPcd.Type has the type found from dependent\r
1932 # package\r
1933 #\r
1934 if FromPcd != None:\r
1935 if ToPcd.Pending and FromPcd.Type not in [None, '']:\r
1936 ToPcd.Type = FromPcd.Type\r
e56468c0 1937 elif (ToPcd.Type not in [None, '']) and (FromPcd.Type not in [None, ''])\\r
1938 and (ToPcd.Type != FromPcd.Type) and (ToPcd.Type in FromPcd.Type):\r
1939 if ToPcd.Type.strip() == "DynamicEx":\r
47fea6af 1940 ToPcd.Type = FromPcd.Type\r
52302d4d
LG
1941 elif ToPcd.Type not in [None, ''] and FromPcd.Type not in [None, ''] \\r
1942 and ToPcd.Type != FromPcd.Type:\r
1943 EdkLogger.error("build", OPTION_CONFLICT, "Mismatched PCD type",\r
1944 ExtraData="%s.%s is defined as [%s] in module %s, but as [%s] in platform."\\r
1945 % (ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName,\r
1946 ToPcd.Type, Module, FromPcd.Type),\r
1947 File=self.MetaFile)\r
1948\r
1949 if FromPcd.MaxDatumSize not in [None, '']:\r
1950 ToPcd.MaxDatumSize = FromPcd.MaxDatumSize\r
1951 if FromPcd.DefaultValue not in [None, '']:\r
1952 ToPcd.DefaultValue = FromPcd.DefaultValue\r
1953 if FromPcd.TokenValue not in [None, '']:\r
1954 ToPcd.TokenValue = FromPcd.TokenValue\r
1955 if FromPcd.MaxDatumSize not in [None, '']:\r
1956 ToPcd.MaxDatumSize = FromPcd.MaxDatumSize\r
1957 if FromPcd.DatumType not in [None, '']:\r
1958 ToPcd.DatumType = FromPcd.DatumType\r
1959 if FromPcd.SkuInfoList not in [None, '', []]:\r
1960 ToPcd.SkuInfoList = FromPcd.SkuInfoList\r
1961\r
1962 # check the validation of datum\r
1963 IsValid, Cause = CheckPcdDatum(ToPcd.DatumType, ToPcd.DefaultValue)\r
1964 if not IsValid:\r
1965 EdkLogger.error('build', FORMAT_INVALID, Cause, File=self.MetaFile,\r
1966 ExtraData="%s.%s" % (ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName))\r
82a6a960
BF
1967 ToPcd.validateranges = FromPcd.validateranges\r
1968 ToPcd.validlists = FromPcd.validlists\r
1969 ToPcd.expressions = FromPcd.expressions\r
52302d4d
LG
1970\r
1971 if ToPcd.DatumType == "VOID*" and ToPcd.MaxDatumSize in ['', None]:\r
1972 EdkLogger.debug(EdkLogger.DEBUG_9, "No MaxDatumSize specified for PCD %s.%s" \\r
1973 % (ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName))\r
1974 Value = ToPcd.DefaultValue\r
1975 if Value in [None, '']:\r
e8a47801 1976 ToPcd.MaxDatumSize = '1'\r
52302d4d 1977 elif Value[0] == 'L':\r
e8a47801 1978 ToPcd.MaxDatumSize = str((len(Value) - 2) * 2)\r
52302d4d
LG
1979 elif Value[0] == '{':\r
1980 ToPcd.MaxDatumSize = str(len(Value.split(',')))\r
1981 else:\r
e8a47801 1982 ToPcd.MaxDatumSize = str(len(Value) - 1)\r
52302d4d
LG
1983\r
1984 # apply default SKU for dynamic PCDS if specified one is not available\r
1985 if (ToPcd.Type in PCD_DYNAMIC_TYPE_LIST or ToPcd.Type in PCD_DYNAMIC_EX_TYPE_LIST) \\r
1986 and ToPcd.SkuInfoList in [None, {}, '']:\r
1987 if self.Platform.SkuName in self.Platform.SkuIds:\r
1988 SkuName = self.Platform.SkuName\r
1989 else:\r
1990 SkuName = 'DEFAULT'\r
1991 ToPcd.SkuInfoList = {\r
1992 SkuName : SkuInfoClass(SkuName, self.Platform.SkuIds[SkuName], '', '', '', '', '', ToPcd.DefaultValue)\r
1993 }\r
1994\r
1995 ## Apply PCD setting defined platform to a module\r
1996 #\r
1997 # @param Module The module from which the PCD setting will be overrided\r
1998 #\r
1999 # @retval PCD_list The list PCDs with settings from platform\r
2000 #\r
2001 def ApplyPcdSetting(self, Module, Pcds):\r
2002 # for each PCD in module\r
47fea6af
YZ
2003 for Name, Guid in Pcds:\r
2004 PcdInModule = Pcds[Name, Guid]\r
52302d4d 2005 # find out the PCD setting in platform\r
47fea6af
YZ
2006 if (Name, Guid) in self.Platform.Pcds:\r
2007 PcdInPlatform = self.Platform.Pcds[Name, Guid]\r
52302d4d
LG
2008 else:\r
2009 PcdInPlatform = None\r
2010 # then override the settings if any\r
2011 self._OverridePcd(PcdInModule, PcdInPlatform, Module)\r
2012 # resolve the VariableGuid value\r
2013 for SkuId in PcdInModule.SkuInfoList:\r
2014 Sku = PcdInModule.SkuInfoList[SkuId]\r
2015 if Sku.VariableGuid == '': continue\r
2016 Sku.VariableGuidValue = GuidValue(Sku.VariableGuid, self.PackageList)\r
2017 if Sku.VariableGuidValue == None:\r
2018 PackageList = "\n\t".join([str(P) for P in self.PackageList])\r
2019 EdkLogger.error(\r
2020 'build',\r
2021 RESOURCE_NOT_AVAILABLE,\r
2022 "Value of GUID [%s] is not found in" % Sku.VariableGuid,\r
2023 ExtraData=PackageList + "\n\t(used with %s.%s from module %s)" \\r
2024 % (Guid, Name, str(Module)),\r
2025 File=self.MetaFile\r
2026 )\r
2027\r
2028 # override PCD settings with module specific setting\r
2029 if Module in self.Platform.Modules:\r
2030 PlatformModule = self.Platform.Modules[str(Module)]\r
2031 for Key in PlatformModule.Pcds:\r
2032 if Key in Pcds:\r
2033 self._OverridePcd(Pcds[Key], PlatformModule.Pcds[Key], Module)\r
2034 return Pcds.values()\r
2035\r
2036 ## Resolve library names to library modules\r
2037 #\r
b36d134f 2038 # (for Edk.x modules)\r
52302d4d
LG
2039 #\r
2040 # @param Module The module from which the library names will be resolved\r
2041 #\r
2042 # @retval library_list The list of library modules\r
2043 #\r
2044 def ResolveLibraryReference(self, Module):\r
2045 EdkLogger.verbose("")\r
2046 EdkLogger.verbose("Library instances of module [%s] [%s]:" % (str(Module), self.Arch))\r
2047 LibraryConsumerList = [Module]\r
2048\r
b36d134f 2049 # "CompilerStub" is a must for Edk modules\r
52302d4d
LG
2050 if Module.Libraries:\r
2051 Module.Libraries.append("CompilerStub")\r
2052 LibraryList = []\r
2053 while len(LibraryConsumerList) > 0:\r
2054 M = LibraryConsumerList.pop()\r
2055 for LibraryName in M.Libraries:\r
2056 Library = self.Platform.LibraryClasses[LibraryName, ':dummy:']\r
2057 if Library == None:\r
2058 for Key in self.Platform.LibraryClasses.data.keys():\r
2059 if LibraryName.upper() == Key.upper():\r
2060 Library = self.Platform.LibraryClasses[Key, ':dummy:']\r
2061 break\r
2062 if Library == None:\r
2063 EdkLogger.warn("build", "Library [%s] is not found" % LibraryName, File=str(M),\r
2064 ExtraData="\t%s [%s]" % (str(Module), self.Arch))\r
2065 continue\r
2066\r
2067 if Library not in LibraryList:\r
2068 LibraryList.append(Library)\r
2069 LibraryConsumerList.append(Library)\r
2070 EdkLogger.verbose("\t" + LibraryName + " : " + str(Library) + ' ' + str(type(Library)))\r
2071 return LibraryList\r
2072\r
6780eef1
LG
2073 ## Calculate the priority value of the build option\r
2074 #\r
2075 # @param Key Build option definition contain: TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE\r
2076 #\r
2077 # @retval Value Priority value based on the priority list.\r
2078 #\r
2079 def CalculatePriorityValue(self, Key):\r
47fea6af
YZ
2080 Target, ToolChain, Arch, CommandType, Attr = Key.split('_')\r
2081 PriorityValue = 0x11111\r
6780eef1
LG
2082 if Target == "*":\r
2083 PriorityValue &= 0x01111\r
2084 if ToolChain == "*":\r
2085 PriorityValue &= 0x10111\r
2086 if Arch == "*":\r
2087 PriorityValue &= 0x11011\r
2088 if CommandType == "*":\r
2089 PriorityValue &= 0x11101\r
2090 if Attr == "*":\r
2091 PriorityValue &= 0x11110\r
47fea6af
YZ
2092\r
2093 return self.PrioList["0x%0.5x" % PriorityValue]\r
2094\r
6780eef1 2095\r
52302d4d
LG
2096 ## Expand * in build option key\r
2097 #\r
2098 # @param Options Options to be expanded\r
2099 #\r
2100 # @retval options Options expanded\r
6780eef1 2101 # \r
52302d4d
LG
2102 def _ExpandBuildOption(self, Options, ModuleStyle=None):\r
2103 BuildOptions = {}\r
2104 FamilyMatch = False\r
2105 FamilyIsNull = True\r
47fea6af 2106\r
6780eef1
LG
2107 OverrideList = {}\r
2108 #\r
2109 # Construct a list contain the build options which need override.\r
2110 #\r
2111 for Key in Options:\r
2112 #\r
2113 # Key[0] -- tool family\r
2114 # Key[1] -- TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE\r
2115 #\r
1ba5124e
YL
2116 if (Key[0] == self.BuildRuleFamily and\r
2117 (ModuleStyle == None or len(Key) < 3 or (len(Key) > 2 and Key[2] == ModuleStyle))):\r
6780eef1
LG
2118 Target, ToolChain, Arch, CommandType, Attr = Key[1].split('_')\r
2119 if Target == self.BuildTarget or Target == "*":\r
2120 if ToolChain == self.ToolChain or ToolChain == "*":\r
2121 if Arch == self.Arch or Arch == "*":\r
2122 if Options[Key].startswith("="):\r
47fea6af 2123 if OverrideList.get(Key[1]) != None:\r
6780eef1
LG
2124 OverrideList.pop(Key[1])\r
2125 OverrideList[Key[1]] = Options[Key]\r
2126 \r
2127 #\r
2128 # Use the highest priority value. \r
2129 #\r
2130 if (len(OverrideList) >= 2):\r
47fea6af 2131 KeyList = OverrideList.keys()\r
6780eef1 2132 for Index in range(len(KeyList)):\r
47fea6af 2133 NowKey = KeyList[Index]\r
6780eef1
LG
2134 Target1, ToolChain1, Arch1, CommandType1, Attr1 = NowKey.split("_")\r
2135 for Index1 in range(len(KeyList) - Index - 1):\r
2136 NextKey = KeyList[Index1 + Index + 1]\r
2137 #\r
2138 # Compare two Key, if one is included by another, choose the higher priority one\r
2139 # \r
2140 Target2, ToolChain2, Arch2, CommandType2, Attr2 = NextKey.split("_")\r
2141 if Target1 == Target2 or Target1 == "*" or Target2 == "*":\r
2142 if ToolChain1 == ToolChain2 or ToolChain1 == "*" or ToolChain2 == "*":\r
2143 if Arch1 == Arch2 or Arch1 == "*" or Arch2 == "*":\r
2144 if CommandType1 == CommandType2 or CommandType1 == "*" or CommandType2 == "*":\r
2145 if Attr1 == Attr2 or Attr1 == "*" or Attr2 == "*":\r
2146 if self.CalculatePriorityValue(NowKey) > self.CalculatePriorityValue(NextKey):\r
47fea6af 2147 if Options.get((self.BuildRuleFamily, NextKey)) != None:\r
6780eef1
LG
2148 Options.pop((self.BuildRuleFamily, NextKey))\r
2149 else:\r
47fea6af 2150 if Options.get((self.BuildRuleFamily, NowKey)) != None:\r
6780eef1
LG
2151 Options.pop((self.BuildRuleFamily, NowKey))\r
2152 \r
52302d4d
LG
2153 for Key in Options:\r
2154 if ModuleStyle != None and len (Key) > 2:\r
2155 # Check Module style is EDK or EDKII.\r
2156 # Only append build option for the matched style module.\r
2157 if ModuleStyle == EDK_NAME and Key[2] != EDK_NAME:\r
2158 continue\r
2159 elif ModuleStyle == EDKII_NAME and Key[2] != EDKII_NAME:\r
2160 continue\r
2161 Family = Key[0]\r
2162 Target, Tag, Arch, Tool, Attr = Key[1].split("_")\r
2163 # if tool chain family doesn't match, skip it\r
2164 if Tool in self.ToolDefinition and Family != "":\r
2165 FamilyIsNull = False\r
2166 if self.ToolDefinition[Tool].get(TAB_TOD_DEFINES_BUILDRULEFAMILY, "") != "":\r
2167 if Family != self.ToolDefinition[Tool][TAB_TOD_DEFINES_BUILDRULEFAMILY]:\r
2168 continue\r
2169 elif Family != self.ToolDefinition[Tool][TAB_TOD_DEFINES_FAMILY]:\r
2170 continue\r
2171 FamilyMatch = True\r
2172 # expand any wildcard\r
2173 if Target == "*" or Target == self.BuildTarget:\r
2174 if Tag == "*" or Tag == self.ToolChain:\r
2175 if Arch == "*" or Arch == self.Arch:\r
2176 if Tool not in BuildOptions:\r
2177 BuildOptions[Tool] = {}\r
5015bee2 2178 if Attr != "FLAGS" or Attr not in BuildOptions[Tool] or Options[Key].startswith('='):\r
52302d4d
LG
2179 BuildOptions[Tool][Attr] = Options[Key]\r
2180 else:\r
2181 # append options for the same tool\r
2182 BuildOptions[Tool][Attr] += " " + Options[Key]\r
2183 # Build Option Family has been checked, which need't to be checked again for family.\r
2184 if FamilyMatch or FamilyIsNull:\r
2185 return BuildOptions\r
1ba5124e 2186\r
52302d4d
LG
2187 for Key in Options:\r
2188 if ModuleStyle != None and len (Key) > 2:\r
2189 # Check Module style is EDK or EDKII.\r
2190 # Only append build option for the matched style module.\r
2191 if ModuleStyle == EDK_NAME and Key[2] != EDK_NAME:\r
2192 continue\r
2193 elif ModuleStyle == EDKII_NAME and Key[2] != EDKII_NAME:\r
2194 continue\r
2195 Family = Key[0]\r
2196 Target, Tag, Arch, Tool, Attr = Key[1].split("_")\r
2197 # if tool chain family doesn't match, skip it\r
47fea6af 2198 if Tool not in self.ToolDefinition or Family == "":\r
52302d4d
LG
2199 continue\r
2200 # option has been added before\r
2201 if Family != self.ToolDefinition[Tool][TAB_TOD_DEFINES_FAMILY]:\r
2202 continue\r
2203\r
2204 # expand any wildcard\r
2205 if Target == "*" or Target == self.BuildTarget:\r
2206 if Tag == "*" or Tag == self.ToolChain:\r
2207 if Arch == "*" or Arch == self.Arch:\r
2208 if Tool not in BuildOptions:\r
2209 BuildOptions[Tool] = {}\r
5015bee2 2210 if Attr != "FLAGS" or Attr not in BuildOptions[Tool] or Options[Key].startswith('='):\r
52302d4d
LG
2211 BuildOptions[Tool][Attr] = Options[Key]\r
2212 else:\r
2213 # append options for the same tool\r
2214 BuildOptions[Tool][Attr] += " " + Options[Key]\r
2215 return BuildOptions\r
2216\r
2217 ## Append build options in platform to a module\r
2218 #\r
2219 # @param Module The module to which the build options will be appened\r
2220 #\r
2221 # @retval options The options appended with build options in platform\r
2222 #\r
2223 def ApplyBuildOption(self, Module):\r
2224 # Get the different options for the different style module\r
2225 if Module.AutoGenVersion < 0x00010005:\r
2226 PlatformOptions = self.EdkBuildOption\r
35f69db9 2227 ModuleTypeOptions = self.Platform.GetBuildOptionsByModuleType(EDK_NAME, Module.ModuleType)\r
52302d4d
LG
2228 else:\r
2229 PlatformOptions = self.EdkIIBuildOption\r
35f69db9
YL
2230 ModuleTypeOptions = self.Platform.GetBuildOptionsByModuleType(EDKII_NAME, Module.ModuleType)\r
2231 ModuleTypeOptions = self._ExpandBuildOption(ModuleTypeOptions)\r
52302d4d
LG
2232 ModuleOptions = self._ExpandBuildOption(Module.BuildOptions)\r
2233 if Module in self.Platform.Modules:\r
2234 PlatformModule = self.Platform.Modules[str(Module)]\r
2235 PlatformModuleOptions = self._ExpandBuildOption(PlatformModule.BuildOptions)\r
2236 else:\r
2237 PlatformModuleOptions = {}\r
2238\r
fe4bf2f9 2239 BuildRuleOrder = None\r
35f69db9 2240 for Options in [self.ToolDefinition, ModuleOptions, PlatformOptions, ModuleTypeOptions, PlatformModuleOptions]:\r
fe4bf2f9
YL
2241 for Tool in Options:\r
2242 for Attr in Options[Tool]:\r
2243 if Attr == TAB_TOD_DEFINES_BUILDRULEORDER:\r
2244 BuildRuleOrder = Options[Tool][Attr]\r
2245\r
35f69db9
YL
2246 AllTools = set(ModuleOptions.keys() + PlatformOptions.keys() +\r
2247 PlatformModuleOptions.keys() + ModuleTypeOptions.keys() +\r
2248 self.ToolDefinition.keys())\r
52302d4d
LG
2249 BuildOptions = {}\r
2250 for Tool in AllTools:\r
2251 if Tool not in BuildOptions:\r
2252 BuildOptions[Tool] = {}\r
2253\r
35f69db9 2254 for Options in [self.ToolDefinition, ModuleOptions, PlatformOptions, ModuleTypeOptions, PlatformModuleOptions]:\r
52302d4d
LG
2255 if Tool not in Options:\r
2256 continue\r
2257 for Attr in Options[Tool]:\r
2258 Value = Options[Tool][Attr]\r
fe4bf2f9
YL
2259 #\r
2260 # Do not generate it in Makefile\r
2261 #\r
2262 if Attr == TAB_TOD_DEFINES_BUILDRULEORDER:\r
2263 continue\r
52302d4d
LG
2264 if Attr not in BuildOptions[Tool]:\r
2265 BuildOptions[Tool][Attr] = ""\r
2266 # check if override is indicated\r
2267 if Value.startswith('='):\r
05cc51ad
LY
2268 ToolPath = Value[1:]\r
2269 ToolPath = mws.handleWsMacro(ToolPath)\r
2270 BuildOptions[Tool][Attr] = ToolPath\r
5015bee2 2271 else:\r
05cc51ad 2272 Value = mws.handleWsMacro(Value)\r
52302d4d 2273 BuildOptions[Tool][Attr] += " " + Value\r
f3decdc3
LG
2274 if Module.AutoGenVersion < 0x00010005 and self.Workspace.UniFlag != None:\r
2275 #\r
2276 # Override UNI flag only for EDK module.\r
2277 #\r
2278 if 'BUILD' not in BuildOptions:\r
2279 BuildOptions['BUILD'] = {}\r
2280 BuildOptions['BUILD']['FLAGS'] = self.Workspace.UniFlag\r
fe4bf2f9 2281 return BuildOptions, BuildRuleOrder\r
52302d4d
LG
2282\r
2283 Platform = property(_GetPlatform)\r
2284 Name = property(_GetName)\r
2285 Guid = property(_GetGuid)\r
2286 Version = property(_GetVersion)\r
2287\r
2288 OutputDir = property(_GetOutputDir)\r
2289 BuildDir = property(_GetBuildDir)\r
2290 MakeFileDir = property(_GetMakeFileDir)\r
2291 FdfFile = property(_GetFdfFile)\r
2292\r
2293 PcdTokenNumber = property(_GetPcdTokenNumbers) # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber\r
2294 DynamicPcdList = property(_GetDynamicPcdList) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]\r
2295 NonDynamicPcdList = property(_GetNonDynamicPcdList) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]\r
2bc3256c 2296 NonDynamicPcdDict = property(_GetNonDynamicPcdDict)\r
52302d4d
LG
2297 PackageList = property(_GetPackageList)\r
2298\r
2299 ToolDefinition = property(_GetToolDefinition) # toolcode : tool path\r
2300 ToolDefinitionFile = property(_GetToolDefFile) # toolcode : lib path\r
2301 ToolChainFamily = property(_GetToolChainFamily)\r
2302 BuildRuleFamily = property(_GetBuildRuleFamily)\r
2303 BuildOption = property(_GetBuildOptions) # toolcode : option\r
2304 EdkBuildOption = property(_GetEdkBuildOptions) # edktoolcode : option\r
2305 EdkIIBuildOption = property(_GetEdkIIBuildOptions) # edkiitoolcode : option\r
2306\r
2307 BuildCommand = property(_GetBuildCommand)\r
2308 BuildRule = property(_GetBuildRule)\r
2309 ModuleAutoGenList = property(_GetModuleAutoGenList)\r
2310 LibraryAutoGenList = property(_GetLibraryAutoGenList)\r
0923aa1c 2311 GenFdsCommand = property(_GenFdsCommand)\r
52302d4d
LG
2312\r
2313## ModuleAutoGen class\r
2314#\r
2315# This class encapsules the AutoGen behaviors for the build tools. In addition to\r
2316# the generation of AutoGen.h and AutoGen.c, it will generate *.depex file according\r
2317# to the [depex] section in module's inf file.\r
2318#\r
2319class ModuleAutoGen(AutoGen):\r
2320 ## The real constructor of ModuleAutoGen\r
2321 #\r
2322 # This method is not supposed to be called by users of ModuleAutoGen. It's\r
2323 # only used by factory method __new__() to do real initialization work for an\r
2324 # object of ModuleAutoGen\r
2325 #\r
2326 # @param Workspace EdkIIWorkspaceBuild object\r
2327 # @param ModuleFile The path of module file\r
2328 # @param Target Build target (DEBUG, RELEASE)\r
2329 # @param Toolchain Name of tool chain\r
2330 # @param Arch The arch the module supports\r
2331 # @param PlatformFile Platform meta-file\r
2332 #\r
2333 def _Init(self, Workspace, ModuleFile, Target, Toolchain, Arch, PlatformFile):\r
2334 EdkLogger.debug(EdkLogger.DEBUG_9, "AutoGen module [%s] [%s]" % (ModuleFile, Arch))\r
2335 GlobalData.gProcessingFile = "%s [%s, %s, %s]" % (ModuleFile, Arch, Toolchain, Target)\r
2336\r
2337 self.Workspace = Workspace\r
2338 self.WorkspaceDir = Workspace.WorkspaceDir\r
2339\r
2340 self.MetaFile = ModuleFile\r
2341 self.PlatformInfo = PlatformAutoGen(Workspace, PlatformFile, Target, Toolchain, Arch)\r
2342 # check if this module is employed by active platform\r
2343 if not self.PlatformInfo.ValidModule(self.MetaFile):\r
2344 EdkLogger.verbose("Module [%s] for [%s] is not employed by active platform\n" \\r
2345 % (self.MetaFile, Arch))\r
2346 return False\r
2347\r
2348 self.SourceDir = self.MetaFile.SubDir\r
05cc51ad 2349 self.SourceDir = mws.relpath(self.SourceDir, self.WorkspaceDir)\r
97fa0ee9 2350\r
52302d4d
LG
2351 self.SourceOverrideDir = None\r
2352 # use overrided path defined in DSC file\r
2353 if self.MetaFile.Key in GlobalData.gOverrideDir:\r
2354 self.SourceOverrideDir = GlobalData.gOverrideDir[self.MetaFile.Key]\r
2355\r
2356 self.ToolChain = Toolchain\r
2357 self.BuildTarget = Target\r
2358 self.Arch = Arch\r
2359 self.ToolChainFamily = self.PlatformInfo.ToolChainFamily\r
2360 self.BuildRuleFamily = self.PlatformInfo.BuildRuleFamily\r
2361\r
2362 self.IsMakeFileCreated = False\r
2363 self.IsCodeFileCreated = False\r
da92f276
LG
2364 self.IsAsBuiltInfCreated = False\r
2365 self.DepexGenerated = False\r
52302d4d
LG
2366\r
2367 self.BuildDatabase = self.Workspace.BuildDatabase\r
fe4bf2f9 2368 self.BuildRuleOrder = None\r
52302d4d
LG
2369\r
2370 self._Module = None\r
2371 self._Name = None\r
2372 self._Guid = None\r
2373 self._Version = None\r
2374 self._ModuleType = None\r
2375 self._ComponentType = None\r
2376 self._PcdIsDriver = None\r
2377 self._AutoGenVersion = None\r
2378 self._LibraryFlag = None\r
2379 self._CustomMakefile = None\r
2380 self._Macro = None\r
2381\r
2382 self._BuildDir = None\r
2383 self._OutputDir = None\r
2384 self._DebugDir = None\r
2385 self._MakeFileDir = None\r
2386\r
2387 self._IncludePathList = None\r
725cdb8f 2388 self._IncludePathLength = 0\r
52302d4d
LG
2389 self._AutoGenFileList = None\r
2390 self._UnicodeFileList = None\r
2391 self._SourceFileList = None\r
2392 self._ObjectFileList = None\r
2393 self._BinaryFileList = None\r
2394\r
2395 self._DependentPackageList = None\r
2396 self._DependentLibraryList = None\r
2397 self._LibraryAutoGenList = None\r
2398 self._DerivedPackageList = None\r
2399 self._ModulePcdList = None\r
2400 self._LibraryPcdList = None\r
e8a47801 2401 self._PcdComments = sdict()\r
52302d4d 2402 self._GuidList = None\r
e8a47801
LG
2403 self._GuidsUsedByPcd = None\r
2404 self._GuidComments = sdict()\r
52302d4d 2405 self._ProtocolList = None\r
e8a47801 2406 self._ProtocolComments = sdict()\r
52302d4d 2407 self._PpiList = None\r
e8a47801 2408 self._PpiComments = sdict()\r
52302d4d
LG
2409 self._DepexList = None\r
2410 self._DepexExpressionList = None\r
2411 self._BuildOption = None\r
79b74a03 2412 self._BuildOptionIncPathList = None\r
52302d4d
LG
2413 self._BuildTargets = None\r
2414 self._IntroBuildTargetList = None\r
2415 self._FinalBuildTargetList = None\r
2416 self._FileTypes = None\r
2417 self._BuildRules = None\r
2bc3256c
LG
2418 \r
2419 ## The Modules referenced to this Library\r
2420 # Only Library has this attribute\r
2421 self._ReferenceModules = [] \r
2422 \r
2423 ## Store the FixedAtBuild Pcds\r
2424 # \r
2425 self._FixedAtBuildPcds = []\r
2426 self.ConstPcd = {}\r
52302d4d
LG
2427 return True\r
2428\r
2429 def __repr__(self):\r
2430 return "%s [%s]" % (self.MetaFile, self.Arch)\r
2431\r
2bc3256c
LG
2432 # Get FixedAtBuild Pcds of this Module\r
2433 def _GetFixedAtBuildPcds(self):\r
2434 if self._FixedAtBuildPcds:\r
2435 return self._FixedAtBuildPcds\r
2436 for Pcd in self.ModulePcdList:\r
2437 if self.IsLibrary:\r
2438 if not (Pcd.Pending == False and Pcd.Type == "FixedAtBuild"):\r
2439 continue\r
2440 elif Pcd.Type != "FixedAtBuild":\r
2441 continue\r
2442 if Pcd not in self._FixedAtBuildPcds:\r
2443 self._FixedAtBuildPcds.append(Pcd)\r
2444 \r
2445 return self._FixedAtBuildPcds \r
2446\r
867d1cd4
YL
2447 def _GetUniqueBaseName(self):\r
2448 BaseName = self.Name\r
2449 for Module in self.PlatformInfo.ModuleAutoGenList:\r
2450 if Module.MetaFile == self.MetaFile:\r
2451 continue\r
2452 if Module.Name == self.Name:\r
867d1cd4
YL
2453 if uuid.UUID(Module.Guid) == uuid.UUID(self.Guid):\r
2454 EdkLogger.error("build", FILE_DUPLICATED, 'Modules have same BaseName and FILE_GUID:\n'\r
2455 ' %s\n %s' % (Module.MetaFile, self.MetaFile))\r
2456 BaseName = '%s_%s' % (self.Name, self.Guid)\r
2457 return BaseName\r
2458\r
52302d4d
LG
2459 # Macros could be used in build_rule.txt (also Makefile)\r
2460 def _GetMacros(self):\r
2461 if self._Macro == None:\r
2462 self._Macro = sdict()\r
2463 self._Macro["WORKSPACE" ] = self.WorkspaceDir\r
2464 self._Macro["MODULE_NAME" ] = self.Name\r
867d1cd4 2465 self._Macro["MODULE_NAME_GUID" ] = self._GetUniqueBaseName()\r
52302d4d
LG
2466 self._Macro["MODULE_GUID" ] = self.Guid\r
2467 self._Macro["MODULE_VERSION" ] = self.Version\r
2468 self._Macro["MODULE_TYPE" ] = self.ModuleType\r
2469 self._Macro["MODULE_FILE" ] = str(self.MetaFile)\r
2470 self._Macro["MODULE_FILE_BASE_NAME" ] = self.MetaFile.BaseName\r
2471 self._Macro["MODULE_RELATIVE_DIR" ] = self.SourceDir\r
2472 self._Macro["MODULE_DIR" ] = self.SourceDir\r
2473\r
2474 self._Macro["BASE_NAME" ] = self.Name\r
2475\r
2476 self._Macro["ARCH" ] = self.Arch\r
2477 self._Macro["TOOLCHAIN" ] = self.ToolChain\r
2478 self._Macro["TOOLCHAIN_TAG" ] = self.ToolChain\r
0d2711a6 2479 self._Macro["TOOL_CHAIN_TAG" ] = self.ToolChain\r
52302d4d
LG
2480 self._Macro["TARGET" ] = self.BuildTarget\r
2481\r
2482 self._Macro["BUILD_DIR" ] = self.PlatformInfo.BuildDir\r
2483 self._Macro["BIN_DIR" ] = os.path.join(self.PlatformInfo.BuildDir, self.Arch)\r
2484 self._Macro["LIB_DIR" ] = os.path.join(self.PlatformInfo.BuildDir, self.Arch)\r
2485 self._Macro["MODULE_BUILD_DIR" ] = self.BuildDir\r
2486 self._Macro["OUTPUT_DIR" ] = self.OutputDir\r
2487 self._Macro["DEBUG_DIR" ] = self.DebugDir\r
df1e1b63
YZ
2488 self._Macro["DEST_DIR_OUTPUT" ] = self.OutputDir\r
2489 self._Macro["DEST_DIR_DEBUG" ] = self.DebugDir\r
3570e332
YZ
2490 self._Macro["PLATFORM_NAME" ] = self.PlatformInfo.Name\r
2491 self._Macro["PLATFORM_GUID" ] = self.PlatformInfo.Guid\r
2492 self._Macro["PLATFORM_VERSION" ] = self.PlatformInfo.Version\r
2493 self._Macro["PLATFORM_RELATIVE_DIR" ] = self.PlatformInfo.SourceDir\r
2494 self._Macro["PLATFORM_DIR" ] = mws.join(self.WorkspaceDir, self.PlatformInfo.SourceDir)\r
2495 self._Macro["PLATFORM_OUTPUT_DIR" ] = self.PlatformInfo.OutputDir\r
52302d4d
LG
2496 return self._Macro\r
2497\r
2498 ## Return the module build data object\r
2499 def _GetModule(self):\r
2500 if self._Module == None:\r
0d2711a6 2501 self._Module = self.Workspace.BuildDatabase[self.MetaFile, self.Arch, self.BuildTarget, self.ToolChain]\r
52302d4d
LG
2502 return self._Module\r
2503\r
2504 ## Return the module name\r
2505 def _GetBaseName(self):\r
2506 return self.Module.BaseName\r
2507\r
b36d134f
LG
2508 ## Return the module DxsFile if exist\r
2509 def _GetDxsFile(self):\r
2510 return self.Module.DxsFile\r
2511\r
52302d4d
LG
2512 ## Return the module SourceOverridePath\r
2513 def _GetSourceOverridePath(self):\r
2514 return self.Module.SourceOverridePath\r
2515\r
2516 ## Return the module meta-file GUID\r
2517 def _GetGuid(self):\r
97fa0ee9
YL
2518 #\r
2519 # To build same module more than once, the module path with FILE_GUID overridden has\r
2520 # the file name FILE_GUIDmodule.inf, but the relative path (self.MetaFile.File) is the realy path\r
2521 # in DSC. The overridden GUID can be retrieved from file name\r
2522 #\r
2523 if os.path.basename(self.MetaFile.File) != os.path.basename(self.MetaFile.Path):\r
2524 #\r
2525 # Length of GUID is 36\r
2526 #\r
2527 return os.path.basename(self.MetaFile.Path)[:36]\r
52302d4d
LG
2528 return self.Module.Guid\r
2529\r
2530 ## Return the module version\r
2531 def _GetVersion(self):\r
2532 return self.Module.Version\r
2533\r
2534 ## Return the module type\r
2535 def _GetModuleType(self):\r
2536 return self.Module.ModuleType\r
2537\r
b36d134f 2538 ## Return the component type (for Edk.x style of module)\r
52302d4d
LG
2539 def _GetComponentType(self):\r
2540 return self.Module.ComponentType\r
2541\r
2542 ## Return the build type\r
2543 def _GetBuildType(self):\r
2544 return self.Module.BuildType\r
2545\r
2546 ## Return the PCD_IS_DRIVER setting\r
2547 def _GetPcdIsDriver(self):\r
2548 return self.Module.PcdIsDriver\r
2549\r
2550 ## Return the autogen version, i.e. module meta-file version\r
2551 def _GetAutoGenVersion(self):\r
2552 return self.Module.AutoGenVersion\r
2553\r
2554 ## Check if the module is library or not\r
2555 def _IsLibrary(self):\r
2556 if self._LibraryFlag == None:\r
2557 if self.Module.LibraryClass != None and self.Module.LibraryClass != []:\r
2558 self._LibraryFlag = True\r
2559 else:\r
2560 self._LibraryFlag = False\r
2561 return self._LibraryFlag\r
2562\r
e8a47801
LG
2563 ## Check if the module is binary module or not\r
2564 def _IsBinaryModule(self):\r
2565 return self.Module.IsBinaryModule\r
2566\r
52302d4d
LG
2567 ## Return the directory to store intermediate files of the module\r
2568 def _GetBuildDir(self):\r
2569 if self._BuildDir == None:\r
2570 self._BuildDir = path.join(\r
2571 self.PlatformInfo.BuildDir,\r
2572 self.Arch,\r
2573 self.SourceDir,\r
2574 self.MetaFile.BaseName\r
2575 )\r
2576 CreateDirectory(self._BuildDir)\r
2577 return self._BuildDir\r
2578\r
2579 ## Return the directory to store the intermediate object files of the mdoule\r
2580 def _GetOutputDir(self):\r
2581 if self._OutputDir == None:\r
2582 self._OutputDir = path.join(self.BuildDir, "OUTPUT")\r
2583 CreateDirectory(self._OutputDir)\r
2584 return self._OutputDir\r
2585\r
2586 ## Return the directory to store auto-gened source files of the mdoule\r
2587 def _GetDebugDir(self):\r
2588 if self._DebugDir == None:\r
2589 self._DebugDir = path.join(self.BuildDir, "DEBUG")\r
2590 CreateDirectory(self._DebugDir)\r
2591 return self._DebugDir\r
2592\r
2593 ## Return the path of custom file\r
2594 def _GetCustomMakefile(self):\r
2595 if self._CustomMakefile == None:\r
2596 self._CustomMakefile = {}\r
2597 for Type in self.Module.CustomMakefile:\r
2598 if Type in gMakeTypeMap:\r
2599 MakeType = gMakeTypeMap[Type]\r
2600 else:\r
2601 MakeType = 'nmake'\r
2602 if self.SourceOverrideDir != None:\r
2603 File = os.path.join(self.SourceOverrideDir, self.Module.CustomMakefile[Type])\r
2604 if not os.path.exists(File):\r
2605 File = os.path.join(self.SourceDir, self.Module.CustomMakefile[Type])\r
2606 else:\r
2607 File = os.path.join(self.SourceDir, self.Module.CustomMakefile[Type])\r
2608 self._CustomMakefile[MakeType] = File\r
2609 return self._CustomMakefile\r
2610\r
2611 ## Return the directory of the makefile\r
2612 #\r
2613 # @retval string The directory string of module's makefile\r
2614 #\r
2615 def _GetMakeFileDir(self):\r
2616 return self.BuildDir\r
2617\r
2618 ## Return build command string\r
2619 #\r
2620 # @retval string Build command string\r
2621 #\r
2622 def _GetBuildCommand(self):\r
2623 return self.PlatformInfo.BuildCommand\r
2624\r
2625 ## Get object list of all packages the module and its dependent libraries belong to\r
2626 #\r
2627 # @retval list The list of package object\r
2628 #\r
2629 def _GetDerivedPackageList(self):\r
2630 PackageList = []\r
2631 for M in [self.Module] + self.DependentLibraryList:\r
2632 for Package in M.Packages:\r
2633 if Package in PackageList:\r
2634 continue\r
2635 PackageList.append(Package)\r
2636 return PackageList\r
97fa0ee9
YL
2637 \r
2638 ## Get the depex string\r
2639 #\r
2640 # @return : a string contain all depex expresion.\r
2641 def _GetDepexExpresionString(self):\r
2642 DepexStr = ''\r
2643 DepexList = []\r
2644 ## DPX_SOURCE IN Define section.\r
2645 if self.Module.DxsFile:\r
2646 return DepexStr\r
2647 for M in [self.Module] + self.DependentLibraryList:\r
2648 Filename = M.MetaFile.Path\r
2649 InfObj = InfSectionParser.InfSectionParser(Filename)\r
2650 DepexExpresionList = InfObj.GetDepexExpresionList()\r
2651 for DepexExpresion in DepexExpresionList:\r
2652 for key in DepexExpresion.keys():\r
2653 Arch, ModuleType = key\r
2654 # the type of build module is USER_DEFINED.\r
2655 # All different DEPEX section tags would be copied into the As Built INF file\r
2656 # and there would be separate DEPEX section tags\r
2657 if self.ModuleType.upper() == SUP_MODULE_USER_DEFINED:\r
2658 if (Arch.upper() == self.Arch.upper()) and (ModuleType.upper() != TAB_ARCH_COMMON):\r
2659 DepexList.append({(Arch, ModuleType): DepexExpresion[key][:]})\r
2660 else:\r
2661 if Arch.upper() == TAB_ARCH_COMMON or \\r
2662 (Arch.upper() == self.Arch.upper() and \\r
2663 ModuleType.upper() in [TAB_ARCH_COMMON, self.ModuleType.upper()]):\r
2664 DepexList.append({(Arch, ModuleType): DepexExpresion[key][:]})\r
2665 \r
2666 #the type of build module is USER_DEFINED.\r
2667 if self.ModuleType.upper() == SUP_MODULE_USER_DEFINED:\r
2668 for Depex in DepexList:\r
2669 for key in Depex.keys():\r
2670 DepexStr += '[Depex.%s.%s]\n' % key\r
2671 DepexStr += '\n'.join(['# '+ val for val in Depex[key]])\r
2672 DepexStr += '\n\n'\r
2673 if not DepexStr:\r
2674 return '[Depex.%s]\n' % self.Arch\r
2675 return DepexStr\r
2676 \r
2677 #the type of build module not is USER_DEFINED.\r
2678 Count = 0\r
2679 for Depex in DepexList:\r
2680 Count += 1\r
2681 if DepexStr != '':\r
2682 DepexStr += ' AND '\r
2683 DepexStr += '('\r
2684 for D in Depex.values():\r
2685 DepexStr += ' '.join([val for val in D])\r
2686 Index = DepexStr.find('END')\r
2687 if Index > -1 and Index == len(DepexStr) - 3:\r
2688 DepexStr = DepexStr[:-3]\r
2689 DepexStr = DepexStr.strip()\r
2690 DepexStr += ')'\r
2691 if Count == 1:\r
2692 DepexStr = DepexStr.lstrip('(').rstrip(')').strip()\r
2693 if not DepexStr:\r
2694 return '[Depex.%s]\n' % self.Arch\r
2695 return '[Depex.%s]\n# ' % self.Arch + DepexStr\r
2696 \r
52302d4d
LG
2697 ## Merge dependency expression\r
2698 #\r
2699 # @retval list The token list of the dependency expression after parsed\r
2700 #\r
2701 def _GetDepexTokenList(self):\r
2702 if self._DepexList == None:\r
2703 self._DepexList = {}\r
b36d134f 2704 if self.DxsFile or self.IsLibrary or TAB_DEPENDENCY_EXPRESSION_FILE in self.FileTypes:\r
52302d4d
LG
2705 return self._DepexList\r
2706\r
2707 self._DepexList[self.ModuleType] = []\r
2708\r
2709 for ModuleType in self._DepexList:\r
2710 DepexList = self._DepexList[ModuleType]\r
2711 #\r
2712 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion\r
2713 #\r
2714 for M in [self.Module] + self.DependentLibraryList:\r
2715 Inherited = False\r
2716 for D in M.Depex[self.Arch, ModuleType]:\r
2717 if DepexList != []:\r
2718 DepexList.append('AND')\r
2719 DepexList.append('(')\r
2720 DepexList.extend(D)\r
2721 if DepexList[-1] == 'END': # no need of a END at this time\r
2722 DepexList.pop()\r
2723 DepexList.append(')')\r
2724 Inherited = True\r
2725 if Inherited:\r
2726 EdkLogger.verbose("DEPEX[%s] (+%s) = %s" % (self.Name, M.BaseName, DepexList))\r
2727 if 'BEFORE' in DepexList or 'AFTER' in DepexList:\r
2728 break\r
2729 if len(DepexList) > 0:\r
2730 EdkLogger.verbose('')\r
2731 return self._DepexList\r
2732\r
2733 ## Merge dependency expression\r
2734 #\r
2735 # @retval list The token list of the dependency expression after parsed\r
2736 #\r
2737 def _GetDepexExpressionTokenList(self):\r
2738 if self._DepexExpressionList == None:\r
2739 self._DepexExpressionList = {}\r
b36d134f 2740 if self.DxsFile or self.IsLibrary or TAB_DEPENDENCY_EXPRESSION_FILE in self.FileTypes:\r
52302d4d
LG
2741 return self._DepexExpressionList\r
2742\r
2743 self._DepexExpressionList[self.ModuleType] = ''\r
2744\r
2745 for ModuleType in self._DepexExpressionList:\r
2746 DepexExpressionList = self._DepexExpressionList[ModuleType]\r
2747 #\r
2748 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion\r
2749 #\r
2750 for M in [self.Module] + self.DependentLibraryList:\r
2751 Inherited = False\r
2752 for D in M.DepexExpression[self.Arch, ModuleType]:\r
2753 if DepexExpressionList != '':\r
2754 DepexExpressionList += ' AND '\r
2755 DepexExpressionList += '('\r
2756 DepexExpressionList += D\r
2757 DepexExpressionList = DepexExpressionList.rstrip('END').strip()\r
2758 DepexExpressionList += ')'\r
2759 Inherited = True\r
2760 if Inherited:\r
2761 EdkLogger.verbose("DEPEX[%s] (+%s) = %s" % (self.Name, M.BaseName, DepexExpressionList))\r
2762 if 'BEFORE' in DepexExpressionList or 'AFTER' in DepexExpressionList:\r
2763 break\r
2764 if len(DepexExpressionList) > 0:\r
2765 EdkLogger.verbose('')\r
2766 self._DepexExpressionList[ModuleType] = DepexExpressionList\r
2767 return self._DepexExpressionList\r
2768\r
2769 ## Return the list of specification version required for the module\r
2770 #\r
2771 # @retval list The list of specification defined in module file\r
2772 #\r
2773 def _GetSpecification(self):\r
2774 return self.Module.Specification\r
2775\r
2776 ## Tool option for the module build\r
2777 #\r
2778 # @param PlatformInfo The object of PlatformBuildInfo\r
2779 # @retval dict The dict containing valid options\r
2780 #\r
2781 def _GetModuleBuildOption(self):\r
2782 if self._BuildOption == None:\r
fe4bf2f9
YL
2783 self._BuildOption, self.BuildRuleOrder = self.PlatformInfo.ApplyBuildOption(self.Module)\r
2784 if self.BuildRuleOrder:\r
2785 self.BuildRuleOrder = ['.%s' % Ext for Ext in self.BuildRuleOrder.split()]\r
52302d4d
LG
2786 return self._BuildOption\r
2787\r
79b74a03
LG
2788 ## Get include path list from tool option for the module build\r
2789 #\r
2790 # @retval list The include path list\r
2791 #\r
2792 def _GetBuildOptionIncPathList(self):\r
2793 if self._BuildOptionIncPathList == None:\r
2794 #\r
d40b2ee6 2795 # Regular expression for finding Include Directories, the difference between MSFT and INTEL/GCC/RVCT\r
79b74a03
LG
2796 # is the former use /I , the Latter used -I to specify include directories\r
2797 #\r
2798 if self.PlatformInfo.ToolChainFamily in ('MSFT'):\r
47fea6af 2799 gBuildOptIncludePattern = re.compile(r"(?:.*?)/I[ \t]*([^ ]*)", re.MULTILINE | re.DOTALL)\r
d40b2ee6 2800 elif self.PlatformInfo.ToolChainFamily in ('INTEL', 'GCC', 'RVCT'):\r
47fea6af 2801 gBuildOptIncludePattern = re.compile(r"(?:.*?)-I[ \t]*([^ ]*)", re.MULTILINE | re.DOTALL)\r
d40b2ee6
LG
2802 else:\r
2803 #\r
2804 # New ToolChainFamily, don't known whether there is option to specify include directories\r
2805 #\r
2806 self._BuildOptionIncPathList = []\r
2807 return self._BuildOptionIncPathList\r
79b74a03
LG
2808 \r
2809 BuildOptionIncPathList = []\r
2810 for Tool in ('CC', 'PP', 'VFRPP', 'ASLPP', 'ASLCC', 'APP', 'ASM'):\r
2811 Attr = 'FLAGS'\r
2812 try:\r
2813 FlagOption = self.BuildOption[Tool][Attr]\r
2814 except KeyError:\r
2815 FlagOption = ''\r
2816 \r
d40b2ee6
LG
2817 if self.PlatformInfo.ToolChainFamily != 'RVCT':\r
2818 IncPathList = [NormPath(Path, self.Macros) for Path in gBuildOptIncludePattern.findall(FlagOption)]\r
2819 else:\r
2820 #\r
2821 # RVCT may specify a list of directory seperated by commas\r
2822 #\r
2823 IncPathList = []\r
2824 for Path in gBuildOptIncludePattern.findall(FlagOption):\r
2825 PathList = GetSplitList(Path, TAB_COMMA_SPLIT)\r
2826 IncPathList += [NormPath(PathEntry, self.Macros) for PathEntry in PathList]\r
2827\r
79b74a03
LG
2828 #\r
2829 # EDK II modules must not reference header files outside of the packages they depend on or \r
2830 # within the module's directory tree. Report error if violation.\r
2831 #\r
2832 if self.AutoGenVersion >= 0x00010005 and len(IncPathList) > 0:\r
2833 for Path in IncPathList:\r
2834 if (Path not in self.IncludePathList) and (CommonPath([Path, self.MetaFile.Dir]) != self.MetaFile.Dir):\r
47fea6af
YZ
2835 ErrMsg = "The include directory for the EDK II module in this line is invalid %s specified in %s FLAGS '%s'" % (Path, Tool, FlagOption)\r
2836 EdkLogger.error("build",\r
79b74a03 2837 PARAMETER_INVALID,\r
47fea6af
YZ
2838 ExtraData=ErrMsg,\r
2839 File=str(self.MetaFile))\r
79b74a03
LG
2840\r
2841 \r
2842 BuildOptionIncPathList += IncPathList\r
2843 \r
2844 self._BuildOptionIncPathList = BuildOptionIncPathList\r
2845 \r
2846 return self._BuildOptionIncPathList\r
2847 \r
52302d4d
LG
2848 ## Return a list of files which can be built from source\r
2849 #\r
2850 # What kind of files can be built is determined by build rules in\r
97fa0ee9 2851 # $(CONF_DIRECTORY)/build_rule.txt and toolchain family.\r
52302d4d
LG
2852 #\r
2853 def _GetSourceFileList(self):\r
2854 if self._SourceFileList == None:\r
2855 self._SourceFileList = []\r
2856 for F in self.Module.Sources:\r
2857 # match tool chain\r
08dd311f 2858 if F.TagName not in ("", "*", self.ToolChain):\r
52302d4d
LG
2859 EdkLogger.debug(EdkLogger.DEBUG_9, "The toolchain [%s] for processing file [%s] is found, "\r
2860 "but [%s] is needed" % (F.TagName, str(F), self.ToolChain))\r
2861 continue\r
2862 # match tool chain family\r
08dd311f 2863 if F.ToolChainFamily not in ("", "*", self.ToolChainFamily):\r
52302d4d
LG
2864 EdkLogger.debug(\r
2865 EdkLogger.DEBUG_0,\r
2866 "The file [%s] must be built by tools of [%s], " \\r
2867 "but current toolchain family is [%s]" \\r
2868 % (str(F), F.ToolChainFamily, self.ToolChainFamily))\r
2869 continue\r
2870\r
2871 # add the file path into search path list for file including\r
2872 if F.Dir not in self.IncludePathList and self.AutoGenVersion >= 0x00010005:\r
2873 self.IncludePathList.insert(0, F.Dir)\r
2874 self._SourceFileList.append(F)\r
4cb7bade
YZ
2875\r
2876 self._MatchBuildRuleOrder(self._SourceFileList)\r
2877\r
2878 for F in self._SourceFileList:\r
52302d4d
LG
2879 self._ApplyBuildRule(F, TAB_UNKNOWN_FILE)\r
2880 return self._SourceFileList\r
2881\r
4cb7bade
YZ
2882 def _MatchBuildRuleOrder(self, FileList):\r
2883 Order_Dict = {}\r
2884 self._GetModuleBuildOption()\r
2885 for SingleFile in FileList:\r
2886 if self.BuildRuleOrder and SingleFile.Ext in self.BuildRuleOrder and SingleFile.Ext in self.BuildRules:\r
2887 key = SingleFile.Path.split(SingleFile.Ext)[0]\r
2888 if key in Order_Dict:\r
2889 Order_Dict[key].append(SingleFile.Ext)\r
2890 else:\r
2891 Order_Dict[key] = [SingleFile.Ext]\r
2892\r
2893 RemoveList = []\r
2894 for F in Order_Dict:\r
2895 if len(Order_Dict[F]) > 1:\r
2896 Order_Dict[F].sort(key=lambda i: self.BuildRuleOrder.index(i))\r
2897 for Ext in Order_Dict[F][1:]:\r
2898 RemoveList.append(F + Ext)\r
2899 \r
2900 for item in RemoveList:\r
2901 FileList.remove(item)\r
2902\r
2903 return FileList\r
2904\r
52302d4d
LG
2905 ## Return the list of unicode files\r
2906 def _GetUnicodeFileList(self):\r
2907 if self._UnicodeFileList == None:\r
2908 if TAB_UNICODE_FILE in self.FileTypes:\r
2909 self._UnicodeFileList = self.FileTypes[TAB_UNICODE_FILE]\r
2910 else:\r
2911 self._UnicodeFileList = []\r
2912 return self._UnicodeFileList\r
2913\r
2914 ## Return a list of files which can be built from binary\r
2915 #\r
2916 # "Build" binary files are just to copy them to build directory.\r
2917 #\r
2918 # @retval list The list of files which can be built later\r
2919 #\r
2920 def _GetBinaryFiles(self):\r
2921 if self._BinaryFileList == None:\r
2922 self._BinaryFileList = []\r
2923 for F in self.Module.Binaries:\r
2924 if F.Target not in ['COMMON', '*'] and F.Target != self.BuildTarget:\r
2925 continue\r
2926 self._BinaryFileList.append(F)\r
2927 self._ApplyBuildRule(F, F.Type)\r
2928 return self._BinaryFileList\r
2929\r
2930 def _GetBuildRules(self):\r
2931 if self._BuildRules == None:\r
2932 BuildRules = {}\r
2933 BuildRuleDatabase = self.PlatformInfo.BuildRule\r
2934 for Type in BuildRuleDatabase.FileTypeList:\r
2935 #first try getting build rule by BuildRuleFamily\r
2936 RuleObject = BuildRuleDatabase[Type, self.BuildType, self.Arch, self.BuildRuleFamily]\r
2937 if not RuleObject:\r
2938 # build type is always module type, but ...\r
2939 if self.ModuleType != self.BuildType:\r
2940 RuleObject = BuildRuleDatabase[Type, self.ModuleType, self.Arch, self.BuildRuleFamily]\r
2941 #second try getting build rule by ToolChainFamily\r
2942 if not RuleObject:\r
2943 RuleObject = BuildRuleDatabase[Type, self.BuildType, self.Arch, self.ToolChainFamily]\r
2944 if not RuleObject:\r
2945 # build type is always module type, but ...\r
2946 if self.ModuleType != self.BuildType:\r
2947 RuleObject = BuildRuleDatabase[Type, self.ModuleType, self.Arch, self.ToolChainFamily]\r
2948 if not RuleObject:\r
2949 continue\r
2950 RuleObject = RuleObject.Instantiate(self.Macros)\r
2951 BuildRules[Type] = RuleObject\r
2952 for Ext in RuleObject.SourceFileExtList:\r
2953 BuildRules[Ext] = RuleObject\r
2954 self._BuildRules = BuildRules\r
2955 return self._BuildRules\r
2956\r
2957 def _ApplyBuildRule(self, File, FileType):\r
2958 if self._BuildTargets == None:\r
2959 self._IntroBuildTargetList = set()\r
2960 self._FinalBuildTargetList = set()\r