]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/Python/AutoGen/AutoGen.py
BaseTools/GenFds: remove the old logic since ActivePlatform is abs. path
[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
6780eef1
LG
864 \r
865 #\r
866 # The priority list while override build option \r
867 #\r
868 PrioList = {"0x11111" : 16, # TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE (Highest)\r
869 "0x01111" : 15, # ******_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE\r
870 "0x10111" : 14, # TARGET_*********_ARCH_COMMANDTYPE_ATTRIBUTE\r
871 "0x00111" : 13, # ******_*********_ARCH_COMMANDTYPE_ATTRIBUTE \r
872 "0x11011" : 12, # TARGET_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE\r
873 "0x01011" : 11, # ******_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE\r
874 "0x10011" : 10, # TARGET_*********_****_COMMANDTYPE_ATTRIBUTE\r
875 "0x00011" : 9, # ******_*********_****_COMMANDTYPE_ATTRIBUTE\r
876 "0x11101" : 8, # TARGET_TOOLCHAIN_ARCH_***********_ATTRIBUTE\r
877 "0x01101" : 7, # ******_TOOLCHAIN_ARCH_***********_ATTRIBUTE\r
878 "0x10101" : 6, # TARGET_*********_ARCH_***********_ATTRIBUTE\r
879 "0x00101" : 5, # ******_*********_ARCH_***********_ATTRIBUTE\r
880 "0x11001" : 4, # TARGET_TOOLCHAIN_****_***********_ATTRIBUTE\r
881 "0x01001" : 3, # ******_TOOLCHAIN_****_***********_ATTRIBUTE\r
882 "0x10001" : 2, # TARGET_*********_****_***********_ATTRIBUTE\r
883 "0x00001" : 1} # ******_*********_****_***********_ATTRIBUTE (Lowest)\r
47fea6af 884\r
52302d4d
LG
885 ## The real constructor of PlatformAutoGen\r
886 #\r
887 # This method is not supposed to be called by users of PlatformAutoGen. It's\r
888 # only used by factory method __new__() to do real initialization work for an\r
889 # object of PlatformAutoGen\r
890 #\r
891 # @param Workspace WorkspaceAutoGen object\r
892 # @param PlatformFile Platform file (DSC file)\r
893 # @param Target Build target (DEBUG, RELEASE)\r
894 # @param Toolchain Name of tool chain\r
895 # @param Arch arch of the platform supports\r
896 #\r
897 def _Init(self, Workspace, PlatformFile, Target, Toolchain, Arch):\r
898 EdkLogger.debug(EdkLogger.DEBUG_9, "AutoGen platform [%s] [%s]" % (PlatformFile, Arch))\r
899 GlobalData.gProcessingFile = "%s [%s, %s, %s]" % (PlatformFile, Arch, Toolchain, Target)\r
900\r
901 self.MetaFile = PlatformFile\r
902 self.Workspace = Workspace\r
903 self.WorkspaceDir = Workspace.WorkspaceDir\r
904 self.ToolChain = Toolchain\r
905 self.BuildTarget = Target\r
906 self.Arch = Arch\r
907 self.SourceDir = PlatformFile.SubDir\r
908 self.SourceOverrideDir = None\r
909 self.FdTargetList = self.Workspace.FdTargetList\r
910 self.FvTargetList = self.Workspace.FvTargetList\r
911 self.AllPcdList = []\r
a0a2cd1e
FB
912 # get the original module/package/platform objects\r
913 self.BuildDatabase = Workspace.BuildDatabase\r
52302d4d
LG
914\r
915 # flag indicating if the makefile/C-code file has been created or not\r
916 self.IsMakeFileCreated = False\r
917 self.IsCodeFileCreated = False\r
918\r
919 self._Platform = None\r
920 self._Name = None\r
921 self._Guid = None\r
922 self._Version = None\r
923\r
924 self._BuildRule = None\r
925 self._SourceDir = None\r
926 self._BuildDir = None\r
927 self._OutputDir = None\r
928 self._FvDir = None\r
929 self._MakeFileDir = None\r
930 self._FdfFile = None\r
931\r
932 self._PcdTokenNumber = None # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber\r
933 self._DynamicPcdList = None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]\r
934 self._NonDynamicPcdList = None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]\r
2bc3256c 935 self._NonDynamicPcdDict = {}\r
52302d4d
LG
936\r
937 self._ToolDefinitions = None\r
938 self._ToolDefFile = None # toolcode : tool path\r
939 self._ToolChainFamily = None\r
940 self._BuildRuleFamily = None\r
941 self._BuildOption = None # toolcode : option\r
942 self._EdkBuildOption = None # edktoolcode : option\r
943 self._EdkIIBuildOption = None # edkiitoolcode : option\r
944 self._PackageList = None\r
945 self._ModuleAutoGenList = None\r
946 self._LibraryAutoGenList = None\r
947 self._BuildCommand = None\r
a0a2cd1e
FB
948 self._AsBuildInfList = []\r
949 self._AsBuildModuleList = []\r
950 if GlobalData.gFdfParser != None:\r
951 self._AsBuildInfList = GlobalData.gFdfParser.Profile.InfList\r
952 for Inf in self._AsBuildInfList:\r
953 InfClass = PathClass(NormPath(Inf), GlobalData.gWorkspace, self.Arch)\r
954 M = self.BuildDatabase[InfClass, self.Arch, self.BuildTarget, self.ToolChain]\r
955 if not M.IsSupportedArch:\r
956 continue\r
957 self._AsBuildModuleList.append(InfClass)\r
03af2753
HC
958 # get library/modules for build\r
959 self.LibraryBuildDirectoryList = []\r
960 self.ModuleBuildDirectoryList = []\r
52302d4d
LG
961 return True\r
962\r
963 def __repr__(self):\r
964 return "%s [%s]" % (self.MetaFile, self.Arch)\r
965\r
966 ## Create autogen code for platform and modules\r
967 #\r
968 # Since there's no autogen code for platform, this method will do nothing\r
969 # if CreateModuleCodeFile is set to False.\r
970 #\r
971 # @param CreateModuleCodeFile Flag indicating if creating module's\r
972 # autogen code file or not\r
973 #\r
974 def CreateCodeFile(self, CreateModuleCodeFile=False):\r
975 # only module has code to be greated, so do nothing if CreateModuleCodeFile is False\r
976 if self.IsCodeFileCreated or not CreateModuleCodeFile:\r
977 return\r
978\r
979 for Ma in self.ModuleAutoGenList:\r
980 Ma.CreateCodeFile(True)\r
981\r
982 # don't do this twice\r
983 self.IsCodeFileCreated = True\r
984\r
03af2753
HC
985 ## Generate Fds Command\r
986 def _GenFdsCommand(self):\r
987 return self.Workspace.GenFdsCommand\r
988 \r
52302d4d
LG
989 ## Create makefile for the platform and mdoules in it\r
990 #\r
991 # @param CreateModuleMakeFile Flag indicating if the makefile for\r
992 # modules will be created as well\r
993 #\r
994 def CreateMakeFile(self, CreateModuleMakeFile=False):\r
995 if CreateModuleMakeFile:\r
996 for ModuleFile in self.Platform.Modules:\r
997 Ma = ModuleAutoGen(self.Workspace, ModuleFile, self.BuildTarget,\r
998 self.ToolChain, self.Arch, self.MetaFile)\r
999 Ma.CreateMakeFile(True)\r
97fa0ee9 1000 #Ma.CreateAsBuiltInf()\r
52302d4d
LG
1001\r
1002 # no need to create makefile for the platform more than once\r
1003 if self.IsMakeFileCreated:\r
1004 return\r
1005\r
03af2753 1006 # create library/module build dirs for platform\r
52302d4d 1007 Makefile = GenMake.PlatformMakefile(self)\r
03af2753
HC
1008 self.LibraryBuildDirectoryList = Makefile.GetLibraryBuildDirectoryList()\r
1009 self.ModuleBuildDirectoryList = Makefile.GetModuleBuildDirectoryList()\r
1010\r
52302d4d
LG
1011 self.IsMakeFileCreated = True\r
1012\r
2bc3256c
LG
1013 ## Deal with Shared FixedAtBuild Pcds\r
1014 #\r
1015 def CollectFixedAtBuildPcds(self):\r
1016 for LibAuto in self.LibraryAutoGenList:\r
1017 FixedAtBuildPcds = {} \r
1018 ShareFixedAtBuildPcdsSameValue = {} \r
1019 for Module in LibAuto._ReferenceModules: \r
1020 for Pcd in Module.FixedAtBuildPcds + LibAuto.FixedAtBuildPcds:\r
1021 key = ".".join((Pcd.TokenSpaceGuidCName,Pcd.TokenCName)) \r
1022 if key not in FixedAtBuildPcds:\r
1023 ShareFixedAtBuildPcdsSameValue[key] = True\r
1024 FixedAtBuildPcds[key] = Pcd.DefaultValue\r
1025 else:\r
1026 if FixedAtBuildPcds[key] != Pcd.DefaultValue:\r
1027 ShareFixedAtBuildPcdsSameValue[key] = False \r
1028 for Pcd in LibAuto.FixedAtBuildPcds:\r
1029 key = ".".join((Pcd.TokenSpaceGuidCName,Pcd.TokenCName))\r
1030 if (Pcd.TokenCName,Pcd.TokenSpaceGuidCName) not in self.NonDynamicPcdDict:\r
1031 continue\r
1032 else:\r
1033 DscPcd = self.NonDynamicPcdDict[(Pcd.TokenCName,Pcd.TokenSpaceGuidCName)]\r
1034 if DscPcd.Type != "FixedAtBuild":\r
1035 continue\r
1036 if key in ShareFixedAtBuildPcdsSameValue and ShareFixedAtBuildPcdsSameValue[key]: \r
1037 LibAuto.ConstPcd[key] = Pcd.DefaultValue\r
1038\r
52302d4d
LG
1039 ## Collect dynamic PCDs\r
1040 #\r
1041 # Gather dynamic PCDs list from each module and their settings from platform\r
1042 # This interface should be invoked explicitly when platform action is created.\r
1043 #\r
1044 def CollectPlatformDynamicPcds(self):\r
763e8edf
YZ
1045 # Override the platform Pcd's value by build option\r
1046 if GlobalData.BuildOptionPcd:\r
1047 for key in self.Platform.Pcds:\r
1048 PlatformPcd = self.Platform.Pcds[key]\r
1049 for PcdItem in GlobalData.BuildOptionPcd:\r
1050 if (PlatformPcd.TokenSpaceGuidCName, PlatformPcd.TokenCName) == (PcdItem[0], PcdItem[1]):\r
1051 PlatformPcd.DefaultValue = PcdItem[2]\r
1052 if PlatformPcd.SkuInfoList:\r
1053 Sku = PlatformPcd.SkuInfoList[PlatformPcd.SkuInfoList.keys()[0]]\r
1054 Sku.DefaultValue = PcdItem[2]\r
1055 break\r
1056\r
52302d4d
LG
1057 # for gathering error information\r
1058 NoDatumTypePcdList = set()\r
a0a2cd1e 1059 PcdNotInDb = []\r
52302d4d 1060 self._GuidValue = {}\r
a0a2cd1e
FB
1061 FdfModuleList = []\r
1062 for InfName in self._AsBuildInfList:\r
05cc51ad 1063 InfName = mws.join(self.WorkspaceDir, InfName)\r
a0a2cd1e 1064 FdfModuleList.append(os.path.normpath(InfName))\r
52302d4d
LG
1065 for F in self.Platform.Modules.keys():\r
1066 M = ModuleAutoGen(self.Workspace, F, self.BuildTarget, self.ToolChain, self.Arch, self.MetaFile)\r
1067 #GuidValue.update(M.Guids)\r
1068 \r
1069 self.Platform.Modules[F].M = M\r
47fea6af
YZ
1070\r
1071 for PcdFromModule in M.ModulePcdList + M.LibraryPcdList:\r
52302d4d 1072 # make sure that the "VOID*" kind of datum has MaxDatumSize set\r
e8a47801 1073 if PcdFromModule.DatumType == "VOID*" and PcdFromModule.MaxDatumSize in [None, '']:\r
52302d4d
LG
1074 NoDatumTypePcdList.add("%s.%s [%s]" % (PcdFromModule.TokenSpaceGuidCName, PcdFromModule.TokenCName, F))\r
1075\r
97fa0ee9 1076 # Check the PCD from Binary INF or Source INF\r
a0a2cd1e
FB
1077 if M.IsBinaryModule == True:\r
1078 PcdFromModule.IsFromBinaryInf = True\r
97fa0ee9
YL
1079\r
1080 # Check the PCD from DSC or not \r
a0a2cd1e
FB
1081 if (PcdFromModule.TokenCName, PcdFromModule.TokenSpaceGuidCName) in self.Platform.Pcds.keys():\r
1082 PcdFromModule.IsFromDsc = True\r
1083 else:\r
1084 PcdFromModule.IsFromDsc = False\r
52302d4d 1085 if PcdFromModule.Type in GenC.gDynamicPcd or PcdFromModule.Type in GenC.gDynamicExPcd:\r
a0a2cd1e
FB
1086 if F.Path not in FdfModuleList:\r
1087 # If one of the Source built modules listed in the DSC is not listed \r
1088 # in FDF modules, and the INF lists a PCD can only use the PcdsDynamic \r
1089 # access method (it is only listed in the DEC file that declares the \r
1090 # PCD as PcdsDynamic), then build tool will report warning message\r
1091 # notify the PI that they are attempting to build a module that must \r
1092 # be included in a flash image in order to be functional. These Dynamic \r
1093 # PCD will not be added into the Database unless it is used by other \r
1094 # modules that are included in the FDF file.\r
1095 if PcdFromModule.Type in GenC.gDynamicPcd and \\r
1096 PcdFromModule.IsFromBinaryInf == False:\r
1097 # Print warning message to let the developer make a determine.\r
1098 if PcdFromModule not in PcdNotInDb:\r
a0a2cd1e
FB
1099 PcdNotInDb.append(PcdFromModule)\r
1100 continue\r
1101 # If one of the Source built modules listed in the DSC is not listed in \r
1102 # FDF modules, and the INF lists a PCD can only use the PcdsDynamicEx \r
1103 # access method (it is only listed in the DEC file that declares the \r
1104 # PCD as PcdsDynamicEx), then DO NOT break the build; DO NOT add the \r
1105 # PCD to the Platform's PCD Database.\r
1106 if PcdFromModule.Type in GenC.gDynamicExPcd:\r
1107 if PcdFromModule not in PcdNotInDb:\r
1108 PcdNotInDb.append(PcdFromModule)\r
1109 continue\r
52302d4d
LG
1110 #\r
1111 # If a dynamic PCD used by a PEM module/PEI module & DXE module,\r
1112 # it should be stored in Pcd PEI database, If a dynamic only\r
1113 # used by DXE module, it should be stored in DXE PCD database.\r
1114 # The default Phase is DXE\r
1115 #\r
1116 if M.ModuleType in ["PEIM", "PEI_CORE"]:\r
1117 PcdFromModule.Phase = "PEI"\r
1118 if PcdFromModule not in self._DynaPcdList_:\r
1119 self._DynaPcdList_.append(PcdFromModule)\r
1120 elif PcdFromModule.Phase == 'PEI':\r
1121 # overwrite any the same PCD existing, if Phase is PEI\r
1122 Index = self._DynaPcdList_.index(PcdFromModule)\r
1123 self._DynaPcdList_[Index] = PcdFromModule\r
1124 elif PcdFromModule not in self._NonDynaPcdList_:\r
1125 self._NonDynaPcdList_.append(PcdFromModule)\r
a0a2cd1e
FB
1126 elif PcdFromModule in self._NonDynaPcdList_ and PcdFromModule.IsFromBinaryInf == True:\r
1127 Index = self._NonDynaPcdList_.index(PcdFromModule)\r
1128 if self._NonDynaPcdList_[Index].IsFromBinaryInf == False:\r
1129 #The PCD from Binary INF will override the same one from source INF\r
1130 self._NonDynaPcdList_.remove (self._NonDynaPcdList_[Index])\r
1131 PcdFromModule.Pending = False\r
1132 self._NonDynaPcdList_.append (PcdFromModule)\r
1133 # Parse the DynamicEx PCD from the AsBuild INF module list of FDF.\r
1134 DscModuleList = []\r
1135 for ModuleInf in self.Platform.Modules.keys():\r
1136 DscModuleList.append (os.path.normpath(ModuleInf.Path))\r
1137 # add the PCD from modules that listed in FDF but not in DSC to Database \r
1138 for InfName in FdfModuleList:\r
1139 if InfName not in DscModuleList:\r
1140 InfClass = PathClass(InfName)\r
1141 M = self.BuildDatabase[InfClass, self.Arch, self.BuildTarget, self.ToolChain]\r
1142 # If a module INF in FDF but not in current arch's DSC module list, it must be module (either binary or source) \r
1143 # for different Arch. PCDs in source module for different Arch is already added before, so skip the source module here. \r
1144 # For binary module, if in current arch, we need to list the PCDs into database. \r
1145 if not M.IsSupportedArch:\r
1146 continue\r
1147 # Override the module PCD setting by platform setting\r
1148 ModulePcdList = self.ApplyPcdSetting(M, M.Pcds)\r
1149 for PcdFromModule in ModulePcdList:\r
1150 PcdFromModule.IsFromBinaryInf = True\r
1151 PcdFromModule.IsFromDsc = False\r
1152 # Only allow the DynamicEx and Patchable PCD in AsBuild INF\r
1153 if PcdFromModule.Type not in GenC.gDynamicExPcd and PcdFromModule.Type not in TAB_PCDS_PATCHABLE_IN_MODULE:\r
1154 EdkLogger.error("build", AUTOGEN_ERROR, "PCD setting error",\r
1155 File=self.MetaFile,\r
1156 ExtraData="\n\tExisted %s PCD %s in:\n\t\t%s\n"\r
1157 % (PcdFromModule.Type, PcdFromModule.TokenCName, InfName))\r
1158 # make sure that the "VOID*" kind of datum has MaxDatumSize set\r
1159 if PcdFromModule.DatumType == "VOID*" and PcdFromModule.MaxDatumSize in [None, '']:\r
1160 NoDatumTypePcdList.add("%s.%s [%s]" % (PcdFromModule.TokenSpaceGuidCName, PcdFromModule.TokenCName, InfName))\r
1161 if M.ModuleType in ["PEIM", "PEI_CORE"]:\r
1162 PcdFromModule.Phase = "PEI"\r
1163 if PcdFromModule not in self._DynaPcdList_ and PcdFromModule.Type in GenC.gDynamicExPcd:\r
1164 self._DynaPcdList_.append(PcdFromModule)\r
1165 elif PcdFromModule not in self._NonDynaPcdList_ and PcdFromModule.Type in TAB_PCDS_PATCHABLE_IN_MODULE:\r
1166 self._NonDynaPcdList_.append(PcdFromModule)\r
1167 if PcdFromModule in self._DynaPcdList_ and PcdFromModule.Phase == 'PEI' and PcdFromModule.Type in GenC.gDynamicExPcd:\r
97fa0ee9
YL
1168 # Overwrite the phase of any the same PCD existing, if Phase is PEI.\r
1169 # It is to solve the case that a dynamic PCD used by a PEM module/PEI \r
1170 # module & DXE module at a same time.\r
1171 # Overwrite the type of the PCDs in source INF by the type of AsBuild\r
1172 # INF file as DynamicEx. \r
a0a2cd1e
FB
1173 Index = self._DynaPcdList_.index(PcdFromModule)\r
1174 self._DynaPcdList_[Index].Phase = PcdFromModule.Phase\r
1175 self._DynaPcdList_[Index].Type = PcdFromModule.Type\r
1176 for PcdFromModule in self._NonDynaPcdList_:\r
1177 # If a PCD is not listed in the DSC file, but binary INF files used by \r
1178 # this platform all (that use this PCD) list the PCD in a [PatchPcds] \r
1179 # section, AND all source INF files used by this platform the build \r
1180 # that use the PCD list the PCD in either a [Pcds] or [PatchPcds] \r
1181 # section, then the tools must NOT add the PCD to the Platform's PCD\r
1182 # Database; the build must assign the access method for this PCD as \r
1183 # PcdsPatchableInModule.\r
1184 if PcdFromModule not in self._DynaPcdList_:\r
1185 continue\r
1186 Index = self._DynaPcdList_.index(PcdFromModule)\r
1187 if PcdFromModule.IsFromDsc == False and \\r
1188 PcdFromModule.Type in TAB_PCDS_PATCHABLE_IN_MODULE and \\r
1189 PcdFromModule.IsFromBinaryInf == True and \\r
1190 self._DynaPcdList_[Index].IsFromBinaryInf == False:\r
1191 Index = self._DynaPcdList_.index(PcdFromModule)\r
1192 self._DynaPcdList_.remove (self._DynaPcdList_[Index])\r
52302d4d
LG
1193\r
1194 # print out error information and break the build, if error found\r
1195 if len(NoDatumTypePcdList) > 0:\r
1196 NoDatumTypePcdListString = "\n\t\t".join(NoDatumTypePcdList)\r
1197 EdkLogger.error("build", AUTOGEN_ERROR, "PCD setting error",\r
1198 File=self.MetaFile,\r
1199 ExtraData="\n\tPCD(s) without MaxDatumSize:\n\t\t%s\n"\r
1200 % NoDatumTypePcdListString)\r
1201 self._NonDynamicPcdList = self._NonDynaPcdList_\r
1202 self._DynamicPcdList = self._DynaPcdList_\r
52302d4d
LG
1203 #\r
1204 # Sort dynamic PCD list to:\r
1205 # 1) If PCD's datum type is VOID* and value is unicode string which starts with L, the PCD item should \r
1206 # try to be put header of dynamicd List\r
1207 # 2) If PCD is HII type, the PCD item should be put after unicode type PCD\r
1208 #\r
1209 # The reason of sorting is make sure the unicode string is in double-byte alignment in string table.\r
1210 #\r
1211 UnicodePcdArray = []\r
1212 HiiPcdArray = []\r
1213 OtherPcdArray = []\r
6780eef1 1214 VpdPcdDict = {}\r
e56468c0 1215 VpdFile = VpdInfoFile.VpdInfoFile()\r
1216 NeedProcessVpdMapFile = False \r
1217 \r
1218 if (self.Workspace.ArchList[-1] == self.Arch): \r
1219 for Pcd in self._DynamicPcdList:\r
e56468c0 1220 # just pick the a value to determine whether is unicode string type\r
47fea6af 1221 Sku = Pcd.SkuInfoList[Pcd.SkuInfoList.keys()[0]]\r
e56468c0 1222 Sku.VpdOffset = Sku.VpdOffset.strip()\r
47fea6af 1223\r
e56468c0 1224 PcdValue = Sku.DefaultValue\r
1225 if Pcd.DatumType == 'VOID*' and PcdValue.startswith("L"):\r
1226 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex\r
1227 UnicodePcdArray.append(Pcd)\r
1228 elif len(Sku.VariableName) > 0:\r
1229 # if found HII type PCD then insert to right of UnicodeIndex\r
1230 HiiPcdArray.append(Pcd)\r
1231 else:\r
1232 OtherPcdArray.append(Pcd)\r
e56468c0 1233 if Pcd.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD]:\r
47fea6af
YZ
1234 VpdPcdDict[(Pcd.TokenCName, Pcd.TokenSpaceGuidCName)] = Pcd\r
1235\r
6780eef1 1236 PlatformPcds = self.Platform.Pcds.keys()\r
47fea6af 1237 PlatformPcds.sort()\r
6780eef1
LG
1238 #\r
1239 # Add VPD type PCD into VpdFile and determine whether the VPD PCD need to be fixed up.\r
1240 #\r
1241 for PcdKey in PlatformPcds:\r
e8a47801
LG
1242 Pcd = self.Platform.Pcds[PcdKey]\r
1243 if Pcd.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD] and \\r
1244 PcdKey in VpdPcdDict:\r
1245 Pcd = VpdPcdDict[PcdKey]\r
1246 for (SkuName,Sku) in Pcd.SkuInfoList.items():\r
1247 Sku.VpdOffset = Sku.VpdOffset.strip()\r
5a13737a
YZ
1248 PcdValue = Sku.DefaultValue\r
1249 if PcdValue == "":\r
1250 PcdValue = Pcd.DefaultValue\r
1251 if Sku.VpdOffset != '*':\r
1252 if PcdValue.startswith("{"):\r
1253 Alignment = 8\r
1254 elif PcdValue.startswith("L"):\r
1255 Alignment = 2\r
1256 else:\r
1257 Alignment = 1\r
ca85291f
YZ
1258 try:\r
1259 VpdOffset = int(Sku.VpdOffset)\r
1260 except:\r
1261 try:\r
1262 VpdOffset = int(Sku.VpdOffset, 16)\r
1263 except:\r
1264 EdkLogger.error("build", FORMAT_INVALID, "Invalid offset value %s for PCD %s.%s." % (Sku.VpdOffset, Pcd.TokenSpaceGuidCName, Pcd.TokenCName))\r
1265 if VpdOffset % Alignment != 0:\r
815ada26
YZ
1266 if PcdValue.startswith("{"):\r
1267 EdkLogger.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(Pcd.TokenSpaceGuidCName, Pcd.TokenCName), File=self.MetaFile)\r
1268 else:\r
1269 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
1270 VpdFile.Add(Pcd, Sku.VpdOffset)\r
1271 # if the offset of a VPD is *, then it need to be fixed up by third party tool.\r
1272 if not NeedProcessVpdMapFile and Sku.VpdOffset == "*":\r
1273 NeedProcessVpdMapFile = True\r
1274 if self.Platform.VpdToolGuid == None or self.Platform.VpdToolGuid == '':\r
1275 EdkLogger.error("Build", FILE_NOT_FOUND, \\r
1276 "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
1277\r
1278\r
e56468c0 1279 #\r
1280 # Fix the PCDs define in VPD PCD section that never referenced by module.\r
1281 # An example is PCD for signature usage.\r
6780eef1
LG
1282 # \r
1283 for DscPcd in PlatformPcds:\r
e56468c0 1284 DscPcdEntry = self.Platform.Pcds[DscPcd]\r
1285 if DscPcdEntry.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD]:\r
1286 if not (self.Platform.VpdToolGuid == None or self.Platform.VpdToolGuid == ''):\r
1287 FoundFlag = False\r
1288 for VpdPcd in VpdFile._VpdArray.keys():\r
1289 # This PCD has been referenced by module\r
1290 if (VpdPcd.TokenSpaceGuidCName == DscPcdEntry.TokenSpaceGuidCName) and \\r
1291 (VpdPcd.TokenCName == DscPcdEntry.TokenCName):\r
1292 FoundFlag = True\r
47fea6af 1293\r
e56468c0 1294 # Not found, it should be signature\r
1295 if not FoundFlag :\r
1296 # just pick the a value to determine whether is unicode string type\r
e8a47801
LG
1297 for (SkuName,Sku) in DscPcdEntry.SkuInfoList.items():\r
1298 Sku.VpdOffset = Sku.VpdOffset.strip() \r
1299 \r
1300 # Need to iterate DEC pcd information to get the value & datumtype\r
1301 for eachDec in self.PackageList:\r
1302 for DecPcd in eachDec.Pcds:\r
1303 DecPcdEntry = eachDec.Pcds[DecPcd]\r
1304 if (DecPcdEntry.TokenSpaceGuidCName == DscPcdEntry.TokenSpaceGuidCName) and \\r
1305 (DecPcdEntry.TokenCName == DscPcdEntry.TokenCName):\r
1306 # Print warning message to let the developer make a determine.\r
1307 EdkLogger.warn("build", "Unreferenced vpd pcd used!",\r
1308 File=self.MetaFile, \\r
1309 ExtraData = "PCD: %s.%s used in the DSC file %s is unreferenced." \\r
1310 %(DscPcdEntry.TokenSpaceGuidCName, DscPcdEntry.TokenCName, self.Platform.MetaFile.Path)) \r
1311 \r
1312 DscPcdEntry.DatumType = DecPcdEntry.DatumType\r
1313 DscPcdEntry.DefaultValue = DecPcdEntry.DefaultValue\r
1314 DscPcdEntry.TokenValue = DecPcdEntry.TokenValue\r
1315 DscPcdEntry.TokenSpaceGuidValue = eachDec.Guids[DecPcdEntry.TokenSpaceGuidCName]\r
1316 # Only fix the value while no value provided in DSC file.\r
1317 if (Sku.DefaultValue == "" or Sku.DefaultValue==None):\r
1318 DscPcdEntry.SkuInfoList[DscPcdEntry.SkuInfoList.keys()[0]].DefaultValue = DecPcdEntry.DefaultValue\r
1319 \r
1320 if DscPcdEntry not in self._DynamicPcdList:\r
1321 self._DynamicPcdList.append(DscPcdEntry)\r
1322# Sku = DscPcdEntry.SkuInfoList[DscPcdEntry.SkuInfoList.keys()[0]]\r
1323 Sku.VpdOffset = Sku.VpdOffset.strip()\r
1324 PcdValue = Sku.DefaultValue\r
5a13737a
YZ
1325 if PcdValue == "":\r
1326 PcdValue = DscPcdEntry.DefaultValue\r
1327 if Sku.VpdOffset != '*':\r
1328 if PcdValue.startswith("{"):\r
1329 Alignment = 8\r
1330 elif PcdValue.startswith("L"):\r
1331 Alignment = 2\r
1332 else:\r
1333 Alignment = 1\r
ca85291f
YZ
1334 try:\r
1335 VpdOffset = int(Sku.VpdOffset)\r
1336 except:\r
1337 try:\r
1338 VpdOffset = int(Sku.VpdOffset, 16)\r
1339 except:\r
1340 EdkLogger.error("build", FORMAT_INVALID, "Invalid offset value %s for PCD %s.%s." % (Sku.VpdOffset, DscPcdEntry.TokenSpaceGuidCName, DscPcdEntry.TokenCName))\r
1341 if VpdOffset % Alignment != 0:\r
815ada26
YZ
1342 if PcdValue.startswith("{"):\r
1343 EdkLogger.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(DscPcdEntry.TokenSpaceGuidCName, DscPcdEntry.TokenCName), File=self.MetaFile)\r
1344 else:\r
1345 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
1346 VpdFile.Add(DscPcdEntry, Sku.VpdOffset)\r
1347 if not NeedProcessVpdMapFile and Sku.VpdOffset == "*":\r
1348 NeedProcessVpdMapFile = True \r
1349 if DscPcdEntry.DatumType == 'VOID*' and PcdValue.startswith("L"):\r
1350 UnicodePcdArray.append(DscPcdEntry)\r
1351 elif len(Sku.VariableName) > 0:\r
1352 HiiPcdArray.append(DscPcdEntry)\r
1353 else:\r
1354 OtherPcdArray.append(DscPcdEntry)\r
1355 \r
1356 # if the offset of a VPD is *, then it need to be fixed up by third party tool.\r
e56468c0 1357 \r
e56468c0 1358 \r
1359 \r
1360 if (self.Platform.FlashDefinition == None or self.Platform.FlashDefinition == '') and \\r
1361 VpdFile.GetCount() != 0:\r
1362 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE, \r
1363 "Fail to get FLASH_DEFINITION definition in DSC file %s which is required when DSC contains VPD PCD." % str(self.Platform.MetaFile))\r
47fea6af 1364\r
e56468c0 1365 if VpdFile.GetCount() != 0:\r
e56468c0 1366 FvPath = os.path.join(self.BuildDir, "FV")\r
1367 if not os.path.exists(FvPath):\r
1368 try:\r
1369 os.makedirs(FvPath)\r
1370 except:\r
1371 EdkLogger.error("build", FILE_WRITE_FAILURE, "Fail to create FV folder under %s" % self.BuildDir)\r
47fea6af 1372\r
08dd311f
LG
1373 VpdFilePath = os.path.join(FvPath, "%s.txt" % self.Platform.VpdToolGuid)\r
1374\r
e459de78 1375 if VpdFile.Write(VpdFilePath):\r
e56468c0 1376 # retrieve BPDG tool's path from tool_def.txt according to VPD_TOOL_GUID defined in DSC file.\r
1377 BPDGToolName = None\r
1378 for ToolDef in self.ToolDefinition.values():\r
1379 if ToolDef.has_key("GUID") and ToolDef["GUID"] == self.Platform.VpdToolGuid:\r
1380 if not ToolDef.has_key("PATH"):\r
1381 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE, "PATH attribute was not provided for BPDG guid tool %s in tools_def.txt" % self.Platform.VpdToolGuid)\r
1382 BPDGToolName = ToolDef["PATH"]\r
1383 break\r
1384 # Call third party GUID BPDG tool.\r
1385 if BPDGToolName != None:\r
08dd311f 1386 VpdInfoFile.CallExtenalBPDGTool(BPDGToolName, VpdFilePath)\r
e56468c0 1387 else:\r
1388 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 1389\r
e56468c0 1390 # Process VPD map file generated by third party BPDG tool\r
1391 if NeedProcessVpdMapFile:\r
08dd311f 1392 VpdMapFilePath = os.path.join(self.BuildDir, "FV", "%s.map" % self.Platform.VpdToolGuid)\r
e56468c0 1393 if os.path.exists(VpdMapFilePath):\r
1394 VpdFile.Read(VpdMapFilePath)\r
47fea6af 1395\r
e56468c0 1396 # Fixup "*" offset\r
1397 for Pcd in self._DynamicPcdList:\r
1398 # just pick the a value to determine whether is unicode string type\r
e8a47801
LG
1399 i = 0\r
1400 for (SkuName,Sku) in Pcd.SkuInfoList.items(): \r
1401 if Sku.VpdOffset == "*":\r
1402 Sku.VpdOffset = VpdFile.GetOffset(Pcd)[i].strip()\r
1403 i += 1\r
e56468c0 1404 else:\r
1405 EdkLogger.error("build", FILE_READ_FAILURE, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath)\r
47fea6af 1406\r
e56468c0 1407 # Delete the DynamicPcdList At the last time enter into this function \r
47fea6af 1408 del self._DynamicPcdList[:]\r
52302d4d
LG
1409 self._DynamicPcdList.extend(UnicodePcdArray)\r
1410 self._DynamicPcdList.extend(HiiPcdArray)\r
1411 self._DynamicPcdList.extend(OtherPcdArray)\r
a0a2cd1e 1412 self.AllPcdList = self._NonDynamicPcdList + self._DynamicPcdList\r
52302d4d
LG
1413 \r
1414 ## Return the platform build data object\r
1415 def _GetPlatform(self):\r
1416 if self._Platform == None:\r
0d2711a6 1417 self._Platform = self.BuildDatabase[self.MetaFile, self.Arch, self.BuildTarget, self.ToolChain]\r
52302d4d
LG
1418 return self._Platform\r
1419\r
1420 ## Return platform name\r
1421 def _GetName(self):\r
1422 return self.Platform.PlatformName\r
1423\r
1424 ## Return the meta file GUID\r
1425 def _GetGuid(self):\r
1426 return self.Platform.Guid\r
1427\r
1428 ## Return the platform version\r
1429 def _GetVersion(self):\r
1430 return self.Platform.Version\r
1431\r
1432 ## Return the FDF file name\r
1433 def _GetFdfFile(self):\r
1434 if self._FdfFile == None:\r
1435 if self.Workspace.FdfFile != "":\r
05cc51ad 1436 self._FdfFile= mws.join(self.WorkspaceDir, self.Workspace.FdfFile)\r
52302d4d
LG
1437 else:\r
1438 self._FdfFile = ''\r
1439 return self._FdfFile\r
1440\r
1441 ## Return the build output directory platform specifies\r
1442 def _GetOutputDir(self):\r
1443 return self.Platform.OutputDirectory\r
1444\r
1445 ## Return the directory to store all intermediate and final files built\r
1446 def _GetBuildDir(self):\r
1447 if self._BuildDir == None:\r
1448 if os.path.isabs(self.OutputDir):\r
1449 self._BuildDir = path.join(\r
1450 path.abspath(self.OutputDir),\r
1451 self.BuildTarget + "_" + self.ToolChain,\r
1452 )\r
1453 else:\r
1454 self._BuildDir = path.join(\r
1455 self.WorkspaceDir,\r
1456 self.OutputDir,\r
1457 self.BuildTarget + "_" + self.ToolChain,\r
1458 )\r
1459 return self._BuildDir\r
1460\r
1461 ## Return directory of platform makefile\r
1462 #\r
1463 # @retval string Makefile directory\r
1464 #\r
1465 def _GetMakeFileDir(self):\r
1466 if self._MakeFileDir == None:\r
1467 self._MakeFileDir = path.join(self.BuildDir, self.Arch)\r
1468 return self._MakeFileDir\r
1469\r
1470 ## Return build command string\r
1471 #\r
1472 # @retval string Build command string\r
1473 #\r
1474 def _GetBuildCommand(self):\r
1475 if self._BuildCommand == None:\r
1476 self._BuildCommand = []\r
1477 if "MAKE" in self.ToolDefinition and "PATH" in self.ToolDefinition["MAKE"]:\r
1478 self._BuildCommand += SplitOption(self.ToolDefinition["MAKE"]["PATH"])\r
1479 if "FLAGS" in self.ToolDefinition["MAKE"]:\r
1480 NewOption = self.ToolDefinition["MAKE"]["FLAGS"].strip()\r
1481 if NewOption != '':\r
6780eef1 1482 self._BuildCommand += SplitOption(NewOption)\r
52302d4d
LG
1483 return self._BuildCommand\r
1484\r
1485 ## Get tool chain definition\r
1486 #\r
1487 # Get each tool defition for given tool chain from tools_def.txt and platform\r
1488 #\r
1489 def _GetToolDefinition(self):\r
1490 if self._ToolDefinitions == None:\r
1491 ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDictionary\r
1492 if TAB_TOD_DEFINES_COMMAND_TYPE not in self.Workspace.ToolDef.ToolsDefTxtDatabase:\r
1493 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "No tools found in configuration",\r
1494 ExtraData="[%s]" % self.MetaFile)\r
1495 self._ToolDefinitions = {}\r
1496 DllPathList = set()\r
1497 for Def in ToolDefinition:\r
1498 Target, Tag, Arch, Tool, Attr = Def.split("_")\r
1499 if Target != self.BuildTarget or Tag != self.ToolChain or Arch != self.Arch:\r
1500 continue\r
1501\r
1502 Value = ToolDefinition[Def]\r
1503 # don't record the DLL\r
1504 if Attr == "DLL":\r
1505 DllPathList.add(Value)\r
1506 continue\r
1507\r
1508 if Tool not in self._ToolDefinitions:\r
1509 self._ToolDefinitions[Tool] = {}\r
1510 self._ToolDefinitions[Tool][Attr] = Value\r
1511\r
1512 ToolsDef = ''\r
1513 MakePath = ''\r
1514 if GlobalData.gOptions.SilentMode and "MAKE" in self._ToolDefinitions:\r
1515 if "FLAGS" not in self._ToolDefinitions["MAKE"]:\r
1516 self._ToolDefinitions["MAKE"]["FLAGS"] = ""\r
1517 self._ToolDefinitions["MAKE"]["FLAGS"] += " -s"\r
1518 MakeFlags = ''\r
1519 for Tool in self._ToolDefinitions:\r
1520 for Attr in self._ToolDefinitions[Tool]:\r
1521 Value = self._ToolDefinitions[Tool][Attr]\r
1522 if Tool in self.BuildOption and Attr in self.BuildOption[Tool]:\r
1523 # check if override is indicated\r
1524 if self.BuildOption[Tool][Attr].startswith('='):\r
1525 Value = self.BuildOption[Tool][Attr][1:]\r
1526 else:\r
1527 Value += " " + self.BuildOption[Tool][Attr]\r
1528\r
1529 if Attr == "PATH":\r
1530 # Don't put MAKE definition in the file\r
1531 if Tool == "MAKE":\r
1532 MakePath = Value\r
1533 else:\r
1534 ToolsDef += "%s = %s\n" % (Tool, Value)\r
1535 elif Attr != "DLL":\r
1536 # Don't put MAKE definition in the file\r
1537 if Tool == "MAKE":\r
1538 if Attr == "FLAGS":\r
1539 MakeFlags = Value\r
1540 else:\r
1541 ToolsDef += "%s_%s = %s\n" % (Tool, Attr, Value)\r
1542 ToolsDef += "\n"\r
1543\r
1544 SaveFileOnChange(self.ToolDefinitionFile, ToolsDef)\r
1545 for DllPath in DllPathList:\r
1546 os.environ["PATH"] = DllPath + os.pathsep + os.environ["PATH"]\r
1547 os.environ["MAKE_FLAGS"] = MakeFlags\r
1548\r
1549 return self._ToolDefinitions\r
1550\r
1551 ## Return the paths of tools\r
1552 def _GetToolDefFile(self):\r
1553 if self._ToolDefFile == None:\r
1554 self._ToolDefFile = os.path.join(self.MakeFileDir, "TOOLS_DEF." + self.Arch)\r
1555 return self._ToolDefFile\r
1556\r
1557 ## Retrieve the toolchain family of given toolchain tag. Default to 'MSFT'.\r
1558 def _GetToolChainFamily(self):\r
1559 if self._ToolChainFamily == None:\r
1560 ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDatabase\r
1561 if TAB_TOD_DEFINES_FAMILY not in ToolDefinition \\r
1562 or self.ToolChain not in ToolDefinition[TAB_TOD_DEFINES_FAMILY] \\r
1563 or not ToolDefinition[TAB_TOD_DEFINES_FAMILY][self.ToolChain]:\r
1564 EdkLogger.verbose("No tool chain family found in configuration for %s. Default to MSFT." \\r
1565 % self.ToolChain)\r
1566 self._ToolChainFamily = "MSFT"\r
1567 else:\r
1568 self._ToolChainFamily = ToolDefinition[TAB_TOD_DEFINES_FAMILY][self.ToolChain]\r
1569 return self._ToolChainFamily\r
1570\r
1571 def _GetBuildRuleFamily(self):\r
1572 if self._BuildRuleFamily == None:\r
1573 ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDatabase\r
1574 if TAB_TOD_DEFINES_BUILDRULEFAMILY not in ToolDefinition \\r
1575 or self.ToolChain not in ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY] \\r
1576 or not ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY][self.ToolChain]:\r
1577 EdkLogger.verbose("No tool chain family found in configuration for %s. Default to MSFT." \\r
1578 % self.ToolChain)\r
1579 self._BuildRuleFamily = "MSFT"\r
1580 else:\r
1581 self._BuildRuleFamily = ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY][self.ToolChain]\r
1582 return self._BuildRuleFamily\r
1583\r
1584 ## Return the build options specific for all modules in this platform\r
1585 def _GetBuildOptions(self):\r
1586 if self._BuildOption == None:\r
1587 self._BuildOption = self._ExpandBuildOption(self.Platform.BuildOptions)\r
1588 return self._BuildOption\r
1589\r
1590 ## Return the build options specific for EDK modules in this platform\r
1591 def _GetEdkBuildOptions(self):\r
1592 if self._EdkBuildOption == None:\r
1593 self._EdkBuildOption = self._ExpandBuildOption(self.Platform.BuildOptions, EDK_NAME)\r
1594 return self._EdkBuildOption\r
1595\r
1596 ## Return the build options specific for EDKII modules in this platform\r
1597 def _GetEdkIIBuildOptions(self):\r
1598 if self._EdkIIBuildOption == None:\r
1599 self._EdkIIBuildOption = self._ExpandBuildOption(self.Platform.BuildOptions, EDKII_NAME)\r
1600 return self._EdkIIBuildOption\r
1601\r
97fa0ee9 1602 ## Parse build_rule.txt in Conf Directory.\r
52302d4d
LG
1603 #\r
1604 # @retval BuildRule object\r
1605 #\r
1606 def _GetBuildRule(self):\r
1607 if self._BuildRule == None:\r
1608 BuildRuleFile = None\r
1609 if TAB_TAT_DEFINES_BUILD_RULE_CONF in self.Workspace.TargetTxt.TargetTxtDictionary:\r
1610 BuildRuleFile = self.Workspace.TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_BUILD_RULE_CONF]\r
1611 if BuildRuleFile in [None, '']:\r
97fa0ee9 1612 BuildRuleFile = gDefaultBuildRuleFile\r
52302d4d 1613 self._BuildRule = BuildRule(BuildRuleFile)\r
64b2609f
LG
1614 if self._BuildRule._FileVersion == "":\r
1615 self._BuildRule._FileVersion = AutoGenReqBuildRuleVerNum\r
1616 else:\r
1617 if self._BuildRule._FileVersion < AutoGenReqBuildRuleVerNum :\r
1618 # If Build Rule's version is less than the version number required by the tools, halting the build.\r
47fea6af 1619 EdkLogger.error("build", AUTOGEN_ERROR,\r
64b2609f
LG
1620 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
1621 % (self._BuildRule._FileVersion, AutoGenReqBuildRuleVerNum))\r
47fea6af 1622\r
52302d4d
LG
1623 return self._BuildRule\r
1624\r
1625 ## Summarize the packages used by modules in this platform\r
1626 def _GetPackageList(self):\r
1627 if self._PackageList == None:\r
1628 self._PackageList = set()\r
1629 for La in self.LibraryAutoGenList:\r
1630 self._PackageList.update(La.DependentPackageList)\r
1631 for Ma in self.ModuleAutoGenList:\r
1632 self._PackageList.update(Ma.DependentPackageList)\r
a0a2cd1e
FB
1633 #Collect package set information from INF of FDF\r
1634 PkgSet = set()\r
1635 for ModuleFile in self._AsBuildModuleList:\r
1636 if ModuleFile in self.Platform.Modules:\r
1637 continue\r
1638 ModuleData = self.BuildDatabase[ModuleFile, self.Arch, self.BuildTarget, self.ToolChain]\r
1639 PkgSet.update(ModuleData.Packages)\r
1640 self._PackageList = list(self._PackageList) + list (PkgSet)\r
52302d4d
LG
1641 return self._PackageList\r
1642\r
2bc3256c
LG
1643 def _GetNonDynamicPcdDict(self):\r
1644 if self._NonDynamicPcdDict:\r
1645 return self._NonDynamicPcdDict\r
1646 for Pcd in self.NonDynamicPcdList:\r
1647 self._NonDynamicPcdDict[(Pcd.TokenCName,Pcd.TokenSpaceGuidCName)] = Pcd\r
1648 return self._NonDynamicPcdDict\r
1649\r
52302d4d
LG
1650 ## Get list of non-dynamic PCDs\r
1651 def _GetNonDynamicPcdList(self):\r
e56468c0 1652 if self._NonDynamicPcdList == None:\r
1653 self.CollectPlatformDynamicPcds()\r
52302d4d
LG
1654 return self._NonDynamicPcdList\r
1655\r
1656 ## Get list of dynamic PCDs\r
1657 def _GetDynamicPcdList(self):\r
e56468c0 1658 if self._DynamicPcdList == None:\r
1659 self.CollectPlatformDynamicPcds()\r
52302d4d
LG
1660 return self._DynamicPcdList\r
1661\r
1662 ## Generate Token Number for all PCD\r
1663 def _GetPcdTokenNumbers(self):\r
1664 if self._PcdTokenNumber == None:\r
1665 self._PcdTokenNumber = sdict()\r
1666 TokenNumber = 1\r
d0acc87a
LG
1667 #\r
1668 # Make the Dynamic and DynamicEx PCD use within different TokenNumber area. \r
1669 # Such as:\r
1670 # \r
1671 # Dynamic PCD:\r
1672 # TokenNumber 0 ~ 10\r
1673 # DynamicEx PCD:\r
1674 # TokeNumber 11 ~ 20\r
1675 #\r
52302d4d
LG
1676 for Pcd in self.DynamicPcdList:\r
1677 if Pcd.Phase == "PEI":\r
d0acc87a
LG
1678 if Pcd.Type in ["Dynamic", "DynamicDefault", "DynamicVpd", "DynamicHii"]:\r
1679 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))\r
1680 self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber\r
1681 TokenNumber += 1\r
47fea6af 1682\r
d0acc87a
LG
1683 for Pcd in self.DynamicPcdList:\r
1684 if Pcd.Phase == "PEI":\r
1685 if Pcd.Type in ["DynamicEx", "DynamicExDefault", "DynamicExVpd", "DynamicExHii"]:\r
1686 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))\r
1687 self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber\r
1688 TokenNumber += 1\r
47fea6af 1689\r
52302d4d
LG
1690 for Pcd in self.DynamicPcdList:\r
1691 if Pcd.Phase == "DXE":\r
d0acc87a
LG
1692 if Pcd.Type in ["Dynamic", "DynamicDefault", "DynamicVpd", "DynamicHii"]:\r
1693 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))\r
1694 self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber\r
1695 TokenNumber += 1\r
47fea6af 1696\r
d0acc87a
LG
1697 for Pcd in self.DynamicPcdList:\r
1698 if Pcd.Phase == "DXE":\r
1699 if Pcd.Type in ["DynamicEx", "DynamicExDefault", "DynamicExVpd", "DynamicExHii"]:\r
1700 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))\r
1701 self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber\r
1702 TokenNumber += 1\r
47fea6af 1703\r
52302d4d
LG
1704 for Pcd in self.NonDynamicPcdList:\r
1705 self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber\r
1706 TokenNumber += 1\r
1707 return self._PcdTokenNumber\r
1708\r
1709 ## Summarize ModuleAutoGen objects of all modules/libraries to be built for this platform\r
1710 def _GetAutoGenObjectList(self):\r
1711 self._ModuleAutoGenList = []\r
1712 self._LibraryAutoGenList = []\r
1713 for ModuleFile in self.Platform.Modules:\r
1714 Ma = ModuleAutoGen(\r
1715 self.Workspace,\r
1716 ModuleFile,\r
1717 self.BuildTarget,\r
1718 self.ToolChain,\r
1719 self.Arch,\r
1720 self.MetaFile\r
1721 )\r
1722 if Ma not in self._ModuleAutoGenList:\r
1723 self._ModuleAutoGenList.append(Ma)\r
1724 for La in Ma.LibraryAutoGenList:\r
1725 if La not in self._LibraryAutoGenList:\r
1726 self._LibraryAutoGenList.append(La)\r
2bc3256c
LG
1727 if Ma not in La._ReferenceModules:\r
1728 La._ReferenceModules.append(Ma)\r
52302d4d
LG
1729\r
1730 ## Summarize ModuleAutoGen objects of all modules to be built for this platform\r
1731 def _GetModuleAutoGenList(self):\r
1732 if self._ModuleAutoGenList == None:\r
1733 self._GetAutoGenObjectList()\r
1734 return self._ModuleAutoGenList\r
1735\r
1736 ## Summarize ModuleAutoGen objects of all libraries to be built for this platform\r
1737 def _GetLibraryAutoGenList(self):\r
1738 if self._LibraryAutoGenList == None:\r
1739 self._GetAutoGenObjectList()\r
1740 return self._LibraryAutoGenList\r
1741\r
1742 ## Test if a module is supported by the platform\r
1743 #\r
1744 # An error will be raised directly if the module or its arch is not supported\r
1745 # by the platform or current configuration\r
1746 #\r
1747 def ValidModule(self, Module):\r
a0a2cd1e
FB
1748 return Module in self.Platform.Modules or Module in self.Platform.LibraryInstances \\r
1749 or Module in self._AsBuildModuleList\r
52302d4d
LG
1750\r
1751 ## Resolve the library classes in a module to library instances\r
1752 #\r
1753 # This method will not only resolve library classes but also sort the library\r
1754 # instances according to the dependency-ship.\r
1755 #\r
1756 # @param Module The module from which the library classes will be resolved\r
1757 #\r
1758 # @retval library_list List of library instances sorted\r
1759 #\r
1760 def ApplyLibraryInstance(self, Module):\r
1761 ModuleType = Module.ModuleType\r
1762\r
1763 # for overridding library instances with module specific setting\r
1764 PlatformModule = self.Platform.Modules[str(Module)]\r
1765\r
1766 # add forced library instances (specified under LibraryClasses sections)\r
da92f276
LG
1767 #\r
1768 # If a module has a MODULE_TYPE of USER_DEFINED,\r
1769 # do not link in NULL library class instances from the global [LibraryClasses.*] sections.\r
1770 #\r
1771 if Module.ModuleType != SUP_MODULE_USER_DEFINED:\r
1772 for LibraryClass in self.Platform.LibraryClasses.GetKeys():\r
1773 if LibraryClass.startswith("NULL") and self.Platform.LibraryClasses[LibraryClass, Module.ModuleType]:\r
1774 Module.LibraryClasses[LibraryClass] = self.Platform.LibraryClasses[LibraryClass, Module.ModuleType]\r
52302d4d
LG
1775\r
1776 # add forced library instances (specified in module overrides)\r
1777 for LibraryClass in PlatformModule.LibraryClasses:\r
1778 if LibraryClass.startswith("NULL"):\r
1779 Module.LibraryClasses[LibraryClass] = PlatformModule.LibraryClasses[LibraryClass]\r
1780\r
b36d134f 1781 # EdkII module\r
52302d4d
LG
1782 LibraryConsumerList = [Module]\r
1783 Constructor = []\r
1784 ConsumedByList = sdict()\r
1785 LibraryInstance = sdict()\r
1786\r
1787 EdkLogger.verbose("")\r
1788 EdkLogger.verbose("Library instances of module [%s] [%s]:" % (str(Module), self.Arch))\r
1789 while len(LibraryConsumerList) > 0:\r
1790 M = LibraryConsumerList.pop()\r
1791 for LibraryClassName in M.LibraryClasses:\r
1792 if LibraryClassName not in LibraryInstance:\r
1793 # override library instance for this module\r
1794 if LibraryClassName in PlatformModule.LibraryClasses:\r
1795 LibraryPath = PlatformModule.LibraryClasses[LibraryClassName]\r
1796 else:\r
1797 LibraryPath = self.Platform.LibraryClasses[LibraryClassName, ModuleType]\r
1798 if LibraryPath == None or LibraryPath == "":\r
1799 LibraryPath = M.LibraryClasses[LibraryClassName]\r
1800 if LibraryPath == None or LibraryPath == "":\r
1801 EdkLogger.error("build", RESOURCE_NOT_AVAILABLE,\r
1802 "Instance of library class [%s] is not found" % LibraryClassName,\r
1803 File=self.MetaFile,\r
1804 ExtraData="in [%s] [%s]\n\tconsumed by module [%s]" % (str(M), self.Arch, str(Module)))\r
1805\r
0d2711a6 1806 LibraryModule = self.BuildDatabase[LibraryPath, self.Arch, self.BuildTarget, self.ToolChain]\r
52302d4d
LG
1807 # for those forced library instance (NULL library), add a fake library class\r
1808 if LibraryClassName.startswith("NULL"):\r
1809 LibraryModule.LibraryClass.append(LibraryClassObject(LibraryClassName, [ModuleType]))\r
1810 elif LibraryModule.LibraryClass == None \\r
1811 or len(LibraryModule.LibraryClass) == 0 \\r
1812 or (ModuleType != 'USER_DEFINED'\r
1813 and ModuleType not in LibraryModule.LibraryClass[0].SupModList):\r
1814 # only USER_DEFINED can link against any library instance despite of its SupModList\r
1815 EdkLogger.error("build", OPTION_MISSING,\r
1816 "Module type [%s] is not supported by library instance [%s]" \\r
1817 % (ModuleType, LibraryPath), File=self.MetaFile,\r
1818 ExtraData="consumed by [%s]" % str(Module))\r
1819\r
1820 LibraryInstance[LibraryClassName] = LibraryModule\r
1821 LibraryConsumerList.append(LibraryModule)\r
1822 EdkLogger.verbose("\t" + str(LibraryClassName) + " : " + str(LibraryModule))\r
1823 else:\r
1824 LibraryModule = LibraryInstance[LibraryClassName]\r
1825\r
1826 if LibraryModule == None:\r
1827 continue\r
1828\r
1829 if LibraryModule.ConstructorList != [] and LibraryModule not in Constructor:\r
1830 Constructor.append(LibraryModule)\r
1831\r
1832 if LibraryModule not in ConsumedByList:\r
1833 ConsumedByList[LibraryModule] = []\r
1834 # don't add current module itself to consumer list\r
1835 if M != Module:\r
1836 if M in ConsumedByList[LibraryModule]:\r
1837 continue\r
1838 ConsumedByList[LibraryModule].append(M)\r
1839 #\r
1840 # Initialize the sorted output list to the empty set\r
1841 #\r
1842 SortedLibraryList = []\r
1843 #\r
1844 # Q <- Set of all nodes with no incoming edges\r
1845 #\r
1846 LibraryList = [] #LibraryInstance.values()\r
1847 Q = []\r
1848 for LibraryClassName in LibraryInstance:\r
1849 M = LibraryInstance[LibraryClassName]\r
1850 LibraryList.append(M)\r
1851 if ConsumedByList[M] == []:\r
1852 Q.append(M)\r
1853\r
1854 #\r
1855 # start the DAG algorithm\r
1856 #\r
1857 while True:\r
1858 EdgeRemoved = True\r
1859 while Q == [] and EdgeRemoved:\r
1860 EdgeRemoved = False\r
1861 # for each node Item with a Constructor\r
1862 for Item in LibraryList:\r
1863 if Item not in Constructor:\r
1864 continue\r
1865 # for each Node without a constructor with an edge e from Item to Node\r
1866 for Node in ConsumedByList[Item]:\r
1867 if Node in Constructor:\r
1868 continue\r
1869 # remove edge e from the graph if Node has no constructor\r
1870 ConsumedByList[Item].remove(Node)\r
1871 EdgeRemoved = True\r
1872 if ConsumedByList[Item] == []:\r
1873 # insert Item into Q\r
1874 Q.insert(0, Item)\r
1875 break\r
1876 if Q != []:\r
1877 break\r
1878 # DAG is done if there's no more incoming edge for all nodes\r
1879 if Q == []:\r
1880 break\r
1881\r
1882 # remove node from Q\r
1883 Node = Q.pop()\r
1884 # output Node\r
1885 SortedLibraryList.append(Node)\r
1886\r
1887 # for each node Item with an edge e from Node to Item do\r
1888 for Item in LibraryList:\r
1889 if Node not in ConsumedByList[Item]:\r
1890 continue\r
1891 # remove edge e from the graph\r
1892 ConsumedByList[Item].remove(Node)\r
1893\r
1894 if ConsumedByList[Item] != []:\r
1895 continue\r
1896 # insert Item into Q, if Item has no other incoming edges\r
1897 Q.insert(0, Item)\r
1898\r
1899 #\r
1900 # if any remaining node Item in the graph has a constructor and an incoming edge, then the graph has a cycle\r
1901 #\r
1902 for Item in LibraryList:\r
1903 if ConsumedByList[Item] != [] and Item in Constructor and len(Constructor) > 1:\r
1904 ErrorMessage = "\tconsumed by " + "\n\tconsumed by ".join([str(L) for L in ConsumedByList[Item]])\r
1905 EdkLogger.error("build", BUILD_ERROR, 'Library [%s] with constructors has a cycle' % str(Item),\r
1906 ExtraData=ErrorMessage, File=self.MetaFile)\r
1907 if Item not in SortedLibraryList:\r
1908 SortedLibraryList.append(Item)\r
1909\r
1910 #\r
1911 # Build the list of constructor and destructir names\r
1912 # The DAG Topo sort produces the destructor order, so the list of constructors must generated in the reverse order\r
1913 #\r
1914 SortedLibraryList.reverse()\r
1915 return SortedLibraryList\r
1916\r
1917\r
1918 ## Override PCD setting (type, value, ...)\r
1919 #\r
1920 # @param ToPcd The PCD to be overrided\r
1921 # @param FromPcd The PCD overrideing from\r
1922 #\r
1923 def _OverridePcd(self, ToPcd, FromPcd, Module=""):\r
1924 #\r
1925 # in case there's PCDs coming from FDF file, which have no type given.\r
1926 # at this point, ToPcd.Type has the type found from dependent\r
1927 # package\r
1928 #\r
1929 if FromPcd != None:\r
1930 if ToPcd.Pending and FromPcd.Type not in [None, '']:\r
1931 ToPcd.Type = FromPcd.Type\r
e56468c0 1932 elif (ToPcd.Type not in [None, '']) and (FromPcd.Type not in [None, ''])\\r
1933 and (ToPcd.Type != FromPcd.Type) and (ToPcd.Type in FromPcd.Type):\r
1934 if ToPcd.Type.strip() == "DynamicEx":\r
47fea6af 1935 ToPcd.Type = FromPcd.Type\r
52302d4d
LG
1936 elif ToPcd.Type not in [None, ''] and FromPcd.Type not in [None, ''] \\r
1937 and ToPcd.Type != FromPcd.Type:\r
1938 EdkLogger.error("build", OPTION_CONFLICT, "Mismatched PCD type",\r
1939 ExtraData="%s.%s is defined as [%s] in module %s, but as [%s] in platform."\\r
1940 % (ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName,\r
1941 ToPcd.Type, Module, FromPcd.Type),\r
1942 File=self.MetaFile)\r
1943\r
1944 if FromPcd.MaxDatumSize not in [None, '']:\r
1945 ToPcd.MaxDatumSize = FromPcd.MaxDatumSize\r
1946 if FromPcd.DefaultValue not in [None, '']:\r
1947 ToPcd.DefaultValue = FromPcd.DefaultValue\r
1948 if FromPcd.TokenValue not in [None, '']:\r
1949 ToPcd.TokenValue = FromPcd.TokenValue\r
1950 if FromPcd.MaxDatumSize not in [None, '']:\r
1951 ToPcd.MaxDatumSize = FromPcd.MaxDatumSize\r
1952 if FromPcd.DatumType not in [None, '']:\r
1953 ToPcd.DatumType = FromPcd.DatumType\r
1954 if FromPcd.SkuInfoList not in [None, '', []]:\r
1955 ToPcd.SkuInfoList = FromPcd.SkuInfoList\r
1956\r
1957 # check the validation of datum\r
1958 IsValid, Cause = CheckPcdDatum(ToPcd.DatumType, ToPcd.DefaultValue)\r
1959 if not IsValid:\r
1960 EdkLogger.error('build', FORMAT_INVALID, Cause, File=self.MetaFile,\r
1961 ExtraData="%s.%s" % (ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName))\r
82a6a960
BF
1962 ToPcd.validateranges = FromPcd.validateranges\r
1963 ToPcd.validlists = FromPcd.validlists\r
1964 ToPcd.expressions = FromPcd.expressions\r
52302d4d
LG
1965\r
1966 if ToPcd.DatumType == "VOID*" and ToPcd.MaxDatumSize in ['', None]:\r
1967 EdkLogger.debug(EdkLogger.DEBUG_9, "No MaxDatumSize specified for PCD %s.%s" \\r
1968 % (ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName))\r
1969 Value = ToPcd.DefaultValue\r
1970 if Value in [None, '']:\r
e8a47801 1971 ToPcd.MaxDatumSize = '1'\r
52302d4d 1972 elif Value[0] == 'L':\r
e8a47801 1973 ToPcd.MaxDatumSize = str((len(Value) - 2) * 2)\r
52302d4d
LG
1974 elif Value[0] == '{':\r
1975 ToPcd.MaxDatumSize = str(len(Value.split(',')))\r
1976 else:\r
e8a47801 1977 ToPcd.MaxDatumSize = str(len(Value) - 1)\r
52302d4d
LG
1978\r
1979 # apply default SKU for dynamic PCDS if specified one is not available\r
1980 if (ToPcd.Type in PCD_DYNAMIC_TYPE_LIST or ToPcd.Type in PCD_DYNAMIC_EX_TYPE_LIST) \\r
1981 and ToPcd.SkuInfoList in [None, {}, '']:\r
1982 if self.Platform.SkuName in self.Platform.SkuIds:\r
1983 SkuName = self.Platform.SkuName\r
1984 else:\r
1985 SkuName = 'DEFAULT'\r
1986 ToPcd.SkuInfoList = {\r
1987 SkuName : SkuInfoClass(SkuName, self.Platform.SkuIds[SkuName], '', '', '', '', '', ToPcd.DefaultValue)\r
1988 }\r
1989\r
1990 ## Apply PCD setting defined platform to a module\r
1991 #\r
1992 # @param Module The module from which the PCD setting will be overrided\r
1993 #\r
1994 # @retval PCD_list The list PCDs with settings from platform\r
1995 #\r
1996 def ApplyPcdSetting(self, Module, Pcds):\r
1997 # for each PCD in module\r
47fea6af
YZ
1998 for Name, Guid in Pcds:\r
1999 PcdInModule = Pcds[Name, Guid]\r
52302d4d 2000 # find out the PCD setting in platform\r
47fea6af
YZ
2001 if (Name, Guid) in self.Platform.Pcds:\r
2002 PcdInPlatform = self.Platform.Pcds[Name, Guid]\r
52302d4d
LG
2003 else:\r
2004 PcdInPlatform = None\r
2005 # then override the settings if any\r
2006 self._OverridePcd(PcdInModule, PcdInPlatform, Module)\r
2007 # resolve the VariableGuid value\r
2008 for SkuId in PcdInModule.SkuInfoList:\r
2009 Sku = PcdInModule.SkuInfoList[SkuId]\r
2010 if Sku.VariableGuid == '': continue\r
2011 Sku.VariableGuidValue = GuidValue(Sku.VariableGuid, self.PackageList)\r
2012 if Sku.VariableGuidValue == None:\r
2013 PackageList = "\n\t".join([str(P) for P in self.PackageList])\r
2014 EdkLogger.error(\r
2015 'build',\r
2016 RESOURCE_NOT_AVAILABLE,\r
2017 "Value of GUID [%s] is not found in" % Sku.VariableGuid,\r
2018 ExtraData=PackageList + "\n\t(used with %s.%s from module %s)" \\r
2019 % (Guid, Name, str(Module)),\r
2020 File=self.MetaFile\r
2021 )\r
2022\r
2023 # override PCD settings with module specific setting\r
2024 if Module in self.Platform.Modules:\r
2025 PlatformModule = self.Platform.Modules[str(Module)]\r
2026 for Key in PlatformModule.Pcds:\r
2027 if Key in Pcds:\r
2028 self._OverridePcd(Pcds[Key], PlatformModule.Pcds[Key], Module)\r
2029 return Pcds.values()\r
2030\r
2031 ## Resolve library names to library modules\r
2032 #\r
b36d134f 2033 # (for Edk.x modules)\r
52302d4d
LG
2034 #\r
2035 # @param Module The module from which the library names will be resolved\r
2036 #\r
2037 # @retval library_list The list of library modules\r
2038 #\r
2039 def ResolveLibraryReference(self, Module):\r
2040 EdkLogger.verbose("")\r
2041 EdkLogger.verbose("Library instances of module [%s] [%s]:" % (str(Module), self.Arch))\r
2042 LibraryConsumerList = [Module]\r
2043\r
b36d134f 2044 # "CompilerStub" is a must for Edk modules\r
52302d4d
LG
2045 if Module.Libraries:\r
2046 Module.Libraries.append("CompilerStub")\r
2047 LibraryList = []\r
2048 while len(LibraryConsumerList) > 0:\r
2049 M = LibraryConsumerList.pop()\r
2050 for LibraryName in M.Libraries:\r
2051 Library = self.Platform.LibraryClasses[LibraryName, ':dummy:']\r
2052 if Library == None:\r
2053 for Key in self.Platform.LibraryClasses.data.keys():\r
2054 if LibraryName.upper() == Key.upper():\r
2055 Library = self.Platform.LibraryClasses[Key, ':dummy:']\r
2056 break\r
2057 if Library == None:\r
2058 EdkLogger.warn("build", "Library [%s] is not found" % LibraryName, File=str(M),\r
2059 ExtraData="\t%s [%s]" % (str(Module), self.Arch))\r
2060 continue\r
2061\r
2062 if Library not in LibraryList:\r
2063 LibraryList.append(Library)\r
2064 LibraryConsumerList.append(Library)\r
2065 EdkLogger.verbose("\t" + LibraryName + " : " + str(Library) + ' ' + str(type(Library)))\r
2066 return LibraryList\r
2067\r
6780eef1
LG
2068 ## Calculate the priority value of the build option\r
2069 #\r
2070 # @param Key Build option definition contain: TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE\r
2071 #\r
2072 # @retval Value Priority value based on the priority list.\r
2073 #\r
2074 def CalculatePriorityValue(self, Key):\r
47fea6af
YZ
2075 Target, ToolChain, Arch, CommandType, Attr = Key.split('_')\r
2076 PriorityValue = 0x11111\r
6780eef1
LG
2077 if Target == "*":\r
2078 PriorityValue &= 0x01111\r
2079 if ToolChain == "*":\r
2080 PriorityValue &= 0x10111\r
2081 if Arch == "*":\r
2082 PriorityValue &= 0x11011\r
2083 if CommandType == "*":\r
2084 PriorityValue &= 0x11101\r
2085 if Attr == "*":\r
2086 PriorityValue &= 0x11110\r
47fea6af
YZ
2087\r
2088 return self.PrioList["0x%0.5x" % PriorityValue]\r
2089\r
6780eef1 2090\r
52302d4d
LG
2091 ## Expand * in build option key\r
2092 #\r
2093 # @param Options Options to be expanded\r
2094 #\r
2095 # @retval options Options expanded\r
6780eef1 2096 # \r
52302d4d
LG
2097 def _ExpandBuildOption(self, Options, ModuleStyle=None):\r
2098 BuildOptions = {}\r
2099 FamilyMatch = False\r
2100 FamilyIsNull = True\r
47fea6af 2101\r
6780eef1
LG
2102 OverrideList = {}\r
2103 #\r
2104 # Construct a list contain the build options which need override.\r
2105 #\r
2106 for Key in Options:\r
2107 #\r
2108 # Key[0] -- tool family\r
2109 # Key[1] -- TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE\r
2110 #\r
1ba5124e
YL
2111 if (Key[0] == self.BuildRuleFamily and\r
2112 (ModuleStyle == None or len(Key) < 3 or (len(Key) > 2 and Key[2] == ModuleStyle))):\r
6780eef1
LG
2113 Target, ToolChain, Arch, CommandType, Attr = Key[1].split('_')\r
2114 if Target == self.BuildTarget or Target == "*":\r
2115 if ToolChain == self.ToolChain or ToolChain == "*":\r
2116 if Arch == self.Arch or Arch == "*":\r
2117 if Options[Key].startswith("="):\r
47fea6af 2118 if OverrideList.get(Key[1]) != None:\r
6780eef1
LG
2119 OverrideList.pop(Key[1])\r
2120 OverrideList[Key[1]] = Options[Key]\r
2121 \r
2122 #\r
2123 # Use the highest priority value. \r
2124 #\r
2125 if (len(OverrideList) >= 2):\r
47fea6af 2126 KeyList = OverrideList.keys()\r
6780eef1 2127 for Index in range(len(KeyList)):\r
47fea6af 2128 NowKey = KeyList[Index]\r
6780eef1
LG
2129 Target1, ToolChain1, Arch1, CommandType1, Attr1 = NowKey.split("_")\r
2130 for Index1 in range(len(KeyList) - Index - 1):\r
2131 NextKey = KeyList[Index1 + Index + 1]\r
2132 #\r
2133 # Compare two Key, if one is included by another, choose the higher priority one\r
2134 # \r
2135 Target2, ToolChain2, Arch2, CommandType2, Attr2 = NextKey.split("_")\r
2136 if Target1 == Target2 or Target1 == "*" or Target2 == "*":\r
2137 if ToolChain1 == ToolChain2 or ToolChain1 == "*" or ToolChain2 == "*":\r
2138 if Arch1 == Arch2 or Arch1 == "*" or Arch2 == "*":\r
2139 if CommandType1 == CommandType2 or CommandType1 == "*" or CommandType2 == "*":\r
2140 if Attr1 == Attr2 or Attr1 == "*" or Attr2 == "*":\r
2141 if self.CalculatePriorityValue(NowKey) > self.CalculatePriorityValue(NextKey):\r
47fea6af 2142 if Options.get((self.BuildRuleFamily, NextKey)) != None:\r
6780eef1
LG
2143 Options.pop((self.BuildRuleFamily, NextKey))\r
2144 else:\r
47fea6af 2145 if Options.get((self.BuildRuleFamily, NowKey)) != None:\r
6780eef1
LG
2146 Options.pop((self.BuildRuleFamily, NowKey))\r
2147 \r
52302d4d
LG
2148 for Key in Options:\r
2149 if ModuleStyle != None and len (Key) > 2:\r
2150 # Check Module style is EDK or EDKII.\r
2151 # Only append build option for the matched style module.\r
2152 if ModuleStyle == EDK_NAME and Key[2] != EDK_NAME:\r
2153 continue\r
2154 elif ModuleStyle == EDKII_NAME and Key[2] != EDKII_NAME:\r
2155 continue\r
2156 Family = Key[0]\r
2157 Target, Tag, Arch, Tool, Attr = Key[1].split("_")\r
2158 # if tool chain family doesn't match, skip it\r
2159 if Tool in self.ToolDefinition and Family != "":\r
2160 FamilyIsNull = False\r
2161 if self.ToolDefinition[Tool].get(TAB_TOD_DEFINES_BUILDRULEFAMILY, "") != "":\r
2162 if Family != self.ToolDefinition[Tool][TAB_TOD_DEFINES_BUILDRULEFAMILY]:\r
2163 continue\r
2164 elif Family != self.ToolDefinition[Tool][TAB_TOD_DEFINES_FAMILY]:\r
2165 continue\r
2166 FamilyMatch = True\r
2167 # expand any wildcard\r
2168 if Target == "*" or Target == self.BuildTarget:\r
2169 if Tag == "*" or Tag == self.ToolChain:\r
2170 if Arch == "*" or Arch == self.Arch:\r
2171 if Tool not in BuildOptions:\r
2172 BuildOptions[Tool] = {}\r
5015bee2 2173 if Attr != "FLAGS" or Attr not in BuildOptions[Tool] or Options[Key].startswith('='):\r
52302d4d
LG
2174 BuildOptions[Tool][Attr] = Options[Key]\r
2175 else:\r
2176 # append options for the same tool\r
2177 BuildOptions[Tool][Attr] += " " + Options[Key]\r
2178 # Build Option Family has been checked, which need't to be checked again for family.\r
2179 if FamilyMatch or FamilyIsNull:\r
2180 return BuildOptions\r
1ba5124e 2181\r
52302d4d
LG
2182 for Key in Options:\r
2183 if ModuleStyle != None and len (Key) > 2:\r
2184 # Check Module style is EDK or EDKII.\r
2185 # Only append build option for the matched style module.\r
2186 if ModuleStyle == EDK_NAME and Key[2] != EDK_NAME:\r
2187 continue\r
2188 elif ModuleStyle == EDKII_NAME and Key[2] != EDKII_NAME:\r
2189 continue\r
2190 Family = Key[0]\r
2191 Target, Tag, Arch, Tool, Attr = Key[1].split("_")\r
2192 # if tool chain family doesn't match, skip it\r
47fea6af 2193 if Tool not in self.ToolDefinition or Family == "":\r
52302d4d
LG
2194 continue\r
2195 # option has been added before\r
2196 if Family != self.ToolDefinition[Tool][TAB_TOD_DEFINES_FAMILY]:\r
2197 continue\r
2198\r
2199 # expand any wildcard\r
2200 if Target == "*" or Target == self.BuildTarget:\r
2201 if Tag == "*" or Tag == self.ToolChain:\r
2202 if Arch == "*" or Arch == self.Arch:\r
2203 if Tool not in BuildOptions:\r
2204 BuildOptions[Tool] = {}\r
5015bee2 2205 if Attr != "FLAGS" or Attr not in BuildOptions[Tool] or Options[Key].startswith('='):\r
52302d4d
LG
2206 BuildOptions[Tool][Attr] = Options[Key]\r
2207 else:\r
2208 # append options for the same tool\r
2209 BuildOptions[Tool][Attr] += " " + Options[Key]\r
2210 return BuildOptions\r
2211\r
2212 ## Append build options in platform to a module\r
2213 #\r
2214 # @param Module The module to which the build options will be appened\r
2215 #\r
2216 # @retval options The options appended with build options in platform\r
2217 #\r
2218 def ApplyBuildOption(self, Module):\r
2219 # Get the different options for the different style module\r
2220 if Module.AutoGenVersion < 0x00010005:\r
2221 PlatformOptions = self.EdkBuildOption\r
35f69db9 2222 ModuleTypeOptions = self.Platform.GetBuildOptionsByModuleType(EDK_NAME, Module.ModuleType)\r
52302d4d
LG
2223 else:\r
2224 PlatformOptions = self.EdkIIBuildOption\r
35f69db9
YL
2225 ModuleTypeOptions = self.Platform.GetBuildOptionsByModuleType(EDKII_NAME, Module.ModuleType)\r
2226 ModuleTypeOptions = self._ExpandBuildOption(ModuleTypeOptions)\r
52302d4d
LG
2227 ModuleOptions = self._ExpandBuildOption(Module.BuildOptions)\r
2228 if Module in self.Platform.Modules:\r
2229 PlatformModule = self.Platform.Modules[str(Module)]\r
2230 PlatformModuleOptions = self._ExpandBuildOption(PlatformModule.BuildOptions)\r
2231 else:\r
2232 PlatformModuleOptions = {}\r
2233\r
fe4bf2f9 2234 BuildRuleOrder = None\r
35f69db9 2235 for Options in [self.ToolDefinition, ModuleOptions, PlatformOptions, ModuleTypeOptions, PlatformModuleOptions]:\r
fe4bf2f9
YL
2236 for Tool in Options:\r
2237 for Attr in Options[Tool]:\r
2238 if Attr == TAB_TOD_DEFINES_BUILDRULEORDER:\r
2239 BuildRuleOrder = Options[Tool][Attr]\r
2240\r
35f69db9
YL
2241 AllTools = set(ModuleOptions.keys() + PlatformOptions.keys() +\r
2242 PlatformModuleOptions.keys() + ModuleTypeOptions.keys() +\r
2243 self.ToolDefinition.keys())\r
52302d4d
LG
2244 BuildOptions = {}\r
2245 for Tool in AllTools:\r
2246 if Tool not in BuildOptions:\r
2247 BuildOptions[Tool] = {}\r
2248\r
35f69db9 2249 for Options in [self.ToolDefinition, ModuleOptions, PlatformOptions, ModuleTypeOptions, PlatformModuleOptions]:\r
52302d4d
LG
2250 if Tool not in Options:\r
2251 continue\r
2252 for Attr in Options[Tool]:\r
2253 Value = Options[Tool][Attr]\r
fe4bf2f9
YL
2254 #\r
2255 # Do not generate it in Makefile\r
2256 #\r
2257 if Attr == TAB_TOD_DEFINES_BUILDRULEORDER:\r
2258 continue\r
52302d4d
LG
2259 if Attr not in BuildOptions[Tool]:\r
2260 BuildOptions[Tool][Attr] = ""\r
2261 # check if override is indicated\r
2262 if Value.startswith('='):\r
05cc51ad
LY
2263 ToolPath = Value[1:]\r
2264 ToolPath = mws.handleWsMacro(ToolPath)\r
2265 BuildOptions[Tool][Attr] = ToolPath\r
5015bee2 2266 else:\r
05cc51ad 2267 Value = mws.handleWsMacro(Value)\r
52302d4d 2268 BuildOptions[Tool][Attr] += " " + Value\r
f3decdc3
LG
2269 if Module.AutoGenVersion < 0x00010005 and self.Workspace.UniFlag != None:\r
2270 #\r
2271 # Override UNI flag only for EDK module.\r
2272 #\r
2273 if 'BUILD' not in BuildOptions:\r
2274 BuildOptions['BUILD'] = {}\r
2275 BuildOptions['BUILD']['FLAGS'] = self.Workspace.UniFlag\r
fe4bf2f9 2276 return BuildOptions, BuildRuleOrder\r
52302d4d
LG
2277\r
2278 Platform = property(_GetPlatform)\r
2279 Name = property(_GetName)\r
2280 Guid = property(_GetGuid)\r
2281 Version = property(_GetVersion)\r
2282\r
2283 OutputDir = property(_GetOutputDir)\r
2284 BuildDir = property(_GetBuildDir)\r
2285 MakeFileDir = property(_GetMakeFileDir)\r
2286 FdfFile = property(_GetFdfFile)\r
2287\r
2288 PcdTokenNumber = property(_GetPcdTokenNumbers) # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber\r
2289 DynamicPcdList = property(_GetDynamicPcdList) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]\r
2290 NonDynamicPcdList = property(_GetNonDynamicPcdList) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]\r
2bc3256c 2291 NonDynamicPcdDict = property(_GetNonDynamicPcdDict)\r
52302d4d
LG
2292 PackageList = property(_GetPackageList)\r
2293\r
2294 ToolDefinition = property(_GetToolDefinition) # toolcode : tool path\r
2295 ToolDefinitionFile = property(_GetToolDefFile) # toolcode : lib path\r
2296 ToolChainFamily = property(_GetToolChainFamily)\r
2297 BuildRuleFamily = property(_GetBuildRuleFamily)\r
2298 BuildOption = property(_GetBuildOptions) # toolcode : option\r
2299 EdkBuildOption = property(_GetEdkBuildOptions) # edktoolcode : option\r
2300 EdkIIBuildOption = property(_GetEdkIIBuildOptions) # edkiitoolcode : option\r
2301\r
2302 BuildCommand = property(_GetBuildCommand)\r
2303 BuildRule = property(_GetBuildRule)\r
2304 ModuleAutoGenList = property(_GetModuleAutoGenList)\r
2305 LibraryAutoGenList = property(_GetLibraryAutoGenList)\r
0923aa1c 2306 GenFdsCommand = property(_GenFdsCommand)\r
52302d4d
LG
2307\r
2308## ModuleAutoGen class\r
2309#\r
2310# This class encapsules the AutoGen behaviors for the build tools. In addition to\r
2311# the generation of AutoGen.h and AutoGen.c, it will generate *.depex file according\r
2312# to the [depex] section in module's inf file.\r
2313#\r
2314class ModuleAutoGen(AutoGen):\r
2315 ## The real constructor of ModuleAutoGen\r
2316 #\r
2317 # This method is not supposed to be called by users of ModuleAutoGen. It's\r
2318 # only used by factory method __new__() to do real initialization work for an\r
2319 # object of ModuleAutoGen\r
2320 #\r
2321 # @param Workspace EdkIIWorkspaceBuild object\r
2322 # @param ModuleFile The path of module file\r
2323 # @param Target Build target (DEBUG, RELEASE)\r
2324 # @param Toolchain Name of tool chain\r
2325 # @param Arch The arch the module supports\r
2326 # @param PlatformFile Platform meta-file\r
2327 #\r
2328 def _Init(self, Workspace, ModuleFile, Target, Toolchain, Arch, PlatformFile):\r
2329 EdkLogger.debug(EdkLogger.DEBUG_9, "AutoGen module [%s] [%s]" % (ModuleFile, Arch))\r
2330 GlobalData.gProcessingFile = "%s [%s, %s, %s]" % (ModuleFile, Arch, Toolchain, Target)\r
2331\r
2332 self.Workspace = Workspace\r
2333 self.WorkspaceDir = Workspace.WorkspaceDir\r
2334\r
2335 self.MetaFile = ModuleFile\r
2336 self.PlatformInfo = PlatformAutoGen(Workspace, PlatformFile, Target, Toolchain, Arch)\r
2337 # check if this module is employed by active platform\r
2338 if not self.PlatformInfo.ValidModule(self.MetaFile):\r
2339 EdkLogger.verbose("Module [%s] for [%s] is not employed by active platform\n" \\r
2340 % (self.MetaFile, Arch))\r
2341 return False\r
2342\r
2343 self.SourceDir = self.MetaFile.SubDir\r
05cc51ad 2344 self.SourceDir = mws.relpath(self.SourceDir, self.WorkspaceDir)\r
97fa0ee9 2345\r
52302d4d
LG
2346 self.SourceOverrideDir = None\r
2347 # use overrided path defined in DSC file\r
2348 if self.MetaFile.Key in GlobalData.gOverrideDir:\r
2349 self.SourceOverrideDir = GlobalData.gOverrideDir[self.MetaFile.Key]\r
2350\r
2351 self.ToolChain = Toolchain\r
2352 self.BuildTarget = Target\r
2353 self.Arch = Arch\r
2354 self.ToolChainFamily = self.PlatformInfo.ToolChainFamily\r
2355 self.BuildRuleFamily = self.PlatformInfo.BuildRuleFamily\r
2356\r
2357 self.IsMakeFileCreated = False\r
2358 self.IsCodeFileCreated = False\r
da92f276
LG
2359 self.IsAsBuiltInfCreated = False\r
2360 self.DepexGenerated = False\r
52302d4d
LG
2361\r
2362 self.BuildDatabase = self.Workspace.BuildDatabase\r
fe4bf2f9 2363 self.BuildRuleOrder = None\r
52302d4d
LG
2364\r
2365 self._Module = None\r
2366 self._Name = None\r
2367 self._Guid = None\r
2368 self._Version = None\r
2369 self._ModuleType = None\r
2370 self._ComponentType = None\r
2371 self._PcdIsDriver = None\r
2372 self._AutoGenVersion = None\r
2373 self._LibraryFlag = None\r
2374 self._CustomMakefile = None\r
2375 self._Macro = None\r
2376\r
2377 self._BuildDir = None\r
2378 self._OutputDir = None\r
2379 self._DebugDir = None\r
2380 self._MakeFileDir = None\r
2381\r
2382 self._IncludePathList = None\r
725cdb8f 2383 self._IncludePathLength = 0\r
52302d4d
LG
2384 self._AutoGenFileList = None\r
2385 self._UnicodeFileList = None\r
2386 self._SourceFileList = None\r
2387 self._ObjectFileList = None\r
2388 self._BinaryFileList = None\r
2389\r
2390 self._DependentPackageList = None\r
2391 self._DependentLibraryList = None\r
2392 self._LibraryAutoGenList = None\r
2393 self._DerivedPackageList = None\r
2394 self._ModulePcdList = None\r
2395 self._LibraryPcdList = None\r
e8a47801 2396 self._PcdComments = sdict()\r
52302d4d 2397 self._GuidList = None\r
e8a47801
LG
2398 self._GuidsUsedByPcd = None\r
2399 self._GuidComments = sdict()\r
52302d4d 2400 self._ProtocolList = None\r
e8a47801 2401 self._ProtocolComments = sdict()\r
52302d4d 2402 self._PpiList = None\r
e8a47801 2403 self._PpiComments = sdict()\r
52302d4d
LG
2404 self._DepexList = None\r
2405 self._DepexExpressionList = None\r
2406 self._BuildOption = None\r
79b74a03 2407 self._BuildOptionIncPathList = None\r
52302d4d
LG
2408 self._BuildTargets = None\r
2409 self._IntroBuildTargetList = None\r
2410 self._FinalBuildTargetList = None\r
2411 self._FileTypes = None\r
2412 self._BuildRules = None\r
2bc3256c
LG
2413 \r
2414 ## The Modules referenced to this Library\r
2415 # Only Library has this attribute\r
2416 self._ReferenceModules = [] \r
2417 \r
2418 ## Store the FixedAtBuild Pcds\r
2419 # \r
2420 self._FixedAtBuildPcds = []\r
2421 self.ConstPcd = {}\r
52302d4d
LG
2422 return True\r
2423\r
2424 def __repr__(self):\r
2425 return "%s [%s]" % (self.MetaFile, self.Arch)\r
2426\r
2bc3256c
LG
2427 # Get FixedAtBuild Pcds of this Module\r
2428 def _GetFixedAtBuildPcds(self):\r
2429 if self._FixedAtBuildPcds:\r
2430 return self._FixedAtBuildPcds\r
2431 for Pcd in self.ModulePcdList:\r
2432 if self.IsLibrary:\r
2433 if not (Pcd.Pending == False and Pcd.Type == "FixedAtBuild"):\r
2434 continue\r
2435 elif Pcd.Type != "FixedAtBuild":\r
2436 continue\r
2437 if Pcd not in self._FixedAtBuildPcds:\r
2438 self._FixedAtBuildPcds.append(Pcd)\r
2439 \r
2440 return self._FixedAtBuildPcds \r
2441\r
867d1cd4
YL
2442 def _GetUniqueBaseName(self):\r
2443 BaseName = self.Name\r
2444 for Module in self.PlatformInfo.ModuleAutoGenList:\r
2445 if Module.MetaFile == self.MetaFile:\r
2446 continue\r
2447 if Module.Name == self.Name:\r
867d1cd4
YL
2448 if uuid.UUID(Module.Guid) == uuid.UUID(self.Guid):\r
2449 EdkLogger.error("build", FILE_DUPLICATED, 'Modules have same BaseName and FILE_GUID:\n'\r
2450 ' %s\n %s' % (Module.MetaFile, self.MetaFile))\r
2451 BaseName = '%s_%s' % (self.Name, self.Guid)\r
2452 return BaseName\r
2453\r
52302d4d
LG
2454 # Macros could be used in build_rule.txt (also Makefile)\r
2455 def _GetMacros(self):\r
2456 if self._Macro == None:\r
2457 self._Macro = sdict()\r
2458 self._Macro["WORKSPACE" ] = self.WorkspaceDir\r
2459 self._Macro["MODULE_NAME" ] = self.Name\r
867d1cd4 2460 self._Macro["MODULE_NAME_GUID" ] = self._GetUniqueBaseName()\r
52302d4d
LG
2461 self._Macro["MODULE_GUID" ] = self.Guid\r
2462 self._Macro["MODULE_VERSION" ] = self.Version\r
2463 self._Macro["MODULE_TYPE" ] = self.ModuleType\r
2464 self._Macro["MODULE_FILE" ] = str(self.MetaFile)\r
2465 self._Macro["MODULE_FILE_BASE_NAME" ] = self.MetaFile.BaseName\r
2466 self._Macro["MODULE_RELATIVE_DIR" ] = self.SourceDir\r
2467 self._Macro["MODULE_DIR" ] = self.SourceDir\r
2468\r
2469 self._Macro["BASE_NAME" ] = self.Name\r
2470\r
2471 self._Macro["ARCH" ] = self.Arch\r
2472 self._Macro["TOOLCHAIN" ] = self.ToolChain\r
2473 self._Macro["TOOLCHAIN_TAG" ] = self.ToolChain\r
0d2711a6 2474 self._Macro["TOOL_CHAIN_TAG" ] = self.ToolChain\r
52302d4d
LG
2475 self._Macro["TARGET" ] = self.BuildTarget\r
2476\r
2477 self._Macro["BUILD_DIR" ] = self.PlatformInfo.BuildDir\r
2478 self._Macro["BIN_DIR" ] = os.path.join(self.PlatformInfo.BuildDir, self.Arch)\r
2479 self._Macro["LIB_DIR" ] = os.path.join(self.PlatformInfo.BuildDir, self.Arch)\r
2480 self._Macro["MODULE_BUILD_DIR" ] = self.BuildDir\r
2481 self._Macro["OUTPUT_DIR" ] = self.OutputDir\r
2482 self._Macro["DEBUG_DIR" ] = self.DebugDir\r
df1e1b63
YZ
2483 self._Macro["DEST_DIR_OUTPUT" ] = self.OutputDir\r
2484 self._Macro["DEST_DIR_DEBUG" ] = self.DebugDir\r
3570e332
YZ
2485 self._Macro["PLATFORM_NAME" ] = self.PlatformInfo.Name\r
2486 self._Macro["PLATFORM_GUID" ] = self.PlatformInfo.Guid\r
2487 self._Macro["PLATFORM_VERSION" ] = self.PlatformInfo.Version\r
2488 self._Macro["PLATFORM_RELATIVE_DIR" ] = self.PlatformInfo.SourceDir\r
2489 self._Macro["PLATFORM_DIR" ] = mws.join(self.WorkspaceDir, self.PlatformInfo.SourceDir)\r
2490 self._Macro["PLATFORM_OUTPUT_DIR" ] = self.PlatformInfo.OutputDir\r
52302d4d
LG
2491 return self._Macro\r
2492\r
2493 ## Return the module build data object\r
2494 def _GetModule(self):\r
2495 if self._Module == None:\r
0d2711a6 2496 self._Module = self.Workspace.BuildDatabase[self.MetaFile, self.Arch, self.BuildTarget, self.ToolChain]\r
52302d4d
LG
2497 return self._Module\r
2498\r
2499 ## Return the module name\r
2500 def _GetBaseName(self):\r
2501 return self.Module.BaseName\r
2502\r
b36d134f
LG
2503 ## Return the module DxsFile if exist\r
2504 def _GetDxsFile(self):\r
2505 return self.Module.DxsFile\r
2506\r
52302d4d
LG
2507 ## Return the module SourceOverridePath\r
2508 def _GetSourceOverridePath(self):\r
2509 return self.Module.SourceOverridePath\r
2510\r
2511 ## Return the module meta-file GUID\r
2512 def _GetGuid(self):\r
97fa0ee9
YL
2513 #\r
2514 # To build same module more than once, the module path with FILE_GUID overridden has\r
2515 # the file name FILE_GUIDmodule.inf, but the relative path (self.MetaFile.File) is the realy path\r
2516 # in DSC. The overridden GUID can be retrieved from file name\r
2517 #\r
2518 if os.path.basename(self.MetaFile.File) != os.path.basename(self.MetaFile.Path):\r
2519 #\r
2520 # Length of GUID is 36\r
2521 #\r
2522 return os.path.basename(self.MetaFile.Path)[:36]\r
52302d4d
LG
2523 return self.Module.Guid\r
2524\r
2525 ## Return the module version\r
2526 def _GetVersion(self):\r
2527 return self.Module.Version\r
2528\r
2529 ## Return the module type\r
2530 def _GetModuleType(self):\r
2531 return self.Module.ModuleType\r
2532\r
b36d134f 2533 ## Return the component type (for Edk.x style of module)\r
52302d4d
LG
2534 def _GetComponentType(self):\r
2535 return self.Module.ComponentType\r
2536\r
2537 ## Return the build type\r
2538 def _GetBuildType(self):\r
2539 return self.Module.BuildType\r
2540\r
2541 ## Return the PCD_IS_DRIVER setting\r
2542 def _GetPcdIsDriver(self):\r
2543 return self.Module.PcdIsDriver\r
2544\r
2545 ## Return the autogen version, i.e. module meta-file version\r
2546 def _GetAutoGenVersion(self):\r
2547 return self.Module.AutoGenVersion\r
2548\r
2549 ## Check if the module is library or not\r
2550 def _IsLibrary(self):\r
2551 if self._LibraryFlag == None:\r
2552 if self.Module.LibraryClass != None and self.Module.LibraryClass != []:\r
2553 self._LibraryFlag = True\r
2554 else:\r
2555 self._LibraryFlag = False\r
2556 return self._LibraryFlag\r
2557\r
e8a47801
LG
2558 ## Check if the module is binary module or not\r
2559 def _IsBinaryModule(self):\r
2560 return self.Module.IsBinaryModule\r
2561\r
52302d4d
LG
2562 ## Return the directory to store intermediate files of the module\r
2563 def _GetBuildDir(self):\r
2564 if self._BuildDir == None:\r
2565 self._BuildDir = path.join(\r
2566 self.PlatformInfo.BuildDir,\r
2567 self.Arch,\r
2568 self.SourceDir,\r
2569 self.MetaFile.BaseName\r
2570 )\r
2571 CreateDirectory(self._BuildDir)\r
2572 return self._BuildDir\r
2573\r
2574 ## Return the directory to store the intermediate object files of the mdoule\r
2575 def _GetOutputDir(self):\r
2576 if self._OutputDir == None:\r
2577 self._OutputDir = path.join(self.BuildDir, "OUTPUT")\r
2578 CreateDirectory(self._OutputDir)\r
2579 return self._OutputDir\r
2580\r
2581 ## Return the directory to store auto-gened source files of the mdoule\r
2582 def _GetDebugDir(self):\r
2583 if self._DebugDir == None:\r
2584 self._DebugDir = path.join(self.BuildDir, "DEBUG")\r
2585 CreateDirectory(self._DebugDir)\r
2586 return self._DebugDir\r
2587\r
2588 ## Return the path of custom file\r
2589 def _GetCustomMakefile(self):\r
2590 if self._CustomMakefile == None:\r
2591 self._CustomMakefile = {}\r
2592 for Type in self.Module.CustomMakefile:\r
2593 if Type in gMakeTypeMap:\r
2594 MakeType = gMakeTypeMap[Type]\r
2595 else:\r
2596 MakeType = 'nmake'\r
2597 if self.SourceOverrideDir != None:\r
2598 File = os.path.join(self.SourceOverrideDir, self.Module.CustomMakefile[Type])\r
2599 if not os.path.exists(File):\r
2600 File = os.path.join(self.SourceDir, self.Module.CustomMakefile[Type])\r
2601 else:\r
2602 File = os.path.join(self.SourceDir, self.Module.CustomMakefile[Type])\r
2603 self._CustomMakefile[MakeType] = File\r
2604 return self._CustomMakefile\r
2605\r
2606 ## Return the directory of the makefile\r
2607 #\r
2608 # @retval string The directory string of module's makefile\r
2609 #\r
2610 def _GetMakeFileDir(self):\r
2611 return self.BuildDir\r
2612\r
2613 ## Return build command string\r
2614 #\r
2615 # @retval string Build command string\r
2616 #\r
2617 def _GetBuildCommand(self):\r
2618 return self.PlatformInfo.BuildCommand\r
2619\r
2620 ## Get object list of all packages the module and its dependent libraries belong to\r
2621 #\r
2622 # @retval list The list of package object\r
2623 #\r
2624 def _GetDerivedPackageList(self):\r
2625 PackageList = []\r
2626 for M in [self.Module] + self.DependentLibraryList:\r
2627 for Package in M.Packages:\r
2628 if Package in PackageList:\r
2629 continue\r
2630 PackageList.append(Package)\r
2631 return PackageList\r
97fa0ee9
YL
2632 \r
2633 ## Get the depex string\r
2634 #\r
2635 # @return : a string contain all depex expresion.\r
2636 def _GetDepexExpresionString(self):\r
2637 DepexStr = ''\r
2638 DepexList = []\r
2639 ## DPX_SOURCE IN Define section.\r
2640 if self.Module.DxsFile:\r
2641 return DepexStr\r
2642 for M in [self.Module] + self.DependentLibraryList:\r
2643 Filename = M.MetaFile.Path\r
2644 InfObj = InfSectionParser.InfSectionParser(Filename)\r
2645 DepexExpresionList = InfObj.GetDepexExpresionList()\r
2646 for DepexExpresion in DepexExpresionList:\r
2647 for key in DepexExpresion.keys():\r
2648 Arch, ModuleType = key\r
2649 # the type of build module is USER_DEFINED.\r
2650 # All different DEPEX section tags would be copied into the As Built INF file\r
2651 # and there would be separate DEPEX section tags\r
2652 if self.ModuleType.upper() == SUP_MODULE_USER_DEFINED:\r
2653 if (Arch.upper() == self.Arch.upper()) and (ModuleType.upper() != TAB_ARCH_COMMON):\r
2654 DepexList.append({(Arch, ModuleType): DepexExpresion[key][:]})\r
2655 else:\r
2656 if Arch.upper() == TAB_ARCH_COMMON or \\r
2657 (Arch.upper() == self.Arch.upper() and \\r
2658 ModuleType.upper() in [TAB_ARCH_COMMON, self.ModuleType.upper()]):\r
2659 DepexList.append({(Arch, ModuleType): DepexExpresion[key][:]})\r
2660 \r
2661 #the type of build module is USER_DEFINED.\r
2662 if self.ModuleType.upper() == SUP_MODULE_USER_DEFINED:\r
2663 for Depex in DepexList:\r
2664 for key in Depex.keys():\r
2665 DepexStr += '[Depex.%s.%s]\n' % key\r
2666 DepexStr += '\n'.join(['# '+ val for val in Depex[key]])\r
2667 DepexStr += '\n\n'\r
2668 if not DepexStr:\r
2669 return '[Depex.%s]\n' % self.Arch\r
2670 return DepexStr\r
2671 \r
2672 #the type of build module not is USER_DEFINED.\r
2673 Count = 0\r
2674 for Depex in DepexList:\r
2675 Count += 1\r
2676 if DepexStr != '':\r
2677 DepexStr += ' AND '\r
2678 DepexStr += '('\r
2679 for D in Depex.values():\r
2680 DepexStr += ' '.join([val for val in D])\r
2681 Index = DepexStr.find('END')\r
2682 if Index > -1 and Index == len(DepexStr) - 3:\r
2683 DepexStr = DepexStr[:-3]\r
2684 DepexStr = DepexStr.strip()\r
2685 DepexStr += ')'\r
2686 if Count == 1:\r
2687 DepexStr = DepexStr.lstrip('(').rstrip(')').strip()\r
2688 if not DepexStr:\r
2689 return '[Depex.%s]\n' % self.Arch\r
2690 return '[Depex.%s]\n# ' % self.Arch + DepexStr\r
2691 \r
52302d4d
LG
2692 ## Merge dependency expression\r
2693 #\r
2694 # @retval list The token list of the dependency expression after parsed\r
2695 #\r
2696 def _GetDepexTokenList(self):\r
2697 if self._DepexList == None:\r
2698 self._DepexList = {}\r
b36d134f 2699 if self.DxsFile or self.IsLibrary or TAB_DEPENDENCY_EXPRESSION_FILE in self.FileTypes:\r
52302d4d
LG
2700 return self._DepexList\r
2701\r
2702 self._DepexList[self.ModuleType] = []\r
2703\r
2704 for ModuleType in self._DepexList:\r
2705 DepexList = self._DepexList[ModuleType]\r
2706 #\r
2707 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion\r
2708 #\r
2709 for M in [self.Module] + self.DependentLibraryList:\r
2710 Inherited = False\r
2711 for D in M.Depex[self.Arch, ModuleType]:\r
2712 if DepexList != []:\r
2713 DepexList.append('AND')\r
2714 DepexList.append('(')\r
2715 DepexList.extend(D)\r
2716 if DepexList[-1] == 'END': # no need of a END at this time\r
2717 DepexList.pop()\r
2718 DepexList.append(')')\r
2719 Inherited = True\r
2720 if Inherited:\r
2721 EdkLogger.verbose("DEPEX[%s] (+%s) = %s" % (self.Name, M.BaseName, DepexList))\r
2722 if 'BEFORE' in DepexList or 'AFTER' in DepexList:\r
2723 break\r
2724 if len(DepexList) > 0:\r
2725 EdkLogger.verbose('')\r
2726 return self._DepexList\r
2727\r
2728 ## Merge dependency expression\r
2729 #\r
2730 # @retval list The token list of the dependency expression after parsed\r
2731 #\r
2732 def _GetDepexExpressionTokenList(self):\r
2733 if self._DepexExpressionList == None:\r
2734 self._DepexExpressionList = {}\r
b36d134f 2735 if self.DxsFile or self.IsLibrary or TAB_DEPENDENCY_EXPRESSION_FILE in self.FileTypes:\r
52302d4d
LG
2736 return self._DepexExpressionList\r
2737\r
2738 self._DepexExpressionList[self.ModuleType] = ''\r
2739\r
2740 for ModuleType in self._DepexExpressionList:\r
2741 DepexExpressionList = self._DepexExpressionList[ModuleType]\r
2742 #\r
2743 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion\r
2744 #\r
2745 for M in [self.Module] + self.DependentLibraryList:\r
2746 Inherited = False\r
2747 for D in M.DepexExpression[self.Arch, ModuleType]:\r
2748 if DepexExpressionList != '':\r
2749 DepexExpressionList += ' AND '\r
2750 DepexExpressionList += '('\r
2751 DepexExpressionList += D\r
2752 DepexExpressionList = DepexExpressionList.rstrip('END').strip()\r
2753 DepexExpressionList += ')'\r
2754 Inherited = True\r
2755 if Inherited:\r
2756 EdkLogger.verbose("DEPEX[%s] (+%s) = %s" % (self.Name, M.BaseName, DepexExpressionList))\r
2757 if 'BEFORE' in DepexExpressionList or 'AFTER' in DepexExpressionList:\r
2758 break\r
2759 if len(DepexExpressionList) > 0:\r
2760 EdkLogger.verbose('')\r
2761 self._DepexExpressionList[ModuleType] = DepexExpressionList\r
2762 return self._DepexExpressionList\r
2763\r
2764 ## Return the list of specification version required for the module\r
2765 #\r
2766 # @retval list The list of specification defined in module file\r
2767 #\r
2768 def _GetSpecification(self):\r
2769 return self.Module.Specification\r
2770\r
2771 ## Tool option for the module build\r
2772 #\r
2773 # @param PlatformInfo The object of PlatformBuildInfo\r
2774 # @retval dict The dict containing valid options\r
2775 #\r
2776 def _GetModuleBuildOption(self):\r
2777 if self._BuildOption == None:\r
fe4bf2f9
YL
2778 self._BuildOption, self.BuildRuleOrder = self.PlatformInfo.ApplyBuildOption(self.Module)\r
2779 if self.BuildRuleOrder:\r
2780 self.BuildRuleOrder = ['.%s' % Ext for Ext in self.BuildRuleOrder.split()]\r
52302d4d
LG
2781 return self._BuildOption\r
2782\r
79b74a03
LG
2783 ## Get include path list from tool option for the module build\r
2784 #\r
2785 # @retval list The include path list\r
2786 #\r
2787 def _GetBuildOptionIncPathList(self):\r
2788 if self._BuildOptionIncPathList == None:\r
2789 #\r
d40b2ee6 2790 # Regular expression for finding Include Directories, the difference between MSFT and INTEL/GCC/RVCT\r
79b74a03
LG
2791 # is the former use /I , the Latter used -I to specify include directories\r
2792 #\r
2793 if self.PlatformInfo.ToolChainFamily in ('MSFT'):\r
47fea6af 2794 gBuildOptIncludePattern = re.compile(r"(?:.*?)/I[ \t]*([^ ]*)", re.MULTILINE | re.DOTALL)\r
d40b2ee6 2795 elif self.PlatformInfo.ToolChainFamily in ('INTEL', 'GCC', 'RVCT'):\r
47fea6af 2796 gBuildOptIncludePattern = re.compile(r"(?:.*?)-I[ \t]*([^ ]*)", re.MULTILINE | re.DOTALL)\r
d40b2ee6
LG
2797 else:\r
2798 #\r
2799 # New ToolChainFamily, don't known whether there is option to specify include directories\r
2800 #\r
2801 self._BuildOptionIncPathList = []\r
2802 return self._BuildOptionIncPathList\r
79b74a03
LG
2803 \r
2804 BuildOptionIncPathList = []\r
2805 for Tool in ('CC', 'PP', 'VFRPP', 'ASLPP', 'ASLCC', 'APP', 'ASM'):\r
2806 Attr = 'FLAGS'\r
2807 try:\r
2808 FlagOption = self.BuildOption[Tool][Attr]\r
2809 except KeyError:\r
2810 FlagOption = ''\r
2811 \r
d40b2ee6
LG
2812 if self.PlatformInfo.ToolChainFamily != 'RVCT':\r
2813 IncPathList = [NormPath(Path, self.Macros) for Path in gBuildOptIncludePattern.findall(FlagOption)]\r
2814 else:\r
2815 #\r
2816 # RVCT may specify a list of directory seperated by commas\r
2817 #\r
2818 IncPathList = []\r
2819 for Path in gBuildOptIncludePattern.findall(FlagOption):\r
2820 PathList = GetSplitList(Path, TAB_COMMA_SPLIT)\r
2821 IncPathList += [NormPath(PathEntry, self.Macros) for PathEntry in PathList]\r
2822\r
79b74a03
LG
2823 #\r
2824 # EDK II modules must not reference header files outside of the packages they depend on or \r
2825 # within the module's directory tree. Report error if violation.\r
2826 #\r
2827 if self.AutoGenVersion >= 0x00010005 and len(IncPathList) > 0:\r
2828 for Path in IncPathList:\r
2829 if (Path not in self.IncludePathList) and (CommonPath([Path, self.MetaFile.Dir]) != self.MetaFile.Dir):\r
47fea6af
YZ
2830 ErrMsg = "The include directory for the EDK II module in this line is invalid %s specified in %s FLAGS '%s'" % (Path, Tool, FlagOption)\r
2831 EdkLogger.error("build",\r
79b74a03 2832 PARAMETER_INVALID,\r
47fea6af
YZ
2833 ExtraData=ErrMsg,\r
2834 File=str(self.MetaFile))\r
79b74a03
LG
2835\r
2836 \r
2837 BuildOptionIncPathList += IncPathList\r
2838 \r
2839 self._BuildOptionIncPathList = BuildOptionIncPathList\r
2840 \r
2841 return self._BuildOptionIncPathList\r
2842 \r
52302d4d
LG
2843 ## Return a list of files which can be built from source\r
2844 #\r
2845 # What kind of files can be built is determined by build rules in\r
97fa0ee9 2846 # $(CONF_DIRECTORY)/build_rule.txt and toolchain family.\r
52302d4d
LG
2847 #\r
2848 def _GetSourceFileList(self):\r
2849 if self._SourceFileList == None:\r
2850 self._SourceFileList = []\r
2851 for F in self.Module.Sources:\r
2852 # match tool chain\r
08dd311f 2853 if F.TagName not in ("", "*", self.ToolChain):\r
52302d4d
LG
2854 EdkLogger.debug(EdkLogger.DEBUG_9, "The toolchain [%s] for processing file [%s] is found, "\r
2855 "but [%s] is needed" % (F.TagName, str(F), self.ToolChain))\r
2856 continue\r
2857 # match tool chain family\r
08dd311f 2858 if F.ToolChainFamily not in ("", "*", self.ToolChainFamily):\r
52302d4d
LG
2859 EdkLogger.debug(\r
2860 EdkLogger.DEBUG_0,\r
2861 "The file [%s] must be built by tools of [%s], " \\r
2862 "but current toolchain family is [%s]" \\r
2863 % (str(F), F.ToolChainFamily, self.ToolChainFamily))\r
2864 continue\r
2865\r
2866 # add the file path into search path list for file including\r
2867 if F.Dir not in self.IncludePathList and self.AutoGenVersion >= 0x00010005:\r
2868 self.IncludePathList.insert(0, F.Dir)\r
2869 self._SourceFileList.append(F)\r
4cb7bade
YZ
2870\r
2871 self._MatchBuildRuleOrder(self._SourceFileList)\r
2872\r
2873 for F in self._SourceFileList:\r
52302d4d
LG
2874 self._ApplyBuildRule(F, TAB_UNKNOWN_FILE)\r
2875 return self._SourceFileList\r
2876\r
4cb7bade
YZ
2877 def _MatchBuildRuleOrder(self, FileList):\r
2878 Order_Dict = {}\r
2879 self._GetModuleBuildOption()\r
2880 for SingleFile in FileList:\r
2881 if self.BuildRuleOrder and SingleFile.Ext in self.BuildRuleOrder and SingleFile.Ext in self.BuildRules:\r
2882 key = SingleFile.Path.split(SingleFile.Ext)[0]\r
2883 if key in Order_Dict:\r
2884 Order_Dict[key].append(SingleFile.Ext)\r
2885 else:\r
2886 Order_Dict[key] = [SingleFile.Ext]\r
2887\r
2888 RemoveList = []\r
2889 for F in Order_Dict:\r
2890 if len(Order_Dict[F]) > 1:\r
2891 Order_Dict[F].sort(key=lambda i: self.BuildRuleOrder.index(i))\r
2892 for Ext in Order_Dict[F][1:]:\r
2893 RemoveList.append(F + Ext)\r
2894 \r
2895 for item in RemoveList:\r
2896 FileList.remove(item)\r
2897\r
2898 return FileList\r
2899\r
52302d4d
LG
2900 ## Return the list of unicode files\r
2901 def _GetUnicodeFileList(self):\r
2902 if self._UnicodeFileList == None:\r
2903 if TAB_UNICODE_FILE in self.FileTypes:\r
2904 self._UnicodeFileList = self.FileTypes[TAB_UNICODE_FILE]\r
2905 else:\r
2906 self._UnicodeFileList = []\r
2907 return self._UnicodeFileList\r
2908\r
2909 ## Return a list of files which can be built from binary\r
2910 #\r
2911 # "Build" binary files are just to copy them to build directory.\r
2912 #\r
2913 # @retval list The list of files which can be built later\r
2914 #\r
2915 def _GetBinaryFiles(self):\r
2916 if self._BinaryFileList == None:\r
2917 self._BinaryFileList = []\r
2918 for F in self.Module.Binaries:\r
2919 if F.Target not in ['COMMON', '*'] and F.Target != self.BuildTarget:\r
2920 continue\r
2921 self._BinaryFileList.append(F)\r
2922 self._ApplyBuildRule(F, F.Type)\r
2923 return self._BinaryFileList\r
2924\r
2925 def _GetBuildRules(self):\r
2926 if self._BuildRules == None:\r
2927 BuildRules = {}\r
2928 BuildRuleDatabase = self.PlatformInfo.BuildRule\r
2929 for Type in BuildRuleDatabase.FileTypeList:\r
2930 #first try getting build rule by BuildRuleFamily\r
2931 RuleObject = BuildRuleDatabase[Type, self.BuildType, self.Arch, self.BuildRuleFamily]\r
2932 if not RuleObject:\r
2933 # build type is always module type, but ...\r
2934 if self.ModuleType != self.BuildType:\r
2935 RuleObject = BuildRuleDatabase[Type, self.ModuleType, self.Arch, self.BuildRuleFamily]\r
2936 #second try getting build rule by ToolChainFamily\r
2937 if not RuleObject:\r
2938 RuleObject = BuildRuleDatabase[Type, self.BuildType, self.Arch, self.ToolChainFamily]\r
2939 if not RuleObject:\r
2940 # build type is always module type, but ...\r
2941 if self.ModuleType != self.BuildType:\r
2942 RuleObject = BuildRuleDatabase[Type, self.ModuleType, self.Arch, self.ToolChainFamily]\r
2943 if not RuleObject:\r
2944 continue\r
2945 RuleObject = RuleObject.Instantiate(self.Macros)\r
2946 BuildRules[Type] = RuleObject\r
2947 for Ext in RuleObject.SourceFileExtList:\r
2948 BuildRules[Ext] = RuleObject\r
2949 self._BuildRules = BuildRules\r
2950 return self._BuildRules\r
2951\r
2952 def _ApplyBuildRule(self, File, FileType):\r
2953 if self._BuildTargets == None:\r
2954 self._IntroBuildTargetList = set()\r
2955 self._FinalBuildTargetList = set()\r
2956 self._BuildTargets = {}\r
2957 self._FileTypes = {}\r
2958\r
fcd4fbf3
YL
2959 SubDirectory = os.path.join(self.OutputDir, File.SubDir)\r
2960 if not os.path.exists(SubDirectory):\r
2961 CreateDirectory(SubDirectory)\r
52302d4d
LG
2962 LastTarget = None\r
2963 RuleChain = []\r
2964 SourceList = [File]\r
2965 Index = 0\r
fe4bf2f9
YL
2966 #\r
2967 # Make sure to get build rule order value\r
2968 #\r
2969 self._GetModuleBuildOption()\r
2970\r
52302d4d
LG
2971 while Index < len(SourceList):\r
2972 Source = SourceList[Index]\r
2973 Index = Index + 1\r
2974\r
2975 if Source != File:\r
2976 CreateDirectory(Source.Dir)\r
2977\r
2978 if File.IsBinary and File == Source and self._BinaryFileList != None and File in self._BinaryFileList:\r
da92f276
LG
2979 # Skip all files that are not binary libraries\r
2980 if not self.IsLibrary:\r
47fea6af 2981 continue\r
52302d4d
LG
2982 RuleObject = self.BuildRules[TAB_DEFAULT_BINARY_FILE]\r
2983 elif FileType in self.BuildRules:\r
2984 RuleObject = self.BuildRules[FileType]\r
2985 elif Source.Ext in self.BuildRules:\r
2986 RuleObject = self.BuildRules[Source.Ext]\r
2987 else:\r
2988 # stop at no more rules\r
2989 if LastTarget:\r
2990 self._FinalBuildTargetList.add(LastTarget)\r
2991 break\r
2992\r
2993 FileType = RuleObject.SourceFileType\r
2994 if FileType not in self._FileTypes:\r
2995 self._FileTypes[FileType] = set()\r
2996 self._FileTypes[FileType].add(Source)\r
2997\r
2998 # stop at STATIC_LIBRARY for library\r
2999 if self.IsLibrary and FileType == TAB_STATIC_LIBRARY:\r
3000 if LastTarget:\r
3001 self._FinalBuildTargetList.add(LastTarget)\r
3002 break\r
3003\r
fe4bf2f9 3004 Target = RuleObject.Apply(Source, self.BuildRuleOrder)\r
52302d4d
LG
3005 if not Target:\r
3006 if LastTarget:\r
3007 self._FinalBuildTargetList.add(LastTarget)\r
3008 break\r
3009 elif not Target.Outputs:\r
3010 # Only do build for target with outputs\r
3011 self._FinalBuildTargetList.add(Target)\r
3012\r
3013 if FileType not in self._BuildTargets:\r
3014 self._BuildTargets[FileType] = set()\r
3015 self._BuildTargets[FileType].add(Target)\r
3016\r
3017 if not Source.IsBinary and Source == File:\r
3018 self._IntroBuildTargetList.add(Target)\r
3019\r
3020 # to avoid cyclic rule\r
3021 if FileType in RuleChain:\r
3022 break\r
3023\r
3024 RuleChain.append(FileType)\r
3025 SourceList.extend(Target.Outputs)\r
3026 LastTarget = Target\r
3027 FileType = TAB_UNKNOWN_FILE\r
3028\r
3029 def _GetTargets(self):\r
3030 if self._BuildTargets == None:\r
3031 self._IntroBuildTargetList = set()\r
3032 self._FinalBuildTargetList = set()\r
3033 self._BuildTargets = {}\r
3034 self._FileTypes = {}\r
3035\r
b36d134f 3036 #TRICK: call _GetSourceFileList to apply build rule for source files\r
52302d4d
LG
3037 if self.SourceFileList:\r
3038 pass\r
3039\r
3040 #TRICK: call _GetBinaryFileList to apply build rule for binary files\r
3041 if self.BinaryFileList:\r
3042 pass\r
3043\r
3044 return self._BuildTargets\r
3045\r
3046 def _GetIntroTargetList(self):\r
3047 self._GetTargets()\r
3048 return self._IntroBuildTargetList\r
3049\r
3050 def _GetFinalTargetList(self):\r
3051 self._GetTargets()\r
3052 return self._FinalBuildTargetList\r
3053\r
3054 def _GetFileTypes(self):\r
3055 self._GetTargets()\r
3056 return self._FileTypes\r
3057\r
3058 ## Get the list of package object the module depends on\r
3059 #\r
3060 # @retval list The package object list\r
3061 #\r
3062 def _GetDependentPackageList(self):\r
3063 return self.Module.Packages\r
3064\r
3065 ## Return the list of auto-generated code file\r
3066 #\r
3067 # @retval list The list of auto-generated file\r
3068 #\r
3069 def _GetAutoGenFileList(self):\r
3070 UniStringAutoGenC = True\r
4234283c 3071 UniStringBinBuffer = StringIO()\r
52302d4d 3072 if self.BuildType == 'UEFI_HII':\r
52302d4d
LG
3073 UniStringAutoGenC = False\r
3074 if self._AutoGenFileList == None:\r
3075 self._AutoGenFileList = {}\r
3076 AutoGenC = TemplateString()\r
3077 AutoGenH = TemplateString()\r
3078 StringH = TemplateString()\r
3079 GenC.CreateCode(self, AutoGenC, AutoGenH, StringH, UniStringAutoGenC, UniStringBinBuffer)\r
07b8564b
YL
3080 #\r
3081 # AutoGen.c is generated if there are library classes in inf, or there are object files\r
3082 #\r
3083 if str(AutoGenC) != "" and (len(self.Module.LibraryClasses) > 0\r
3084 or TAB_OBJECT_FILE in self.FileTypes):\r
52302d4d
LG
3085 AutoFile = PathClass(gAutoGenCodeFileName, self.DebugDir)\r
3086 self._AutoGenFileList[AutoFile] = str(AutoGenC)\r
3087 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)\r
3088 if str(AutoGenH) != "":\r
3089 AutoFile = PathClass(gAutoGenHeaderFileName, self.DebugDir)\r
3090 self._AutoGenFileList[AutoFile] = str(AutoGenH)\r
3091 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)\r
3092 if str(StringH) != "":\r
3093 AutoFile = PathClass(gAutoGenStringFileName % {"module_name":self.Name}, self.DebugDir)\r
3094 self._AutoGenFileList[AutoFile] = str(StringH)\r
3095 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)\r
3096 if UniStringBinBuffer != None and UniStringBinBuffer.getvalue() != "":\r
3097 AutoFile = PathClass(gAutoGenStringFormFileName % {"module_name":self.Name}, self.OutputDir)\r
3098 self._AutoGenFileList[AutoFile] = UniStringBinBuffer.getvalue()\r
3099 AutoFile.IsBinary = True\r
3100 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)\r
3101 if UniStringBinBuffer != None:\r
3102 UniStringBinBuffer.close()\r
3103 return self._AutoGenFileList\r
3104\r
3105 ## Return the list of library modules explicitly or implicityly used by this module\r
3106 def _GetLibraryList(self):\r
3107 if self._DependentLibraryList == None:\r
3108 # only merge library classes and PCD for non-library module\r
3109 if self.IsLibrary:\r
3110 self._DependentLibraryList = []\r
3111 else:\r
3112 if self.AutoGenVersion < 0x00010005:\r
3113 self._DependentLibraryList = self.PlatformInfo.ResolveLibraryReference(self.Module)\r
3114 else:\r
3115 self._DependentLibraryList = self.PlatformInfo.ApplyLibraryInstance(self.Module)\r
3116 return self._DependentLibraryList\r
3117\r
e8a47801
LG
3118 @staticmethod\r
3119 def UpdateComments(Recver, Src):\r
3120 for Key in Src:\r
3121 if Key not in Recver:\r
3122 Recver[Key] = []\r
3123 Recver[Key].extend(Src[Key])\r
52302d4d
LG
3124 ## Get the list of PCDs from current module\r
3125 #\r
3126 # @retval list The list of PCD\r
3127 #\r
3128 def _GetModulePcdList(self):\r
3129 if self._ModulePcdList == None:\r
3130 # apply PCD settings from platform\r
3131 self._ModulePcdList = self.PlatformInfo.ApplyPcdSetting(self.Module, self.Module.Pcds)\r
e8a47801 3132 self.UpdateComments(self._PcdComments, self.Module.PcdComments)\r
52302d4d
LG
3133 return self._ModulePcdList\r
3134\r
3135 ## Get the list of PCDs from dependent libraries\r
3136 #\r
3137 # @retval list The list of PCD\r
3138 #\r
3139 def _GetLibraryPcdList(self):\r
3140 if self._LibraryPcdList == None:\r
79b74a03 3141 Pcds = sdict()\r
52302d4d
LG
3142 if not self.IsLibrary:\r
3143 # get PCDs from dependent libraries\r
3144 for Library in self.DependentLibraryList:\r
e8a47801 3145 self.UpdateComments(self._PcdComments, Library.PcdComments)\r
52302d4d
LG
3146 for Key in Library.Pcds:\r
3147 # skip duplicated PCDs\r
3148 if Key in self.Module.Pcds or Key in Pcds:\r
3149 continue\r
3150 Pcds[Key] = copy.copy(Library.Pcds[Key])\r
3151 # apply PCD settings from platform\r
3152 self._LibraryPcdList = self.PlatformInfo.ApplyPcdSetting(self.Module, Pcds)\r
3153 else:\r
3154 self._LibraryPcdList = []\r
3155 return self._LibraryPcdList\r
3156\r
3157 ## Get the GUID value mapping\r
3158 #\r
3159 # @retval dict The mapping between GUID cname and its value\r
3160 #\r
3161 def _GetGuidList(self):\r
3162 if self._GuidList == None:\r
8200fcfe
YL
3163 self._GuidList = sdict()\r
3164 self._GuidList.update(self.Module.Guids)\r
52302d4d
LG
3165 for Library in self.DependentLibraryList:\r
3166 self._GuidList.update(Library.Guids)\r
e8a47801
LG
3167 self.UpdateComments(self._GuidComments, Library.GuidComments)\r
3168 self.UpdateComments(self._GuidComments, self.Module.GuidComments)\r
52302d4d
LG
3169 return self._GuidList\r
3170\r
e8a47801
LG
3171 def GetGuidsUsedByPcd(self):\r
3172 if self._GuidsUsedByPcd == None:\r
3173 self._GuidsUsedByPcd = sdict()\r
3174 self._GuidsUsedByPcd.update(self.Module.GetGuidsUsedByPcd())\r
3175 for Library in self.DependentLibraryList:\r
3176 self._GuidsUsedByPcd.update(Library.GetGuidsUsedByPcd())\r
3177 return self._GuidsUsedByPcd\r
52302d4d
LG
3178 ## Get the protocol value mapping\r
3179 #\r
3180 # @retval dict The mapping between protocol cname and its value\r
3181 #\r
3182 def _GetProtocolList(self):\r
3183 if self._ProtocolList == None:\r
8200fcfe
YL
3184 self._ProtocolList = sdict()\r
3185 self._ProtocolList.update(self.Module.Protocols)\r
52302d4d
LG
3186 for Library in self.DependentLibraryList:\r
3187 self._ProtocolList.update(Library.Protocols)\r
e8a47801
LG
3188 self.UpdateComments(self._ProtocolComments, Library.ProtocolComments)\r
3189 self.UpdateComments(self._ProtocolComments, self.Module.ProtocolComments)\r
52302d4d
LG
3190 return self._ProtocolList\r
3191\r
3192 ## Get the PPI value mapping\r
3193 #\r
3194 # @retval dict The mapping between PPI cname and its value\r
3195 #\r
3196 def _GetPpiList(self):\r
3197 if self._PpiList == None:\r
8200fcfe
YL
3198 self._PpiList = sdict()\r
3199 self._PpiList.update(self.Module.Ppis)\r
52302d4d
LG
3200 for Library in self.DependentLibraryList:\r
3201 self._PpiList.update(Library.Ppis)\r
e8a47801
LG
3202 self.UpdateComments(self._PpiComments, Library.PpiComments)\r
3203 self.UpdateComments(self._PpiComments, self.Module.PpiComments)\r
52302d4d
LG
3204 return self._PpiList\r
3205\r
3206 ## Get the list of include search path\r
3207 #\r
3208 # @retval list The list path\r
3209 #\r
3210 def _GetIncludePathList(self):\r
3211 if self._IncludePathList == None:\r
3212 self._IncludePathList = []\r
3213 if self.AutoGenVersion < 0x00010005:\r
3214 for Inc in self.Module.Includes:\r
3215 if Inc not in self._IncludePathList:\r
3216 self._IncludePathList.append(Inc)\r
b36d134f 3217 # for Edk modules\r
52302d4d
LG
3218 Inc = path.join(Inc, self.Arch.capitalize())\r
3219 if os.path.exists(Inc) and Inc not in self._IncludePathList:\r
3220 self._IncludePathList.append(Inc)\r
b36d134f 3221 # Edk module needs to put DEBUG_DIR at the end of search path and not to use SOURCE_DIR all the time\r
52302d4d
LG
3222 self._IncludePathList.append(self.DebugDir)\r
3223 else:\r
3224 self._IncludePathList.append(self.MetaFile.Dir)\r
3225 self._IncludePathList.append(self.DebugDir)\r
3226\r
3227 for Package in self.Module.Packages:\r
05cc51ad 3228 PackageDir = mws.join(self.WorkspaceDir, Package.MetaFile.Dir)\r
52302d4d
LG
3229 if PackageDir not in self._IncludePathList:\r
3230 self._IncludePathList.append(PackageDir)\r
3231 for Inc in Package.Includes:\r
3232 if Inc not in self._IncludePathList:\r
3233 self._IncludePathList.append(str(Inc))\r
3234 return self._IncludePathList\r
3235\r
725cdb8f
YZ
3236 def _GetIncludePathLength(self):\r
3237 self._IncludePathLength = 0\r
3238 if self._IncludePathList:\r
3239 for inc in self._IncludePathList:\r
3240 self._IncludePathLength += len(' ' + inc)\r
3241 return self._IncludePathLength\r
3242\r
97fa0ee9
YL
3243 ## Get HII EX PCDs which maybe used by VFR\r
3244 #\r
3245 # efivarstore used by VFR may relate with HII EX PCDs\r
3246 # Get the variable name and GUID from efivarstore and HII EX PCD\r
3247 # List the HII EX PCDs in As Built INF if both name and GUID match.\r
3248 #\r
3249 # @retval list HII EX PCDs\r
3250 #\r
3251 def _GetPcdsMaybeUsedByVfr(self):\r
3252 if not self.SourceFileList:\r
3253 return []\r
3254\r
3255 NameGuids = []\r
3256 for SrcFile in self.SourceFileList:\r
3257 if SrcFile.Ext.lower() != '.vfr':\r
3258 continue\r
3259 Vfri = os.path.join(self.OutputDir, SrcFile.BaseName + '.i')\r
3260 if not os.path.exists(Vfri):\r
3261 continue\r
3262 VfriFile = open(Vfri, 'r')\r
3263 Content = VfriFile.read()\r
3264 VfriFile.close()\r
3265 Pos = Content.find('efivarstore')\r
3266 while Pos != -1:\r
3267 #\r
3268 # Make sure 'efivarstore' is the start of efivarstore statement\r
3269 # In case of the value of 'name' (name = efivarstore) is equal to 'efivarstore'\r
3270 #\r
3271 Index = Pos - 1\r
3272 while Index >= 0 and Content[Index] in ' \t\r\n':\r
3273 Index -= 1\r
3274 if Index >= 0 and Content[Index] != ';':\r
3275 Pos = Content.find('efivarstore', Pos + len('efivarstore'))\r
3276 continue\r
3277 #\r
3278 # 'efivarstore' must be followed by name and guid\r
3279 #\r
3280 Name = gEfiVarStoreNamePattern.search(Content, Pos)\r
3281 if not Name:\r
3282 break\r
3283 Guid = gEfiVarStoreGuidPattern.search(Content, Pos)\r
3284 if not Guid:\r
3285 break\r
3286 NameArray = ConvertStringToByteArray('L"' + Name.group(1) + '"')\r
3287 NameGuids.append((NameArray, GuidStructureStringToGuidString(Guid.group(1))))\r
3288 Pos = Content.find('efivarstore', Name.end())\r
3289 if not NameGuids:\r
3290 return []\r
3291 HiiExPcds = []\r
3292 for Pcd in self.PlatformInfo.Platform.Pcds.values():\r
3293 if Pcd.Type != TAB_PCDS_DYNAMIC_EX_HII:\r
3294 continue\r
3295 for SkuName in Pcd.SkuInfoList:\r
3296 SkuInfo = Pcd.SkuInfoList[SkuName]\r
3297 Name = ConvertStringToByteArray(SkuInfo.VariableName)\r
3298 Value = GuidValue(SkuInfo.VariableGuid, self.PlatformInfo.PackageList)\r
3299 if not Value:\r
3300 continue\r
3301 Guid = GuidStructureStringToGuidString(Value)\r
3302 if (Name, Guid) in NameGuids and Pcd not in HiiExPcds:\r
3303 HiiExPcds.append(Pcd)\r
3304 break\r
3305\r
3306 return HiiExPcds\r
3307\r
aeaaf754
YL
3308 def _GenOffsetBin(self):\r
3309 VfrUniBaseName = {}\r
3310 for SourceFile in self.Module.Sources:\r
3311 if SourceFile.Type.upper() == ".VFR" :\r
3312 #\r
3313 # search the .map file to find the offset of vfr binary in the PE32+/TE file. \r
3314 #\r
3315 VfrUniBaseName[SourceFile.BaseName] = (SourceFile.BaseName + "Bin")\r
3316 if SourceFile.Type.upper() == ".UNI" :\r
3317 #\r
3318 # search the .map file to find the offset of Uni strings binary in the PE32+/TE file. \r
3319 #\r
3320 VfrUniBaseName["UniOffsetName"] = (self.Name + "Strings")\r
3321\r
3322 if len(VfrUniBaseName) == 0:\r
3323 return None\r
3324 MapFileName = os.path.join(self.OutputDir, self.Name + ".map")\r
3325 EfiFileName = os.path.join(self.OutputDir, self.Name + ".efi")\r
3326 VfrUniOffsetList = GetVariableOffset(MapFileName, EfiFileName, VfrUniBaseName.values())\r
3327 if not VfrUniOffsetList:\r
3328 return None\r
3329\r
3330 OutputName = '%sOffset.bin' % self.Name\r
3331 UniVfrOffsetFileName = os.path.join( self.OutputDir, OutputName)\r
3332\r
3333 try:\r
3334 fInputfile = open(UniVfrOffsetFileName, "wb+", 0)\r
3335 except:\r
3336 EdkLogger.error("build", FILE_OPEN_FAILURE, "File open failed for %s" % UniVfrOffsetFileName,None)\r
3337\r
3338 # Use a instance of StringIO to cache data\r
3339 fStringIO = StringIO('') \r
3340\r
3341 for Item in VfrUniOffsetList:\r
3342 if (Item[0].find("Strings") != -1):\r
3343 #\r
3344 # UNI offset in image.\r
3345 # GUID + Offset\r
3346 # { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } }\r
3347 #\r
3348 UniGuid = [0xe0, 0xc5, 0x13, 0x89, 0xf6, 0x33, 0x86, 0x4d, 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66]\r
3349 UniGuid = [chr(ItemGuid) for ItemGuid in UniGuid]\r
3350 fStringIO.write(''.join(UniGuid)) \r
3351 UniValue = pack ('Q', int (Item[1], 16))\r
3352 fStringIO.write (UniValue)\r
3353 else:\r
3354 #\r
3355 # VFR binary offset in image.\r
3356 # GUID + Offset\r
3357 # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } };\r
3358 #\r
3359 VfrGuid = [0xb4, 0x7c, 0xbc, 0xd0, 0x47, 0x6a, 0x5f, 0x49, 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2]\r
3360 VfrGuid = [chr(ItemGuid) for ItemGuid in VfrGuid]\r
3361 fStringIO.write(''.join(VfrGuid)) \r
3362 type (Item[1]) \r
3363 VfrValue = pack ('Q', int (Item[1], 16))\r
3364 fStringIO.write (VfrValue)\r
3365 #\r
3366 # write data into file.\r
3367 #\r
3368 try : \r
3369 fInputfile.write (fStringIO.getvalue())\r
3370 except:\r
3371 EdkLogger.error("build", FILE_WRITE_FAILURE, "Write data to file %s failed, please check whether the "\r
3372 "file been locked or using by other applications." %UniVfrOffsetFileName,None)\r
3373\r
3374 fStringIO.close ()\r
3375 fInputfile.close ()\r
3376 return OutputName\r
3377\r
da92f276
LG
3378 ## Create AsBuilt INF file the module\r
3379 #\r
3380 def CreateAsBuiltInf(self):\r
3381 if self.IsAsBuiltInfCreated:\r
3382 return\r
3383 \r
3384 # Skip the following code for EDK I inf\r
3385 if self.AutoGenVersion < 0x00010005:\r
3386 return\r
3387 \r
3388 # Skip the following code for libraries\r
3389 if self.IsLibrary:\r
3390 return\r
3391 \r
3392 # Skip the following code for modules with no source files\r
3393 if self.SourceFileList == None or self.SourceFileList == []:\r
3394 return\r
3395\r
3396 # Skip the following code for modules without any binary files\r
3397 if self.BinaryFileList <> None and self.BinaryFileList <> []:\r
3398 return\r
3399 \r
3400 ### TODO: How to handles mixed source and binary modules\r
3401\r
e8a47801 3402 # Find all DynamicEx and PatchableInModule PCDs used by this module and dependent libraries\r
da92f276
LG
3403 # Also find all packages that the DynamicEx PCDs depend on\r
3404 Pcds = []\r
e8a47801 3405 PatchablePcds = {}\r
47fea6af 3406 Packages = []\r
e8a47801
LG
3407 PcdCheckList = []\r
3408 PcdTokenSpaceList = []\r
da92f276 3409 for Pcd in self.ModulePcdList + self.LibraryPcdList:\r
e8a47801
LG
3410 if Pcd.Type == TAB_PCDS_PATCHABLE_IN_MODULE:\r
3411 PatchablePcds[Pcd.TokenCName] = Pcd\r
3412 PcdCheckList.append((Pcd.TokenCName, Pcd.TokenSpaceGuidCName, 'PatchableInModule'))\r
3413 elif Pcd.Type in GenC.gDynamicExPcd:\r
3414 if Pcd not in Pcds:\r
3415 Pcds += [Pcd]\r
3416 PcdCheckList.append((Pcd.TokenCName, Pcd.TokenSpaceGuidCName, 'DynamicEx'))\r
3417 PcdCheckList.append((Pcd.TokenCName, Pcd.TokenSpaceGuidCName, 'Dynamic'))\r
3418 PcdTokenSpaceList.append(Pcd.TokenSpaceGuidCName)\r
3419 GuidList = sdict()\r
3420 GuidList.update(self.GuidList)\r
3421 for TokenSpace in self.GetGuidsUsedByPcd():\r
3422 # If token space is not referred by patch PCD or Ex PCD, remove the GUID from GUID list\r
3423 # The GUIDs in GUIDs section should really be the GUIDs in source INF or referred by Ex an patch PCDs\r
3424 if TokenSpace not in PcdTokenSpaceList and TokenSpace in GuidList:\r
3425 GuidList.pop(TokenSpace)\r
3426 CheckList = (GuidList, self.PpiList, self.ProtocolList, PcdCheckList)\r
3427 for Package in self.DerivedPackageList:\r
3428 if Package in Packages:\r
3429 continue\r
3430 BeChecked = (Package.Guids, Package.Ppis, Package.Protocols, Package.Pcds)\r
3431 Found = False\r
3432 for Index in range(len(BeChecked)):\r
3433 for Item in CheckList[Index]:\r
3434 if Item in BeChecked[Index]:\r
3435 Packages += [Package]\r
3436 Found = True\r
3437 break\r
3438 if Found: break\r
da92f276 3439\r
97fa0ee9
YL
3440 VfrPcds = self._GetPcdsMaybeUsedByVfr()\r
3441 for Pkg in self.PlatformInfo.PackageList:\r
3442 if Pkg in Packages:\r
3443 continue\r
3444 for VfrPcd in VfrPcds:\r
3445 if ((VfrPcd.TokenCName, VfrPcd.TokenSpaceGuidCName, 'DynamicEx') in Pkg.Pcds or\r
3446 (VfrPcd.TokenCName, VfrPcd.TokenSpaceGuidCName, 'Dynamic') in Pkg.Pcds):\r
3447 Packages += [Pkg]\r
3448 break\r
3449\r
da92f276
LG
3450 ModuleType = self.ModuleType\r
3451 if ModuleType == 'UEFI_DRIVER' and self.DepexGenerated:\r
e8a47801
LG
3452 ModuleType = 'DXE_DRIVER'\r
3453\r
3454 DriverType = ''\r
3455 if self.PcdIsDriver != '':\r
3456 DriverType = self.PcdIsDriver\r
da92f276 3457\r
97fa0ee9
YL
3458 Guid = self.Guid\r
3459 MDefs = self.Module.Defines\r
3460\r
da92f276
LG
3461 AsBuiltInfDict = {\r
3462 'module_name' : self.Name,\r
97fa0ee9 3463 'module_guid' : Guid,\r
da92f276 3464 'module_module_type' : ModuleType,\r
97fa0ee9 3465 'module_version_string' : [MDefs['VERSION_STRING']] if 'VERSION_STRING' in MDefs else [],\r
e8a47801 3466 'pcd_is_driver_string' : [],\r
da92f276
LG
3467 'module_uefi_specification_version' : [],\r
3468 'module_pi_specification_version' : [],\r
97fa0ee9
YL
3469 'module_entry_point' : self.Module.ModuleEntryPointList,\r
3470 'module_unload_image' : self.Module.ModuleUnloadImageList,\r
3471 'module_constructor' : self.Module.ConstructorList,\r
3472 'module_destructor' : self.Module.DestructorList,\r
3473 'module_shadow' : [MDefs['SHADOW']] if 'SHADOW' in MDefs else [],\r
3474 'module_pci_vendor_id' : [MDefs['PCI_VENDOR_ID']] if 'PCI_VENDOR_ID' in MDefs else [],\r
3475 'module_pci_device_id' : [MDefs['PCI_DEVICE_ID']] if 'PCI_DEVICE_ID' in MDefs else [],\r
3476 'module_pci_class_code' : [MDefs['PCI_CLASS_CODE']] if 'PCI_CLASS_CODE' in MDefs else [],\r
3477 'module_pci_revision' : [MDefs['PCI_REVISION']] if 'PCI_REVISION' in MDefs else [],\r
3478 'module_build_number' : [MDefs['BUILD_NUMBER']] if 'BUILD_NUMBER' in MDefs else [],\r
3479 'module_spec' : [MDefs['SPEC']] if 'SPEC' in MDefs else [],\r
3480 'module_uefi_hii_resource_section' : [MDefs['UEFI_HII_RESOURCE_SECTION']] if 'UEFI_HII_RESOURCE_SECTION' in MDefs else [],\r
3481 'module_uni_file' : [MDefs['MODULE_UNI_FILE']] if 'MODULE_UNI_FILE' in MDefs else [],\r
da92f276 3482 'module_arch' : self.Arch,\r
47fea6af 3483 'package_item' : ['%s' % (Package.MetaFile.File.replace('\\', '/')) for Package in Packages],\r
da92f276 3484 'binary_item' : [],\r
e8a47801 3485 'patchablepcd_item' : [],\r
da92f276 3486 'pcd_item' : [],\r
e8a47801
LG
3487 'protocol_item' : [],\r
3488 'ppi_item' : [],\r
3489 'guid_item' : [],\r
3490 'flags_item' : [],\r
3491 'libraryclasses_item' : []\r
da92f276 3492 }\r
97fa0ee9
YL
3493\r
3494 if self.AutoGenVersion > int(gInfSpecVersion, 0):\r
3495 AsBuiltInfDict['module_inf_version'] = '0x%08x' % self.AutoGenVersion\r
3496 else:\r
3497 AsBuiltInfDict['module_inf_version'] = gInfSpecVersion\r
3498\r
e8a47801
LG
3499 if DriverType:\r
3500 AsBuiltInfDict['pcd_is_driver_string'] += [DriverType]\r
da92f276
LG
3501\r
3502 if 'UEFI_SPECIFICATION_VERSION' in self.Specification:\r
3503 AsBuiltInfDict['module_uefi_specification_version'] += [self.Specification['UEFI_SPECIFICATION_VERSION']]\r
3504 if 'PI_SPECIFICATION_VERSION' in self.Specification:\r
3505 AsBuiltInfDict['module_pi_specification_version'] += [self.Specification['PI_SPECIFICATION_VERSION']]\r
3506\r
47fea6af 3507 OutputDir = self.OutputDir.replace('\\', '/').strip('/')\r
da92f276
LG
3508 if self.ModuleType in ['BASE', 'USER_DEFINED']:\r
3509 for Item in self.CodaTargetList:\r
47fea6af
YZ
3510 File = Item.Target.Path.replace('\\', '/').strip('/').replace(OutputDir, '').strip('/')\r
3511 if Item.Target.Ext.lower() == '.aml':\r
da92f276 3512 AsBuiltInfDict['binary_item'] += ['ASL|' + File]\r
47fea6af 3513 elif Item.Target.Ext.lower() == '.acpi':\r
da92f276
LG
3514 AsBuiltInfDict['binary_item'] += ['ACPI|' + File]\r
3515 else:\r
3516 AsBuiltInfDict['binary_item'] += ['BIN|' + File]\r
3517 else:\r
3518 for Item in self.CodaTargetList:\r
47fea6af
YZ
3519 File = Item.Target.Path.replace('\\', '/').strip('/').replace(OutputDir, '').strip('/')\r
3520 if Item.Target.Ext.lower() == '.efi':\r
da92f276
LG
3521 AsBuiltInfDict['binary_item'] += ['PE32|' + self.Name + '.efi']\r
3522 else:\r
3523 AsBuiltInfDict['binary_item'] += ['BIN|' + File]\r
3524 if self.DepexGenerated:\r
3525 if self.ModuleType in ['PEIM']:\r
3526 AsBuiltInfDict['binary_item'] += ['PEI_DEPEX|' + self.Name + '.depex']\r
47fea6af 3527 if self.ModuleType in ['DXE_DRIVER', 'DXE_RUNTIME_DRIVER', 'DXE_SAL_DRIVER', 'UEFI_DRIVER']:\r
da92f276
LG
3528 AsBuiltInfDict['binary_item'] += ['DXE_DEPEX|' + self.Name + '.depex']\r
3529 if self.ModuleType in ['DXE_SMM_DRIVER']:\r
3530 AsBuiltInfDict['binary_item'] += ['SMM_DEPEX|' + self.Name + '.depex']\r
3531\r
aeaaf754
YL
3532 Bin = self._GenOffsetBin()\r
3533 if Bin:\r
3534 AsBuiltInfDict['binary_item'] += ['BIN|%s' % Bin]\r
3535\r
e8a47801
LG
3536 for Root, Dirs, Files in os.walk(OutputDir):\r
3537 for File in Files:\r
3538 if File.lower().endswith('.pdb'):\r
3539 AsBuiltInfDict['binary_item'] += ['DISPOSABLE|' + File]\r
3540 HeaderComments = self.Module.HeaderComments\r
3541 StartPos = 0\r
3542 for Index in range(len(HeaderComments)):\r
3543 if HeaderComments[Index].find('@BinaryHeader') != -1:\r
3544 HeaderComments[Index] = HeaderComments[Index].replace('@BinaryHeader', '@file')\r
3545 StartPos = Index\r
3546 break\r
3547 AsBuiltInfDict['header_comments'] = '\n'.join(HeaderComments[StartPos:]).replace(':#', '://')\r
97fa0ee9
YL
3548 AsBuiltInfDict['tail_comments'] = '\n'.join(self.Module.TailComments)\r
3549\r
e8a47801
LG
3550 GenList = [\r
3551 (self.ProtocolList, self._ProtocolComments, 'protocol_item'),\r
3552 (self.PpiList, self._PpiComments, 'ppi_item'),\r
3553 (GuidList, self._GuidComments, 'guid_item')\r
3554 ]\r
3555 for Item in GenList:\r
3556 for CName in Item[0]:\r
3557 Comments = ''\r
3558 if CName in Item[1]:\r
3559 Comments = '\n '.join(Item[1][CName])\r
3560 Entry = CName\r
3561 if Comments:\r
3562 Entry = Comments + '\n ' + CName\r
3563 AsBuiltInfDict[Item[2]].append(Entry)\r
3564 PatchList = parsePcdInfoFromMapFile(\r
3565 os.path.join(self.OutputDir, self.Name + '.map'),\r
3566 os.path.join(self.OutputDir, self.Name + '.efi')\r
3567 )\r
3568 if PatchList:\r
3569 for PatchPcd in PatchList:\r
3570 if PatchPcd[0] not in PatchablePcds:\r
3571 continue\r
3572 Pcd = PatchablePcds[PatchPcd[0]]\r
3573 PcdValue = ''\r
3574 if Pcd.DatumType != 'VOID*':\r
3575 HexFormat = '0x%02x'\r
3576 if Pcd.DatumType == 'UINT16':\r
3577 HexFormat = '0x%04x'\r
3578 elif Pcd.DatumType == 'UINT32':\r
3579 HexFormat = '0x%08x'\r
3580 elif Pcd.DatumType == 'UINT64':\r
3581 HexFormat = '0x%016x'\r
3582 PcdValue = HexFormat % int(Pcd.DefaultValue, 0)\r
3583 else:\r
3584 if Pcd.MaxDatumSize == None or Pcd.MaxDatumSize == '':\r
3585 EdkLogger.error("build", AUTOGEN_ERROR,\r
3586 "Unknown [MaxDatumSize] of PCD [%s.%s]" % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName)\r
3587 )\r
3588 ArraySize = int(Pcd.MaxDatumSize, 0)\r
3589 PcdValue = Pcd.DefaultValue\r
3590 if PcdValue[0] != '{':\r
3591 Unicode = False\r
3592 if PcdValue[0] == 'L':\r
3593 Unicode = True\r
3594 PcdValue = PcdValue.lstrip('L')\r
3595 PcdValue = eval(PcdValue)\r
3596 NewValue = '{'\r
3597 for Index in range(0, len(PcdValue)):\r
3598 if Unicode:\r
3599 CharVal = ord(PcdValue[Index])\r
3600 NewValue = NewValue + '0x%02x' % (CharVal & 0x00FF) + ', ' \\r
3601 + '0x%02x' % (CharVal >> 8) + ', '\r
3602 else:\r
3603 NewValue = NewValue + '0x%02x' % (ord(PcdValue[Index]) % 0x100) + ', '\r
3604 Padding = '0x00, '\r
3605 if Unicode:\r
3606 Padding = Padding * 2\r
3607 ArraySize = ArraySize / 2\r
3608 if ArraySize < (len(PcdValue) + 1):\r
3609 EdkLogger.error("build", AUTOGEN_ERROR,\r
3610 "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName)\r
3611 )\r
3612 if ArraySize > len(PcdValue) + 1:\r
3613 NewValue = NewValue + Padding * (ArraySize - len(PcdValue) - 1)\r
3614 PcdValue = NewValue + Padding.strip().rstrip(',') + '}'\r
3615 elif len(PcdValue.split(',')) <= ArraySize:\r
3616 PcdValue = PcdValue.rstrip('}') + ', 0x00' * (ArraySize - len(PcdValue.split(',')))\r
3617 PcdValue += '}'\r
3618 else:\r
3619 EdkLogger.error("build", AUTOGEN_ERROR,\r
3620 "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName)\r
3621 )\r
3622 PcdItem = '%s.%s|%s|0x%X' % \\r
3623 (Pcd.TokenSpaceGuidCName, Pcd.TokenCName, PcdValue, PatchPcd[1])\r
3624 PcdComments = ''\r
3625 if (Pcd.TokenSpaceGuidCName, Pcd.TokenCName) in self._PcdComments:\r
3626 PcdComments = '\n '.join(self._PcdComments[Pcd.TokenSpaceGuidCName, Pcd.TokenCName])\r
3627 if PcdComments:\r
3628 PcdItem = PcdComments + '\n ' + PcdItem\r
3629 AsBuiltInfDict['patchablepcd_item'].append(PcdItem)\r
97fa0ee9
YL
3630\r
3631 HiiPcds = []\r
3632 for Pcd in Pcds + VfrPcds:\r
e8a47801
LG
3633 PcdComments = ''\r
3634 PcdCommentList = []\r
3635 HiiInfo = ''\r
97fa0ee9 3636 SkuId = ''\r
e8a47801
LG
3637 if Pcd.Type == TAB_PCDS_DYNAMIC_EX_HII:\r
3638 for SkuName in Pcd.SkuInfoList:\r
3639 SkuInfo = Pcd.SkuInfoList[SkuName]\r
97fa0ee9 3640 SkuId = SkuInfo.SkuId\r
e8a47801
LG
3641 HiiInfo = '## %s|%s|%s' % (SkuInfo.VariableName, SkuInfo.VariableGuid, SkuInfo.VariableOffset)\r
3642 break\r
97fa0ee9
YL
3643 if SkuId:\r
3644 #\r
3645 # Don't generate duplicated HII PCD\r
3646 #\r
3647 if (SkuId, Pcd.TokenSpaceGuidCName, Pcd.TokenCName) in HiiPcds:\r
3648 continue\r
3649 else:\r
3650 HiiPcds.append((SkuId, Pcd.TokenSpaceGuidCName, Pcd.TokenCName))\r
e8a47801
LG
3651 if (Pcd.TokenSpaceGuidCName, Pcd.TokenCName) in self._PcdComments:\r
3652 PcdCommentList = self._PcdComments[Pcd.TokenSpaceGuidCName, Pcd.TokenCName][:]\r
3653 if HiiInfo:\r
3654 UsageIndex = -1\r
97fa0ee9 3655 UsageStr = ''\r
e8a47801
LG
3656 for Index, Comment in enumerate(PcdCommentList):\r
3657 for Usage in UsageList:\r
3658 if Comment.find(Usage) != -1:\r
97fa0ee9 3659 UsageStr = Usage\r
e8a47801
LG
3660 UsageIndex = Index\r
3661 break\r
3662 if UsageIndex != -1:\r
97fa0ee9 3663 PcdCommentList[UsageIndex] = '## %s %s %s' % (UsageStr, HiiInfo, PcdCommentList[UsageIndex].replace(UsageStr, '')) \r
e8a47801 3664 else:\r
97fa0ee9 3665 PcdCommentList.append('## UNDEFINED ' + HiiInfo)\r
e8a47801
LG
3666 PcdComments = '\n '.join(PcdCommentList)\r
3667 PcdEntry = Pcd.TokenSpaceGuidCName + '.' + Pcd.TokenCName\r
3668 if PcdComments:\r
3669 PcdEntry = PcdComments + '\n ' + PcdEntry\r
3670 AsBuiltInfDict['pcd_item'] += [PcdEntry]\r
da92f276
LG
3671 for Item in self.BuildOption:\r
3672 if 'FLAGS' in self.BuildOption[Item]:\r
3673 AsBuiltInfDict['flags_item'] += ['%s:%s_%s_%s_%s_FLAGS = %s' % (self.ToolChainFamily, self.BuildTarget, self.ToolChain, self.Arch, Item, self.BuildOption[Item]['FLAGS'].strip())]\r
97fa0ee9
YL
3674\r
3675 # Generated LibraryClasses section in comments.\r
3676 for Library in self.LibraryAutoGenList:\r
3677 AsBuiltInfDict['libraryclasses_item'] += [Library.MetaFile.File.replace('\\', '/')]\r
3678 \r
3679 # Generated depex expression section in comments.\r
3680 AsBuiltInfDict['depexsection_item'] = ''\r
3681 DepexExpresion = self._GetDepexExpresionString()\r
3682 if DepexExpresion:\r
3683 AsBuiltInfDict['depexsection_item'] = DepexExpresion\r
da92f276
LG
3684 \r
3685 AsBuiltInf = TemplateString()\r
3686 AsBuiltInf.Append(gAsBuiltInfHeaderString.Replace(AsBuiltInfDict))\r
3687 \r
3688 SaveFileOnChange(os.path.join(self.OutputDir, self.Name + '.inf'), str(AsBuiltInf), False)\r
3689 \r
3690 self.IsAsBuiltInfCreated = True\r
3691 \r
52302d4d
LG
3692 ## Create makefile for the module and its dependent libraries\r
3693 #\r
3694 # @param CreateLibraryMakeFile Flag indicating if or not the makefiles of\r
3695 # dependent libraries will be created\r
3696 #\r
3697 def CreateMakeFile(self, CreateLibraryMakeFile=True):\r
fae62ff2 3698 # Ignore generating makefile when it is a binary module\r
a0a2cd1e
FB
3699 if self.IsBinaryModule:\r
3700 return\r
fae62ff2 3701\r
52302d4d
LG
3702 if self.IsMakeFileCreated:\r
3703 return\r
3704\r
3705 if not self.IsLibrary and CreateLibraryMakeFile:\r
3706 for LibraryAutoGen in self.LibraryAutoGenList:\r
3707 LibraryAutoGen.CreateMakeFile()\r
3708\r
3709 if len(self.CustomMakefile) == 0:\r
3710 Makefile = GenMake.ModuleMakefile(self)\r
3711 else:\r
3712 Makefile = GenMake.CustomMakefile(self)\r
3713 if Makefile.Generate():\r
3714 EdkLogger.debug(EdkLogger.DEBUG_9, "Generated makefile for module %s [%s]" %\r
3715 (self.Name, self.Arch))\r
3716 else:\r
3717 EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of makefile for module %s [%s]" %\r
3718 (self.Name, self.Arch))\r
3719\r
3720 self.IsMakeFileCreated = True\r
3721\r
a0a2cd1e
FB
3722 def CopyBinaryFiles(self):\r
3723 for File in self.Module.Binaries:\r
3724 SrcPath = File.Path\r
3725 DstPath = os.path.join(self.OutputDir , os.path.basename(SrcPath))\r
3726 CopyLongFilePath(SrcPath, DstPath)\r
52302d4d
LG
3727 ## Create autogen code for the module and its dependent libraries\r
3728 #\r
3729 # @param CreateLibraryCodeFile Flag indicating if or not the code of\r
3730 # dependent libraries will be created\r
3731 #\r
3732 def CreateCodeFile(self, CreateLibraryCodeFile=True):\r
3733 if self.IsCodeFileCreated:\r
3734 return\r
3735\r
e8a47801
LG
3736 # Need to generate PcdDatabase even PcdDriver is binarymodule\r
3737 if self.IsBinaryModule and self.PcdIsDriver != '':\r
3738 CreatePcdDatabaseCode(self, TemplateString(), TemplateString())\r
3739 return\r
a0a2cd1e 3740 if self.IsBinaryModule:\r
49d9b71d
HC
3741 if self.IsLibrary:\r
3742 self.CopyBinaryFiles()\r
a0a2cd1e 3743 return\r
e8a47801 3744\r
52302d4d
LG
3745 if not self.IsLibrary and CreateLibraryCodeFile:\r
3746 for LibraryAutoGen in self.LibraryAutoGenList:\r
3747 LibraryAutoGen.CreateCodeFile()\r
3748\r
3749 AutoGenList = []\r
3750 IgoredAutoGenList = []\r
3751\r
3752 for File in self.AutoGenFileList:\r
3753 if GenC.Generate(File.Path, self.AutoGenFileList[File], File.IsBinary):\r
b36d134f 3754 #Ignore Edk AutoGen.c\r
52302d4d
LG
3755 if self.AutoGenVersion < 0x00010005 and File.Name == 'AutoGen.c':\r
3756 continue\r
3757\r
3758 AutoGenList.append(str(File))\r
3759 else:\r
3760 IgoredAutoGenList.append(str(File))\r
3761\r
3762 # Skip the following code for EDK I inf\r
3763 if self.AutoGenVersion < 0x00010005:\r
3764 return\r
3765\r
3766 for ModuleType in self.DepexList:\r
40d841f6
LG
3767 # Ignore empty [depex] section or [depex] section for "USER_DEFINED" module\r
3768 if len(self.DepexList[ModuleType]) == 0 or ModuleType == "USER_DEFINED":\r
52302d4d 3769 continue\r
40d841f6 3770\r
52302d4d
LG
3771 Dpx = GenDepex.DependencyExpression(self.DepexList[ModuleType], ModuleType, True)\r
3772 DpxFile = gAutoGenDepexFileName % {"module_name" : self.Name}\r
3773\r
da92f276 3774 if len(Dpx.PostfixNotation) <> 0:\r
0d2711a6 3775 self.DepexGenerated = True\r
da92f276 3776\r
52302d4d
LG
3777 if Dpx.Generate(path.join(self.OutputDir, DpxFile)):\r
3778 AutoGenList.append(str(DpxFile))\r
3779 else:\r
3780 IgoredAutoGenList.append(str(DpxFile))\r
3781\r
3782 if IgoredAutoGenList == []:\r
3783 EdkLogger.debug(EdkLogger.DEBUG_9, "Generated [%s] files for module %s [%s]" %\r
3784 (" ".join(AutoGenList), self.Name, self.Arch))\r
3785 elif AutoGenList == []:\r
3786 EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of [%s] files for module %s [%s]" %\r
3787 (" ".join(IgoredAutoGenList), self.Name, self.Arch))\r
3788 else:\r
3789 EdkLogger.debug(EdkLogger.DEBUG_9, "Generated [%s] (skipped %s) files for module %s [%s]" %\r
3790 (" ".join(AutoGenList), " ".join(IgoredAutoGenList), self.Name, self.Arch))\r
3791\r
3792 self.IsCodeFileCreated = True\r
3793 return AutoGenList\r
3794\r
3795 ## Summarize the ModuleAutoGen objects of all libraries used by this module\r
3796 def _GetLibraryAutoGenList(self):\r
3797 if self._LibraryAutoGenList == None:\r
3798 self._LibraryAutoGenList = []\r
3799 for Library in self.DependentLibraryList:\r
3800 La = ModuleAutoGen(\r
3801 self.Workspace,\r
3802 Library.MetaFile,\r
3803 self.BuildTarget,\r
3804 self.ToolChain,\r
3805 self.Arch,\r
3806 self.PlatformInfo.MetaFile\r
3807 )\r
3808 if La not in self._LibraryAutoGenList:\r
3809 self._LibraryAutoGenList.append(La)\r
3810 for Lib in La.CodaTargetList:\r
3811 self._ApplyBuildRule(Lib.Target, TAB_UNKNOWN_FILE)\r
3812 return self._LibraryAutoGenList\r
3813\r
52302d4d
LG
3814 Module = property(_GetModule)\r
3815 Name = property(_GetBaseName)\r
3816 Guid = property(_GetGuid)\r
3817 Version = property(_GetVersion)\r
3818 ModuleType = property(_GetModuleType)\r
3819 ComponentType = property(_GetComponentType)\r
3820 BuildType = property(_GetBuildType)\r
3821 PcdIsDriver = property(_GetPcdIsDriver)\r
3822 AutoGenVersion = property(_GetAutoGenVersion)\r
3823 Macros = property(_GetMacros)\r
3824 Specification = property(_GetSpecification)\r
3825\r
3826 IsLibrary = property(_IsLibrary)\r
e8a47801 3827 IsBinaryModule = property(_IsBinaryModule)\r
52302d4d
LG
3828 BuildDir = property(_GetBuildDir)\r
3829 OutputDir = property(_GetOutputDir)\r
3830 DebugDir = property(_GetDebugDir)\r
3831 MakeFileDir = property(_GetMakeFileDir)\r
3832 CustomMakefile = property(_GetCustomMakefile)\r
3833\r
3834 IncludePathList = property(_GetIncludePathList)\r
725cdb8f 3835 IncludePathLength = property(_GetIncludePathLength)\r
52302d4d
LG
3836 AutoGenFileList = property(_GetAutoGenFileList)\r
3837 UnicodeFileList = property(_GetUnicodeFileList)\r
3838 SourceFileList = property(_GetSourceFileList)\r
3839 BinaryFileList = property(_GetBinaryFiles) # FileType : [File List]\r
3840 Targets = property(_GetTargets)\r
3841 IntroTargetList = property(_GetIntroTargetList)\r
3842 CodaTargetList = property(_GetFinalTargetList)\r
3843 FileTypes = property(_GetFileTypes)\r
3844 BuildRules = property(_GetBuildRules)\r
3845\r
3846 DependentPackageList = property(_GetDependentPackageList)\r
3847 DependentLibraryList = property(_GetLibraryList)\r
3848 LibraryAutoGenList = property(_GetLibraryAutoGenList)\r
3849 DerivedPackageList = property(_GetDerivedPackageList)\r
3850\r
3851 ModulePcdList = property(_GetModulePcdList)\r
3852 LibraryPcdList = property(_GetLibraryPcdList)\r
3853 GuidList = property(_GetGuidList)\r
3854 ProtocolList = property(_GetProtocolList)\r
3855 PpiList = property(_GetPpiList)\r
3856 DepexList = property(_GetDepexTokenList)\r
b36d134f 3857 DxsFile = property(_GetDxsFile)\r
52302d4d
LG
3858 DepexExpressionList = property(_GetDepexExpressionTokenList)\r
3859 BuildOption = property(_GetModuleBuildOption)\r
79b74a03 3860 BuildOptionIncPathList = property(_GetBuildOptionIncPathList)\r
52302d4d 3861 BuildCommand = property(_GetBuildCommand)\r
2bc3256c
LG
3862 \r
3863 FixedAtBuildPcds = property(_GetFixedAtBuildPcds)\r
52302d4d
LG
3864\r
3865# This acts like the main() function for the script, unless it is 'import'ed into another script.\r
3866if __name__ == '__main__':\r
3867 pass\r
3868\r