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