2 # Generate AutoGen.h, AutoGen.c and *.depex files
4 # Copyright (c) 2007 - 2011, 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
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 *
37 import Common
.VpdInfoFile
as VpdInfoFile
39 ## Regular expression for splitting Dependency Expression stirng into tokens
40 gDepexTokenPattern
= re
.compile("(\(|\)|\w+| \S+\.inf)")
42 ## Mapping Makefile type
43 gMakeTypeMap
= {"MSFT":"nmake", "GCC":"gmake"}
46 ## Build rule configuration file
47 gBuildRuleFile
= 'Conf/build_rule.txt'
49 ## default file name for AutoGen
50 gAutoGenCodeFileName
= "AutoGen.c"
51 gAutoGenHeaderFileName
= "AutoGen.h"
52 gAutoGenStringFileName
= "%(module_name)sStrDefs.h"
53 gAutoGenStringFormFileName
= "%(module_name)sStrDefs.hpk"
54 gAutoGenDepexFileName
= "%(module_name)s.depex"
57 # Template string to generic AsBuilt INF
59 gAsBuiltInfHeaderString
= TemplateString("""## @file
63 # FILE auto-generated Binary INF
68 INF_VERSION = 0x00010016
69 BASE_NAME = ${module_name}
70 FILE_GUID = ${module_guid}
71 MODULE_TYPE = ${module_module_type}
72 VERSION_STRING = ${module_version_string}${BEGIN}
73 UEFI_SPECIFICATION_VERSION = ${module_uefi_specification_version}${END}${BEGIN}
74 PI_SPECIFICATION_VERSION = ${module_pi_specification_version}${END}
79 [Binaries.${module_arch}]${BEGIN}
86 ## ${flags_item}${END}
89 ## Base class for AutoGen
91 # This class just implements the cache mechanism of AutoGen objects.
93 class AutoGen(object):
94 # database to maintain the objects of xxxAutoGen
95 _CACHE_
= {} # (BuildTarget, ToolChain) : {ARCH : {platform file: AutoGen object}}}
99 # @param Class class object of real AutoGen class
100 # (WorkspaceAutoGen, ModuleAutoGen or PlatformAutoGen)
101 # @param Workspace Workspace directory or WorkspaceAutoGen object
102 # @param MetaFile The path of meta file
103 # @param Target Build target
104 # @param Toolchain Tool chain name
105 # @param Arch Target arch
106 # @param *args The specific class related parameters
107 # @param **kwargs The specific class related dict parameters
109 def __new__(Class
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
110 # check if the object has been created
111 Key
= (Target
, Toolchain
)
112 if Key
not in Class
._CACHE
_ or Arch
not in Class
._CACHE
_[Key
] \
113 or MetaFile
not in Class
._CACHE
_[Key
][Arch
]:
114 AutoGenObject
= super(AutoGen
, Class
).__new
__(Class
)
115 # call real constructor
116 if not AutoGenObject
._Init
(Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
118 if Key
not in Class
._CACHE
_:
119 Class
._CACHE
_[Key
] = {}
120 if Arch
not in Class
._CACHE
_[Key
]:
121 Class
._CACHE
_[Key
][Arch
] = {}
122 Class
._CACHE
_[Key
][Arch
][MetaFile
] = AutoGenObject
124 AutoGenObject
= Class
._CACHE
_[Key
][Arch
][MetaFile
]
130 # The file path of platform file will be used to represent hash value of this object
132 # @retval int Hash value of the file path of platform file
135 return hash(self
.MetaFile
)
139 # The file path of platform file will be used to represent this object
141 # @retval string String of platform file path
144 return str(self
.MetaFile
)
147 def __eq__(self
, Other
):
148 return Other
and self
.MetaFile
== Other
150 ## Workspace AutoGen class
152 # This class is used mainly to control the whole platform build for different
153 # architecture. This class will generate top level makefile.
155 class WorkspaceAutoGen(AutoGen
):
156 ## Real constructor of WorkspaceAutoGen
158 # This method behaves the same as __init__ except that it needs explict invoke
159 # (in super class's __new__ method)
161 # @param WorkspaceDir Root directory of workspace
162 # @param ActivePlatform Meta-file of active platform
163 # @param Target Build target
164 # @param Toolchain Tool chain name
165 # @param ArchList List of architecture of current build
166 # @param MetaFileDb Database containing meta-files
167 # @param BuildConfig Configuration of build
168 # @param ToolDefinition Tool chain definitions
169 # @param FlashDefinitionFile File of flash definition
170 # @param Fds FD list to be generated
171 # @param Fvs FV list to be generated
172 # @param Caps Capsule list to be generated
173 # @param SkuId SKU id from command line
175 def _Init(self
, WorkspaceDir
, ActivePlatform
, Target
, Toolchain
, ArchList
, MetaFileDb
,
176 BuildConfig
, ToolDefinition
, FlashDefinitionFile
='', Fds
=None, Fvs
=None, Caps
=None, SkuId
='', UniFlag
=None):
183 self
.MetaFile
= ActivePlatform
.MetaFile
184 self
.WorkspaceDir
= WorkspaceDir
185 self
.Platform
= ActivePlatform
186 self
.BuildTarget
= Target
187 self
.ToolChain
= Toolchain
188 self
.ArchList
= ArchList
190 self
.UniFlag
= UniFlag
192 self
.BuildDatabase
= MetaFileDb
193 self
.TargetTxt
= BuildConfig
194 self
.ToolDef
= ToolDefinition
195 self
.FdfFile
= FlashDefinitionFile
196 self
.FdTargetList
= Fds
197 self
.FvTargetList
= Fvs
198 self
.CapTargetList
= Caps
199 self
.AutoGenObjectList
= []
201 # there's many relative directory operations, so ...
202 os
.chdir(self
.WorkspaceDir
)
204 # parse FDF file to get PCDs in it, if any
205 if self
.FdfFile
!= None and self
.FdfFile
!= '':
207 # Make global macros available when parsing FDF file
209 InputMacroDict
.update(self
.BuildDatabase
.WorkspaceDb
._GlobalMacros
)
211 # Mark now build in AutoGen Phase
213 GlobalData
.gAutoGenPhase
= True
214 Fdf
= FdfParser(self
.FdfFile
.Path
)
216 GlobalData
.gAutoGenPhase
= False
217 PcdSet
= Fdf
.Profile
.PcdDict
218 ModuleList
= Fdf
.Profile
.InfList
219 self
.FdfProfile
= Fdf
.Profile
223 self
.FdfProfile
= None
225 # apply SKU and inject PCDs from Flash Definition file
226 for Arch
in self
.ArchList
:
227 Platform
= self
.BuildDatabase
[self
.MetaFile
, Arch
]
228 Platform
.SkuName
= self
.SkuId
229 for Name
, Guid
in PcdSet
:
230 Platform
.AddPcd(Name
, Guid
, PcdSet
[Name
, Guid
])
232 Pa
= PlatformAutoGen(self
, self
.MetaFile
, Target
, Toolchain
, Arch
)
234 # Explicitly collect platform's dynamic PCDs
236 Pa
.CollectPlatformDynamicPcds()
237 self
.AutoGenObjectList
.append(Pa
)
240 # Check PCDs token value conflict in each DEC file.
242 self
._CheckAllPcdsTokenValueConflict
()
245 # Check PCD type and definition between DSC and DEC
247 self
._CheckPcdDefineAndType
()
249 self
._BuildDir
= None
251 self
._MakeFileDir
= None
252 self
._BuildCommand
= None
256 def _CheckPcdDefineAndType(self
):
258 "FixedAtBuild", "PatchableInModule", "FeatureFlag",
259 "Dynamic", #"DynamicHii", "DynamicVpd",
260 "DynamicEx", # "DynamicExHii", "DynamicExVpd"
263 # This dict store PCDs which are not used by any modules with specified arches
265 for Pa
in self
.AutoGenObjectList
:
266 # Key of DSC's Pcds dictionary is PcdCName, TokenSpaceGuid
267 for Pcd
in Pa
.Platform
.Pcds
:
268 PcdType
= Pa
.Platform
.Pcds
[Pcd
].Type
270 # If no PCD type, this PCD comes from FDF
274 # Try to remove Hii and Vpd suffix
275 if PcdType
.startswith("DynamicEx"):
276 PcdType
= "DynamicEx"
277 elif PcdType
.startswith("Dynamic"):
280 for Package
in Pa
.PackageList
:
281 # Key of DEC's Pcds dictionary is PcdCName, TokenSpaceGuid, PcdType
282 if (Pcd
[0], Pcd
[1], PcdType
) in Package
.Pcds
:
284 for Type
in PcdTypeList
:
285 if (Pcd
[0], Pcd
[1], Type
) in Package
.Pcds
:
289 "Type [%s] of PCD [%s.%s] in DSC file doesn't match the type [%s] defined in DEC file." \
290 % (Pa
.Platform
.Pcds
[Pcd
].Type
, Pcd
[1], Pcd
[0], Type
),
295 UnusedPcd
.setdefault(Pcd
, []).append(Pa
.Arch
)
297 for Pcd
in UnusedPcd
:
300 "The PCD was not specified by any INF module in the platform for the given architecture.\n"
301 "\tPCD: [%s.%s]\n\tPlatform: [%s]\n\tArch: %s"
302 % (Pcd
[1], Pcd
[0], os
.path
.basename(str(self
.MetaFile
)), str(UnusedPcd
[Pcd
])),
307 return "%s [%s]" % (self
.MetaFile
, ", ".join(self
.ArchList
))
309 ## Return the directory to store FV files
311 if self
._FvDir
== None:
312 self
._FvDir
= path
.join(self
.BuildDir
, 'FV')
315 ## Return the directory to store all intermediate and final files built
316 def _GetBuildDir(self
):
317 return self
.AutoGenObjectList
[0].BuildDir
319 ## Return the build output directory platform specifies
320 def _GetOutputDir(self
):
321 return self
.Platform
.OutputDirectory
323 ## Return platform name
325 return self
.Platform
.PlatformName
327 ## Return meta-file GUID
329 return self
.Platform
.Guid
331 ## Return platform version
332 def _GetVersion(self
):
333 return self
.Platform
.Version
335 ## Return paths of tools
336 def _GetToolDefinition(self
):
337 return self
.AutoGenObjectList
[0].ToolDefinition
339 ## Return directory of platform makefile
341 # @retval string Makefile directory
343 def _GetMakeFileDir(self
):
344 if self
._MakeFileDir
== None:
345 self
._MakeFileDir
= self
.BuildDir
346 return self
._MakeFileDir
348 ## Return build command string
350 # @retval string Build command string
352 def _GetBuildCommand(self
):
353 if self
._BuildCommand
== None:
354 # BuildCommand should be all the same. So just get one from platform AutoGen
355 self
._BuildCommand
= self
.AutoGenObjectList
[0].BuildCommand
356 return self
._BuildCommand
358 ## Check the PCDs token value conflict in each DEC file.
360 # Will cause build break and raise error message while two PCDs conflict.
364 def _CheckAllPcdsTokenValueConflict(self
):
365 for Pa
in self
.AutoGenObjectList
:
366 for Package
in Pa
.PackageList
:
367 PcdList
= Package
.Pcds
.values()
368 PcdList
.sort(lambda x
, y
: cmp(x
.TokenValue
, y
.TokenValue
))
370 while (Count
< len(PcdList
) - 1) :
371 Item
= PcdList
[Count
]
372 ItemNext
= PcdList
[Count
+ 1]
374 # Make sure in the same token space the TokenValue should be unique
376 if (Item
.TokenValue
== ItemNext
.TokenValue
):
377 SameTokenValuePcdList
= []
378 SameTokenValuePcdList
.append(Item
)
379 SameTokenValuePcdList
.append(ItemNext
)
380 RemainPcdListLength
= len(PcdList
) - Count
- 2
381 for ValueSameCount
in range(RemainPcdListLength
):
382 if PcdList
[len(PcdList
) - RemainPcdListLength
+ ValueSameCount
].TokenValue
== Item
.TokenValue
:
383 SameTokenValuePcdList
.append(PcdList
[len(PcdList
) - RemainPcdListLength
+ ValueSameCount
])
387 # Sort same token value PCD list with TokenGuid and TokenCName
389 SameTokenValuePcdList
.sort(lambda x
, y
: cmp("%s.%s"%(x
.TokenSpaceGuidCName
, x
.TokenCName
), "%s.%s"%(y
.TokenSpaceGuidCName
, y
.TokenCName
)))
390 SameTokenValuePcdListCount
= 0
391 while (SameTokenValuePcdListCount
< len(SameTokenValuePcdList
) - 1):
392 TemListItem
= SameTokenValuePcdList
[SameTokenValuePcdListCount
]
393 TemListItemNext
= SameTokenValuePcdList
[SameTokenValuePcdListCount
+ 1]
395 if (TemListItem
.TokenSpaceGuidCName
== TemListItemNext
.TokenSpaceGuidCName
) and (TemListItem
.TokenCName
!= TemListItemNext
.TokenCName
):
399 "The TokenValue [%s] of PCD [%s.%s] is conflict with: [%s.%s] in %s"\
400 % (TemListItem
.TokenValue
, TemListItem
.TokenSpaceGuidCName
, TemListItem
.TokenCName
, TemListItemNext
.TokenSpaceGuidCName
, TemListItemNext
.TokenCName
, Package
),
403 SameTokenValuePcdListCount
+= 1
404 Count
+= SameTokenValuePcdListCount
407 PcdList
= Package
.Pcds
.values()
408 PcdList
.sort(lambda x
, y
: cmp("%s.%s"%(x
.TokenSpaceGuidCName
, x
.TokenCName
), "%s.%s"%(y
.TokenSpaceGuidCName
, y
.TokenCName
)))
410 while (Count
< len(PcdList
) - 1) :
411 Item
= PcdList
[Count
]
412 ItemNext
= PcdList
[Count
+ 1]
414 # Check PCDs with same TokenSpaceGuidCName.TokenCName have same token value as well.
416 if (Item
.TokenSpaceGuidCName
== ItemNext
.TokenSpaceGuidCName
) and (Item
.TokenCName
== ItemNext
.TokenCName
) and (Item
.TokenValue
!= ItemNext
.TokenValue
):
420 "The TokenValue [%s] of PCD [%s.%s] in %s defined in two places should be same as well."\
421 % (Item
.TokenValue
, Item
.TokenSpaceGuidCName
, Item
.TokenCName
, Package
),
427 ## Create makefile for the platform and modules in it
429 # @param CreateDepsMakeFile Flag indicating if the makefile for
430 # modules will be created as well
432 def CreateMakeFile(self
, CreateDepsMakeFile
=False):
433 # create makefile for platform
434 Makefile
= GenMake
.TopLevelMakefile(self
)
435 if Makefile
.Generate():
436 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated makefile for platform [%s] %s\n" %
437 (self
.MetaFile
, self
.ArchList
))
439 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Skipped the generation of makefile for platform [%s] %s\n" %
440 (self
.MetaFile
, self
.ArchList
))
442 if CreateDepsMakeFile
:
443 for Pa
in self
.AutoGenObjectList
:
444 Pa
.CreateMakeFile(CreateDepsMakeFile
)
446 ## Create autogen code for platform and modules
448 # Since there's no autogen code for platform, this method will do nothing
449 # if CreateModuleCodeFile is set to False.
451 # @param CreateDepsCodeFile Flag indicating if creating module's
452 # autogen code file or not
454 def CreateCodeFile(self
, CreateDepsCodeFile
=False):
455 if not CreateDepsCodeFile
:
457 for Pa
in self
.AutoGenObjectList
:
458 Pa
.CreateCodeFile(CreateDepsCodeFile
)
460 ## Create AsBuilt INF file the platform
462 def CreateAsBuiltInf(self
):
465 Name
= property(_GetName
)
466 Guid
= property(_GetGuid
)
467 Version
= property(_GetVersion
)
468 OutputDir
= property(_GetOutputDir
)
470 ToolDefinition
= property(_GetToolDefinition
) # toolcode : tool path
472 BuildDir
= property(_GetBuildDir
)
473 FvDir
= property(_GetFvDir
)
474 MakeFileDir
= property(_GetMakeFileDir
)
475 BuildCommand
= property(_GetBuildCommand
)
477 ## AutoGen class for platform
479 # PlatformAutoGen class will process the original information in platform
480 # file in order to generate makefile for platform.
482 class PlatformAutoGen(AutoGen
):
484 # Used to store all PCDs for both PEI and DXE phase, in order to generate
485 # correct PCD database
488 _NonDynaPcdList_
= []
491 # The priority list while override build option
493 PrioList
= {"0x11111" : 16, # TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE (Highest)
494 "0x01111" : 15, # ******_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
495 "0x10111" : 14, # TARGET_*********_ARCH_COMMANDTYPE_ATTRIBUTE
496 "0x00111" : 13, # ******_*********_ARCH_COMMANDTYPE_ATTRIBUTE
497 "0x11011" : 12, # TARGET_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
498 "0x01011" : 11, # ******_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
499 "0x10011" : 10, # TARGET_*********_****_COMMANDTYPE_ATTRIBUTE
500 "0x00011" : 9, # ******_*********_****_COMMANDTYPE_ATTRIBUTE
501 "0x11101" : 8, # TARGET_TOOLCHAIN_ARCH_***********_ATTRIBUTE
502 "0x01101" : 7, # ******_TOOLCHAIN_ARCH_***********_ATTRIBUTE
503 "0x10101" : 6, # TARGET_*********_ARCH_***********_ATTRIBUTE
504 "0x00101" : 5, # ******_*********_ARCH_***********_ATTRIBUTE
505 "0x11001" : 4, # TARGET_TOOLCHAIN_****_***********_ATTRIBUTE
506 "0x01001" : 3, # ******_TOOLCHAIN_****_***********_ATTRIBUTE
507 "0x10001" : 2, # TARGET_*********_****_***********_ATTRIBUTE
508 "0x00001" : 1} # ******_*********_****_***********_ATTRIBUTE (Lowest)
510 ## The real constructor of PlatformAutoGen
512 # This method is not supposed to be called by users of PlatformAutoGen. It's
513 # only used by factory method __new__() to do real initialization work for an
514 # object of PlatformAutoGen
516 # @param Workspace WorkspaceAutoGen object
517 # @param PlatformFile Platform file (DSC file)
518 # @param Target Build target (DEBUG, RELEASE)
519 # @param Toolchain Name of tool chain
520 # @param Arch arch of the platform supports
522 def _Init(self
, Workspace
, PlatformFile
, Target
, Toolchain
, Arch
):
523 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "AutoGen platform [%s] [%s]" % (PlatformFile
, Arch
))
524 GlobalData
.gProcessingFile
= "%s [%s, %s, %s]" % (PlatformFile
, Arch
, Toolchain
, Target
)
526 self
.MetaFile
= PlatformFile
527 self
.Workspace
= Workspace
528 self
.WorkspaceDir
= Workspace
.WorkspaceDir
529 self
.ToolChain
= Toolchain
530 self
.BuildTarget
= Target
532 self
.SourceDir
= PlatformFile
.SubDir
533 self
.SourceOverrideDir
= None
534 self
.FdTargetList
= self
.Workspace
.FdTargetList
535 self
.FvTargetList
= self
.Workspace
.FvTargetList
538 # flag indicating if the makefile/C-code file has been created or not
539 self
.IsMakeFileCreated
= False
540 self
.IsCodeFileCreated
= False
542 self
._Platform
= None
547 self
._BuildRule
= None
548 self
._SourceDir
= None
549 self
._BuildDir
= None
550 self
._OutputDir
= None
552 self
._MakeFileDir
= None
555 self
._PcdTokenNumber
= None # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber
556 self
._DynamicPcdList
= None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
557 self
._NonDynamicPcdList
= None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
559 self
._ToolDefinitions
= None
560 self
._ToolDefFile
= None # toolcode : tool path
561 self
._ToolChainFamily
= None
562 self
._BuildRuleFamily
= None
563 self
._BuildOption
= None # toolcode : option
564 self
._EdkBuildOption
= None # edktoolcode : option
565 self
._EdkIIBuildOption
= None # edkiitoolcode : option
566 self
._PackageList
= None
567 self
._ModuleAutoGenList
= None
568 self
._LibraryAutoGenList
= None
569 self
._BuildCommand
= None
571 # get the original module/package/platform objects
572 self
.BuildDatabase
= Workspace
.BuildDatabase
576 return "%s [%s]" % (self
.MetaFile
, self
.Arch
)
578 ## Create autogen code for platform and modules
580 # Since there's no autogen code for platform, this method will do nothing
581 # if CreateModuleCodeFile is set to False.
583 # @param CreateModuleCodeFile Flag indicating if creating module's
584 # autogen code file or not
586 def CreateCodeFile(self
, CreateModuleCodeFile
=False):
587 # only module has code to be greated, so do nothing if CreateModuleCodeFile is False
588 if self
.IsCodeFileCreated
or not CreateModuleCodeFile
:
591 for Ma
in self
.ModuleAutoGenList
:
592 Ma
.CreateCodeFile(True)
594 # don't do this twice
595 self
.IsCodeFileCreated
= True
597 ## Create makefile for the platform and mdoules in it
599 # @param CreateModuleMakeFile Flag indicating if the makefile for
600 # modules will be created as well
602 def CreateMakeFile(self
, CreateModuleMakeFile
=False):
603 if CreateModuleMakeFile
:
604 for ModuleFile
in self
.Platform
.Modules
:
605 Ma
= ModuleAutoGen(self
.Workspace
, ModuleFile
, self
.BuildTarget
,
606 self
.ToolChain
, self
.Arch
, self
.MetaFile
)
607 Ma
.CreateMakeFile(True)
608 Ma
.CreateAsBuiltInf()
610 # no need to create makefile for the platform more than once
611 if self
.IsMakeFileCreated
:
614 # create makefile for platform
615 Makefile
= GenMake
.PlatformMakefile(self
)
616 if Makefile
.Generate():
617 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated makefile for platform [%s] [%s]\n" %
618 (self
.MetaFile
, self
.Arch
))
620 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Skipped the generation of makefile for platform [%s] [%s]\n" %
621 (self
.MetaFile
, self
.Arch
))
622 self
.IsMakeFileCreated
= True
624 ## Collect dynamic PCDs
626 # Gather dynamic PCDs list from each module and their settings from platform
627 # This interface should be invoked explicitly when platform action is created.
629 def CollectPlatformDynamicPcds(self
):
630 # for gathering error information
631 NoDatumTypePcdList
= set()
634 for F
in self
.Platform
.Modules
.keys():
635 M
= ModuleAutoGen(self
.Workspace
, F
, self
.BuildTarget
, self
.ToolChain
, self
.Arch
, self
.MetaFile
)
636 #GuidValue.update(M.Guids)
638 self
.Platform
.Modules
[F
].M
= M
640 for PcdFromModule
in M
.ModulePcdList
+M
.LibraryPcdList
:
641 # make sure that the "VOID*" kind of datum has MaxDatumSize set
642 if PcdFromModule
.DatumType
== "VOID*" and PcdFromModule
.MaxDatumSize
== None:
643 NoDatumTypePcdList
.add("%s.%s [%s]" % (PcdFromModule
.TokenSpaceGuidCName
, PcdFromModule
.TokenCName
, F
))
645 if PcdFromModule
.Type
in GenC
.gDynamicPcd
or PcdFromModule
.Type
in GenC
.gDynamicExPcd
:
647 # If a dynamic PCD used by a PEM module/PEI module & DXE module,
648 # it should be stored in Pcd PEI database, If a dynamic only
649 # used by DXE module, it should be stored in DXE PCD database.
650 # The default Phase is DXE
652 if M
.ModuleType
in ["PEIM", "PEI_CORE"]:
653 PcdFromModule
.Phase
= "PEI"
654 if PcdFromModule
not in self
._DynaPcdList
_:
655 self
._DynaPcdList
_.append(PcdFromModule
)
656 elif PcdFromModule
.Phase
== 'PEI':
657 # overwrite any the same PCD existing, if Phase is PEI
658 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
659 self
._DynaPcdList
_[Index
] = PcdFromModule
660 elif PcdFromModule
not in self
._NonDynaPcdList
_:
661 self
._NonDynaPcdList
_.append(PcdFromModule
)
663 # print out error information and break the build, if error found
664 if len(NoDatumTypePcdList
) > 0:
665 NoDatumTypePcdListString
= "\n\t\t".join(NoDatumTypePcdList
)
666 EdkLogger
.error("build", AUTOGEN_ERROR
, "PCD setting error",
668 ExtraData
="\n\tPCD(s) without MaxDatumSize:\n\t\t%s\n"
669 % NoDatumTypePcdListString
)
670 self
._NonDynamicPcdList
= self
._NonDynaPcdList
_
671 self
._DynamicPcdList
= self
._DynaPcdList
_
672 self
.AllPcdList
= self
._NonDynamicPcdList
+ self
._DynamicPcdList
675 # Sort dynamic PCD list to:
676 # 1) If PCD's datum type is VOID* and value is unicode string which starts with L, the PCD item should
677 # try to be put header of dynamicd List
678 # 2) If PCD is HII type, the PCD item should be put after unicode type PCD
680 # The reason of sorting is make sure the unicode string is in double-byte alignment in string table.
686 VpdFile
= VpdInfoFile
.VpdInfoFile()
687 NeedProcessVpdMapFile
= False
689 if (self
.Workspace
.ArchList
[-1] == self
.Arch
):
690 for Pcd
in self
._DynamicPcdList
:
691 # just pick the a value to determine whether is unicode string type
692 Sku
= Pcd
.SkuInfoList
[Pcd
.SkuInfoList
.keys()[0]]
693 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
695 PcdValue
= Sku
.DefaultValue
696 if Pcd
.DatumType
== 'VOID*' and PcdValue
.startswith("L"):
697 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
698 UnicodePcdArray
.append(Pcd
)
699 elif len(Sku
.VariableName
) > 0:
700 # if found HII type PCD then insert to right of UnicodeIndex
701 HiiPcdArray
.append(Pcd
)
703 OtherPcdArray
.append(Pcd
)
704 if Pcd
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
]:
705 VpdPcdDict
[(Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
)] = Pcd
707 PlatformPcds
= self
.Platform
.Pcds
.keys()
710 # Add VPD type PCD into VpdFile and determine whether the VPD PCD need to be fixed up.
712 for PcdKey
in PlatformPcds
:
713 Pcd
= self
.Platform
.Pcds
[PcdKey
]
714 if Pcd
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
]:
715 Pcd
= VpdPcdDict
[PcdKey
]
716 Sku
= Pcd
.SkuInfoList
[Pcd
.SkuInfoList
.keys()[0]]
717 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
719 # Fix the optional data of VPD PCD.
721 if (Pcd
.DatumType
.strip() != "VOID*"):
722 if Sku
.DefaultValue
== '':
723 Pcd
.SkuInfoList
[Pcd
.SkuInfoList
.keys()[0]].DefaultValue
= Pcd
.MaxDatumSize
724 Pcd
.MaxDatumSize
= None
726 EdkLogger
.error("build", AUTOGEN_ERROR
, "PCD setting error",
728 ExtraData
="\n\tPCD: %s.%s format incorrect in DSC: %s\n\t\t\n"
729 % (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
, self
.Platform
.MetaFile
.Path
))
731 VpdFile
.Add(Pcd
, Sku
.VpdOffset
)
732 # if the offset of a VPD is *, then it need to be fixed up by third party tool.
733 if not NeedProcessVpdMapFile
and Sku
.VpdOffset
== "*":
734 NeedProcessVpdMapFile
= True
735 if self
.Platform
.VpdToolGuid
== None or self
.Platform
.VpdToolGuid
== '':
736 EdkLogger
.error("Build", FILE_NOT_FOUND
, \
737 "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.")
741 # Fix the PCDs define in VPD PCD section that never referenced by module.
742 # An example is PCD for signature usage.
744 for DscPcd
in PlatformPcds
:
745 DscPcdEntry
= self
.Platform
.Pcds
[DscPcd
]
746 if DscPcdEntry
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
]:
747 if not (self
.Platform
.VpdToolGuid
== None or self
.Platform
.VpdToolGuid
== ''):
749 for VpdPcd
in VpdFile
._VpdArray
.keys():
750 # This PCD has been referenced by module
751 if (VpdPcd
.TokenSpaceGuidCName
== DscPcdEntry
.TokenSpaceGuidCName
) and \
752 (VpdPcd
.TokenCName
== DscPcdEntry
.TokenCName
):
755 # Not found, it should be signature
757 # just pick the a value to determine whether is unicode string type
758 Sku
= DscPcdEntry
.SkuInfoList
[DscPcdEntry
.SkuInfoList
.keys()[0]]
759 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
761 # Need to iterate DEC pcd information to get the value & datumtype
762 for eachDec
in self
.PackageList
:
763 for DecPcd
in eachDec
.Pcds
:
764 DecPcdEntry
= eachDec
.Pcds
[DecPcd
]
765 if (DecPcdEntry
.TokenSpaceGuidCName
== DscPcdEntry
.TokenSpaceGuidCName
) and \
766 (DecPcdEntry
.TokenCName
== DscPcdEntry
.TokenCName
):
767 # Print warning message to let the developer make a determine.
768 EdkLogger
.warn("build", "Unreferenced vpd pcd used!",
769 File
=self
.MetaFile
, \
770 ExtraData
= "PCD: %s.%s used in the DSC file %s is unreferenced." \
771 %(DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
, self
.Platform
.MetaFile
.Path
))
773 DscPcdEntry
.DatumType
= DecPcdEntry
.DatumType
774 DscPcdEntry
.DefaultValue
= DecPcdEntry
.DefaultValue
775 # Only fix the value while no value provided in DSC file.
776 if (Sku
.DefaultValue
== "" or Sku
.DefaultValue
==None):
777 DscPcdEntry
.SkuInfoList
[DscPcdEntry
.SkuInfoList
.keys()[0]].DefaultValue
= DecPcdEntry
.DefaultValue
780 VpdFile
.Add(DscPcdEntry
, Sku
.VpdOffset
)
781 # if the offset of a VPD is *, then it need to be fixed up by third party tool.
782 if not NeedProcessVpdMapFile
and Sku
.VpdOffset
== "*":
783 NeedProcessVpdMapFile
= True
786 if (self
.Platform
.FlashDefinition
== None or self
.Platform
.FlashDefinition
== '') and \
787 VpdFile
.GetCount() != 0:
788 EdkLogger
.error("build", ATTRIBUTE_NOT_AVAILABLE
,
789 "Fail to get FLASH_DEFINITION definition in DSC file %s which is required when DSC contains VPD PCD." % str(self
.Platform
.MetaFile
))
791 if VpdFile
.GetCount() != 0:
792 WorkspaceDb
= self
.BuildDatabase
.WorkspaceDb
793 DscTimeStamp
= WorkspaceDb
.GetTimeStamp(WorkspaceDb
.GetFileId(str(self
.Platform
.MetaFile
)))
794 FvPath
= os
.path
.join(self
.BuildDir
, "FV")
795 if not os
.path
.exists(FvPath
):
799 EdkLogger
.error("build", FILE_WRITE_FAILURE
, "Fail to create FV folder under %s" % self
.BuildDir
)
802 VpdFilePath
= os
.path
.join(FvPath
, "%s.txt" % self
.Platform
.VpdToolGuid
)
805 if not os
.path
.exists(VpdFilePath
) or os
.path
.getmtime(VpdFilePath
) < DscTimeStamp
:
806 VpdFile
.Write(VpdFilePath
)
808 # retrieve BPDG tool's path from tool_def.txt according to VPD_TOOL_GUID defined in DSC file.
810 for ToolDef
in self
.ToolDefinition
.values():
811 if ToolDef
.has_key("GUID") and ToolDef
["GUID"] == self
.Platform
.VpdToolGuid
:
812 if not ToolDef
.has_key("PATH"):
813 EdkLogger
.error("build", ATTRIBUTE_NOT_AVAILABLE
, "PATH attribute was not provided for BPDG guid tool %s in tools_def.txt" % self
.Platform
.VpdToolGuid
)
814 BPDGToolName
= ToolDef
["PATH"]
816 # Call third party GUID BPDG tool.
817 if BPDGToolName
!= None:
818 VpdInfoFile
.CallExtenalBPDGTool(BPDGToolName
, VpdFilePath
)
820 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.")
822 # Process VPD map file generated by third party BPDG tool
823 if NeedProcessVpdMapFile
:
824 VpdMapFilePath
= os
.path
.join(self
.BuildDir
, "FV", "%s.map" % self
.Platform
.VpdToolGuid
)
825 if os
.path
.exists(VpdMapFilePath
):
826 VpdFile
.Read(VpdMapFilePath
)
829 for Pcd
in self
._DynamicPcdList
:
830 # just pick the a value to determine whether is unicode string type
831 Sku
= Pcd
.SkuInfoList
[Pcd
.SkuInfoList
.keys()[0]]
832 if Sku
.VpdOffset
== "*":
833 Sku
.VpdOffset
= VpdFile
.GetOffset(Pcd
)[0]
835 EdkLogger
.error("build", FILE_READ_FAILURE
, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath
)
837 # Delete the DynamicPcdList At the last time enter into this function
838 del self
._DynamicPcdList
[:]
839 self
._DynamicPcdList
.extend(UnicodePcdArray
)
840 self
._DynamicPcdList
.extend(HiiPcdArray
)
841 self
._DynamicPcdList
.extend(OtherPcdArray
)
844 ## Return the platform build data object
845 def _GetPlatform(self
):
846 if self
._Platform
== None:
847 self
._Platform
= self
.BuildDatabase
[self
.MetaFile
, self
.Arch
]
848 return self
._Platform
850 ## Return platform name
852 return self
.Platform
.PlatformName
854 ## Return the meta file GUID
856 return self
.Platform
.Guid
858 ## Return the platform version
859 def _GetVersion(self
):
860 return self
.Platform
.Version
862 ## Return the FDF file name
863 def _GetFdfFile(self
):
864 if self
._FdfFile
== None:
865 if self
.Workspace
.FdfFile
!= "":
866 self
._FdfFile
= path
.join(self
.WorkspaceDir
, self
.Workspace
.FdfFile
)
871 ## Return the build output directory platform specifies
872 def _GetOutputDir(self
):
873 return self
.Platform
.OutputDirectory
875 ## Return the directory to store all intermediate and final files built
876 def _GetBuildDir(self
):
877 if self
._BuildDir
== None:
878 if os
.path
.isabs(self
.OutputDir
):
879 self
._BuildDir
= path
.join(
880 path
.abspath(self
.OutputDir
),
881 self
.BuildTarget
+ "_" + self
.ToolChain
,
884 self
._BuildDir
= path
.join(
887 self
.BuildTarget
+ "_" + self
.ToolChain
,
889 return self
._BuildDir
891 ## Return directory of platform makefile
893 # @retval string Makefile directory
895 def _GetMakeFileDir(self
):
896 if self
._MakeFileDir
== None:
897 self
._MakeFileDir
= path
.join(self
.BuildDir
, self
.Arch
)
898 return self
._MakeFileDir
900 ## Return build command string
902 # @retval string Build command string
904 def _GetBuildCommand(self
):
905 if self
._BuildCommand
== None:
906 self
._BuildCommand
= []
907 if "MAKE" in self
.ToolDefinition
and "PATH" in self
.ToolDefinition
["MAKE"]:
908 self
._BuildCommand
+= SplitOption(self
.ToolDefinition
["MAKE"]["PATH"])
909 if "FLAGS" in self
.ToolDefinition
["MAKE"]:
910 NewOption
= self
.ToolDefinition
["MAKE"]["FLAGS"].strip()
912 self
._BuildCommand
+= SplitOption(NewOption
)
913 return self
._BuildCommand
915 ## Get tool chain definition
917 # Get each tool defition for given tool chain from tools_def.txt and platform
919 def _GetToolDefinition(self
):
920 if self
._ToolDefinitions
== None:
921 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDictionary
922 if TAB_TOD_DEFINES_COMMAND_TYPE
not in self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
:
923 EdkLogger
.error('build', RESOURCE_NOT_AVAILABLE
, "No tools found in configuration",
924 ExtraData
="[%s]" % self
.MetaFile
)
925 self
._ToolDefinitions
= {}
927 for Def
in ToolDefinition
:
928 Target
, Tag
, Arch
, Tool
, Attr
= Def
.split("_")
929 if Target
!= self
.BuildTarget
or Tag
!= self
.ToolChain
or Arch
!= self
.Arch
:
932 Value
= ToolDefinition
[Def
]
933 # don't record the DLL
935 DllPathList
.add(Value
)
938 if Tool
not in self
._ToolDefinitions
:
939 self
._ToolDefinitions
[Tool
] = {}
940 self
._ToolDefinitions
[Tool
][Attr
] = Value
944 if GlobalData
.gOptions
.SilentMode
and "MAKE" in self
._ToolDefinitions
:
945 if "FLAGS" not in self
._ToolDefinitions
["MAKE"]:
946 self
._ToolDefinitions
["MAKE"]["FLAGS"] = ""
947 self
._ToolDefinitions
["MAKE"]["FLAGS"] += " -s"
949 for Tool
in self
._ToolDefinitions
:
950 for Attr
in self
._ToolDefinitions
[Tool
]:
951 Value
= self
._ToolDefinitions
[Tool
][Attr
]
952 if Tool
in self
.BuildOption
and Attr
in self
.BuildOption
[Tool
]:
953 # check if override is indicated
954 if self
.BuildOption
[Tool
][Attr
].startswith('='):
955 Value
= self
.BuildOption
[Tool
][Attr
][1:]
957 Value
+= " " + self
.BuildOption
[Tool
][Attr
]
960 # Don't put MAKE definition in the file
964 ToolsDef
+= "%s = %s\n" % (Tool
, Value
)
966 # Don't put MAKE definition in the file
971 ToolsDef
+= "%s_%s = %s\n" % (Tool
, Attr
, Value
)
974 SaveFileOnChange(self
.ToolDefinitionFile
, ToolsDef
)
975 for DllPath
in DllPathList
:
976 os
.environ
["PATH"] = DllPath
+ os
.pathsep
+ os
.environ
["PATH"]
977 os
.environ
["MAKE_FLAGS"] = MakeFlags
979 return self
._ToolDefinitions
981 ## Return the paths of tools
982 def _GetToolDefFile(self
):
983 if self
._ToolDefFile
== None:
984 self
._ToolDefFile
= os
.path
.join(self
.MakeFileDir
, "TOOLS_DEF." + self
.Arch
)
985 return self
._ToolDefFile
987 ## Retrieve the toolchain family of given toolchain tag. Default to 'MSFT'.
988 def _GetToolChainFamily(self
):
989 if self
._ToolChainFamily
== None:
990 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
991 if TAB_TOD_DEFINES_FAMILY
not in ToolDefinition \
992 or self
.ToolChain
not in ToolDefinition
[TAB_TOD_DEFINES_FAMILY
] \
993 or not ToolDefinition
[TAB_TOD_DEFINES_FAMILY
][self
.ToolChain
]:
994 EdkLogger
.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
996 self
._ToolChainFamily
= "MSFT"
998 self
._ToolChainFamily
= ToolDefinition
[TAB_TOD_DEFINES_FAMILY
][self
.ToolChain
]
999 return self
._ToolChainFamily
1001 def _GetBuildRuleFamily(self
):
1002 if self
._BuildRuleFamily
== None:
1003 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
1004 if TAB_TOD_DEFINES_BUILDRULEFAMILY
not in ToolDefinition \
1005 or self
.ToolChain
not in ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
] \
1006 or not ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
][self
.ToolChain
]:
1007 EdkLogger
.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
1009 self
._BuildRuleFamily
= "MSFT"
1011 self
._BuildRuleFamily
= ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
][self
.ToolChain
]
1012 return self
._BuildRuleFamily
1014 ## Return the build options specific for all modules in this platform
1015 def _GetBuildOptions(self
):
1016 if self
._BuildOption
== None:
1017 self
._BuildOption
= self
._ExpandBuildOption
(self
.Platform
.BuildOptions
)
1018 return self
._BuildOption
1020 ## Return the build options specific for EDK modules in this platform
1021 def _GetEdkBuildOptions(self
):
1022 if self
._EdkBuildOption
== None:
1023 self
._EdkBuildOption
= self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, EDK_NAME
)
1024 return self
._EdkBuildOption
1026 ## Return the build options specific for EDKII modules in this platform
1027 def _GetEdkIIBuildOptions(self
):
1028 if self
._EdkIIBuildOption
== None:
1029 self
._EdkIIBuildOption
= self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, EDKII_NAME
)
1030 return self
._EdkIIBuildOption
1032 ## Parse build_rule.txt in $(WORKSPACE)/Conf/build_rule.txt
1034 # @retval BuildRule object
1036 def _GetBuildRule(self
):
1037 if self
._BuildRule
== None:
1038 BuildRuleFile
= None
1039 if TAB_TAT_DEFINES_BUILD_RULE_CONF
in self
.Workspace
.TargetTxt
.TargetTxtDictionary
:
1040 BuildRuleFile
= self
.Workspace
.TargetTxt
.TargetTxtDictionary
[TAB_TAT_DEFINES_BUILD_RULE_CONF
]
1041 if BuildRuleFile
in [None, '']:
1042 BuildRuleFile
= gBuildRuleFile
1043 self
._BuildRule
= BuildRule(BuildRuleFile
)
1044 return self
._BuildRule
1046 ## Summarize the packages used by modules in this platform
1047 def _GetPackageList(self
):
1048 if self
._PackageList
== None:
1049 self
._PackageList
= set()
1050 for La
in self
.LibraryAutoGenList
:
1051 self
._PackageList
.update(La
.DependentPackageList
)
1052 for Ma
in self
.ModuleAutoGenList
:
1053 self
._PackageList
.update(Ma
.DependentPackageList
)
1054 self
._PackageList
= list(self
._PackageList
)
1055 return self
._PackageList
1057 ## Get list of non-dynamic PCDs
1058 def _GetNonDynamicPcdList(self
):
1059 if self
._NonDynamicPcdList
== None:
1060 self
.CollectPlatformDynamicPcds()
1061 return self
._NonDynamicPcdList
1063 ## Get list of dynamic PCDs
1064 def _GetDynamicPcdList(self
):
1065 if self
._DynamicPcdList
== None:
1066 self
.CollectPlatformDynamicPcds()
1067 return self
._DynamicPcdList
1069 ## Generate Token Number for all PCD
1070 def _GetPcdTokenNumbers(self
):
1071 if self
._PcdTokenNumber
== None:
1072 self
._PcdTokenNumber
= sdict()
1074 for Pcd
in self
.DynamicPcdList
:
1075 if Pcd
.Phase
== "PEI":
1076 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
1077 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
1080 for Pcd
in self
.DynamicPcdList
:
1081 if Pcd
.Phase
== "DXE":
1082 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
1083 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
1086 for Pcd
in self
.NonDynamicPcdList
:
1087 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
1089 return self
._PcdTokenNumber
1091 ## Summarize ModuleAutoGen objects of all modules/libraries to be built for this platform
1092 def _GetAutoGenObjectList(self
):
1093 self
._ModuleAutoGenList
= []
1094 self
._LibraryAutoGenList
= []
1095 for ModuleFile
in self
.Platform
.Modules
:
1104 if Ma
not in self
._ModuleAutoGenList
:
1105 self
._ModuleAutoGenList
.append(Ma
)
1106 for La
in Ma
.LibraryAutoGenList
:
1107 if La
not in self
._LibraryAutoGenList
:
1108 self
._LibraryAutoGenList
.append(La
)
1110 ## Summarize ModuleAutoGen objects of all modules to be built for this platform
1111 def _GetModuleAutoGenList(self
):
1112 if self
._ModuleAutoGenList
== None:
1113 self
._GetAutoGenObjectList
()
1114 return self
._ModuleAutoGenList
1116 ## Summarize ModuleAutoGen objects of all libraries to be built for this platform
1117 def _GetLibraryAutoGenList(self
):
1118 if self
._LibraryAutoGenList
== None:
1119 self
._GetAutoGenObjectList
()
1120 return self
._LibraryAutoGenList
1122 ## Test if a module is supported by the platform
1124 # An error will be raised directly if the module or its arch is not supported
1125 # by the platform or current configuration
1127 def ValidModule(self
, Module
):
1128 return Module
in self
.Platform
.Modules
or Module
in self
.Platform
.LibraryInstances
1130 ## Resolve the library classes in a module to library instances
1132 # This method will not only resolve library classes but also sort the library
1133 # instances according to the dependency-ship.
1135 # @param Module The module from which the library classes will be resolved
1137 # @retval library_list List of library instances sorted
1139 def ApplyLibraryInstance(self
, Module
):
1140 ModuleType
= Module
.ModuleType
1142 # for overridding library instances with module specific setting
1143 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
1145 # add forced library instances (specified under LibraryClasses sections)
1147 # If a module has a MODULE_TYPE of USER_DEFINED,
1148 # do not link in NULL library class instances from the global [LibraryClasses.*] sections.
1150 if Module
.ModuleType
!= SUP_MODULE_USER_DEFINED
:
1151 for LibraryClass
in self
.Platform
.LibraryClasses
.GetKeys():
1152 if LibraryClass
.startswith("NULL") and self
.Platform
.LibraryClasses
[LibraryClass
, Module
.ModuleType
]:
1153 Module
.LibraryClasses
[LibraryClass
] = self
.Platform
.LibraryClasses
[LibraryClass
, Module
.ModuleType
]
1155 # add forced library instances (specified in module overrides)
1156 for LibraryClass
in PlatformModule
.LibraryClasses
:
1157 if LibraryClass
.startswith("NULL"):
1158 Module
.LibraryClasses
[LibraryClass
] = PlatformModule
.LibraryClasses
[LibraryClass
]
1161 LibraryConsumerList
= [Module
]
1163 ConsumedByList
= sdict()
1164 LibraryInstance
= sdict()
1166 EdkLogger
.verbose("")
1167 EdkLogger
.verbose("Library instances of module [%s] [%s]:" % (str(Module
), self
.Arch
))
1168 while len(LibraryConsumerList
) > 0:
1169 M
= LibraryConsumerList
.pop()
1170 for LibraryClassName
in M
.LibraryClasses
:
1171 if LibraryClassName
not in LibraryInstance
:
1172 # override library instance for this module
1173 if LibraryClassName
in PlatformModule
.LibraryClasses
:
1174 LibraryPath
= PlatformModule
.LibraryClasses
[LibraryClassName
]
1176 LibraryPath
= self
.Platform
.LibraryClasses
[LibraryClassName
, ModuleType
]
1177 if LibraryPath
== None or LibraryPath
== "":
1178 LibraryPath
= M
.LibraryClasses
[LibraryClassName
]
1179 if LibraryPath
== None or LibraryPath
== "":
1180 EdkLogger
.error("build", RESOURCE_NOT_AVAILABLE
,
1181 "Instance of library class [%s] is not found" % LibraryClassName
,
1183 ExtraData
="in [%s] [%s]\n\tconsumed by module [%s]" % (str(M
), self
.Arch
, str(Module
)))
1185 LibraryModule
= self
.BuildDatabase
[LibraryPath
, self
.Arch
]
1186 # for those forced library instance (NULL library), add a fake library class
1187 if LibraryClassName
.startswith("NULL"):
1188 LibraryModule
.LibraryClass
.append(LibraryClassObject(LibraryClassName
, [ModuleType
]))
1189 elif LibraryModule
.LibraryClass
== None \
1190 or len(LibraryModule
.LibraryClass
) == 0 \
1191 or (ModuleType
!= 'USER_DEFINED'
1192 and ModuleType
not in LibraryModule
.LibraryClass
[0].SupModList
):
1193 # only USER_DEFINED can link against any library instance despite of its SupModList
1194 EdkLogger
.error("build", OPTION_MISSING
,
1195 "Module type [%s] is not supported by library instance [%s]" \
1196 % (ModuleType
, LibraryPath
), File
=self
.MetaFile
,
1197 ExtraData
="consumed by [%s]" % str(Module
))
1199 LibraryInstance
[LibraryClassName
] = LibraryModule
1200 LibraryConsumerList
.append(LibraryModule
)
1201 EdkLogger
.verbose("\t" + str(LibraryClassName
) + " : " + str(LibraryModule
))
1203 LibraryModule
= LibraryInstance
[LibraryClassName
]
1205 if LibraryModule
== None:
1208 if LibraryModule
.ConstructorList
!= [] and LibraryModule
not in Constructor
:
1209 Constructor
.append(LibraryModule
)
1211 if LibraryModule
not in ConsumedByList
:
1212 ConsumedByList
[LibraryModule
] = []
1213 # don't add current module itself to consumer list
1215 if M
in ConsumedByList
[LibraryModule
]:
1217 ConsumedByList
[LibraryModule
].append(M
)
1219 # Initialize the sorted output list to the empty set
1221 SortedLibraryList
= []
1223 # Q <- Set of all nodes with no incoming edges
1225 LibraryList
= [] #LibraryInstance.values()
1227 for LibraryClassName
in LibraryInstance
:
1228 M
= LibraryInstance
[LibraryClassName
]
1229 LibraryList
.append(M
)
1230 if ConsumedByList
[M
] == []:
1234 # start the DAG algorithm
1238 while Q
== [] and EdgeRemoved
:
1240 # for each node Item with a Constructor
1241 for Item
in LibraryList
:
1242 if Item
not in Constructor
:
1244 # for each Node without a constructor with an edge e from Item to Node
1245 for Node
in ConsumedByList
[Item
]:
1246 if Node
in Constructor
:
1248 # remove edge e from the graph if Node has no constructor
1249 ConsumedByList
[Item
].remove(Node
)
1251 if ConsumedByList
[Item
] == []:
1252 # insert Item into Q
1257 # DAG is done if there's no more incoming edge for all nodes
1261 # remove node from Q
1264 SortedLibraryList
.append(Node
)
1266 # for each node Item with an edge e from Node to Item do
1267 for Item
in LibraryList
:
1268 if Node
not in ConsumedByList
[Item
]:
1270 # remove edge e from the graph
1271 ConsumedByList
[Item
].remove(Node
)
1273 if ConsumedByList
[Item
] != []:
1275 # insert Item into Q, if Item has no other incoming edges
1279 # if any remaining node Item in the graph has a constructor and an incoming edge, then the graph has a cycle
1281 for Item
in LibraryList
:
1282 if ConsumedByList
[Item
] != [] and Item
in Constructor
and len(Constructor
) > 1:
1283 ErrorMessage
= "\tconsumed by " + "\n\tconsumed by ".join([str(L
) for L
in ConsumedByList
[Item
]])
1284 EdkLogger
.error("build", BUILD_ERROR
, 'Library [%s] with constructors has a cycle' % str(Item
),
1285 ExtraData
=ErrorMessage
, File
=self
.MetaFile
)
1286 if Item
not in SortedLibraryList
:
1287 SortedLibraryList
.append(Item
)
1290 # Build the list of constructor and destructir names
1291 # The DAG Topo sort produces the destructor order, so the list of constructors must generated in the reverse order
1293 SortedLibraryList
.reverse()
1294 return SortedLibraryList
1297 ## Override PCD setting (type, value, ...)
1299 # @param ToPcd The PCD to be overrided
1300 # @param FromPcd The PCD overrideing from
1302 def _OverridePcd(self
, ToPcd
, FromPcd
, Module
=""):
1304 # in case there's PCDs coming from FDF file, which have no type given.
1305 # at this point, ToPcd.Type has the type found from dependent
1309 if ToPcd
.Pending
and FromPcd
.Type
not in [None, '']:
1310 ToPcd
.Type
= FromPcd
.Type
1311 elif (ToPcd
.Type
not in [None, '']) and (FromPcd
.Type
not in [None, ''])\
1312 and (ToPcd
.Type
!= FromPcd
.Type
) and (ToPcd
.Type
in FromPcd
.Type
):
1313 if ToPcd
.Type
.strip() == "DynamicEx":
1314 ToPcd
.Type
= FromPcd
.Type
1315 elif ToPcd
.Type
not in [None, ''] and FromPcd
.Type
not in [None, ''] \
1316 and ToPcd
.Type
!= FromPcd
.Type
:
1317 EdkLogger
.error("build", OPTION_CONFLICT
, "Mismatched PCD type",
1318 ExtraData
="%s.%s is defined as [%s] in module %s, but as [%s] in platform."\
1319 % (ToPcd
.TokenSpaceGuidCName
, ToPcd
.TokenCName
,
1320 ToPcd
.Type
, Module
, FromPcd
.Type
),
1323 if FromPcd
.MaxDatumSize
not in [None, '']:
1324 ToPcd
.MaxDatumSize
= FromPcd
.MaxDatumSize
1325 if FromPcd
.DefaultValue
not in [None, '']:
1326 ToPcd
.DefaultValue
= FromPcd
.DefaultValue
1327 if FromPcd
.TokenValue
not in [None, '']:
1328 ToPcd
.TokenValue
= FromPcd
.TokenValue
1329 if FromPcd
.MaxDatumSize
not in [None, '']:
1330 ToPcd
.MaxDatumSize
= FromPcd
.MaxDatumSize
1331 if FromPcd
.DatumType
not in [None, '']:
1332 ToPcd
.DatumType
= FromPcd
.DatumType
1333 if FromPcd
.SkuInfoList
not in [None, '', []]:
1334 ToPcd
.SkuInfoList
= FromPcd
.SkuInfoList
1336 # check the validation of datum
1337 IsValid
, Cause
= CheckPcdDatum(ToPcd
.DatumType
, ToPcd
.DefaultValue
)
1339 EdkLogger
.error('build', FORMAT_INVALID
, Cause
, File
=self
.MetaFile
,
1340 ExtraData
="%s.%s" % (ToPcd
.TokenSpaceGuidCName
, ToPcd
.TokenCName
))
1342 if ToPcd
.DatumType
== "VOID*" and ToPcd
.MaxDatumSize
in ['', None]:
1343 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "No MaxDatumSize specified for PCD %s.%s" \
1344 % (ToPcd
.TokenSpaceGuidCName
, ToPcd
.TokenCName
))
1345 Value
= ToPcd
.DefaultValue
1346 if Value
in [None, '']:
1347 ToPcd
.MaxDatumSize
= 1
1348 elif Value
[0] == 'L':
1349 ToPcd
.MaxDatumSize
= str(len(Value
) * 2)
1350 elif Value
[0] == '{':
1351 ToPcd
.MaxDatumSize
= str(len(Value
.split(',')))
1353 ToPcd
.MaxDatumSize
= str(len(Value
))
1355 # apply default SKU for dynamic PCDS if specified one is not available
1356 if (ToPcd
.Type
in PCD_DYNAMIC_TYPE_LIST
or ToPcd
.Type
in PCD_DYNAMIC_EX_TYPE_LIST
) \
1357 and ToPcd
.SkuInfoList
in [None, {}, '']:
1358 if self
.Platform
.SkuName
in self
.Platform
.SkuIds
:
1359 SkuName
= self
.Platform
.SkuName
1362 ToPcd
.SkuInfoList
= {
1363 SkuName
: SkuInfoClass(SkuName
, self
.Platform
.SkuIds
[SkuName
], '', '', '', '', '', ToPcd
.DefaultValue
)
1366 ## Apply PCD setting defined platform to a module
1368 # @param Module The module from which the PCD setting will be overrided
1370 # @retval PCD_list The list PCDs with settings from platform
1372 def ApplyPcdSetting(self
, Module
, Pcds
):
1373 # for each PCD in module
1374 for Name
,Guid
in Pcds
:
1375 PcdInModule
= Pcds
[Name
,Guid
]
1376 # find out the PCD setting in platform
1377 if (Name
,Guid
) in self
.Platform
.Pcds
:
1378 PcdInPlatform
= self
.Platform
.Pcds
[Name
,Guid
]
1380 PcdInPlatform
= None
1381 # then override the settings if any
1382 self
._OverridePcd
(PcdInModule
, PcdInPlatform
, Module
)
1383 # resolve the VariableGuid value
1384 for SkuId
in PcdInModule
.SkuInfoList
:
1385 Sku
= PcdInModule
.SkuInfoList
[SkuId
]
1386 if Sku
.VariableGuid
== '': continue
1387 Sku
.VariableGuidValue
= GuidValue(Sku
.VariableGuid
, self
.PackageList
)
1388 if Sku
.VariableGuidValue
== None:
1389 PackageList
= "\n\t".join([str(P
) for P
in self
.PackageList
])
1392 RESOURCE_NOT_AVAILABLE
,
1393 "Value of GUID [%s] is not found in" % Sku
.VariableGuid
,
1394 ExtraData
=PackageList
+ "\n\t(used with %s.%s from module %s)" \
1395 % (Guid
, Name
, str(Module
)),
1399 # override PCD settings with module specific setting
1400 if Module
in self
.Platform
.Modules
:
1401 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
1402 for Key
in PlatformModule
.Pcds
:
1404 self
._OverridePcd
(Pcds
[Key
], PlatformModule
.Pcds
[Key
], Module
)
1405 return Pcds
.values()
1407 ## Resolve library names to library modules
1409 # (for Edk.x modules)
1411 # @param Module The module from which the library names will be resolved
1413 # @retval library_list The list of library modules
1415 def ResolveLibraryReference(self
, Module
):
1416 EdkLogger
.verbose("")
1417 EdkLogger
.verbose("Library instances of module [%s] [%s]:" % (str(Module
), self
.Arch
))
1418 LibraryConsumerList
= [Module
]
1420 # "CompilerStub" is a must for Edk modules
1421 if Module
.Libraries
:
1422 Module
.Libraries
.append("CompilerStub")
1424 while len(LibraryConsumerList
) > 0:
1425 M
= LibraryConsumerList
.pop()
1426 for LibraryName
in M
.Libraries
:
1427 Library
= self
.Platform
.LibraryClasses
[LibraryName
, ':dummy:']
1429 for Key
in self
.Platform
.LibraryClasses
.data
.keys():
1430 if LibraryName
.upper() == Key
.upper():
1431 Library
= self
.Platform
.LibraryClasses
[Key
, ':dummy:']
1434 EdkLogger
.warn("build", "Library [%s] is not found" % LibraryName
, File
=str(M
),
1435 ExtraData
="\t%s [%s]" % (str(Module
), self
.Arch
))
1438 if Library
not in LibraryList
:
1439 LibraryList
.append(Library
)
1440 LibraryConsumerList
.append(Library
)
1441 EdkLogger
.verbose("\t" + LibraryName
+ " : " + str(Library
) + ' ' + str(type(Library
)))
1444 ## Calculate the priority value of the build option
1446 # @param Key Build option definition contain: TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
1448 # @retval Value Priority value based on the priority list.
1450 def CalculatePriorityValue(self
, Key
):
1451 Target
, ToolChain
, Arch
, CommandType
, Attr
= Key
.split('_')
1452 PriorityValue
= 0x11111
1454 PriorityValue
&= 0x01111
1455 if ToolChain
== "*":
1456 PriorityValue
&= 0x10111
1458 PriorityValue
&= 0x11011
1459 if CommandType
== "*":
1460 PriorityValue
&= 0x11101
1462 PriorityValue
&= 0x11110
1464 return self
.PrioList
["0x%0.5x"%PriorityValue
]
1467 ## Expand * in build option key
1469 # @param Options Options to be expanded
1471 # @retval options Options expanded
1473 def _ExpandBuildOption(self
, Options
, ModuleStyle
=None):
1480 # Construct a list contain the build options which need override.
1484 # Key[0] -- tool family
1485 # Key[1] -- TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
1487 if Key
[0] == self
.BuildRuleFamily
:
1488 Target
, ToolChain
, Arch
, CommandType
, Attr
= Key
[1].split('_')
1489 if Target
== self
.BuildTarget
or Target
== "*":
1490 if ToolChain
== self
.ToolChain
or ToolChain
== "*":
1491 if Arch
== self
.Arch
or Arch
== "*":
1492 if Options
[Key
].startswith("="):
1493 if OverrideList
.get(Key
[1]) != None:
1494 OverrideList
.pop(Key
[1])
1495 OverrideList
[Key
[1]] = Options
[Key
]
1498 # Use the highest priority value.
1500 if (len(OverrideList
) >= 2):
1501 KeyList
= OverrideList
.keys()
1502 for Index
in range(len(KeyList
)):
1503 NowKey
= KeyList
[Index
]
1504 Target1
, ToolChain1
, Arch1
, CommandType1
, Attr1
= NowKey
.split("_")
1505 for Index1
in range(len(KeyList
) - Index
- 1):
1506 NextKey
= KeyList
[Index1
+ Index
+ 1]
1508 # Compare two Key, if one is included by another, choose the higher priority one
1510 Target2
, ToolChain2
, Arch2
, CommandType2
, Attr2
= NextKey
.split("_")
1511 if Target1
== Target2
or Target1
== "*" or Target2
== "*":
1512 if ToolChain1
== ToolChain2
or ToolChain1
== "*" or ToolChain2
== "*":
1513 if Arch1
== Arch2
or Arch1
== "*" or Arch2
== "*":
1514 if CommandType1
== CommandType2
or CommandType1
== "*" or CommandType2
== "*":
1515 if Attr1
== Attr2
or Attr1
== "*" or Attr2
== "*":
1516 if self
.CalculatePriorityValue(NowKey
) > self
.CalculatePriorityValue(NextKey
):
1517 if Options
.get((self
.BuildRuleFamily
, NextKey
)) != None:
1518 Options
.pop((self
.BuildRuleFamily
, NextKey
))
1520 if Options
.get((self
.BuildRuleFamily
, NowKey
)) != None:
1521 Options
.pop((self
.BuildRuleFamily
, NowKey
))
1525 if ModuleStyle
!= None and len (Key
) > 2:
1526 # Check Module style is EDK or EDKII.
1527 # Only append build option for the matched style module.
1528 if ModuleStyle
== EDK_NAME
and Key
[2] != EDK_NAME
:
1530 elif ModuleStyle
== EDKII_NAME
and Key
[2] != EDKII_NAME
:
1533 Target
, Tag
, Arch
, Tool
, Attr
= Key
[1].split("_")
1534 # if tool chain family doesn't match, skip it
1535 if Tool
in self
.ToolDefinition
and Family
!= "":
1536 FamilyIsNull
= False
1537 if self
.ToolDefinition
[Tool
].get(TAB_TOD_DEFINES_BUILDRULEFAMILY
, "") != "":
1538 if Family
!= self
.ToolDefinition
[Tool
][TAB_TOD_DEFINES_BUILDRULEFAMILY
]:
1540 elif Family
!= self
.ToolDefinition
[Tool
][TAB_TOD_DEFINES_FAMILY
]:
1543 # expand any wildcard
1544 if Target
== "*" or Target
== self
.BuildTarget
:
1545 if Tag
== "*" or Tag
== self
.ToolChain
:
1546 if Arch
== "*" or Arch
== self
.Arch
:
1547 if Tool
not in BuildOptions
:
1548 BuildOptions
[Tool
] = {}
1549 if Attr
!= "FLAGS" or Attr
not in BuildOptions
[Tool
]:
1550 BuildOptions
[Tool
][Attr
] = Options
[Key
]
1552 # append options for the same tool
1553 BuildOptions
[Tool
][Attr
] += " " + Options
[Key
]
1554 # Build Option Family has been checked, which need't to be checked again for family.
1555 if FamilyMatch
or FamilyIsNull
:
1559 if ModuleStyle
!= None and len (Key
) > 2:
1560 # Check Module style is EDK or EDKII.
1561 # Only append build option for the matched style module.
1562 if ModuleStyle
== EDK_NAME
and Key
[2] != EDK_NAME
:
1564 elif ModuleStyle
== EDKII_NAME
and Key
[2] != EDKII_NAME
:
1567 Target
, Tag
, Arch
, Tool
, Attr
= Key
[1].split("_")
1568 # if tool chain family doesn't match, skip it
1569 if Tool
not in self
.ToolDefinition
or Family
=="":
1571 # option has been added before
1572 if Family
!= self
.ToolDefinition
[Tool
][TAB_TOD_DEFINES_FAMILY
]:
1575 # expand any wildcard
1576 if Target
== "*" or Target
== self
.BuildTarget
:
1577 if Tag
== "*" or Tag
== self
.ToolChain
:
1578 if Arch
== "*" or Arch
== self
.Arch
:
1579 if Tool
not in BuildOptions
:
1580 BuildOptions
[Tool
] = {}
1581 if Attr
!= "FLAGS" or Attr
not in BuildOptions
[Tool
]:
1582 BuildOptions
[Tool
][Attr
] = Options
[Key
]
1584 # append options for the same tool
1585 BuildOptions
[Tool
][Attr
] += " " + Options
[Key
]
1588 ## Append build options in platform to a module
1590 # @param Module The module to which the build options will be appened
1592 # @retval options The options appended with build options in platform
1594 def ApplyBuildOption(self
, Module
):
1595 # Get the different options for the different style module
1596 if Module
.AutoGenVersion
< 0x00010005:
1597 PlatformOptions
= self
.EdkBuildOption
1599 PlatformOptions
= self
.EdkIIBuildOption
1600 ModuleOptions
= self
._ExpandBuildOption
(Module
.BuildOptions
)
1601 if Module
in self
.Platform
.Modules
:
1602 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
1603 PlatformModuleOptions
= self
._ExpandBuildOption
(PlatformModule
.BuildOptions
)
1605 PlatformModuleOptions
= {}
1607 AllTools
= set(ModuleOptions
.keys() + PlatformOptions
.keys() + PlatformModuleOptions
.keys() + self
.ToolDefinition
.keys())
1609 for Tool
in AllTools
:
1610 if Tool
not in BuildOptions
:
1611 BuildOptions
[Tool
] = {}
1613 for Options
in [self
.ToolDefinition
, ModuleOptions
, PlatformOptions
, PlatformModuleOptions
]:
1614 if Tool
not in Options
:
1616 for Attr
in Options
[Tool
]:
1617 Value
= Options
[Tool
][Attr
]
1618 if Attr
not in BuildOptions
[Tool
]:
1619 BuildOptions
[Tool
][Attr
] = ""
1620 # check if override is indicated
1621 if Value
.startswith('='):
1622 BuildOptions
[Tool
][Attr
] = Value
[1:]
1624 BuildOptions
[Tool
][Attr
] += " " + Value
1625 if Module
.AutoGenVersion
< 0x00010005 and self
.Workspace
.UniFlag
!= None:
1627 # Override UNI flag only for EDK module.
1629 if 'BUILD' not in BuildOptions
:
1630 BuildOptions
['BUILD'] = {}
1631 BuildOptions
['BUILD']['FLAGS'] = self
.Workspace
.UniFlag
1634 Platform
= property(_GetPlatform
)
1635 Name
= property(_GetName
)
1636 Guid
= property(_GetGuid
)
1637 Version
= property(_GetVersion
)
1639 OutputDir
= property(_GetOutputDir
)
1640 BuildDir
= property(_GetBuildDir
)
1641 MakeFileDir
= property(_GetMakeFileDir
)
1642 FdfFile
= property(_GetFdfFile
)
1644 PcdTokenNumber
= property(_GetPcdTokenNumbers
) # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber
1645 DynamicPcdList
= property(_GetDynamicPcdList
) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
1646 NonDynamicPcdList
= property(_GetNonDynamicPcdList
) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
1647 PackageList
= property(_GetPackageList
)
1649 ToolDefinition
= property(_GetToolDefinition
) # toolcode : tool path
1650 ToolDefinitionFile
= property(_GetToolDefFile
) # toolcode : lib path
1651 ToolChainFamily
= property(_GetToolChainFamily
)
1652 BuildRuleFamily
= property(_GetBuildRuleFamily
)
1653 BuildOption
= property(_GetBuildOptions
) # toolcode : option
1654 EdkBuildOption
= property(_GetEdkBuildOptions
) # edktoolcode : option
1655 EdkIIBuildOption
= property(_GetEdkIIBuildOptions
) # edkiitoolcode : option
1657 BuildCommand
= property(_GetBuildCommand
)
1658 BuildRule
= property(_GetBuildRule
)
1659 ModuleAutoGenList
= property(_GetModuleAutoGenList
)
1660 LibraryAutoGenList
= property(_GetLibraryAutoGenList
)
1662 ## ModuleAutoGen class
1664 # This class encapsules the AutoGen behaviors for the build tools. In addition to
1665 # the generation of AutoGen.h and AutoGen.c, it will generate *.depex file according
1666 # to the [depex] section in module's inf file.
1668 class ModuleAutoGen(AutoGen
):
1669 ## The real constructor of ModuleAutoGen
1671 # This method is not supposed to be called by users of ModuleAutoGen. It's
1672 # only used by factory method __new__() to do real initialization work for an
1673 # object of ModuleAutoGen
1675 # @param Workspace EdkIIWorkspaceBuild object
1676 # @param ModuleFile The path of module file
1677 # @param Target Build target (DEBUG, RELEASE)
1678 # @param Toolchain Name of tool chain
1679 # @param Arch The arch the module supports
1680 # @param PlatformFile Platform meta-file
1682 def _Init(self
, Workspace
, ModuleFile
, Target
, Toolchain
, Arch
, PlatformFile
):
1683 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "AutoGen module [%s] [%s]" % (ModuleFile
, Arch
))
1684 GlobalData
.gProcessingFile
= "%s [%s, %s, %s]" % (ModuleFile
, Arch
, Toolchain
, Target
)
1686 self
.Workspace
= Workspace
1687 self
.WorkspaceDir
= Workspace
.WorkspaceDir
1689 self
.MetaFile
= ModuleFile
1690 self
.PlatformInfo
= PlatformAutoGen(Workspace
, PlatformFile
, Target
, Toolchain
, Arch
)
1691 # check if this module is employed by active platform
1692 if not self
.PlatformInfo
.ValidModule(self
.MetaFile
):
1693 EdkLogger
.verbose("Module [%s] for [%s] is not employed by active platform\n" \
1694 % (self
.MetaFile
, Arch
))
1697 self
.SourceDir
= self
.MetaFile
.SubDir
1698 self
.SourceOverrideDir
= None
1699 # use overrided path defined in DSC file
1700 if self
.MetaFile
.Key
in GlobalData
.gOverrideDir
:
1701 self
.SourceOverrideDir
= GlobalData
.gOverrideDir
[self
.MetaFile
.Key
]
1703 self
.ToolChain
= Toolchain
1704 self
.BuildTarget
= Target
1706 self
.ToolChainFamily
= self
.PlatformInfo
.ToolChainFamily
1707 self
.BuildRuleFamily
= self
.PlatformInfo
.BuildRuleFamily
1709 self
.IsMakeFileCreated
= False
1710 self
.IsCodeFileCreated
= False
1711 self
.IsAsBuiltInfCreated
= False
1712 self
.DepexGenerated
= False
1714 self
.BuildDatabase
= self
.Workspace
.BuildDatabase
1719 self
._Version
= None
1720 self
._ModuleType
= None
1721 self
._ComponentType
= None
1722 self
._PcdIsDriver
= None
1723 self
._AutoGenVersion
= None
1724 self
._LibraryFlag
= None
1725 self
._CustomMakefile
= None
1728 self
._BuildDir
= None
1729 self
._OutputDir
= None
1730 self
._DebugDir
= None
1731 self
._MakeFileDir
= None
1733 self
._IncludePathList
= None
1734 self
._AutoGenFileList
= None
1735 self
._UnicodeFileList
= None
1736 self
._SourceFileList
= None
1737 self
._ObjectFileList
= None
1738 self
._BinaryFileList
= None
1740 self
._DependentPackageList
= None
1741 self
._DependentLibraryList
= None
1742 self
._LibraryAutoGenList
= None
1743 self
._DerivedPackageList
= None
1744 self
._ModulePcdList
= None
1745 self
._LibraryPcdList
= None
1746 self
._GuidList
= None
1747 self
._ProtocolList
= None
1748 self
._PpiList
= None
1749 self
._DepexList
= None
1750 self
._DepexExpressionList
= None
1751 self
._BuildOption
= None
1752 self
._BuildTargets
= None
1753 self
._IntroBuildTargetList
= None
1754 self
._FinalBuildTargetList
= None
1755 self
._FileTypes
= None
1756 self
._BuildRules
= None
1761 return "%s [%s]" % (self
.MetaFile
, self
.Arch
)
1763 # Macros could be used in build_rule.txt (also Makefile)
1764 def _GetMacros(self
):
1765 if self
._Macro
== None:
1766 self
._Macro
= sdict()
1767 self
._Macro
["WORKSPACE" ] = self
.WorkspaceDir
1768 self
._Macro
["MODULE_NAME" ] = self
.Name
1769 self
._Macro
["MODULE_GUID" ] = self
.Guid
1770 self
._Macro
["MODULE_VERSION" ] = self
.Version
1771 self
._Macro
["MODULE_TYPE" ] = self
.ModuleType
1772 self
._Macro
["MODULE_FILE" ] = str(self
.MetaFile
)
1773 self
._Macro
["MODULE_FILE_BASE_NAME" ] = self
.MetaFile
.BaseName
1774 self
._Macro
["MODULE_RELATIVE_DIR" ] = self
.SourceDir
1775 self
._Macro
["MODULE_DIR" ] = self
.SourceDir
1777 self
._Macro
["BASE_NAME" ] = self
.Name
1779 self
._Macro
["ARCH" ] = self
.Arch
1780 self
._Macro
["TOOLCHAIN" ] = self
.ToolChain
1781 self
._Macro
["TOOLCHAIN_TAG" ] = self
.ToolChain
1782 self
._Macro
["TARGET" ] = self
.BuildTarget
1784 self
._Macro
["BUILD_DIR" ] = self
.PlatformInfo
.BuildDir
1785 self
._Macro
["BIN_DIR" ] = os
.path
.join(self
.PlatformInfo
.BuildDir
, self
.Arch
)
1786 self
._Macro
["LIB_DIR" ] = os
.path
.join(self
.PlatformInfo
.BuildDir
, self
.Arch
)
1787 self
._Macro
["MODULE_BUILD_DIR" ] = self
.BuildDir
1788 self
._Macro
["OUTPUT_DIR" ] = self
.OutputDir
1789 self
._Macro
["DEBUG_DIR" ] = self
.DebugDir
1792 ## Return the module build data object
1793 def _GetModule(self
):
1794 if self
._Module
== None:
1795 self
._Module
= self
.Workspace
.BuildDatabase
[self
.MetaFile
, self
.Arch
]
1798 ## Return the module name
1799 def _GetBaseName(self
):
1800 return self
.Module
.BaseName
1802 ## Return the module DxsFile if exist
1803 def _GetDxsFile(self
):
1804 return self
.Module
.DxsFile
1806 ## Return the module SourceOverridePath
1807 def _GetSourceOverridePath(self
):
1808 return self
.Module
.SourceOverridePath
1810 ## Return the module meta-file GUID
1812 return self
.Module
.Guid
1814 ## Return the module version
1815 def _GetVersion(self
):
1816 return self
.Module
.Version
1818 ## Return the module type
1819 def _GetModuleType(self
):
1820 return self
.Module
.ModuleType
1822 ## Return the component type (for Edk.x style of module)
1823 def _GetComponentType(self
):
1824 return self
.Module
.ComponentType
1826 ## Return the build type
1827 def _GetBuildType(self
):
1828 return self
.Module
.BuildType
1830 ## Return the PCD_IS_DRIVER setting
1831 def _GetPcdIsDriver(self
):
1832 return self
.Module
.PcdIsDriver
1834 ## Return the autogen version, i.e. module meta-file version
1835 def _GetAutoGenVersion(self
):
1836 return self
.Module
.AutoGenVersion
1838 ## Check if the module is library or not
1839 def _IsLibrary(self
):
1840 if self
._LibraryFlag
== None:
1841 if self
.Module
.LibraryClass
!= None and self
.Module
.LibraryClass
!= []:
1842 self
._LibraryFlag
= True
1844 self
._LibraryFlag
= False
1845 return self
._LibraryFlag
1847 ## Return the directory to store intermediate files of the module
1848 def _GetBuildDir(self
):
1849 if self
._BuildDir
== None:
1850 self
._BuildDir
= path
.join(
1851 self
.PlatformInfo
.BuildDir
,
1854 self
.MetaFile
.BaseName
1856 CreateDirectory(self
._BuildDir
)
1857 return self
._BuildDir
1859 ## Return the directory to store the intermediate object files of the mdoule
1860 def _GetOutputDir(self
):
1861 if self
._OutputDir
== None:
1862 self
._OutputDir
= path
.join(self
.BuildDir
, "OUTPUT")
1863 CreateDirectory(self
._OutputDir
)
1864 return self
._OutputDir
1866 ## Return the directory to store auto-gened source files of the mdoule
1867 def _GetDebugDir(self
):
1868 if self
._DebugDir
== None:
1869 self
._DebugDir
= path
.join(self
.BuildDir
, "DEBUG")
1870 CreateDirectory(self
._DebugDir
)
1871 return self
._DebugDir
1873 ## Return the path of custom file
1874 def _GetCustomMakefile(self
):
1875 if self
._CustomMakefile
== None:
1876 self
._CustomMakefile
= {}
1877 for Type
in self
.Module
.CustomMakefile
:
1878 if Type
in gMakeTypeMap
:
1879 MakeType
= gMakeTypeMap
[Type
]
1882 if self
.SourceOverrideDir
!= None:
1883 File
= os
.path
.join(self
.SourceOverrideDir
, self
.Module
.CustomMakefile
[Type
])
1884 if not os
.path
.exists(File
):
1885 File
= os
.path
.join(self
.SourceDir
, self
.Module
.CustomMakefile
[Type
])
1887 File
= os
.path
.join(self
.SourceDir
, self
.Module
.CustomMakefile
[Type
])
1888 self
._CustomMakefile
[MakeType
] = File
1889 return self
._CustomMakefile
1891 ## Return the directory of the makefile
1893 # @retval string The directory string of module's makefile
1895 def _GetMakeFileDir(self
):
1896 return self
.BuildDir
1898 ## Return build command string
1900 # @retval string Build command string
1902 def _GetBuildCommand(self
):
1903 return self
.PlatformInfo
.BuildCommand
1905 ## Get object list of all packages the module and its dependent libraries belong to
1907 # @retval list The list of package object
1909 def _GetDerivedPackageList(self
):
1911 for M
in [self
.Module
] + self
.DependentLibraryList
:
1912 for Package
in M
.Packages
:
1913 if Package
in PackageList
:
1915 PackageList
.append(Package
)
1918 ## Merge dependency expression
1920 # @retval list The token list of the dependency expression after parsed
1922 def _GetDepexTokenList(self
):
1923 if self
._DepexList
== None:
1924 self
._DepexList
= {}
1925 if self
.DxsFile
or self
.IsLibrary
or TAB_DEPENDENCY_EXPRESSION_FILE
in self
.FileTypes
:
1926 return self
._DepexList
1928 self
._DepexList
[self
.ModuleType
] = []
1930 for ModuleType
in self
._DepexList
:
1931 DepexList
= self
._DepexList
[ModuleType
]
1933 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
1935 for M
in [self
.Module
] + self
.DependentLibraryList
:
1937 for D
in M
.Depex
[self
.Arch
, ModuleType
]:
1939 DepexList
.append('AND')
1940 DepexList
.append('(')
1942 if DepexList
[-1] == 'END': # no need of a END at this time
1944 DepexList
.append(')')
1947 EdkLogger
.verbose("DEPEX[%s] (+%s) = %s" % (self
.Name
, M
.BaseName
, DepexList
))
1948 if 'BEFORE' in DepexList
or 'AFTER' in DepexList
:
1950 if len(DepexList
) > 0:
1951 EdkLogger
.verbose('')
1952 return self
._DepexList
1954 ## Merge dependency expression
1956 # @retval list The token list of the dependency expression after parsed
1958 def _GetDepexExpressionTokenList(self
):
1959 if self
._DepexExpressionList
== None:
1960 self
._DepexExpressionList
= {}
1961 if self
.DxsFile
or self
.IsLibrary
or TAB_DEPENDENCY_EXPRESSION_FILE
in self
.FileTypes
:
1962 return self
._DepexExpressionList
1964 self
._DepexExpressionList
[self
.ModuleType
] = ''
1966 for ModuleType
in self
._DepexExpressionList
:
1967 DepexExpressionList
= self
._DepexExpressionList
[ModuleType
]
1969 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
1971 for M
in [self
.Module
] + self
.DependentLibraryList
:
1973 for D
in M
.DepexExpression
[self
.Arch
, ModuleType
]:
1974 if DepexExpressionList
!= '':
1975 DepexExpressionList
+= ' AND '
1976 DepexExpressionList
+= '('
1977 DepexExpressionList
+= D
1978 DepexExpressionList
= DepexExpressionList
.rstrip('END').strip()
1979 DepexExpressionList
+= ')'
1982 EdkLogger
.verbose("DEPEX[%s] (+%s) = %s" % (self
.Name
, M
.BaseName
, DepexExpressionList
))
1983 if 'BEFORE' in DepexExpressionList
or 'AFTER' in DepexExpressionList
:
1985 if len(DepexExpressionList
) > 0:
1986 EdkLogger
.verbose('')
1987 self
._DepexExpressionList
[ModuleType
] = DepexExpressionList
1988 return self
._DepexExpressionList
1990 ## Return the list of specification version required for the module
1992 # @retval list The list of specification defined in module file
1994 def _GetSpecification(self
):
1995 return self
.Module
.Specification
1997 ## Tool option for the module build
1999 # @param PlatformInfo The object of PlatformBuildInfo
2000 # @retval dict The dict containing valid options
2002 def _GetModuleBuildOption(self
):
2003 if self
._BuildOption
== None:
2004 self
._BuildOption
= self
.PlatformInfo
.ApplyBuildOption(self
.Module
)
2005 return self
._BuildOption
2007 ## Return a list of files which can be built from source
2009 # What kind of files can be built is determined by build rules in
2010 # $(WORKSPACE)/Conf/build_rule.txt and toolchain family.
2012 def _GetSourceFileList(self
):
2013 if self
._SourceFileList
== None:
2014 self
._SourceFileList
= []
2015 for F
in self
.Module
.Sources
:
2017 if F
.TagName
not in ("", "*", self
.ToolChain
):
2018 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "The toolchain [%s] for processing file [%s] is found, "
2019 "but [%s] is needed" % (F
.TagName
, str(F
), self
.ToolChain
))
2021 # match tool chain family
2022 if F
.ToolChainFamily
not in ("", "*", self
.ToolChainFamily
):
2025 "The file [%s] must be built by tools of [%s], " \
2026 "but current toolchain family is [%s]" \
2027 % (str(F
), F
.ToolChainFamily
, self
.ToolChainFamily
))
2030 # add the file path into search path list for file including
2031 if F
.Dir
not in self
.IncludePathList
and self
.AutoGenVersion
>= 0x00010005:
2032 self
.IncludePathList
.insert(0, F
.Dir
)
2033 self
._SourceFileList
.append(F
)
2034 self
._ApplyBuildRule
(F
, TAB_UNKNOWN_FILE
)
2035 return self
._SourceFileList
2037 ## Return the list of unicode files
2038 def _GetUnicodeFileList(self
):
2039 if self
._UnicodeFileList
== None:
2040 if TAB_UNICODE_FILE
in self
.FileTypes
:
2041 self
._UnicodeFileList
= self
.FileTypes
[TAB_UNICODE_FILE
]
2043 self
._UnicodeFileList
= []
2044 return self
._UnicodeFileList
2046 ## Return a list of files which can be built from binary
2048 # "Build" binary files are just to copy them to build directory.
2050 # @retval list The list of files which can be built later
2052 def _GetBinaryFiles(self
):
2053 if self
._BinaryFileList
== None:
2054 self
._BinaryFileList
= []
2055 for F
in self
.Module
.Binaries
:
2056 if F
.Target
not in ['COMMON', '*'] and F
.Target
!= self
.BuildTarget
:
2058 self
._BinaryFileList
.append(F
)
2059 self
._ApplyBuildRule
(F
, F
.Type
)
2060 return self
._BinaryFileList
2062 def _GetBuildRules(self
):
2063 if self
._BuildRules
== None:
2065 BuildRuleDatabase
= self
.PlatformInfo
.BuildRule
2066 for Type
in BuildRuleDatabase
.FileTypeList
:
2067 #first try getting build rule by BuildRuleFamily
2068 RuleObject
= BuildRuleDatabase
[Type
, self
.BuildType
, self
.Arch
, self
.BuildRuleFamily
]
2070 # build type is always module type, but ...
2071 if self
.ModuleType
!= self
.BuildType
:
2072 RuleObject
= BuildRuleDatabase
[Type
, self
.ModuleType
, self
.Arch
, self
.BuildRuleFamily
]
2073 #second try getting build rule by ToolChainFamily
2075 RuleObject
= BuildRuleDatabase
[Type
, self
.BuildType
, self
.Arch
, self
.ToolChainFamily
]
2077 # build type is always module type, but ...
2078 if self
.ModuleType
!= self
.BuildType
:
2079 RuleObject
= BuildRuleDatabase
[Type
, self
.ModuleType
, self
.Arch
, self
.ToolChainFamily
]
2082 RuleObject
= RuleObject
.Instantiate(self
.Macros
)
2083 BuildRules
[Type
] = RuleObject
2084 for Ext
in RuleObject
.SourceFileExtList
:
2085 BuildRules
[Ext
] = RuleObject
2086 self
._BuildRules
= BuildRules
2087 return self
._BuildRules
2089 def _ApplyBuildRule(self
, File
, FileType
):
2090 if self
._BuildTargets
== None:
2091 self
._IntroBuildTargetList
= set()
2092 self
._FinalBuildTargetList
= set()
2093 self
._BuildTargets
= {}
2094 self
._FileTypes
= {}
2100 while Index
< len(SourceList
):
2101 Source
= SourceList
[Index
]
2105 CreateDirectory(Source
.Dir
)
2107 if File
.IsBinary
and File
== Source
and self
._BinaryFileList
!= None and File
in self
._BinaryFileList
:
2108 # Skip all files that are not binary libraries
2109 if not self
.IsLibrary
:
2111 RuleObject
= self
.BuildRules
[TAB_DEFAULT_BINARY_FILE
]
2112 elif FileType
in self
.BuildRules
:
2113 RuleObject
= self
.BuildRules
[FileType
]
2114 elif Source
.Ext
in self
.BuildRules
:
2115 RuleObject
= self
.BuildRules
[Source
.Ext
]
2117 # stop at no more rules
2119 self
._FinalBuildTargetList
.add(LastTarget
)
2122 FileType
= RuleObject
.SourceFileType
2123 if FileType
not in self
._FileTypes
:
2124 self
._FileTypes
[FileType
] = set()
2125 self
._FileTypes
[FileType
].add(Source
)
2127 # stop at STATIC_LIBRARY for library
2128 if self
.IsLibrary
and FileType
== TAB_STATIC_LIBRARY
:
2130 self
._FinalBuildTargetList
.add(LastTarget
)
2133 Target
= RuleObject
.Apply(Source
)
2136 self
._FinalBuildTargetList
.add(LastTarget
)
2138 elif not Target
.Outputs
:
2139 # Only do build for target with outputs
2140 self
._FinalBuildTargetList
.add(Target
)
2142 if FileType
not in self
._BuildTargets
:
2143 self
._BuildTargets
[FileType
] = set()
2144 self
._BuildTargets
[FileType
].add(Target
)
2146 if not Source
.IsBinary
and Source
== File
:
2147 self
._IntroBuildTargetList
.add(Target
)
2149 # to avoid cyclic rule
2150 if FileType
in RuleChain
:
2153 RuleChain
.append(FileType
)
2154 SourceList
.extend(Target
.Outputs
)
2156 FileType
= TAB_UNKNOWN_FILE
2158 def _GetTargets(self
):
2159 if self
._BuildTargets
== None:
2160 self
._IntroBuildTargetList
= set()
2161 self
._FinalBuildTargetList
= set()
2162 self
._BuildTargets
= {}
2163 self
._FileTypes
= {}
2165 #TRICK: call _GetSourceFileList to apply build rule for source files
2166 if self
.SourceFileList
:
2169 #TRICK: call _GetBinaryFileList to apply build rule for binary files
2170 if self
.BinaryFileList
:
2173 return self
._BuildTargets
2175 def _GetIntroTargetList(self
):
2177 return self
._IntroBuildTargetList
2179 def _GetFinalTargetList(self
):
2181 return self
._FinalBuildTargetList
2183 def _GetFileTypes(self
):
2185 return self
._FileTypes
2187 ## Get the list of package object the module depends on
2189 # @retval list The package object list
2191 def _GetDependentPackageList(self
):
2192 return self
.Module
.Packages
2194 ## Return the list of auto-generated code file
2196 # @retval list The list of auto-generated file
2198 def _GetAutoGenFileList(self
):
2199 UniStringAutoGenC
= True
2200 UniStringBinBuffer
= StringIO()
2201 if self
.BuildType
== 'UEFI_HII':
2202 UniStringAutoGenC
= False
2203 if self
._AutoGenFileList
== None:
2204 self
._AutoGenFileList
= {}
2205 AutoGenC
= TemplateString()
2206 AutoGenH
= TemplateString()
2207 StringH
= TemplateString()
2208 GenC
.CreateCode(self
, AutoGenC
, AutoGenH
, StringH
, UniStringAutoGenC
, UniStringBinBuffer
)
2209 if str(AutoGenC
) != "" and TAB_C_CODE_FILE
in self
.FileTypes
:
2210 AutoFile
= PathClass(gAutoGenCodeFileName
, self
.DebugDir
)
2211 self
._AutoGenFileList
[AutoFile
] = str(AutoGenC
)
2212 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
2213 if str(AutoGenH
) != "":
2214 AutoFile
= PathClass(gAutoGenHeaderFileName
, self
.DebugDir
)
2215 self
._AutoGenFileList
[AutoFile
] = str(AutoGenH
)
2216 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
2217 if str(StringH
) != "":
2218 AutoFile
= PathClass(gAutoGenStringFileName
% {"module_name":self
.Name
}, self
.DebugDir
)
2219 self
._AutoGenFileList
[AutoFile
] = str(StringH
)
2220 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
2221 if UniStringBinBuffer
!= None and UniStringBinBuffer
.getvalue() != "":
2222 AutoFile
= PathClass(gAutoGenStringFormFileName
% {"module_name":self
.Name
}, self
.OutputDir
)
2223 self
._AutoGenFileList
[AutoFile
] = UniStringBinBuffer
.getvalue()
2224 AutoFile
.IsBinary
= True
2225 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
2226 if UniStringBinBuffer
!= None:
2227 UniStringBinBuffer
.close()
2228 return self
._AutoGenFileList
2230 ## Return the list of library modules explicitly or implicityly used by this module
2231 def _GetLibraryList(self
):
2232 if self
._DependentLibraryList
== None:
2233 # only merge library classes and PCD for non-library module
2235 self
._DependentLibraryList
= []
2237 if self
.AutoGenVersion
< 0x00010005:
2238 self
._DependentLibraryList
= self
.PlatformInfo
.ResolveLibraryReference(self
.Module
)
2240 self
._DependentLibraryList
= self
.PlatformInfo
.ApplyLibraryInstance(self
.Module
)
2241 return self
._DependentLibraryList
2243 ## Get the list of PCDs from current module
2245 # @retval list The list of PCD
2247 def _GetModulePcdList(self
):
2248 if self
._ModulePcdList
== None:
2249 # apply PCD settings from platform
2250 self
._ModulePcdList
= self
.PlatformInfo
.ApplyPcdSetting(self
.Module
, self
.Module
.Pcds
)
2251 return self
._ModulePcdList
2253 ## Get the list of PCDs from dependent libraries
2255 # @retval list The list of PCD
2257 def _GetLibraryPcdList(self
):
2258 if self
._LibraryPcdList
== None:
2260 if not self
.IsLibrary
:
2261 # get PCDs from dependent libraries
2262 for Library
in self
.DependentLibraryList
:
2263 for Key
in Library
.Pcds
:
2264 # skip duplicated PCDs
2265 if Key
in self
.Module
.Pcds
or Key
in Pcds
:
2267 Pcds
[Key
] = copy
.copy(Library
.Pcds
[Key
])
2268 # apply PCD settings from platform
2269 self
._LibraryPcdList
= self
.PlatformInfo
.ApplyPcdSetting(self
.Module
, Pcds
)
2271 self
._LibraryPcdList
= []
2272 return self
._LibraryPcdList
2274 ## Get the GUID value mapping
2276 # @retval dict The mapping between GUID cname and its value
2278 def _GetGuidList(self
):
2279 if self
._GuidList
== None:
2280 self
._GuidList
= self
.Module
.Guids
2281 for Library
in self
.DependentLibraryList
:
2282 self
._GuidList
.update(Library
.Guids
)
2283 return self
._GuidList
2285 ## Get the protocol value mapping
2287 # @retval dict The mapping between protocol cname and its value
2289 def _GetProtocolList(self
):
2290 if self
._ProtocolList
== None:
2291 self
._ProtocolList
= self
.Module
.Protocols
2292 for Library
in self
.DependentLibraryList
:
2293 self
._ProtocolList
.update(Library
.Protocols
)
2294 return self
._ProtocolList
2296 ## Get the PPI value mapping
2298 # @retval dict The mapping between PPI cname and its value
2300 def _GetPpiList(self
):
2301 if self
._PpiList
== None:
2302 self
._PpiList
= self
.Module
.Ppis
2303 for Library
in self
.DependentLibraryList
:
2304 self
._PpiList
.update(Library
.Ppis
)
2305 return self
._PpiList
2307 ## Get the list of include search path
2309 # @retval list The list path
2311 def _GetIncludePathList(self
):
2312 if self
._IncludePathList
== None:
2313 self
._IncludePathList
= []
2314 if self
.AutoGenVersion
< 0x00010005:
2315 for Inc
in self
.Module
.Includes
:
2316 if Inc
not in self
._IncludePathList
:
2317 self
._IncludePathList
.append(Inc
)
2319 Inc
= path
.join(Inc
, self
.Arch
.capitalize())
2320 if os
.path
.exists(Inc
) and Inc
not in self
._IncludePathList
:
2321 self
._IncludePathList
.append(Inc
)
2322 # Edk module needs to put DEBUG_DIR at the end of search path and not to use SOURCE_DIR all the time
2323 self
._IncludePathList
.append(self
.DebugDir
)
2325 self
._IncludePathList
.append(self
.MetaFile
.Dir
)
2326 self
._IncludePathList
.append(self
.DebugDir
)
2328 for Package
in self
.Module
.Packages
:
2329 PackageDir
= path
.join(self
.WorkspaceDir
, Package
.MetaFile
.Dir
)
2330 if PackageDir
not in self
._IncludePathList
:
2331 self
._IncludePathList
.append(PackageDir
)
2332 for Inc
in Package
.Includes
:
2333 if Inc
not in self
._IncludePathList
:
2334 self
._IncludePathList
.append(str(Inc
))
2335 return self
._IncludePathList
2337 ## Create AsBuilt INF file the module
2339 def CreateAsBuiltInf(self
):
2340 if self
.IsAsBuiltInfCreated
:
2343 # Skip the following code for EDK I inf
2344 if self
.AutoGenVersion
< 0x00010005:
2347 # Skip the following code for libraries
2351 # Skip the following code for modules with no source files
2352 if self
.SourceFileList
== None or self
.SourceFileList
== []:
2355 # Skip the following code for modules without any binary files
2356 if self
.BinaryFileList
<> None and self
.BinaryFileList
<> []:
2359 ### TODO: How to handles mixed source and binary modules
2361 # Find all DynamicEx PCDs used by this module and dependent libraries
2362 # Also find all packages that the DynamicEx PCDs depend on
2365 for Pcd
in self
.ModulePcdList
+ self
.LibraryPcdList
:
2366 if Pcd
.Type
in GenC
.gDynamicExPcd
:
2369 for Package
in self
.DerivedPackageList
:
2370 if Package
not in Packages
:
2371 if (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, 'DynamicEx') in Package
.Pcds
:
2372 Packages
+= [Package
]
2373 elif (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, 'Dynamic') in Package
.Pcds
:
2374 Packages
+= [Package
]
2376 ModuleType
= self
.ModuleType
2377 if ModuleType
== 'UEFI_DRIVER' and self
.DepexGenerated
:
2378 ModuleType
= 'DXE_DRIVER'
2381 'module_name' : self
.Name
,
2382 'module_guid' : self
.Guid
,
2383 'module_module_type' : ModuleType
,
2384 'module_version_string' : self
.Version
,
2385 'module_uefi_specification_version' : [],
2386 'module_pi_specification_version' : [],
2387 'module_arch' : self
.Arch
,
2388 'package_item' : ['%s' % (Package
.MetaFile
.File
.replace('\\','/')) for Package
in Packages
],
2394 if 'UEFI_SPECIFICATION_VERSION' in self
.Specification
:
2395 AsBuiltInfDict
['module_uefi_specification_version'] += [self
.Specification
['UEFI_SPECIFICATION_VERSION']]
2396 if 'PI_SPECIFICATION_VERSION' in self
.Specification
:
2397 AsBuiltInfDict
['module_pi_specification_version'] += [self
.Specification
['PI_SPECIFICATION_VERSION']]
2399 OutputDir
= self
.OutputDir
.replace('\\','/').strip('/')
2400 if self
.ModuleType
in ['BASE', 'USER_DEFINED']:
2401 for Item
in self
.CodaTargetList
:
2402 File
= Item
.Target
.Path
.replace('\\','/').strip('/').replace(OutputDir
,'').strip('/')
2403 if Item
.Target
.Ext
.lower() == '.aml':
2404 AsBuiltInfDict
['binary_item'] += ['ASL|' + File
]
2405 elif Item
.Target
.Ext
.lower() == '.acpi':
2406 AsBuiltInfDict
['binary_item'] += ['ACPI|' + File
]
2408 AsBuiltInfDict
['binary_item'] += ['BIN|' + File
]
2410 for Item
in self
.CodaTargetList
:
2411 File
= Item
.Target
.Path
.replace('\\','/').strip('/').replace(OutputDir
,'').strip('/')
2412 if Item
.Target
.Ext
.lower() == '.efi':
2413 AsBuiltInfDict
['binary_item'] += ['PE32|' + self
.Name
+ '.efi']
2415 AsBuiltInfDict
['binary_item'] += ['BIN|' + File
]
2416 if self
.DepexGenerated
:
2417 if self
.ModuleType
in ['PEIM']:
2418 AsBuiltInfDict
['binary_item'] += ['PEI_DEPEX|' + self
.Name
+ '.depex']
2419 if self
.ModuleType
in ['DXE_DRIVER','DXE_RUNTIME_DRIVER','DXE_SAL_DRIVER','UEFI_DRIVER']:
2420 AsBuiltInfDict
['binary_item'] += ['DXE_DEPEX|' + self
.Name
+ '.depex']
2421 if self
.ModuleType
in ['DXE_SMM_DRIVER']:
2422 AsBuiltInfDict
['binary_item'] += ['SMM_DEPEX|' + self
.Name
+ '.depex']
2425 AsBuiltInfDict
['pcd_item'] += [Pcd
.TokenSpaceGuidCName
+ '.' + Pcd
.TokenCName
]
2427 for Item
in self
.BuildOption
:
2428 if 'FLAGS' in self
.BuildOption
[Item
]:
2429 AsBuiltInfDict
['flags_item'] += ['%s:%s_%s_%s_%s_FLAGS = %s' % (self
.ToolChainFamily
, self
.BuildTarget
, self
.ToolChain
, self
.Arch
, Item
, self
.BuildOption
[Item
]['FLAGS'].strip())]
2431 AsBuiltInf
= TemplateString()
2432 AsBuiltInf
.Append(gAsBuiltInfHeaderString
.Replace(AsBuiltInfDict
))
2434 SaveFileOnChange(os
.path
.join(self
.OutputDir
, self
.Name
+ '.inf'), str(AsBuiltInf
), False)
2436 self
.IsAsBuiltInfCreated
= True
2438 ## Create makefile for the module and its dependent libraries
2440 # @param CreateLibraryMakeFile Flag indicating if or not the makefiles of
2441 # dependent libraries will be created
2443 def CreateMakeFile(self
, CreateLibraryMakeFile
=True):
2444 if self
.IsMakeFileCreated
:
2447 if not self
.IsLibrary
and CreateLibraryMakeFile
:
2448 for LibraryAutoGen
in self
.LibraryAutoGenList
:
2449 LibraryAutoGen
.CreateMakeFile()
2451 if len(self
.CustomMakefile
) == 0:
2452 Makefile
= GenMake
.ModuleMakefile(self
)
2454 Makefile
= GenMake
.CustomMakefile(self
)
2455 if Makefile
.Generate():
2456 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated makefile for module %s [%s]" %
2457 (self
.Name
, self
.Arch
))
2459 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Skipped the generation of makefile for module %s [%s]" %
2460 (self
.Name
, self
.Arch
))
2462 self
.IsMakeFileCreated
= True
2464 ## Create autogen code for the module and its dependent libraries
2466 # @param CreateLibraryCodeFile Flag indicating if or not the code of
2467 # dependent libraries will be created
2469 def CreateCodeFile(self
, CreateLibraryCodeFile
=True):
2470 if self
.IsCodeFileCreated
:
2473 if not self
.IsLibrary
and CreateLibraryCodeFile
:
2474 for LibraryAutoGen
in self
.LibraryAutoGenList
:
2475 LibraryAutoGen
.CreateCodeFile()
2478 IgoredAutoGenList
= []
2480 for File
in self
.AutoGenFileList
:
2481 if GenC
.Generate(File
.Path
, self
.AutoGenFileList
[File
], File
.IsBinary
):
2482 #Ignore Edk AutoGen.c
2483 if self
.AutoGenVersion
< 0x00010005 and File
.Name
== 'AutoGen.c':
2486 AutoGenList
.append(str(File
))
2488 IgoredAutoGenList
.append(str(File
))
2490 # Skip the following code for EDK I inf
2491 if self
.AutoGenVersion
< 0x00010005:
2494 for ModuleType
in self
.DepexList
:
2495 # Ignore empty [depex] section or [depex] section for "USER_DEFINED" module
2496 if len(self
.DepexList
[ModuleType
]) == 0 or ModuleType
== "USER_DEFINED":
2499 Dpx
= GenDepex
.DependencyExpression(self
.DepexList
[ModuleType
], ModuleType
, True)
2500 DpxFile
= gAutoGenDepexFileName
% {"module_name" : self
.Name
}
2502 if len(Dpx
.PostfixNotation
) <> 0:
2503 self
.DepexGenerated
= True
2505 if Dpx
.Generate(path
.join(self
.OutputDir
, DpxFile
)):
2506 AutoGenList
.append(str(DpxFile
))
2508 IgoredAutoGenList
.append(str(DpxFile
))
2510 if IgoredAutoGenList
== []:
2511 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated [%s] files for module %s [%s]" %
2512 (" ".join(AutoGenList
), self
.Name
, self
.Arch
))
2513 elif AutoGenList
== []:
2514 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Skipped the generation of [%s] files for module %s [%s]" %
2515 (" ".join(IgoredAutoGenList
), self
.Name
, self
.Arch
))
2517 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated [%s] (skipped %s) files for module %s [%s]" %
2518 (" ".join(AutoGenList
), " ".join(IgoredAutoGenList
), self
.Name
, self
.Arch
))
2520 self
.IsCodeFileCreated
= True
2523 ## Summarize the ModuleAutoGen objects of all libraries used by this module
2524 def _GetLibraryAutoGenList(self
):
2525 if self
._LibraryAutoGenList
== None:
2526 self
._LibraryAutoGenList
= []
2527 for Library
in self
.DependentLibraryList
:
2534 self
.PlatformInfo
.MetaFile
2536 if La
not in self
._LibraryAutoGenList
:
2537 self
._LibraryAutoGenList
.append(La
)
2538 for Lib
in La
.CodaTargetList
:
2539 self
._ApplyBuildRule
(Lib
.Target
, TAB_UNKNOWN_FILE
)
2540 return self
._LibraryAutoGenList
2542 Module
= property(_GetModule
)
2543 Name
= property(_GetBaseName
)
2544 Guid
= property(_GetGuid
)
2545 Version
= property(_GetVersion
)
2546 ModuleType
= property(_GetModuleType
)
2547 ComponentType
= property(_GetComponentType
)
2548 BuildType
= property(_GetBuildType
)
2549 PcdIsDriver
= property(_GetPcdIsDriver
)
2550 AutoGenVersion
= property(_GetAutoGenVersion
)
2551 Macros
= property(_GetMacros
)
2552 Specification
= property(_GetSpecification
)
2554 IsLibrary
= property(_IsLibrary
)
2556 BuildDir
= property(_GetBuildDir
)
2557 OutputDir
= property(_GetOutputDir
)
2558 DebugDir
= property(_GetDebugDir
)
2559 MakeFileDir
= property(_GetMakeFileDir
)
2560 CustomMakefile
= property(_GetCustomMakefile
)
2562 IncludePathList
= property(_GetIncludePathList
)
2563 AutoGenFileList
= property(_GetAutoGenFileList
)
2564 UnicodeFileList
= property(_GetUnicodeFileList
)
2565 SourceFileList
= property(_GetSourceFileList
)
2566 BinaryFileList
= property(_GetBinaryFiles
) # FileType : [File List]
2567 Targets
= property(_GetTargets
)
2568 IntroTargetList
= property(_GetIntroTargetList
)
2569 CodaTargetList
= property(_GetFinalTargetList
)
2570 FileTypes
= property(_GetFileTypes
)
2571 BuildRules
= property(_GetBuildRules
)
2573 DependentPackageList
= property(_GetDependentPackageList
)
2574 DependentLibraryList
= property(_GetLibraryList
)
2575 LibraryAutoGenList
= property(_GetLibraryAutoGenList
)
2576 DerivedPackageList
= property(_GetDerivedPackageList
)
2578 ModulePcdList
= property(_GetModulePcdList
)
2579 LibraryPcdList
= property(_GetLibraryPcdList
)
2580 GuidList
= property(_GetGuidList
)
2581 ProtocolList
= property(_GetProtocolList
)
2582 PpiList
= property(_GetPpiList
)
2583 DepexList
= property(_GetDepexTokenList
)
2584 DxsFile
= property(_GetDxsFile
)
2585 DepexExpressionList
= property(_GetDepexExpressionTokenList
)
2586 BuildOption
= property(_GetModuleBuildOption
)
2587 BuildCommand
= property(_GetBuildCommand
)
2589 # This acts like the main() function for the script, unless it is 'import'ed into another script.
2590 if __name__
== '__main__':