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