2 # Generate AutoGen.h, AutoGen.c and *.depex files
4 # Copyright (c) 2007 - 2009, Intel Corporation
5 # All rights reserved. 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
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.
18 import os.path as path
24 from StringIO import StringIO
26 from StrGather import *
27 from BuildEngine import BuildRule
29 from Common.BuildToolError import *
30 from Common.DataType import *
31 from Common.Misc import *
32 from Common.String import *
33 import Common.GlobalData as GlobalData
34 from GenFds.FdfParser import *
35 from CommonDataClass.CommonClass import SkuInfoClass
36 from Workspace.BuildClassObject import *
38 ## Regular expression for splitting Dependency Expression stirng into tokens
39 gDepexTokenPattern = re.compile("(\(|\)|\w+| \S+\.inf)")
41 ## Mapping Makefile type
42 gMakeTypeMap = {"MSFT":"nmake", "GCC":"gmake"}
45 ## Build rule configuration file
46 gBuildRuleFile = 'Conf/build_rule.txt'
48 ## default file name for AutoGen
49 gAutoGenCodeFileName = "AutoGen.c"
50 gAutoGenHeaderFileName = "AutoGen.h"
51 gAutoGenStringFileName = "%(module_name)sStrDefs.h"
52 gAutoGenStringFormFileName = "%(module_name)sStrDefs.hpk"
53 gAutoGenDepexFileName = "%(module_name)s.depex"
55 ## Base class for AutoGen
57 # This class just implements the cache mechanism of AutoGen objects.
59 class AutoGen(object):
60 # database to maintain the objects of xxxAutoGen
61 _CACHE_ = {} # (BuildTarget, ToolChain) : {ARCH : {platform file: AutoGen object}}}
65 # @param Class class object of real AutoGen class
66 # (WorkspaceAutoGen, ModuleAutoGen or PlatformAutoGen)
67 # @param Workspace Workspace directory or WorkspaceAutoGen object
68 # @param MetaFile The path of meta file
69 # @param Target Build target
70 # @param Toolchain Tool chain name
71 # @param Arch Target arch
72 # @param *args The specific class related parameters
73 # @param **kwargs The specific class related dict parameters
75 def __new__(Class, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):
76 # check if the object has been created
77 Key = (Target, Toolchain)
78 if Key not in Class._CACHE_ or Arch not in Class._CACHE_[Key] \
79 or MetaFile not in Class._CACHE_[Key][Arch]:
80 AutoGenObject = super(AutoGen, Class).__new__(Class)
81 # call real constructor
82 if not AutoGenObject._Init(Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):
84 if Key not in Class._CACHE_:
85 Class._CACHE_[Key] = {}
86 if Arch not in Class._CACHE_[Key]:
87 Class._CACHE_[Key][Arch] = {}
88 Class._CACHE_[Key][Arch][MetaFile] = AutoGenObject
90 AutoGenObject = Class._CACHE_[Key][Arch][MetaFile]
96 # The file path of platform file will be used to represent hash value of this object
98 # @retval int Hash value of the file path of platform file
101 return hash(self.MetaFile)
105 # The file path of platform file will be used to represent this object
107 # @retval string String of platform file path
110 return str(self.MetaFile)
113 def __eq__(self, Other):
114 return Other and self.MetaFile == Other
116 ## Workspace AutoGen class
118 # This class is used mainly to control the whole platform build for different
119 # architecture. This class will generate top level makefile.
121 class WorkspaceAutoGen(AutoGen):
122 ## Real constructor of WorkspaceAutoGen
124 # This method behaves the same as __init__ except that it needs explict invoke
125 # (in super class's __new__ method)
127 # @param WorkspaceDir Root directory of workspace
128 # @param ActivePlatform Meta-file of active platform
129 # @param Target Build target
130 # @param Toolchain Tool chain name
131 # @param ArchList List of architecture of current build
132 # @param MetaFileDb Database containing meta-files
133 # @param BuildConfig Configuration of build
134 # @param ToolDefinition Tool chain definitions
135 # @param FlashDefinitionFile File of flash definition
136 # @param Fds FD list to be generated
137 # @param Fvs FV list to be generated
138 # @param SkuId SKU id from command line
140 def _Init(self, WorkspaceDir, ActivePlatform, Target, Toolchain, ArchList, MetaFileDb,
141 BuildConfig, ToolDefinition, FlashDefinitionFile='', Fds=[], Fvs=[], SkuId='',
142 ReportFile=None, ReportType=None):
143 self.MetaFile = ActivePlatform.MetaFile
144 self.WorkspaceDir = WorkspaceDir
145 self.Platform = ActivePlatform
146 self.BuildTarget = Target
147 self.ToolChain = Toolchain
148 self.ArchList = ArchList
150 self.ReportFile = ReportFile
151 self.ReportType = ReportType
153 self.BuildDatabase = MetaFileDb
154 self.TargetTxt = BuildConfig
155 self.ToolDef = ToolDefinition
156 self.FdfFile = FlashDefinitionFile
157 self.FdTargetList = Fds
158 self.FvTargetList = Fvs
159 self.AutoGenObjectList = []
161 # there's many relative directory operations, so ...
162 os.chdir(self.WorkspaceDir)
164 # parse FDF file to get PCDs in it, if any
165 if self.FdfFile != None and self.FdfFile != '':
166 Fdf = FdfParser(self.FdfFile.Path)
168 PcdSet = Fdf.Profile.PcdDict
169 ModuleList = Fdf.Profile.InfList
174 # apply SKU and inject PCDs from Flash Definition file
175 for Arch in self.ArchList:
176 Platform = self.BuildDatabase[self.MetaFile, Arch]
177 Platform.SkuName = self.SkuId
178 for Name, Guid in PcdSet:
179 Platform.AddPcd(Name, Guid, PcdSet[Name, Guid])
181 Pa = PlatformAutoGen(self, self.MetaFile, Target, Toolchain, Arch)
183 # Explicitly collect platform's dynamic PCDs
185 Pa.CollectPlatformDynamicPcds()
186 self.AutoGenObjectList.append(Pa)
190 for Pcd in Pa._DynaPcdList_ + Pa._NonDynaPcdList_:
191 if Pcd.TokenSpaceGuidCName not in AllPcds:
192 AllPcds[Pcd.TokenSpaceGuidCName] = {}
193 if Pcd.Type not in AllPcds[Pcd.TokenSpaceGuidCName]:
194 AllPcds[Pcd.TokenSpaceGuidCName][Pcd.Type] = []
195 AllPcds[Pcd.TokenSpaceGuidCName][Pcd.Type] += [Pcd]
196 if len(Pcd.TokenCName) > MaxLen:
197 MaxLen = len(Pcd.TokenCName)
199 if self.ReportFile <> None:
201 if os.path.exists(self.ReportFile):
202 os.remove(self.ReportFile)
204 Fd = open(self.ReportFile, "w")
206 Fd.write ('===============================================================================\n')
207 Fd.write ('Platform Configuration Database Report\n')
208 Fd.write ('===============================================================================\n')
209 Fd.write (' *P - Platform scoped PCD override in DSC file\n')
210 Fd.write (' *F - Platform scoped PCD override in FDF file\n')
211 Fd.write (' *M - Module scoped PCD override in DSC file\n')
212 Fd.write (' *C - Library has a constructor\n')
213 Fd.write (' *D - Library has a destructor\n')
214 Fd.write (' *CD - Library has both a constructor and a destructor\n')
215 Fd.write ('===============================================================================\n')
217 Fd.write ('===============================================================================\n')
218 Fd.write ('PLATFORM: %s\n' % (ActivePlatform.MetaFile))
219 Fd.write ('===============================================================================\n')
221 Fd.write ('%s\n' % (Key))
222 for Type in AllPcds[Key]:
225 if Type == 'FixedAtBuild':
227 if Type == 'PatchableInModule':
229 if Type == 'FeatureFlag':
231 if Type == 'Dynamic':
233 if Type == 'DynamicHii':
236 if Type == 'DynamicVpd':
239 if Type == 'DynamicEx':
242 if Type == 'DynamicExHii':
245 if Type == 'DynamicExVpd':
248 for Pcd in AllPcds[Key][Type]:
250 DecDefaultValue = None
251 for F in Pa.Platform.Modules.keys():
252 for Package in Pa.Platform.Modules[F].M.Module.Packages:
253 if (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, DecType) in Package.Pcds:
254 if DecDefaultValue == None:
255 DecDefaultValue = Package.Pcds[Pcd.TokenCName, Pcd.TokenSpaceGuidCName, DecType].DefaultValue
257 DscDefaultValue = None
258 if (Pcd.TokenCName, Pcd.TokenSpaceGuidCName) in self.BuildDatabase.WorkspaceDb.PlatformList[0].Pcds:
259 DscDefaultValue = self.BuildDatabase.WorkspaceDb.PlatformList[0].Pcds[(Pcd.TokenCName, Pcd.TokenSpaceGuidCName)].DefaultValue
261 if Pcd.DatumType in ('UINT8', 'UINT16', 'UINT32', 'UINT64'):
262 if Pcd.DefaultValue.strip()[0:2].upper() == '0X':
263 PcdDefaultValueNumber = int(Pcd.DefaultValue.strip(), 16)
265 PcdDefaultValueNumber = int(Pcd.DefaultValue.strip())
267 if DecDefaultValue == None:
270 if DecDefaultValue.strip()[0:2].upper() == '0X':
271 DecDefaultValueNumber = int(DecDefaultValue.strip(), 16)
273 DecDefaultValueNumber = int(DecDefaultValue.strip())
274 DecMatch = (DecDefaultValueNumber == PcdDefaultValueNumber)
276 if DscDefaultValue == None:
279 if DscDefaultValue.strip()[0:2].upper() == '0X':
280 DscDefaultValueNumber = int(DscDefaultValue.strip(), 16)
282 DscDefaultValueNumber = int(DscDefaultValue.strip())
283 DscMatch = (DscDefaultValueNumber == PcdDefaultValueNumber)
285 if DecDefaultValue == None:
288 DecMatch = (DecDefaultValue == Pcd.DefaultValue)
290 if DscDefaultValue == None:
293 DscMatch = (DscDefaultValue == Pcd.DefaultValue)
296 Fd.write (' %-*s: %6s %10s = %-22s\n' % (MaxLen + 2, Pcd.TokenCName, TypeName, '('+Pcd.DatumType+')', Pcd.DefaultValue))
299 if (Pcd.TokenCName, Key) in PcdSet:
300 Fd.write (' *F %-*s: %6s %10s = %-22s\n' % (MaxLen + 2, Pcd.TokenCName, TypeName, '('+Pcd.DatumType+')', Pcd.DefaultValue))
302 Fd.write (' *P %-*s: %6s %10s = %-22s\n' % (MaxLen + 2, Pcd.TokenCName, TypeName, '('+Pcd.DatumType+')', Pcd.DefaultValue))
304 for F in Pa.Platform.Modules.keys():
305 for ModulePcd in Pa.Platform.Modules[F].M.ModulePcdList + Pa.Platform.Modules[F].M.LibraryPcdList:
306 if ModulePcd.TokenSpaceGuidCName <> Pcd.TokenSpaceGuidCName:
308 if ModulePcd.TokenCName <> Pcd.TokenCName:
310 if Pcd.DatumType in ('UINT8', 'UINT16', 'UINT32', 'UINT64'):
311 if ModulePcd.DefaultValue.strip()[0:2].upper() == '0X':
312 ModulePcdDefaultValueNumber = int(ModulePcd.DefaultValue.strip(), 16)
314 ModulePcdDefaultValueNumber = int(ModulePcd.DefaultValue.strip())
315 Match = (ModulePcdDefaultValueNumber == PcdDefaultValueNumber)
317 Match = (ModulePcd.DefaultValue == Pcd.DefaultValue)
320 Fd.write (' *M %*s = %s\n' % (MaxLen + 21, str(F).split('\\')[-1], ModulePcd.DefaultValue))
322 if not DecMatch and DscMatch and DecDefaultValue <> None:
323 Fd.write (' %*s = %s\n' % (MaxLen + 21, 'DEC DEFAULT', DecDefaultValue))
327 Fd.write ('===============================================================================\n')
328 Fd.write ('===============================================================================\n')
330 for F in Pa.Platform.Modules.keys():
332 Fd.write ('===============================================================================\n')
333 Fd.write ('MODULE: %s\n' % (F))
334 Fd.write ('===============================================================================\n')
336 Fd.write ('PLATFORM CONFIGURATION DATABASE\n')
337 Fd.write ('-------------------------------------------------------------------------------\n')
341 for Type in AllPcds[Key]:
344 if Type == 'FixedAtBuild':
346 if Type == 'PatchableInModule':
348 if Type == 'FeatureFlag':
350 if Type == 'Dynamic':
352 if Type == 'DynamicHii':
355 if Type == 'DynamicVpd':
358 if Type == 'DynamicEx':
361 if Type == 'DynamicExHii':
364 if Type == 'DynamicExVpd':
367 for Pcd in AllPcds[Key][Type]:
368 for ModulePcd in Pa.Platform.Modules[F].M.ModulePcdList + Pa.Platform.Modules[F].M.LibraryPcdList:
369 if ModulePcd.TokenSpaceGuidCName <> Pcd.TokenSpaceGuidCName:
371 if ModulePcd.TokenCName <> Pcd.TokenCName:
373 if ModulePcd.Type <> Pcd.Type:
380 Fd.write ('%s\n' % (Key))
383 InfDefaultValue = ModulePcd.InfDefaultValue
384 if InfDefaultValue == '':
385 InfDefaultValue = None
387 DecDefaultValue = None
388 for Package in Pa.Platform.Modules[F].M.Module.Packages:
389 if (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, DecType) in Package.Pcds:
390 if DecDefaultValue == None:
391 DecDefaultValue = Package.Pcds[Pcd.TokenCName, Pcd.TokenSpaceGuidCName, DecType].DefaultValue
393 DscDefaultValue = None
394 if (Pcd.TokenCName, Pcd.TokenSpaceGuidCName) in self.BuildDatabase.WorkspaceDb.PlatformList[0].Pcds:
395 DscDefaultValue = self.BuildDatabase.WorkspaceDb.PlatformList[0].Pcds[(Pcd.TokenCName, Pcd.TokenSpaceGuidCName)].DefaultValue
397 DscModuleOverrideDefaultValue = None
398 if F in self.BuildDatabase.WorkspaceDb.PlatformList[0].Modules:
399 if (Pcd.TokenCName, Pcd.TokenSpaceGuidCName) in self.BuildDatabase.WorkspaceDb.PlatformList[0].Modules[F].Pcds:
400 DscModuleOverrideDefaultValue = self.BuildDatabase.WorkspaceDb.PlatformList[0].Modules[F].Pcds[(Pcd.TokenCName, Pcd.TokenSpaceGuidCName)].DefaultValue
402 if Pcd.DatumType in ('UINT8', 'UINT16', 'UINT32', 'UINT64'):
403 if ModulePcd.DefaultValue.strip()[0:2].upper() == '0X':
404 ModulePcdDefaultValueNumber = int(ModulePcd.DefaultValue.strip(), 16)
406 ModulePcdDefaultValueNumber = int(ModulePcd.DefaultValue.strip())
408 if DecDefaultValue == None:
411 if DecDefaultValue.strip()[0:2].upper() == '0X':
412 DecDefaultValueNumber = int(DecDefaultValue.strip(), 16)
414 DecDefaultValueNumber = int(DecDefaultValue.strip())
415 DecMatch = (DecDefaultValueNumber == ModulePcdDefaultValueNumber)
417 if InfDefaultValue == None:
420 if InfDefaultValue.strip()[0:2].upper() == '0X':
421 InfDefaultValueNumber = int(InfDefaultValue.strip(), 16)
423 InfDefaultValueNumber = int(InfDefaultValue.strip())
424 InfMatch = (InfDefaultValueNumber == ModulePcdDefaultValueNumber)
426 if DscDefaultValue == None:
429 if DscDefaultValue.strip()[0:2].upper() == '0X':
430 DscDefaultValueNumber = int(DscDefaultValue.strip(), 16)
432 DscDefaultValueNumber = int(DscDefaultValue.strip())
433 DscMatch = (DscDefaultValueNumber == ModulePcdDefaultValueNumber)
435 if DecDefaultValue == None:
438 DecMatch = (DecDefaultValue == ModulePcd.DefaultValue)
440 if InfDefaultValue == None:
443 InfMatch = (InfDefaultValue == ModulePcd.DefaultValue)
445 if DscDefaultValue == None:
448 DscMatch = (DscDefaultValue == ModulePcd.DefaultValue)
450 if DecMatch and InfMatch:
451 Fd.write (' %-*s: %6s %10s = %-22s\n' % (MaxLen, Pcd.TokenCName, TypeName, '('+Pcd.DatumType+')', ModulePcd.DefaultValue))
453 if DscMatch and DscModuleOverrideDefaultValue == None:
454 if (Pcd.TokenCName, Key) in PcdSet:
455 Fd.write (' *F %-*s: %6s %10s = %-22s\n' % (MaxLen, Pcd.TokenCName, TypeName, '('+Pcd.DatumType+')', ModulePcd.DefaultValue))
457 Fd.write (' *P %-*s: %6s %10s = %-22s\n' % (MaxLen, Pcd.TokenCName, TypeName, '('+Pcd.DatumType+')', ModulePcd.DefaultValue))
459 Fd.write (' *M %-*s: %6s %10s = %-22s\n' % (MaxLen, Pcd.TokenCName, TypeName, '('+Pcd.DatumType+')', ModulePcd.DefaultValue))
460 if DscDefaultValue <> None:
461 Fd.write (' %*s = %s\n' % (MaxLen + 19, 'DSC DEFAULT', DscDefaultValue))
462 if InfDefaultValue <> None:
463 Fd.write (' %*s = %s\n' % (MaxLen + 19, 'INF DEFAULT', InfDefaultValue))
464 if DecDefaultValue <> None and not DecMatch:
465 Fd.write (' %*s = %s\n' % (MaxLen + 19, 'DEC DEFAULT', DecDefaultValue))
466 Fd.write ('-------------------------------------------------------------------------------\n')
467 Fd.write ('LIBRARIES\n')
468 Fd.write ('-------------------------------------------------------------------------------\n')
469 for Lib in Pa.Platform.Modules[F].M.DependentLibraryList:
470 if len(Lib.ConstructorList) > 0:
471 if len(Lib.DestructorList) > 0:
476 if len(Lib.DestructorList) > 0:
480 Fd.write (' %s\n' % (Lib))
481 for Depex in Lib.DepexExpression[Pa.Platform.Modules[F].M.Arch, Pa.Platform.Modules[F].M.ModuleType]:
482 Fd.write (' DEPEX = %s\n' % (Depex))
483 Fd.write ('-------------------------------------------------------------------------------\n')
485 Fd.write ('MODULE DEPENDENCY EXPRESSION\n')
486 if len(Pa.Platform.Modules[F].M.Module.DepexExpression[Pa.Platform.Modules[F].M.Arch, Pa.Platform.Modules[F].M.ModuleType]) == 0:
489 for Depex in Pa.Platform.Modules[F].M.Module.DepexExpression[Pa.Platform.Modules[F].M.Arch, Pa.Platform.Modules[F].M.ModuleType]:
490 Fd.write (' %s\n' % (Depex))
491 Fd.write ('-------------------------------------------------------------------------------\n')
493 Fd.write ('MODULE + LIBRARY DEPENDENCY EXPRESSION\n')
494 if Pa.Platform.Modules[F].M.ModuleType in Pa.Platform.Modules[F].M.DepexExpressionList:
495 if Pa.Platform.Modules[F].M.DepexExpressionList[Pa.Platform.Modules[F].M.ModuleType] == '':
498 Fd.write (' %s\n' % (Pa.Platform.Modules[F].M.DepexExpressionList[Pa.Platform.Modules[F].M.ModuleType]))
501 Fd.write ('-------------------------------------------------------------------------------\n')
505 EdkLogger.error(None, FILE_OPEN_FAILURE, ExtraData=self.ReportFile)
507 self._BuildDir = None
509 self._MakeFileDir = None
510 self._BuildCommand = None
515 return "%s [%s]" % (self.MetaFile, ", ".join(self.ArchList))
517 ## Return the directory to store FV files
519 if self._FvDir == None:
520 self._FvDir = path.join(self.BuildDir, 'FV')
523 ## Return the directory to store all intermediate and final files built
524 def _GetBuildDir(self):
525 return self.AutoGenObjectList[0].BuildDir
527 ## Return the build output directory platform specifies
528 def _GetOutputDir(self):
529 return self.Platform.OutputDirectory
531 ## Return platform name
533 return self.Platform.PlatformName
535 ## Return meta-file GUID
537 return self.Platform.Guid
539 ## Return platform version
540 def _GetVersion(self):
541 return self.Platform.Version
543 ## Return paths of tools
544 def _GetToolDefinition(self):
545 return self.AutoGenObjectList[0].ToolDefinition
547 ## Return directory of platform makefile
549 # @retval string Makefile directory
551 def _GetMakeFileDir(self):
552 if self._MakeFileDir == None:
553 self._MakeFileDir = self.BuildDir
554 return self._MakeFileDir
556 ## Return build command string
558 # @retval string Build command string
560 def _GetBuildCommand(self):
561 if self._BuildCommand == None:
562 # BuildCommand should be all the same. So just get one from platform AutoGen
563 self._BuildCommand = self.AutoGenObjectList[0].BuildCommand
564 return self._BuildCommand
566 ## Create makefile for the platform and mdoules in it
568 # @param CreateDepsMakeFile Flag indicating if the makefile for
569 # modules will be created as well
571 def CreateMakeFile(self, CreateDepsMakeFile=False):
572 # create makefile for platform
573 Makefile = GenMake.TopLevelMakefile(self)
574 if Makefile.Generate():
575 EdkLogger.debug(EdkLogger.DEBUG_9, "Generated makefile for platform [%s] %s\n" %
576 (self.MetaFile, self.ArchList))
578 EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of makefile for platform [%s] %s\n" %
579 (self.MetaFile, self.ArchList))
581 if CreateDepsMakeFile:
582 for Pa in self.AutoGenObjectList:
583 Pa.CreateMakeFile(CreateDepsMakeFile)
585 ## Create autogen code for platform and modules
587 # Since there's no autogen code for platform, this method will do nothing
588 # if CreateModuleCodeFile is set to False.
590 # @param CreateDepsCodeFile Flag indicating if creating module's
591 # autogen code file or not
593 def CreateCodeFile(self, CreateDepsCodeFile=False):
594 if not CreateDepsCodeFile:
596 for Pa in self.AutoGenObjectList:
597 Pa.CreateCodeFile(CreateDepsCodeFile)
599 Name = property(_GetName)
600 Guid = property(_GetGuid)
601 Version = property(_GetVersion)
602 OutputDir = property(_GetOutputDir)
604 ToolDefinition = property(_GetToolDefinition) # toolcode : tool path
606 BuildDir = property(_GetBuildDir)
607 FvDir = property(_GetFvDir)
608 MakeFileDir = property(_GetMakeFileDir)
609 BuildCommand = property(_GetBuildCommand)
611 ## AutoGen class for platform
613 # PlatformAutoGen class will process the original information in platform
614 # file in order to generate makefile for platform.
616 class PlatformAutoGen(AutoGen):
618 # Used to store all PCDs for both PEI and DXE phase, in order to generate
619 # correct PCD database
622 _NonDynaPcdList_ = []
624 ## The real constructor of PlatformAutoGen
626 # This method is not supposed to be called by users of PlatformAutoGen. It's
627 # only used by factory method __new__() to do real initialization work for an
628 # object of PlatformAutoGen
630 # @param Workspace WorkspaceAutoGen object
631 # @param PlatformFile Platform file (DSC file)
632 # @param Target Build target (DEBUG, RELEASE)
633 # @param Toolchain Name of tool chain
634 # @param Arch arch of the platform supports
636 def _Init(self, Workspace, PlatformFile, Target, Toolchain, Arch):
637 EdkLogger.debug(EdkLogger.DEBUG_9, "AutoGen platform [%s] [%s]" % (PlatformFile, Arch))
638 GlobalData.gProcessingFile = "%s [%s, %s, %s]" % (PlatformFile, Arch, Toolchain, Target)
640 self.MetaFile = PlatformFile
641 self.Workspace = Workspace
642 self.WorkspaceDir = Workspace.WorkspaceDir
643 self.ToolChain = Toolchain
644 self.BuildTarget = Target
646 self.SourceDir = PlatformFile.SubDir
647 self.SourceOverrideDir = None
648 self.FdTargetList = self.Workspace.FdTargetList
649 self.FvTargetList = self.Workspace.FvTargetList
651 # flag indicating if the makefile/C-code file has been created or not
652 self.IsMakeFileCreated = False
653 self.IsCodeFileCreated = False
655 self._Platform = None
660 self._BuildRule = None
661 self._SourceDir = None
662 self._BuildDir = None
663 self._OutputDir = None
665 self._MakeFileDir = None
668 self._PcdTokenNumber = None # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber
669 self._DynamicPcdList = None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
670 self._NonDynamicPcdList = None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
672 self._ToolDefinitions = None
673 self._ToolDefFile = None # toolcode : tool path
674 self._ToolChainFamily = None
675 self._BuildRuleFamily = None
676 self._BuildOption = None # toolcode : option
677 self._PackageList = None
678 self._ModuleAutoGenList = None
679 self._LibraryAutoGenList = None
680 self._BuildCommand = None
682 # get the original module/package/platform objects
683 self.BuildDatabase = Workspace.BuildDatabase
687 return "%s [%s]" % (self.MetaFile, self.Arch)
689 ## Create autogen code for platform and modules
691 # Since there's no autogen code for platform, this method will do nothing
692 # if CreateModuleCodeFile is set to False.
694 # @param CreateModuleCodeFile Flag indicating if creating module's
695 # autogen code file or not
697 def CreateCodeFile(self, CreateModuleCodeFile=False):
698 # only module has code to be greated, so do nothing if CreateModuleCodeFile is False
699 if self.IsCodeFileCreated or not CreateModuleCodeFile:
702 for Ma in self.ModuleAutoGenList:
703 Ma.CreateCodeFile(True)
705 # don't do this twice
706 self.IsCodeFileCreated = True
708 ## Create makefile for the platform and mdoules in it
710 # @param CreateModuleMakeFile Flag indicating if the makefile for
711 # modules will be created as well
713 def CreateMakeFile(self, CreateModuleMakeFile=False):
714 if CreateModuleMakeFile:
715 for ModuleFile in self.Platform.Modules:
716 Ma = ModuleAutoGen(self.Workspace, ModuleFile, self.BuildTarget,
717 self.ToolChain, self.Arch, self.MetaFile)
718 Ma.CreateMakeFile(True)
720 # no need to create makefile for the platform more than once
721 if self.IsMakeFileCreated:
724 # create makefile for platform
725 Makefile = GenMake.PlatformMakefile(self)
726 if Makefile.Generate():
727 EdkLogger.debug(EdkLogger.DEBUG_9, "Generated makefile for platform [%s] [%s]\n" %
728 (self.MetaFile, self.Arch))
730 EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of makefile for platform [%s] [%s]\n" %
731 (self.MetaFile, self.Arch))
732 self.IsMakeFileCreated = True
734 ## Collect dynamic PCDs
736 # Gather dynamic PCDs list from each module and their settings from platform
737 # This interface should be invoked explicitly when platform action is created.
739 def CollectPlatformDynamicPcds(self):
740 # for gathering error information
741 NoDatumTypePcdList = set()
744 for F in self.Platform.Modules.keys():
745 M = ModuleAutoGen(self.Workspace, F, self.BuildTarget, self.ToolChain, self.Arch, self.MetaFile)
746 #GuidValue.update(M.Guids)
748 self.Platform.Modules[F].M = M
750 for PcdFromModule in M.ModulePcdList+M.LibraryPcdList:
751 # make sure that the "VOID*" kind of datum has MaxDatumSize set
752 if PcdFromModule.DatumType == "VOID*" and PcdFromModule.MaxDatumSize == None:
753 NoDatumTypePcdList.add("%s.%s [%s]" % (PcdFromModule.TokenSpaceGuidCName, PcdFromModule.TokenCName, F))
755 if PcdFromModule.Type in GenC.gDynamicPcd or PcdFromModule.Type in GenC.gDynamicExPcd:
757 # If a dynamic PCD used by a PEM module/PEI module & DXE module,
758 # it should be stored in Pcd PEI database, If a dynamic only
759 # used by DXE module, it should be stored in DXE PCD database.
760 # The default Phase is DXE
762 if M.ModuleType in ["PEIM", "PEI_CORE"]:
763 PcdFromModule.Phase = "PEI"
764 if PcdFromModule not in self._DynaPcdList_:
765 self._DynaPcdList_.append(PcdFromModule)
766 elif PcdFromModule.Phase == 'PEI':
767 # overwrite any the same PCD existing, if Phase is PEI
768 Index = self._DynaPcdList_.index(PcdFromModule)
769 self._DynaPcdList_[Index] = PcdFromModule
770 elif PcdFromModule not in self._NonDynaPcdList_:
771 self._NonDynaPcdList_.append(PcdFromModule)
773 # print out error information and break the build, if error found
774 if len(NoDatumTypePcdList) > 0:
775 NoDatumTypePcdListString = "\n\t\t".join(NoDatumTypePcdList)
776 EdkLogger.error("build", AUTOGEN_ERROR, "PCD setting error",
778 ExtraData="\n\tPCD(s) without MaxDatumSize:\n\t\t%s\n"
779 % NoDatumTypePcdListString)
780 self._NonDynamicPcdList = self._NonDynaPcdList_
781 self._DynamicPcdList = self._DynaPcdList_
784 # Sort dynamic PCD list to:
785 # 1) If PCD's datum type is VOID* and value is unicode string which starts with L, the PCD item should
786 # try to be put header of dynamicd List
787 # 2) If PCD is HII type, the PCD item should be put after unicode type PCD
789 # The reason of sorting is make sure the unicode string is in double-byte alignment in string table.
794 for Pcd in self._DynamicPcdList:
795 # just pick the a value to determine whether is unicode string type
796 Sku = Pcd.SkuInfoList[Pcd.SkuInfoList.keys()[0]]
797 PcdValue = Sku.DefaultValue
798 if Pcd.DatumType == 'VOID*' and PcdValue.startswith("L"):
799 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
800 UnicodePcdArray.append(Pcd)
801 elif len(Sku.VariableName) > 0:
802 # if found HII type PCD then insert to right of UnicodeIndex
803 HiiPcdArray.append(Pcd)
805 OtherPcdArray.append(Pcd)
806 del self._DynamicPcdList[:]
807 self._DynamicPcdList.extend(UnicodePcdArray)
808 self._DynamicPcdList.extend(HiiPcdArray)
809 self._DynamicPcdList.extend(OtherPcdArray)
812 ## Return the platform build data object
813 def _GetPlatform(self):
814 if self._Platform == None:
815 self._Platform = self.BuildDatabase[self.MetaFile, self.Arch]
816 return self._Platform
818 ## Return platform name
820 return self.Platform.PlatformName
822 ## Return the meta file GUID
824 return self.Platform.Guid
826 ## Return the platform version
827 def _GetVersion(self):
828 return self.Platform.Version
830 ## Return the FDF file name
831 def _GetFdfFile(self):
832 if self._FdfFile == None:
833 if self.Workspace.FdfFile != "":
834 self._FdfFile= path.join(self.WorkspaceDir, self.Workspace.FdfFile)
839 ## Return the build output directory platform specifies
840 def _GetOutputDir(self):
841 return self.Platform.OutputDirectory
843 ## Return the directory to store all intermediate and final files built
844 def _GetBuildDir(self):
845 if self._BuildDir == None:
846 if os.path.isabs(self.OutputDir):
847 self._BuildDir = path.join(
848 path.abspath(self.OutputDir),
849 self.BuildTarget + "_" + self.ToolChain,
852 self._BuildDir = path.join(
855 self.BuildTarget + "_" + self.ToolChain,
857 return self._BuildDir
859 ## Return directory of platform makefile
861 # @retval string Makefile directory
863 def _GetMakeFileDir(self):
864 if self._MakeFileDir == None:
865 self._MakeFileDir = path.join(self.BuildDir, self.Arch)
866 return self._MakeFileDir
868 ## Return build command string
870 # @retval string Build command string
872 def _GetBuildCommand(self):
873 if self._BuildCommand == None:
874 self._BuildCommand = []
875 if "MAKE" in self.ToolDefinition and "PATH" in self.ToolDefinition["MAKE"]:
876 self._BuildCommand += SplitOption(self.ToolDefinition["MAKE"]["PATH"])
877 if "FLAGS" in self.ToolDefinition["MAKE"]:
878 NewOption = self.ToolDefinition["MAKE"]["FLAGS"].strip()
880 self._BuildCommand += SplitOption(NewOption)
881 return self._BuildCommand
883 ## Get tool chain definition
885 # Get each tool defition for given tool chain from tools_def.txt and platform
887 def _GetToolDefinition(self):
888 if self._ToolDefinitions == None:
889 ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDictionary
890 if TAB_TOD_DEFINES_COMMAND_TYPE not in self.Workspace.ToolDef.ToolsDefTxtDatabase:
891 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "No tools found in configuration",
892 ExtraData="[%s]" % self.MetaFile)
893 self._ToolDefinitions = {}
895 for Def in ToolDefinition:
896 Target, Tag, Arch, Tool, Attr = Def.split("_")
897 if Target != self.BuildTarget or Tag != self.ToolChain or Arch != self.Arch:
900 Value = ToolDefinition[Def]
901 # don't record the DLL
903 DllPathList.add(Value)
906 if Tool not in self._ToolDefinitions:
907 self._ToolDefinitions[Tool] = {}
908 self._ToolDefinitions[Tool][Attr] = Value
912 if GlobalData.gOptions.SilentMode and "MAKE" in self._ToolDefinitions:
913 if "FLAGS" not in self._ToolDefinitions["MAKE"]:
914 self._ToolDefinitions["MAKE"]["FLAGS"] = ""
915 self._ToolDefinitions["MAKE"]["FLAGS"] += " -s"
917 for Tool in self._ToolDefinitions:
918 for Attr in self._ToolDefinitions[Tool]:
919 Value = self._ToolDefinitions[Tool][Attr]
920 if Tool in self.BuildOption and Attr in self.BuildOption[Tool]:
921 # check if override is indicated
922 if self.BuildOption[Tool][Attr].startswith('='):
923 Value = self.BuildOption[Tool][Attr][1:]
925 Value += " " + self.BuildOption[Tool][Attr]
928 # Don't put MAKE definition in the file
932 ToolsDef += "%s = %s\n" % (Tool, Value)
934 # Don't put MAKE definition in the file
939 ToolsDef += "%s_%s = %s\n" % (Tool, Attr, Value)
942 SaveFileOnChange(self.ToolDefinitionFile, ToolsDef)
943 for DllPath in DllPathList:
944 os.environ["PATH"] = DllPath + os.pathsep + os.environ["PATH"]
945 os.environ["MAKE_FLAGS"] = MakeFlags
947 return self._ToolDefinitions
949 ## Return the paths of tools
950 def _GetToolDefFile(self):
951 if self._ToolDefFile == None:
952 self._ToolDefFile = os.path.join(self.MakeFileDir, "TOOLS_DEF." + self.Arch)
953 return self._ToolDefFile
955 ## Retrieve the toolchain family of given toolchain tag. Default to 'MSFT'.
956 def _GetToolChainFamily(self):
957 if self._ToolChainFamily == None:
958 ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDatabase
959 if TAB_TOD_DEFINES_FAMILY not in ToolDefinition \
960 or self.ToolChain not in ToolDefinition[TAB_TOD_DEFINES_FAMILY] \
961 or not ToolDefinition[TAB_TOD_DEFINES_FAMILY][self.ToolChain]:
962 EdkLogger.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
964 self._ToolChainFamily = "MSFT"
966 self._ToolChainFamily = ToolDefinition[TAB_TOD_DEFINES_FAMILY][self.ToolChain]
967 return self._ToolChainFamily
969 def _GetBuildRuleFamily(self):
970 if self._BuildRuleFamily == None:
971 ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDatabase
972 if TAB_TOD_DEFINES_BUILDRULEFAMILY not in ToolDefinition \
973 or self.ToolChain not in ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY] \
974 or not ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY][self.ToolChain]:
975 EdkLogger.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
977 self._BuildRuleFamily = "MSFT"
979 self._BuildRuleFamily = ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY][self.ToolChain]
980 return self._BuildRuleFamily
982 ## Return the build options specific to this platform
983 def _GetBuildOptions(self):
984 if self._BuildOption == None:
985 self._BuildOption = self._ExpandBuildOption(self.Platform.BuildOptions)
986 return self._BuildOption
988 ## Parse build_rule.txt in $(WORKSPACE)/Conf/build_rule.txt
990 # @retval BuildRule object
992 def _GetBuildRule(self):
993 if self._BuildRule == None:
995 if TAB_TAT_DEFINES_BUILD_RULE_CONF in self.Workspace.TargetTxt.TargetTxtDictionary:
996 BuildRuleFile = self.Workspace.TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_BUILD_RULE_CONF]
997 if BuildRuleFile in [None, '']:
998 BuildRuleFile = gBuildRuleFile
999 self._BuildRule = BuildRule(BuildRuleFile)
1000 return self._BuildRule
1002 ## Summarize the packages used by modules in this platform
1003 def _GetPackageList(self):
1004 if self._PackageList == None:
1005 self._PackageList = set()
1006 for La in self.LibraryAutoGenList:
1007 self._PackageList.update(La.DependentPackageList)
1008 for Ma in self.ModuleAutoGenList:
1009 self._PackageList.update(Ma.DependentPackageList)
1010 self._PackageList = list(self._PackageList)
1011 return self._PackageList
1013 ## Get list of non-dynamic PCDs
1014 def _GetNonDynamicPcdList(self):
1015 return self._NonDynamicPcdList
1017 ## Get list of dynamic PCDs
1018 def _GetDynamicPcdList(self):
1019 return self._DynamicPcdList
1021 ## Generate Token Number for all PCD
1022 def _GetPcdTokenNumbers(self):
1023 if self._PcdTokenNumber == None:
1024 self._PcdTokenNumber = sdict()
1026 for Pcd in self.DynamicPcdList:
1027 if Pcd.Phase == "PEI":
1028 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))
1029 self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
1032 for Pcd in self.DynamicPcdList:
1033 if Pcd.Phase == "DXE":
1034 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))
1035 self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
1038 for Pcd in self.NonDynamicPcdList:
1039 self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
1041 return self._PcdTokenNumber
1043 ## Summarize ModuleAutoGen objects of all modules/libraries to be built for this platform
1044 def _GetAutoGenObjectList(self):
1045 self._ModuleAutoGenList = []
1046 self._LibraryAutoGenList = []
1047 for ModuleFile in self.Platform.Modules:
1056 if Ma not in self._ModuleAutoGenList:
1057 self._ModuleAutoGenList.append(Ma)
1058 for La in Ma.LibraryAutoGenList:
1059 if La not in self._LibraryAutoGenList:
1060 self._LibraryAutoGenList.append(La)
1062 ## Summarize ModuleAutoGen objects of all modules to be built for this platform
1063 def _GetModuleAutoGenList(self):
1064 if self._ModuleAutoGenList == None:
1065 self._GetAutoGenObjectList()
1066 return self._ModuleAutoGenList
1068 ## Summarize ModuleAutoGen objects of all libraries to be built for this platform
1069 def _GetLibraryAutoGenList(self):
1070 if self._LibraryAutoGenList == None:
1071 self._GetAutoGenObjectList()
1072 return self._LibraryAutoGenList
1074 ## Test if a module is supported by the platform
1076 # An error will be raised directly if the module or its arch is not supported
1077 # by the platform or current configuration
1079 def ValidModule(self, Module):
1080 return Module in self.Platform.Modules or Module in self.Platform.LibraryInstances
1082 ## Resolve the library classes in a module to library instances
1084 # This method will not only resolve library classes but also sort the library
1085 # instances according to the dependency-ship.
1087 # @param Module The module from which the library classes will be resolved
1089 # @retval library_list List of library instances sorted
1091 def ApplyLibraryInstance(self, Module):
1092 ModuleType = Module.ModuleType
1094 # for overridding library instances with module specific setting
1095 PlatformModule = self.Platform.Modules[str(Module)]
1097 # add forced library instances (specified under LibraryClasses sections)
1098 for LibraryClass in self.Platform.LibraryClasses.GetKeys():
1099 if LibraryClass.startswith("NULL"):
1100 Module.LibraryClasses[LibraryClass] = self.Platform.LibraryClasses[LibraryClass]
1102 # add forced library instances (specified in module overrides)
1103 for LibraryClass in PlatformModule.LibraryClasses:
1104 if LibraryClass.startswith("NULL"):
1105 Module.LibraryClasses[LibraryClass] = PlatformModule.LibraryClasses[LibraryClass]
1108 LibraryConsumerList = [Module]
1110 ConsumedByList = sdict()
1111 LibraryInstance = sdict()
1113 EdkLogger.verbose("")
1114 EdkLogger.verbose("Library instances of module [%s] [%s]:" % (str(Module), self.Arch))
1115 while len(LibraryConsumerList) > 0:
1116 M = LibraryConsumerList.pop()
1117 for LibraryClassName in M.LibraryClasses:
1118 if LibraryClassName not in LibraryInstance:
1119 # override library instance for this module
1120 if LibraryClassName in PlatformModule.LibraryClasses:
1121 LibraryPath = PlatformModule.LibraryClasses[LibraryClassName]
1123 LibraryPath = self.Platform.LibraryClasses[LibraryClassName, ModuleType]
1124 if LibraryPath == None or LibraryPath == "":
1125 LibraryPath = M.LibraryClasses[LibraryClassName]
1126 if LibraryPath == None or LibraryPath == "":
1127 EdkLogger.error("build", RESOURCE_NOT_AVAILABLE,
1128 "Instance of library class [%s] is not found" % LibraryClassName,
1130 ExtraData="in [%s] [%s]\n\tconsumed by module [%s]" % (str(M), self.Arch, str(Module)))
1132 LibraryModule = self.BuildDatabase[LibraryPath, self.Arch]
1133 # for those forced library instance (NULL library), add a fake library class
1134 if LibraryClassName.startswith("NULL"):
1135 LibraryModule.LibraryClass.append(LibraryClassObject(LibraryClassName, [ModuleType]))
1136 elif LibraryModule.LibraryClass == None \
1137 or len(LibraryModule.LibraryClass) == 0 \
1138 or (ModuleType != 'USER_DEFINED'
1139 and ModuleType not in LibraryModule.LibraryClass[0].SupModList):
1140 # only USER_DEFINED can link against any library instance despite of its SupModList
1141 EdkLogger.error("build", OPTION_MISSING,
1142 "Module type [%s] is not supported by library instance [%s]" \
1143 % (ModuleType, LibraryPath), File=self.MetaFile,
1144 ExtraData="consumed by [%s]" % str(Module))
1146 LibraryInstance[LibraryClassName] = LibraryModule
1147 LibraryConsumerList.append(LibraryModule)
1148 EdkLogger.verbose("\t" + str(LibraryClassName) + " : " + str(LibraryModule))
1150 LibraryModule = LibraryInstance[LibraryClassName]
1152 if LibraryModule == None:
1155 if LibraryModule.ConstructorList != [] and LibraryModule not in Constructor:
1156 Constructor.append(LibraryModule)
1158 if LibraryModule not in ConsumedByList:
1159 ConsumedByList[LibraryModule] = []
1160 # don't add current module itself to consumer list
1162 if M in ConsumedByList[LibraryModule]:
1164 ConsumedByList[LibraryModule].append(M)
1166 # Initialize the sorted output list to the empty set
1168 SortedLibraryList = []
1170 # Q <- Set of all nodes with no incoming edges
1172 LibraryList = [] #LibraryInstance.values()
1174 for LibraryClassName in LibraryInstance:
1175 M = LibraryInstance[LibraryClassName]
1176 LibraryList.append(M)
1177 if ConsumedByList[M] == []:
1181 # start the DAG algorithm
1185 while Q == [] and EdgeRemoved:
1187 # for each node Item with a Constructor
1188 for Item in LibraryList:
1189 if Item not in Constructor:
1191 # for each Node without a constructor with an edge e from Item to Node
1192 for Node in ConsumedByList[Item]:
1193 if Node in Constructor:
1195 # remove edge e from the graph if Node has no constructor
1196 ConsumedByList[Item].remove(Node)
1198 if ConsumedByList[Item] == []:
1199 # insert Item into Q
1204 # DAG is done if there's no more incoming edge for all nodes
1208 # remove node from Q
1211 SortedLibraryList.append(Node)
1213 # for each node Item with an edge e from Node to Item do
1214 for Item in LibraryList:
1215 if Node not in ConsumedByList[Item]:
1217 # remove edge e from the graph
1218 ConsumedByList[Item].remove(Node)
1220 if ConsumedByList[Item] != []:
1222 # insert Item into Q, if Item has no other incoming edges
1226 # if any remaining node Item in the graph has a constructor and an incoming edge, then the graph has a cycle
1228 for Item in LibraryList:
1229 if ConsumedByList[Item] != [] and Item in Constructor and len(Constructor) > 1:
1230 ErrorMessage = "\tconsumed by " + "\n\tconsumed by ".join([str(L) for L in ConsumedByList[Item]])
1231 EdkLogger.error("build", BUILD_ERROR, 'Library [%s] with constructors has a cycle' % str(Item),
1232 ExtraData=ErrorMessage, File=self.MetaFile)
1233 if Item not in SortedLibraryList:
1234 SortedLibraryList.append(Item)
1237 # Build the list of constructor and destructir names
1238 # The DAG Topo sort produces the destructor order, so the list of constructors must generated in the reverse order
1240 SortedLibraryList.reverse()
1241 return SortedLibraryList
1244 ## Override PCD setting (type, value, ...)
1246 # @param ToPcd The PCD to be overrided
1247 # @param FromPcd The PCD overrideing from
1249 def _OverridePcd(self, ToPcd, FromPcd, Module=""):
1251 # in case there's PCDs coming from FDF file, which have no type given.
1252 # at this point, ToPcd.Type has the type found from dependent
1256 if ToPcd.Pending and FromPcd.Type not in [None, '']:
1257 ToPcd.Type = FromPcd.Type
1258 elif ToPcd.Type not in [None, ''] and FromPcd.Type not in [None, ''] \
1259 and ToPcd.Type != FromPcd.Type:
1260 EdkLogger.error("build", OPTION_CONFLICT, "Mismatched PCD type",
1261 ExtraData="%s.%s is defined as [%s] in module %s, but as [%s] in platform."\
1262 % (ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName,
1263 ToPcd.Type, Module, FromPcd.Type),
1266 if FromPcd.MaxDatumSize not in [None, '']:
1267 ToPcd.MaxDatumSize = FromPcd.MaxDatumSize
1268 if FromPcd.DefaultValue not in [None, '']:
1269 ToPcd.DefaultValue = FromPcd.DefaultValue
1270 if FromPcd.TokenValue not in [None, '']:
1271 ToPcd.TokenValue = FromPcd.TokenValue
1272 if FromPcd.MaxDatumSize not in [None, '']:
1273 ToPcd.MaxDatumSize = FromPcd.MaxDatumSize
1274 if FromPcd.DatumType not in [None, '']:
1275 ToPcd.DatumType = FromPcd.DatumType
1276 if FromPcd.SkuInfoList not in [None, '', []]:
1277 ToPcd.SkuInfoList = FromPcd.SkuInfoList
1279 # check the validation of datum
1280 IsValid, Cause = CheckPcdDatum(ToPcd.DatumType, ToPcd.DefaultValue)
1282 EdkLogger.error('build', FORMAT_INVALID, Cause, File=self.MetaFile,
1283 ExtraData="%s.%s" % (ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName))
1285 if ToPcd.DatumType == "VOID*" and ToPcd.MaxDatumSize in ['', None]:
1286 EdkLogger.debug(EdkLogger.DEBUG_9, "No MaxDatumSize specified for PCD %s.%s" \
1287 % (ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName))
1288 Value = ToPcd.DefaultValue
1289 if Value in [None, '']:
1290 ToPcd.MaxDatumSize = 1
1291 elif Value[0] == 'L':
1292 ToPcd.MaxDatumSize = str(len(Value) * 2)
1293 elif Value[0] == '{':
1294 ToPcd.MaxDatumSize = str(len(Value.split(',')))
1296 ToPcd.MaxDatumSize = str(len(Value))
1298 # apply default SKU for dynamic PCDS if specified one is not available
1299 if (ToPcd.Type in PCD_DYNAMIC_TYPE_LIST or ToPcd.Type in PCD_DYNAMIC_EX_TYPE_LIST) \
1300 and ToPcd.SkuInfoList in [None, {}, '']:
1301 if self.Platform.SkuName in self.Platform.SkuIds:
1302 SkuName = self.Platform.SkuName
1305 ToPcd.SkuInfoList = {
1306 SkuName : SkuInfoClass(SkuName, self.Platform.SkuIds[SkuName], '', '', '', '', '', ToPcd.DefaultValue)
1309 ## Apply PCD setting defined platform to a module
1311 # @param Module The module from which the PCD setting will be overrided
1313 # @retval PCD_list The list PCDs with settings from platform
1315 def ApplyPcdSetting(self, Module, Pcds):
1316 # for each PCD in module
1317 for Name,Guid in Pcds:
1318 PcdInModule = Pcds[Name,Guid]
1319 # find out the PCD setting in platform
1320 if (Name,Guid) in self.Platform.Pcds:
1321 PcdInPlatform = self.Platform.Pcds[Name,Guid]
1323 PcdInPlatform = None
1324 # then override the settings if any
1325 self._OverridePcd(PcdInModule, PcdInPlatform, Module)
1326 # resolve the VariableGuid value
1327 for SkuId in PcdInModule.SkuInfoList:
1328 Sku = PcdInModule.SkuInfoList[SkuId]
1329 if Sku.VariableGuid == '': continue
1330 Sku.VariableGuidValue = GuidValue(Sku.VariableGuid, self.PackageList)
1331 if Sku.VariableGuidValue == None:
1332 PackageList = "\n\t".join([str(P) for P in self.PackageList])
1335 RESOURCE_NOT_AVAILABLE,
1336 "Value of GUID [%s] is not found in" % Sku.VariableGuid,
1337 ExtraData=PackageList + "\n\t(used with %s.%s from module %s)" \
1338 % (Guid, Name, str(Module)),
1342 # override PCD settings with module specific setting
1343 if Module in self.Platform.Modules:
1344 PlatformModule = self.Platform.Modules[str(Module)]
1345 for Key in PlatformModule.Pcds:
1347 self._OverridePcd(Pcds[Key], PlatformModule.Pcds[Key], Module)
1348 return Pcds.values()
1350 ## Resolve library names to library modules
1352 # (for R8.x modules)
1354 # @param Module The module from which the library names will be resolved
1356 # @retval library_list The list of library modules
1358 def ResolveLibraryReference(self, Module):
1359 EdkLogger.verbose("")
1360 EdkLogger.verbose("Library instances of module [%s] [%s]:" % (str(Module), self.Arch))
1361 LibraryConsumerList = [Module]
1363 # "CompilerStub" is a must for R8 modules
1364 if Module.Libraries:
1365 Module.Libraries.append("CompilerStub")
1367 while len(LibraryConsumerList) > 0:
1368 M = LibraryConsumerList.pop()
1369 for LibraryName in M.Libraries:
1370 Library = self.Platform.LibraryClasses[LibraryName, ':dummy:']
1372 for Key in self.Platform.LibraryClasses.data.keys():
1373 if LibraryName.upper() == Key.upper():
1374 Library = self.Platform.LibraryClasses[Key, ':dummy:']
1377 EdkLogger.warn("build", "Library [%s] is not found" % LibraryName, File=str(M),
1378 ExtraData="\t%s [%s]" % (str(Module), self.Arch))
1381 if Library not in LibraryList:
1382 LibraryList.append(Library)
1383 LibraryConsumerList.append(Library)
1384 EdkLogger.verbose("\t" + LibraryName + " : " + str(Library) + ' ' + str(type(Library)))
1387 ## Expand * in build option key
1389 # @param Options Options to be expanded
1391 # @retval options Options expanded
1393 def _ExpandBuildOption(self, Options):
1399 Target, Tag, Arch, Tool, Attr = Key[1].split("_")
1400 # if tool chain family doesn't match, skip it
1401 if Tool in self.ToolDefinition and Family != "":
1402 FamilyIsNull = False
1403 if self.ToolDefinition[Tool].get(TAB_TOD_DEFINES_BUILDRULEFAMILY, "") != "":
1404 if Family != self.ToolDefinition[Tool][TAB_TOD_DEFINES_BUILDRULEFAMILY]:
1406 elif Family != self.ToolDefinition[Tool][TAB_TOD_DEFINES_FAMILY]:
1409 # expand any wildcard
1410 if Target == "*" or Target == self.BuildTarget:
1411 if Tag == "*" or Tag == self.ToolChain:
1412 if Arch == "*" or Arch == self.Arch:
1413 if Tool not in BuildOptions:
1414 BuildOptions[Tool] = {}
1415 if Attr != "FLAGS" or Attr not in BuildOptions[Tool]:
1416 BuildOptions[Tool][Attr] = Options[Key]
1418 # append options for the same tool
1419 BuildOptions[Tool][Attr] += " " + Options[Key]
1420 # Build Option Family has been checked, which need't to be checked again for family.
1421 if FamilyMatch or FamilyIsNull:
1426 Target, Tag, Arch, Tool, Attr = Key[1].split("_")
1427 # if tool chain family doesn't match, skip it
1428 if Tool not in self.ToolDefinition or Family =="":
1430 # option has been added before
1431 if Family != self.ToolDefinition[Tool][TAB_TOD_DEFINES_FAMILY]:
1434 # expand any wildcard
1435 if Target == "*" or Target == self.BuildTarget:
1436 if Tag == "*" or Tag == self.ToolChain:
1437 if Arch == "*" or Arch == self.Arch:
1438 if Tool not in BuildOptions:
1439 BuildOptions[Tool] = {}
1440 if Attr != "FLAGS" or Attr not in BuildOptions[Tool]:
1441 BuildOptions[Tool][Attr] = Options[Key]
1443 # append options for the same tool
1444 BuildOptions[Tool][Attr] += " " + Options[Key]
1447 ## Append build options in platform to a module
1449 # @param Module The module to which the build options will be appened
1451 # @retval options The options appended with build options in platform
1453 def ApplyBuildOption(self, Module):
1454 PlatformOptions = self.BuildOption
1455 ModuleOptions = self._ExpandBuildOption(Module.BuildOptions)
1456 if Module in self.Platform.Modules:
1457 PlatformModule = self.Platform.Modules[str(Module)]
1458 PlatformModuleOptions = self._ExpandBuildOption(PlatformModule.BuildOptions)
1460 PlatformModuleOptions = {}
1462 AllTools = set(ModuleOptions.keys() + PlatformOptions.keys() + PlatformModuleOptions.keys() + self.ToolDefinition.keys())
1464 for Tool in AllTools:
1465 if Tool not in BuildOptions:
1466 BuildOptions[Tool] = {}
1468 for Options in [self.ToolDefinition, ModuleOptions, PlatformOptions, PlatformModuleOptions]:
1469 if Tool not in Options:
1471 for Attr in Options[Tool]:
1472 Value = Options[Tool][Attr]
1473 if Attr not in BuildOptions[Tool]:
1474 BuildOptions[Tool][Attr] = ""
1475 # check if override is indicated
1476 if Value.startswith('='):
1477 BuildOptions[Tool][Attr] = Value[1:]
1479 BuildOptions[Tool][Attr] += " " + Value
1482 Platform = property(_GetPlatform)
1483 Name = property(_GetName)
1484 Guid = property(_GetGuid)
1485 Version = property(_GetVersion)
1487 OutputDir = property(_GetOutputDir)
1488 BuildDir = property(_GetBuildDir)
1489 MakeFileDir = property(_GetMakeFileDir)
1490 FdfFile = property(_GetFdfFile)
1492 PcdTokenNumber = property(_GetPcdTokenNumbers) # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber
1493 DynamicPcdList = property(_GetDynamicPcdList) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
1494 NonDynamicPcdList = property(_GetNonDynamicPcdList) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
1495 PackageList = property(_GetPackageList)
1497 ToolDefinition = property(_GetToolDefinition) # toolcode : tool path
1498 ToolDefinitionFile = property(_GetToolDefFile) # toolcode : lib path
1499 ToolChainFamily = property(_GetToolChainFamily)
1500 BuildRuleFamily = property(_GetBuildRuleFamily)
1501 BuildOption = property(_GetBuildOptions) # toolcode : option
1503 BuildCommand = property(_GetBuildCommand)
1504 BuildRule = property(_GetBuildRule)
1505 ModuleAutoGenList = property(_GetModuleAutoGenList)
1506 LibraryAutoGenList = property(_GetLibraryAutoGenList)
1508 ## ModuleAutoGen class
1510 # This class encapsules the AutoGen behaviors for the build tools. In addition to
1511 # the generation of AutoGen.h and AutoGen.c, it will generate *.depex file according
1512 # to the [depex] section in module's inf file.
1514 class ModuleAutoGen(AutoGen):
1515 ## The real constructor of ModuleAutoGen
1517 # This method is not supposed to be called by users of ModuleAutoGen. It's
1518 # only used by factory method __new__() to do real initialization work for an
1519 # object of ModuleAutoGen
1521 # @param Workspace EdkIIWorkspaceBuild object
1522 # @param ModuleFile The path of module file
1523 # @param Target Build target (DEBUG, RELEASE)
1524 # @param Toolchain Name of tool chain
1525 # @param Arch The arch the module supports
1526 # @param PlatformFile Platform meta-file
1528 def _Init(self, Workspace, ModuleFile, Target, Toolchain, Arch, PlatformFile):
1529 EdkLogger.debug(EdkLogger.DEBUG_9, "AutoGen module [%s] [%s]" % (ModuleFile, Arch))
1530 GlobalData.gProcessingFile = "%s [%s, %s, %s]" % (ModuleFile, Arch, Toolchain, Target)
1532 self.Workspace = Workspace
1533 self.WorkspaceDir = Workspace.WorkspaceDir
1535 self.MetaFile = ModuleFile
1536 self.PlatformInfo = PlatformAutoGen(Workspace, PlatformFile, Target, Toolchain, Arch)
1537 # check if this module is employed by active platform
1538 if not self.PlatformInfo.ValidModule(self.MetaFile):
1539 EdkLogger.verbose("Module [%s] for [%s] is not employed by active platform\n" \
1540 % (self.MetaFile, Arch))
1543 self.SourceDir = self.MetaFile.SubDir
1544 self.SourceOverrideDir = None
1545 # use overrided path defined in DSC file
1546 if self.MetaFile.Key in GlobalData.gOverrideDir:
1547 self.SourceOverrideDir = GlobalData.gOverrideDir[self.MetaFile.Key]
1549 self.ToolChain = Toolchain
1550 self.BuildTarget = Target
1552 self.ToolChainFamily = self.PlatformInfo.ToolChainFamily
1553 self.BuildRuleFamily = self.PlatformInfo.BuildRuleFamily
1555 self.IsMakeFileCreated = False
1556 self.IsCodeFileCreated = False
1558 self.BuildDatabase = self.Workspace.BuildDatabase
1563 self._Version = None
1564 self._ModuleType = None
1565 self._ComponentType = None
1566 self._PcdIsDriver = None
1567 self._AutoGenVersion = None
1568 self._LibraryFlag = None
1569 self._CustomMakefile = None
1572 self._BuildDir = None
1573 self._OutputDir = None
1574 self._DebugDir = None
1575 self._MakeFileDir = None
1577 self._IncludePathList = None
1578 self._AutoGenFileList = None
1579 self._UnicodeFileList = None
1580 self._SourceFileList = None
1581 self._ObjectFileList = None
1582 self._BinaryFileList = None
1584 self._DependentPackageList = None
1585 self._DependentLibraryList = None
1586 self._LibraryAutoGenList = None
1587 self._DerivedPackageList = None
1588 self._ModulePcdList = None
1589 self._LibraryPcdList = None
1590 self._GuidList = None
1591 self._ProtocolList = None
1592 self._PpiList = None
1593 self._DepexList = None
1594 self._DepexExpressionList = None
1595 self._BuildOption = None
1596 self._BuildTargets = None
1597 self._IntroBuildTargetList = None
1598 self._FinalBuildTargetList = None
1599 self._FileTypes = None
1600 self._BuildRules = None
1605 return "%s [%s]" % (self.MetaFile, self.Arch)
1607 # Macros could be used in build_rule.txt (also Makefile)
1608 def _GetMacros(self):
1609 if self._Macro == None:
1610 self._Macro = sdict()
1611 self._Macro["WORKSPACE" ] = self.WorkspaceDir
1612 self._Macro["MODULE_NAME" ] = self.Name
1613 self._Macro["MODULE_GUID" ] = self.Guid
1614 self._Macro["MODULE_VERSION" ] = self.Version
1615 self._Macro["MODULE_TYPE" ] = self.ModuleType
1616 self._Macro["MODULE_FILE" ] = str(self.MetaFile)
1617 self._Macro["MODULE_FILE_BASE_NAME" ] = self.MetaFile.BaseName
1618 self._Macro["MODULE_RELATIVE_DIR" ] = self.SourceDir
1619 self._Macro["MODULE_DIR" ] = self.SourceDir
1621 self._Macro["BASE_NAME" ] = self.Name
1623 self._Macro["ARCH" ] = self.Arch
1624 self._Macro["TOOLCHAIN" ] = self.ToolChain
1625 self._Macro["TOOLCHAIN_TAG" ] = self.ToolChain
1626 self._Macro["TARGET" ] = self.BuildTarget
1628 self._Macro["BUILD_DIR" ] = self.PlatformInfo.BuildDir
1629 self._Macro["BIN_DIR" ] = os.path.join(self.PlatformInfo.BuildDir, self.Arch)
1630 self._Macro["LIB_DIR" ] = os.path.join(self.PlatformInfo.BuildDir, self.Arch)
1631 self._Macro["MODULE_BUILD_DIR" ] = self.BuildDir
1632 self._Macro["OUTPUT_DIR" ] = self.OutputDir
1633 self._Macro["DEBUG_DIR" ] = self.DebugDir
1636 ## Return the module build data object
1637 def _GetModule(self):
1638 if self._Module == None:
1639 self._Module = self.Workspace.BuildDatabase[self.MetaFile, self.Arch]
1642 ## Return the module name
1643 def _GetBaseName(self):
1644 return self.Module.BaseName
1646 ## Return the module SourceOverridePath
1647 def _GetSourceOverridePath(self):
1648 return self.Module.SourceOverridePath
1650 ## Return the module meta-file GUID
1652 return self.Module.Guid
1654 ## Return the module version
1655 def _GetVersion(self):
1656 return self.Module.Version
1658 ## Return the module type
1659 def _GetModuleType(self):
1660 return self.Module.ModuleType
1662 ## Return the component type (for R8.x style of module)
1663 def _GetComponentType(self):
1664 return self.Module.ComponentType
1666 ## Return the build type
1667 def _GetBuildType(self):
1668 return self.Module.BuildType
1670 ## Return the PCD_IS_DRIVER setting
1671 def _GetPcdIsDriver(self):
1672 return self.Module.PcdIsDriver
1674 ## Return the autogen version, i.e. module meta-file version
1675 def _GetAutoGenVersion(self):
1676 return self.Module.AutoGenVersion
1678 ## Check if the module is library or not
1679 def _IsLibrary(self):
1680 if self._LibraryFlag == None:
1681 if self.Module.LibraryClass != None and self.Module.LibraryClass != []:
1682 self._LibraryFlag = True
1684 self._LibraryFlag = False
1685 return self._LibraryFlag
1687 ## Return the directory to store intermediate files of the module
1688 def _GetBuildDir(self):
1689 if self._BuildDir == None:
1690 self._BuildDir = path.join(
1691 self.PlatformInfo.BuildDir,
1694 self.MetaFile.BaseName
1696 CreateDirectory(self._BuildDir)
1697 return self._BuildDir
1699 ## Return the directory to store the intermediate object files of the mdoule
1700 def _GetOutputDir(self):
1701 if self._OutputDir == None:
1702 self._OutputDir = path.join(self.BuildDir, "OUTPUT")
1703 CreateDirectory(self._OutputDir)
1704 return self._OutputDir
1706 ## Return the directory to store auto-gened source files of the mdoule
1707 def _GetDebugDir(self):
1708 if self._DebugDir == None:
1709 self._DebugDir = path.join(self.BuildDir, "DEBUG")
1710 CreateDirectory(self._DebugDir)
1711 return self._DebugDir
1713 ## Return the path of custom file
1714 def _GetCustomMakefile(self):
1715 if self._CustomMakefile == None:
1716 self._CustomMakefile = {}
1717 for Type in self.Module.CustomMakefile:
1718 if Type in gMakeTypeMap:
1719 MakeType = gMakeTypeMap[Type]
1722 if self.SourceOverrideDir != None:
1723 File = os.path.join(self.SourceOverrideDir, self.Module.CustomMakefile[Type])
1724 if not os.path.exists(File):
1725 File = os.path.join(self.SourceDir, self.Module.CustomMakefile[Type])
1727 File = os.path.join(self.SourceDir, self.Module.CustomMakefile[Type])
1728 self._CustomMakefile[MakeType] = File
1729 return self._CustomMakefile
1731 ## Return the directory of the makefile
1733 # @retval string The directory string of module's makefile
1735 def _GetMakeFileDir(self):
1736 return self.BuildDir
1738 ## Return build command string
1740 # @retval string Build command string
1742 def _GetBuildCommand(self):
1743 return self.PlatformInfo.BuildCommand
1745 ## Get object list of all packages the module and its dependent libraries belong to
1747 # @retval list The list of package object
1749 def _GetDerivedPackageList(self):
1751 for M in [self.Module] + self.DependentLibraryList:
1752 for Package in M.Packages:
1753 if Package in PackageList:
1755 PackageList.append(Package)
1758 ## Merge dependency expression
1760 # @retval list The token list of the dependency expression after parsed
1762 def _GetDepexTokenList(self):
1763 if self._DepexList == None:
1764 self._DepexList = {}
1765 if self.IsLibrary or TAB_DEPENDENCY_EXPRESSION_FILE in self.FileTypes:
1766 return self._DepexList
1768 self._DepexList[self.ModuleType] = []
1770 for ModuleType in self._DepexList:
1771 DepexList = self._DepexList[ModuleType]
1773 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
1775 for M in [self.Module] + self.DependentLibraryList:
1777 for D in M.Depex[self.Arch, ModuleType]:
1779 DepexList.append('AND')
1780 DepexList.append('(')
1782 if DepexList[-1] == 'END': # no need of a END at this time
1784 DepexList.append(')')
1787 EdkLogger.verbose("DEPEX[%s] (+%s) = %s" % (self.Name, M.BaseName, DepexList))
1788 if 'BEFORE' in DepexList or 'AFTER' in DepexList:
1790 if len(DepexList) > 0:
1791 EdkLogger.verbose('')
1792 return self._DepexList
1794 ## Merge dependency expression
1796 # @retval list The token list of the dependency expression after parsed
1798 def _GetDepexExpressionTokenList(self):
1799 if self._DepexExpressionList == None:
1800 self._DepexExpressionList = {}
1801 if self.IsLibrary or TAB_DEPENDENCY_EXPRESSION_FILE in self.FileTypes:
1802 return self._DepexExpressionList
1804 self._DepexExpressionList[self.ModuleType] = ''
1806 for ModuleType in self._DepexExpressionList:
1807 DepexExpressionList = self._DepexExpressionList[ModuleType]
1809 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
1811 for M in [self.Module] + self.DependentLibraryList:
1813 for D in M.DepexExpression[self.Arch, ModuleType]:
1814 if DepexExpressionList != '':
1815 DepexExpressionList += ' AND '
1816 DepexExpressionList += '('
1817 DepexExpressionList += D
1818 DepexExpressionList = DepexExpressionList.rstrip('END').strip()
1819 DepexExpressionList += ')'
1822 EdkLogger.verbose("DEPEX[%s] (+%s) = %s" % (self.Name, M.BaseName, DepexExpressionList))
1823 if 'BEFORE' in DepexExpressionList or 'AFTER' in DepexExpressionList:
1825 if len(DepexExpressionList) > 0:
1826 EdkLogger.verbose('')
1827 self._DepexExpressionList[ModuleType] = DepexExpressionList
1828 return self._DepexExpressionList
1830 ## Return the list of specification version required for the module
1832 # @retval list The list of specification defined in module file
1834 def _GetSpecification(self):
1835 return self.Module.Specification
1837 ## Tool option for the module build
1839 # @param PlatformInfo The object of PlatformBuildInfo
1840 # @retval dict The dict containing valid options
1842 def _GetModuleBuildOption(self):
1843 if self._BuildOption == None:
1844 self._BuildOption = self.PlatformInfo.ApplyBuildOption(self.Module)
1845 return self._BuildOption
1847 ## Return a list of files which can be built from source
1849 # What kind of files can be built is determined by build rules in
1850 # $(WORKSPACE)/Conf/build_rule.txt and toolchain family.
1852 def _GetSourceFileList(self):
1853 if self._SourceFileList == None:
1854 self._SourceFileList = []
1855 for F in self.Module.Sources:
1857 if F.TagName != "" and F.TagName != self.ToolChain:
1858 EdkLogger.debug(EdkLogger.DEBUG_9, "The toolchain [%s] for processing file [%s] is found, "
1859 "but [%s] is needed" % (F.TagName, str(F), self.ToolChain))
1861 # match tool chain family
1862 if F.ToolChainFamily != "" and F.ToolChainFamily != self.ToolChainFamily:
1865 "The file [%s] must be built by tools of [%s], " \
1866 "but current toolchain family is [%s]" \
1867 % (str(F), F.ToolChainFamily, self.ToolChainFamily))
1870 # add the file path into search path list for file including
1871 if F.Dir not in self.IncludePathList and self.AutoGenVersion >= 0x00010005:
1872 self.IncludePathList.insert(0, F.Dir)
1873 self._SourceFileList.append(F)
1874 self._ApplyBuildRule(F, TAB_UNKNOWN_FILE)
1875 return self._SourceFileList
1877 ## Return the list of unicode files
1878 def _GetUnicodeFileList(self):
1879 if self._UnicodeFileList == None:
1880 if TAB_UNICODE_FILE in self.FileTypes:
1881 self._UnicodeFileList = self.FileTypes[TAB_UNICODE_FILE]
1883 self._UnicodeFileList = []
1884 return self._UnicodeFileList
1886 ## Return a list of files which can be built from binary
1888 # "Build" binary files are just to copy them to build directory.
1890 # @retval list The list of files which can be built later
1892 def _GetBinaryFiles(self):
1893 if self._BinaryFileList == None:
1894 self._BinaryFileList = []
1895 for F in self.Module.Binaries:
1896 if F.Target not in ['COMMON', '*'] and F.Target != self.BuildTarget:
1898 self._BinaryFileList.append(F)
1899 self._ApplyBuildRule(F, F.Type)
1900 return self._BinaryFileList
1902 def _GetBuildRules(self):
1903 if self._BuildRules == None:
1905 BuildRuleDatabase = self.PlatformInfo.BuildRule
1906 for Type in BuildRuleDatabase.FileTypeList:
1907 #first try getting build rule by BuildRuleFamily
1908 RuleObject = BuildRuleDatabase[Type, self.BuildType, self.Arch, self.BuildRuleFamily]
1910 # build type is always module type, but ...
1911 if self.ModuleType != self.BuildType:
1912 RuleObject = BuildRuleDatabase[Type, self.ModuleType, self.Arch, self.BuildRuleFamily]
1913 #second try getting build rule by ToolChainFamily
1915 RuleObject = BuildRuleDatabase[Type, self.BuildType, self.Arch, self.ToolChainFamily]
1917 # build type is always module type, but ...
1918 if self.ModuleType != self.BuildType:
1919 RuleObject = BuildRuleDatabase[Type, self.ModuleType, self.Arch, self.ToolChainFamily]
1922 RuleObject = RuleObject.Instantiate(self.Macros)
1923 BuildRules[Type] = RuleObject
1924 for Ext in RuleObject.SourceFileExtList:
1925 BuildRules[Ext] = RuleObject
1926 self._BuildRules = BuildRules
1927 return self._BuildRules
1929 def _ApplyBuildRule(self, File, FileType):
1930 if self._BuildTargets == None:
1931 self._IntroBuildTargetList = set()
1932 self._FinalBuildTargetList = set()
1933 self._BuildTargets = {}
1934 self._FileTypes = {}
1940 while Index < len(SourceList):
1941 Source = SourceList[Index]
1945 CreateDirectory(Source.Dir)
1947 if File.IsBinary and File == Source:
1948 RuleObject = self.BuildRules[TAB_DEFAULT_BINARY_FILE]
1949 elif FileType in self.BuildRules:
1950 RuleObject = self.BuildRules[FileType]
1951 elif Source.Ext in self.BuildRules:
1952 RuleObject = self.BuildRules[Source.Ext]
1954 # stop at no more rules
1956 self._FinalBuildTargetList.add(LastTarget)
1959 FileType = RuleObject.SourceFileType
1960 if FileType not in self._FileTypes:
1961 self._FileTypes[FileType] = set()
1962 self._FileTypes[FileType].add(Source)
1964 # stop at STATIC_LIBRARY for library
1965 if self.IsLibrary and FileType == TAB_STATIC_LIBRARY:
1967 self._FinalBuildTargetList.add(LastTarget)
1970 Target = RuleObject.Apply(Source)
1973 self._FinalBuildTargetList.add(LastTarget)
1975 elif not Target.Outputs:
1976 # Only do build for target with outputs
1977 self._FinalBuildTargetList.add(Target)
1979 if FileType not in self._BuildTargets:
1980 self._BuildTargets[FileType] = set()
1981 self._BuildTargets[FileType].add(Target)
1983 if not Source.IsBinary and Source == File:
1984 self._IntroBuildTargetList.add(Target)
1986 # to avoid cyclic rule
1987 if FileType in RuleChain:
1990 RuleChain.append(FileType)
1991 SourceList.extend(Target.Outputs)
1993 FileType = TAB_UNKNOWN_FILE
1995 def _GetTargets(self):
1996 if self._BuildTargets == None:
1997 self._IntroBuildTargetList = set()
1998 self._FinalBuildTargetList = set()
1999 self._BuildTargets = {}
2000 self._FileTypes = {}
2002 #TRICK: call _GetSourceFileList to apply build rule for binary files
2003 if self.SourceFileList:
2006 #TRICK: call _GetBinaryFileList to apply build rule for binary files
2007 if self.BinaryFileList:
2010 return self._BuildTargets
2012 def _GetIntroTargetList(self):
2014 return self._IntroBuildTargetList
2016 def _GetFinalTargetList(self):
2018 return self._FinalBuildTargetList
2020 def _GetFileTypes(self):
2022 return self._FileTypes
2024 ## Get the list of package object the module depends on
2026 # @retval list The package object list
2028 def _GetDependentPackageList(self):
2029 return self.Module.Packages
2031 ## Return the list of auto-generated code file
2033 # @retval list The list of auto-generated file
2035 def _GetAutoGenFileList(self):
2036 UniStringAutoGenC = True
2037 UniStringBinBuffer = None
2038 if self.BuildType == 'UEFI_HII':
2039 UniStringBinBuffer = StringIO()
2040 UniStringAutoGenC = False
2041 if self._AutoGenFileList == None:
2042 self._AutoGenFileList = {}
2043 AutoGenC = TemplateString()
2044 AutoGenH = TemplateString()
2045 StringH = TemplateString()
2046 GenC.CreateCode(self, AutoGenC, AutoGenH, StringH, UniStringAutoGenC, UniStringBinBuffer)
2047 if str(AutoGenC) != "" and TAB_C_CODE_FILE in self.FileTypes:
2048 AutoFile = PathClass(gAutoGenCodeFileName, self.DebugDir)
2049 self._AutoGenFileList[AutoFile] = str(AutoGenC)
2050 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
2051 if str(AutoGenH) != "":
2052 AutoFile = PathClass(gAutoGenHeaderFileName, self.DebugDir)
2053 self._AutoGenFileList[AutoFile] = str(AutoGenH)
2054 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
2055 if str(StringH) != "":
2056 AutoFile = PathClass(gAutoGenStringFileName % {"module_name":self.Name}, self.DebugDir)
2057 self._AutoGenFileList[AutoFile] = str(StringH)
2058 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
2059 if UniStringBinBuffer != None and UniStringBinBuffer.getvalue() != "":
2060 AutoFile = PathClass(gAutoGenStringFormFileName % {"module_name":self.Name}, self.OutputDir)
2061 self._AutoGenFileList[AutoFile] = UniStringBinBuffer.getvalue()
2062 AutoFile.IsBinary = True
2063 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
2064 if UniStringBinBuffer != None:
2065 UniStringBinBuffer.close()
2066 return self._AutoGenFileList
2068 ## Return the list of library modules explicitly or implicityly used by this module
2069 def _GetLibraryList(self):
2070 if self._DependentLibraryList == None:
2071 # only merge library classes and PCD for non-library module
2073 self._DependentLibraryList = []
2075 if self.AutoGenVersion < 0x00010005:
2076 self._DependentLibraryList = self.PlatformInfo.ResolveLibraryReference(self.Module)
2078 self._DependentLibraryList = self.PlatformInfo.ApplyLibraryInstance(self.Module)
2079 return self._DependentLibraryList
2081 ## Get the list of PCDs from current module
2083 # @retval list The list of PCD
2085 def _GetModulePcdList(self):
2086 if self._ModulePcdList == None:
2087 # apply PCD settings from platform
2088 self._ModulePcdList = self.PlatformInfo.ApplyPcdSetting(self.Module, self.Module.Pcds)
2089 return self._ModulePcdList
2091 ## Get the list of PCDs from dependent libraries
2093 # @retval list The list of PCD
2095 def _GetLibraryPcdList(self):
2096 if self._LibraryPcdList == None:
2098 if not self.IsLibrary:
2099 # get PCDs from dependent libraries
2100 for Library in self.DependentLibraryList:
2101 for Key in Library.Pcds:
2102 # skip duplicated PCDs
2103 if Key in self.Module.Pcds or Key in Pcds:
2105 Pcds[Key] = copy.copy(Library.Pcds[Key])
2106 # apply PCD settings from platform
2107 self._LibraryPcdList = self.PlatformInfo.ApplyPcdSetting(self.Module, Pcds)
2109 self._LibraryPcdList = []
2110 return self._LibraryPcdList
2112 ## Get the GUID value mapping
2114 # @retval dict The mapping between GUID cname and its value
2116 def _GetGuidList(self):
2117 if self._GuidList == None:
2118 self._GuidList = self.Module.Guids
2119 for Library in self.DependentLibraryList:
2120 self._GuidList.update(Library.Guids)
2121 return self._GuidList
2123 ## Get the protocol value mapping
2125 # @retval dict The mapping between protocol cname and its value
2127 def _GetProtocolList(self):
2128 if self._ProtocolList == None:
2129 self._ProtocolList = self.Module.Protocols
2130 for Library in self.DependentLibraryList:
2131 self._ProtocolList.update(Library.Protocols)
2132 return self._ProtocolList
2134 ## Get the PPI value mapping
2136 # @retval dict The mapping between PPI cname and its value
2138 def _GetPpiList(self):
2139 if self._PpiList == None:
2140 self._PpiList = self.Module.Ppis
2141 for Library in self.DependentLibraryList:
2142 self._PpiList.update(Library.Ppis)
2143 return self._PpiList
2145 ## Get the list of include search path
2147 # @retval list The list path
2149 def _GetIncludePathList(self):
2150 if self._IncludePathList == None:
2151 self._IncludePathList = []
2152 if self.AutoGenVersion < 0x00010005:
2153 for Inc in self.Module.Includes:
2154 if Inc not in self._IncludePathList:
2155 self._IncludePathList.append(Inc)
2157 Inc = path.join(Inc, self.Arch.capitalize())
2158 if os.path.exists(Inc) and Inc not in self._IncludePathList:
2159 self._IncludePathList.append(Inc)
2160 # r8 module needs to put DEBUG_DIR at the end of search path and not to use SOURCE_DIR all the time
2161 self._IncludePathList.append(self.DebugDir)
2163 self._IncludePathList.append(self.MetaFile.Dir)
2164 self._IncludePathList.append(self.DebugDir)
2166 for Package in self.Module.Packages:
2167 PackageDir = path.join(self.WorkspaceDir, Package.MetaFile.Dir)
2168 if PackageDir not in self._IncludePathList:
2169 self._IncludePathList.append(PackageDir)
2170 for Inc in Package.Includes:
2171 if Inc not in self._IncludePathList:
2172 self._IncludePathList.append(str(Inc))
2173 return self._IncludePathList
2175 ## Create makefile for the module and its dependent libraries
2177 # @param CreateLibraryMakeFile Flag indicating if or not the makefiles of
2178 # dependent libraries will be created
2180 def CreateMakeFile(self, CreateLibraryMakeFile=True):
2181 if self.IsMakeFileCreated:
2184 if not self.IsLibrary and CreateLibraryMakeFile:
2185 for LibraryAutoGen in self.LibraryAutoGenList:
2186 LibraryAutoGen.CreateMakeFile()
2188 if len(self.CustomMakefile) == 0:
2189 Makefile = GenMake.ModuleMakefile(self)
2191 Makefile = GenMake.CustomMakefile(self)
2192 if Makefile.Generate():
2193 EdkLogger.debug(EdkLogger.DEBUG_9, "Generated makefile for module %s [%s]" %
2194 (self.Name, self.Arch))
2196 EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of makefile for module %s [%s]" %
2197 (self.Name, self.Arch))
2199 self.IsMakeFileCreated = True
2201 ## Create autogen code for the module and its dependent libraries
2203 # @param CreateLibraryCodeFile Flag indicating if or not the code of
2204 # dependent libraries will be created
2206 def CreateCodeFile(self, CreateLibraryCodeFile=True):
2207 if self.IsCodeFileCreated:
2210 if not self.IsLibrary and CreateLibraryCodeFile:
2211 for LibraryAutoGen in self.LibraryAutoGenList:
2212 LibraryAutoGen.CreateCodeFile()
2215 IgoredAutoGenList = []
2217 for File in self.AutoGenFileList:
2218 if GenC.Generate(File.Path, self.AutoGenFileList[File], File.IsBinary):
2219 #Ignore R8 AutoGen.c
2220 if self.AutoGenVersion < 0x00010005 and File.Name == 'AutoGen.c':
2223 AutoGenList.append(str(File))
2225 IgoredAutoGenList.append(str(File))
2227 # Skip the following code for EDK I inf
2228 if self.AutoGenVersion < 0x00010005:
2231 for ModuleType in self.DepexList:
2232 if len(self.DepexList[ModuleType]) == 0:
2234 Dpx = GenDepex.DependencyExpression(self.DepexList[ModuleType], ModuleType, True)
2235 DpxFile = gAutoGenDepexFileName % {"module_name" : self.Name}
2237 if Dpx.Generate(path.join(self.OutputDir, DpxFile)):
2238 AutoGenList.append(str(DpxFile))
2240 IgoredAutoGenList.append(str(DpxFile))
2242 if IgoredAutoGenList == []:
2243 EdkLogger.debug(EdkLogger.DEBUG_9, "Generated [%s] files for module %s [%s]" %
2244 (" ".join(AutoGenList), self.Name, self.Arch))
2245 elif AutoGenList == []:
2246 EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of [%s] files for module %s [%s]" %
2247 (" ".join(IgoredAutoGenList), self.Name, self.Arch))
2249 EdkLogger.debug(EdkLogger.DEBUG_9, "Generated [%s] (skipped %s) files for module %s [%s]" %
2250 (" ".join(AutoGenList), " ".join(IgoredAutoGenList), self.Name, self.Arch))
2252 self.IsCodeFileCreated = True
2255 ## Summarize the ModuleAutoGen objects of all libraries used by this module
2256 def _GetLibraryAutoGenList(self):
2257 if self._LibraryAutoGenList == None:
2258 self._LibraryAutoGenList = []
2259 for Library in self.DependentLibraryList:
2266 self.PlatformInfo.MetaFile
2268 if La not in self._LibraryAutoGenList:
2269 self._LibraryAutoGenList.append(La)
2270 for Lib in La.CodaTargetList:
2271 self._ApplyBuildRule(Lib.Target, TAB_UNKNOWN_FILE)
2272 return self._LibraryAutoGenList
2274 ## Return build command string
2276 # @retval string Build command string
2278 def _GetBuildCommand(self):
2279 return self.PlatformInfo.BuildCommand
2282 Module = property(_GetModule)
2283 Name = property(_GetBaseName)
2284 Guid = property(_GetGuid)
2285 Version = property(_GetVersion)
2286 ModuleType = property(_GetModuleType)
2287 ComponentType = property(_GetComponentType)
2288 BuildType = property(_GetBuildType)
2289 PcdIsDriver = property(_GetPcdIsDriver)
2290 AutoGenVersion = property(_GetAutoGenVersion)
2291 Macros = property(_GetMacros)
2292 Specification = property(_GetSpecification)
2294 IsLibrary = property(_IsLibrary)
2296 BuildDir = property(_GetBuildDir)
2297 OutputDir = property(_GetOutputDir)
2298 DebugDir = property(_GetDebugDir)
2299 MakeFileDir = property(_GetMakeFileDir)
2300 CustomMakefile = property(_GetCustomMakefile)
2302 IncludePathList = property(_GetIncludePathList)
2303 AutoGenFileList = property(_GetAutoGenFileList)
2304 UnicodeFileList = property(_GetUnicodeFileList)
2305 SourceFileList = property(_GetSourceFileList)
2306 BinaryFileList = property(_GetBinaryFiles) # FileType : [File List]
2307 Targets = property(_GetTargets)
2308 IntroTargetList = property(_GetIntroTargetList)
2309 CodaTargetList = property(_GetFinalTargetList)
2310 FileTypes = property(_GetFileTypes)
2311 BuildRules = property(_GetBuildRules)
2313 DependentPackageList = property(_GetDependentPackageList)
2314 DependentLibraryList = property(_GetLibraryList)
2315 LibraryAutoGenList = property(_GetLibraryAutoGenList)
2316 DerivedPackageList = property(_GetDerivedPackageList)
2318 ModulePcdList = property(_GetModulePcdList)
2319 LibraryPcdList = property(_GetLibraryPcdList)
2320 GuidList = property(_GetGuidList)
2321 ProtocolList = property(_GetProtocolList)
2322 PpiList = property(_GetPpiList)
2323 DepexList = property(_GetDepexTokenList)
2324 DepexExpressionList = property(_GetDepexExpressionTokenList)
2325 BuildOption = property(_GetModuleBuildOption)
2326 BuildCommand = property(_GetBuildCommand)
2328 # This acts like the main() function for the script, unless it is 'import'ed into another script.
2329 if __name__ == '__main__':