2 # Generate AutoGen.h, AutoGen.c and *.depex files
4 # Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>
5 # This program and the accompanying materials
6 # are licensed and made available under the terms and conditions of the BSD License
7 # which accompanies this distribution. The full text of the license may be found at
8 # http://opensource.org/licenses/bsd-license.php
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.
16 import Common
.LongFilePathOs
as os
18 import os
.path
as path
24 from StringIO
import StringIO
26 from StrGather
import *
27 from BuildEngine
import BuildRule
29 from Common
.LongFilePathSupport
import CopyLongFilePath
30 from Common
.BuildToolError
import *
31 from Common
.DataType
import *
32 from Common
.Misc
import *
33 from Common
.String
import *
34 import Common
.GlobalData
as GlobalData
35 from GenFds
.FdfParser
import *
36 from CommonDataClass
.CommonClass
import SkuInfoClass
37 from Workspace
.BuildClassObject
import *
38 from GenPatchPcdTable
.GenPatchPcdTable
import parsePcdInfoFromMapFile
39 import Common
.VpdInfoFile
as VpdInfoFile
40 from GenPcdDb
import CreatePcdDatabaseCode
41 from Workspace
.MetaFileCommentParser
import UsageList
43 ## Regular expression for splitting Dependency Expression string into tokens
44 gDepexTokenPattern
= re
.compile("(\(|\)|\w+| \S+\.inf)")
46 ## Mapping Makefile type
47 gMakeTypeMap
= {"MSFT":"nmake", "GCC":"gmake"}
50 ## Build rule configuration file
51 gBuildRuleFile
= 'Conf/build_rule.txt'
53 ## Build rule default version
54 AutoGenReqBuildRuleVerNum
= "0.1"
56 ## default file name for AutoGen
57 gAutoGenCodeFileName
= "AutoGen.c"
58 gAutoGenHeaderFileName
= "AutoGen.h"
59 gAutoGenStringFileName
= "%(module_name)sStrDefs.h"
60 gAutoGenStringFormFileName
= "%(module_name)sStrDefs.hpk"
61 gAutoGenDepexFileName
= "%(module_name)s.depex"
64 # Template string to generic AsBuilt INF
66 gAsBuiltInfHeaderString
= TemplateString("""${header_comments}
69 INF_VERSION = 0x00010016
70 BASE_NAME = ${module_name}
71 FILE_GUID = ${module_guid}
72 MODULE_TYPE = ${module_module_type}
73 VERSION_STRING = ${module_version_string}${BEGIN}
74 PCD_IS_DRIVER = ${pcd_is_driver_string}${END}${BEGIN}
75 UEFI_SPECIFICATION_VERSION = ${module_uefi_specification_version}${END}${BEGIN}
76 PI_SPECIFICATION_VERSION = ${module_pi_specification_version}${END}
81 [Binaries.${module_arch}]${BEGIN}
84 [PatchPcd.${module_arch}]${BEGIN}
87 [Protocols.${module_arch}]${BEGIN}
90 [Ppis.${module_arch}]${BEGIN}
93 [Guids.${module_arch}]${BEGIN}
96 [PcdEx.${module_arch}]${BEGIN}
101 ## ${flags_item}${END}
104 ## Base class for AutoGen
106 # This class just implements the cache mechanism of AutoGen objects.
108 class AutoGen(object):
109 # database to maintain the objects of xxxAutoGen
110 _CACHE_
= {} # (BuildTarget, ToolChain) : {ARCH : {platform file: AutoGen object}}}
114 # @param Class class object of real AutoGen class
115 # (WorkspaceAutoGen, ModuleAutoGen or PlatformAutoGen)
116 # @param Workspace Workspace directory or WorkspaceAutoGen object
117 # @param MetaFile The path of meta file
118 # @param Target Build target
119 # @param Toolchain Tool chain name
120 # @param Arch Target arch
121 # @param *args The specific class related parameters
122 # @param **kwargs The specific class related dict parameters
124 def __new__(Class
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
125 # check if the object has been created
126 Key
= (Target
, Toolchain
)
127 if Key
not in Class
._CACHE
_ or Arch
not in Class
._CACHE
_[Key
] \
128 or MetaFile
not in Class
._CACHE
_[Key
][Arch
]:
129 AutoGenObject
= super(AutoGen
, Class
).__new
__(Class
)
130 # call real constructor
131 if not AutoGenObject
._Init
(Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
133 if Key
not in Class
._CACHE
_:
134 Class
._CACHE
_[Key
] = {}
135 if Arch
not in Class
._CACHE
_[Key
]:
136 Class
._CACHE
_[Key
][Arch
] = {}
137 Class
._CACHE
_[Key
][Arch
][MetaFile
] = AutoGenObject
139 AutoGenObject
= Class
._CACHE
_[Key
][Arch
][MetaFile
]
145 # The file path of platform file will be used to represent hash value of this object
147 # @retval int Hash value of the file path of platform file
150 return hash(self
.MetaFile
)
154 # The file path of platform file will be used to represent this object
156 # @retval string String of platform file path
159 return str(self
.MetaFile
)
162 def __eq__(self
, Other
):
163 return Other
and self
.MetaFile
== Other
165 ## Workspace AutoGen class
167 # This class is used mainly to control the whole platform build for different
168 # architecture. This class will generate top level makefile.
170 class WorkspaceAutoGen(AutoGen
):
171 ## Real constructor of WorkspaceAutoGen
173 # This method behaves the same as __init__ except that it needs explicit invoke
174 # (in super class's __new__ method)
176 # @param WorkspaceDir Root directory of workspace
177 # @param ActivePlatform Meta-file of active platform
178 # @param Target Build target
179 # @param Toolchain Tool chain name
180 # @param ArchList List of architecture of current build
181 # @param MetaFileDb Database containing meta-files
182 # @param BuildConfig Configuration of build
183 # @param ToolDefinition Tool chain definitions
184 # @param FlashDefinitionFile File of flash definition
185 # @param Fds FD list to be generated
186 # @param Fvs FV list to be generated
187 # @param Caps Capsule list to be generated
188 # @param SkuId SKU id from command line
190 def _Init(self
, WorkspaceDir
, ActivePlatform
, Target
, Toolchain
, ArchList
, MetaFileDb
,
191 BuildConfig
, ToolDefinition
, FlashDefinitionFile
='', Fds
=None, Fvs
=None, Caps
=None, SkuId
='', UniFlag
=None,
192 Progress
=None, BuildModule
=None):
199 self
.BuildDatabase
= MetaFileDb
200 self
.MetaFile
= ActivePlatform
201 self
.WorkspaceDir
= WorkspaceDir
202 self
.Platform
= self
.BuildDatabase
[self
.MetaFile
, 'COMMON', Target
, Toolchain
]
203 GlobalData
.gActivePlatform
= self
.Platform
204 self
.BuildTarget
= Target
205 self
.ToolChain
= Toolchain
206 self
.ArchList
= ArchList
208 self
.UniFlag
= UniFlag
210 self
.TargetTxt
= BuildConfig
211 self
.ToolDef
= ToolDefinition
212 self
.FdfFile
= FlashDefinitionFile
213 self
.FdTargetList
= Fds
214 self
.FvTargetList
= Fvs
215 self
.CapTargetList
= Caps
216 self
.AutoGenObjectList
= []
218 # there's many relative directory operations, so ...
219 os
.chdir(self
.WorkspaceDir
)
224 if not self
.ArchList
:
225 ArchList
= set(self
.Platform
.SupArchList
)
227 ArchList
= set(self
.ArchList
) & set(self
.Platform
.SupArchList
)
229 EdkLogger
.error("build", PARAMETER_INVALID
,
230 ExtraData
= "Invalid ARCH specified. [Valid ARCH: %s]" % (" ".join(self
.Platform
.SupArchList
)))
231 elif self
.ArchList
and len(ArchList
) != len(self
.ArchList
):
232 SkippedArchList
= set(self
.ArchList
).symmetric_difference(set(self
.Platform
.SupArchList
))
233 EdkLogger
.verbose("\nArch [%s] is ignored because the platform supports [%s] only!"
234 % (" ".join(SkippedArchList
), " ".join(self
.Platform
.SupArchList
)))
235 self
.ArchList
= tuple(ArchList
)
237 # Validate build target
238 if self
.BuildTarget
not in self
.Platform
.BuildTargets
:
239 EdkLogger
.error("build", PARAMETER_INVALID
,
240 ExtraData
="Build target [%s] is not supported by the platform. [Valid target: %s]"
241 % (self
.BuildTarget
, " ".join(self
.Platform
.BuildTargets
)))
243 # parse FDF file to get PCDs in it, if any
245 self
.FdfFile
= self
.Platform
.FlashDefinition
249 EdkLogger
.info('%-16s = %s' % ("Architecture(s)", ' '.join(self
.ArchList
)))
250 EdkLogger
.info('%-16s = %s' % ("Build target", self
.BuildTarget
))
251 EdkLogger
.info('%-16s = %s' % ("Toolchain",self
.ToolChain
))
253 EdkLogger
.info('\n%-24s = %s' % ("Active Platform", self
.Platform
))
255 EdkLogger
.info('%-24s = %s' % ("Active Module", BuildModule
))
258 EdkLogger
.info('%-24s = %s' % ("Flash Image Definition", self
.FdfFile
))
260 EdkLogger
.verbose("\nFLASH_DEFINITION = %s" % self
.FdfFile
)
263 Progress
.Start("\nProcessing meta-data")
267 # Mark now build in AutoGen Phase
269 GlobalData
.gAutoGenPhase
= True
270 Fdf
= FdfParser(self
.FdfFile
.Path
)
272 GlobalData
.gAutoGenPhase
= False
273 PcdSet
= Fdf
.Profile
.PcdDict
274 ModuleList
= Fdf
.Profile
.InfList
275 self
.FdfProfile
= Fdf
.Profile
276 for fvname
in self
.FvTargetList
:
277 if fvname
.upper() not in self
.FdfProfile
.FvDict
:
278 EdkLogger
.error("build", OPTION_VALUE_INVALID
,
279 "No such an FV in FDF file: %s" % fvname
)
283 self
.FdfProfile
= None
284 if self
.FdTargetList
:
285 EdkLogger
.info("No flash definition file found. FD [%s] will be ignored." % " ".join(self
.FdTargetList
))
286 self
.FdTargetList
= []
287 if self
.FvTargetList
:
288 EdkLogger
.info("No flash definition file found. FV [%s] will be ignored." % " ".join(self
.FvTargetList
))
289 self
.FvTargetList
= []
290 if self
.CapTargetList
:
291 EdkLogger
.info("No flash definition file found. Capsule [%s] will be ignored." % " ".join(self
.CapTargetList
))
292 self
.CapTargetList
= []
294 # apply SKU and inject PCDs from Flash Definition file
295 for Arch
in self
.ArchList
:
296 Platform
= self
.BuildDatabase
[self
.MetaFile
, Arch
, Target
, Toolchain
]
300 PGen
= PlatformAutoGen(self
, self
.MetaFile
, Target
, Toolchain
, Arch
)
301 Pkgs
= PGen
.PackageList
304 DecPcds
[Pcd
[0], Pcd
[1]] = Pkg
.Pcds
[Pcd
]
305 DecPcdsKey
.add((Pcd
[0], Pcd
[1], Pcd
[2]))
307 Platform
.SkuName
= self
.SkuId
308 for Name
, Guid
in PcdSet
:
309 if (Name
, Guid
) not in DecPcds
:
313 "PCD (%s.%s) used in FDF is not declared in DEC files." % (Guid
, Name
),
314 File
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
][0],
315 Line
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
][1]
318 # Check whether Dynamic or DynamicEx PCD used in FDF file. If used, build break and give a error message.
319 if (Name
, Guid
, TAB_PCDS_FIXED_AT_BUILD
) in DecPcdsKey \
320 or (Name
, Guid
, TAB_PCDS_PATCHABLE_IN_MODULE
) in DecPcdsKey \
321 or (Name
, Guid
, TAB_PCDS_FEATURE_FLAG
) in DecPcdsKey
:
322 Platform
.AddPcd(Name
, Guid
, PcdSet
[Name
, Guid
])
324 elif (Name
, Guid
, TAB_PCDS_DYNAMIC
) in DecPcdsKey
or (Name
, Guid
, TAB_PCDS_DYNAMIC_EX
) in DecPcdsKey
:
328 "Using Dynamic or DynamicEx type of PCD [%s.%s] in FDF file is not allowed." % (Guid
, Name
),
329 File
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
][0],
330 Line
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
][1]
333 Pa
= PlatformAutoGen(self
, self
.MetaFile
, Target
, Toolchain
, Arch
)
335 # Explicitly collect platform's dynamic PCDs
337 Pa
.CollectPlatformDynamicPcds()
338 Pa
.CollectFixedAtBuildPcds()
339 self
.AutoGenObjectList
.append(Pa
)
342 # Check PCDs token value conflict in each DEC file.
344 self
._CheckAllPcdsTokenValueConflict
()
347 # Check PCD type and definition between DSC and DEC
349 self
._CheckPcdDefineAndType
()
352 self
._CheckDuplicateInFV
(Fdf
)
354 self
._BuildDir
= None
356 self
._MakeFileDir
= None
357 self
._BuildCommand
= None
361 ## _CheckDuplicateInFV() method
363 # Check whether there is duplicate modules/files exist in FV section.
364 # The check base on the file GUID;
366 def _CheckDuplicateInFV(self
, Fdf
):
367 for Fv
in Fdf
.Profile
.FvDict
:
369 for FfsFile
in Fdf
.Profile
.FvDict
[Fv
].FfsList
:
370 if FfsFile
.InfFileName
and FfsFile
.NameGuid
== None:
375 for Pa
in self
.AutoGenObjectList
:
378 for Module
in Pa
.ModuleAutoGenList
:
379 if path
.normpath(Module
.MetaFile
.File
) == path
.normpath(FfsFile
.InfFileName
):
381 if not Module
.Guid
.upper() in _GuidDict
.keys():
382 _GuidDict
[Module
.Guid
.upper()] = FfsFile
385 EdkLogger
.error("build",
387 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s"%(FfsFile
.CurrentLineNum
,
388 FfsFile
.CurrentLineContent
,
389 _GuidDict
[Module
.Guid
.upper()].CurrentLineNum
,
390 _GuidDict
[Module
.Guid
.upper()].CurrentLineContent
,
391 Module
.Guid
.upper()),
392 ExtraData
=self
.FdfFile
)
394 # Some INF files not have entity in DSC file.
397 if FfsFile
.InfFileName
.find('$') == -1:
398 InfPath
= NormPath(FfsFile
.InfFileName
)
399 if not os
.path
.exists(InfPath
):
400 EdkLogger
.error('build', GENFDS_ERROR
, "Non-existant Module %s !" % (FfsFile
.InfFileName
))
402 PathClassObj
= PathClass(FfsFile
.InfFileName
, self
.WorkspaceDir
)
404 # Here we just need to get FILE_GUID from INF file, use 'COMMON' as ARCH attribute. and use
405 # BuildObject from one of AutoGenObjectList is enough.
407 InfObj
= self
.AutoGenObjectList
[0].BuildDatabase
.WorkspaceDb
.BuildObject
[PathClassObj
, 'COMMON', self
.BuildTarget
, self
.ToolChain
]
408 if not InfObj
.Guid
.upper() in _GuidDict
.keys():
409 _GuidDict
[InfObj
.Guid
.upper()] = FfsFile
411 EdkLogger
.error("build",
413 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s"%(FfsFile
.CurrentLineNum
,
414 FfsFile
.CurrentLineContent
,
415 _GuidDict
[InfObj
.Guid
.upper()].CurrentLineNum
,
416 _GuidDict
[InfObj
.Guid
.upper()].CurrentLineContent
,
417 InfObj
.Guid
.upper()),
418 ExtraData
=self
.FdfFile
)
421 if FfsFile
.NameGuid
!= None:
422 _CheckPCDAsGuidPattern
= re
.compile("^PCD\(.+\..+\)$")
425 # If the NameGuid reference a PCD name.
426 # The style must match: PCD(xxxx.yyy)
428 if _CheckPCDAsGuidPattern
.match(FfsFile
.NameGuid
):
430 # Replace the PCD value.
432 _PcdName
= FfsFile
.NameGuid
.lstrip("PCD(").rstrip(")")
434 for Pa
in self
.AutoGenObjectList
:
436 for PcdItem
in Pa
.AllPcdList
:
437 if (PcdItem
.TokenSpaceGuidCName
+ "." + PcdItem
.TokenCName
) == _PcdName
:
439 # First convert from CFormatGuid to GUID string
441 _PcdGuidString
= GuidStructureStringToGuidString(PcdItem
.DefaultValue
)
443 if not _PcdGuidString
:
445 # Then try Byte array.
447 _PcdGuidString
= GuidStructureByteArrayToGuidString(PcdItem
.DefaultValue
)
449 if not _PcdGuidString
:
451 # Not Byte array or CFormat GUID, raise error.
453 EdkLogger
.error("build",
455 "The format of PCD value is incorrect. PCD: %s , Value: %s\n"%(_PcdName
, PcdItem
.DefaultValue
),
456 ExtraData
=self
.FdfFile
)
458 if not _PcdGuidString
.upper() in _GuidDict
.keys():
459 _GuidDict
[_PcdGuidString
.upper()] = FfsFile
463 EdkLogger
.error("build",
465 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s"%(FfsFile
.CurrentLineNum
,
466 FfsFile
.CurrentLineContent
,
467 _GuidDict
[_PcdGuidString
.upper()].CurrentLineNum
,
468 _GuidDict
[_PcdGuidString
.upper()].CurrentLineContent
,
469 FfsFile
.NameGuid
.upper()),
470 ExtraData
=self
.FdfFile
)
472 if not FfsFile
.NameGuid
.upper() in _GuidDict
.keys():
473 _GuidDict
[FfsFile
.NameGuid
.upper()] = FfsFile
476 # Two raw file GUID conflict.
478 EdkLogger
.error("build",
480 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s"%(FfsFile
.CurrentLineNum
,
481 FfsFile
.CurrentLineContent
,
482 _GuidDict
[FfsFile
.NameGuid
.upper()].CurrentLineNum
,
483 _GuidDict
[FfsFile
.NameGuid
.upper()].CurrentLineContent
,
484 FfsFile
.NameGuid
.upper()),
485 ExtraData
=self
.FdfFile
)
488 def _CheckPcdDefineAndType(self
):
490 "FixedAtBuild", "PatchableInModule", "FeatureFlag",
491 "Dynamic", #"DynamicHii", "DynamicVpd",
492 "DynamicEx", # "DynamicExHii", "DynamicExVpd"
495 # This dict store PCDs which are not used by any modules with specified arches
497 for Pa
in self
.AutoGenObjectList
:
498 # Key of DSC's Pcds dictionary is PcdCName, TokenSpaceGuid
499 for Pcd
in Pa
.Platform
.Pcds
:
500 PcdType
= Pa
.Platform
.Pcds
[Pcd
].Type
502 # If no PCD type, this PCD comes from FDF
506 # Try to remove Hii and Vpd suffix
507 if PcdType
.startswith("DynamicEx"):
508 PcdType
= "DynamicEx"
509 elif PcdType
.startswith("Dynamic"):
512 for Package
in Pa
.PackageList
:
513 # Key of DEC's Pcds dictionary is PcdCName, TokenSpaceGuid, PcdType
514 if (Pcd
[0], Pcd
[1], PcdType
) in Package
.Pcds
:
516 for Type
in PcdTypeList
:
517 if (Pcd
[0], Pcd
[1], Type
) in Package
.Pcds
:
521 "Type [%s] of PCD [%s.%s] in DSC file doesn't match the type [%s] defined in DEC file." \
522 % (Pa
.Platform
.Pcds
[Pcd
].Type
, Pcd
[1], Pcd
[0], Type
),
527 UnusedPcd
.setdefault(Pcd
, []).append(Pa
.Arch
)
529 for Pcd
in UnusedPcd
:
532 "The PCD was not specified by any INF module in the platform for the given architecture.\n"
533 "\tPCD: [%s.%s]\n\tPlatform: [%s]\n\tArch: %s"
534 % (Pcd
[1], Pcd
[0], os
.path
.basename(str(self
.MetaFile
)), str(UnusedPcd
[Pcd
])),
539 return "%s [%s]" % (self
.MetaFile
, ", ".join(self
.ArchList
))
541 ## Return the directory to store FV files
543 if self
._FvDir
== None:
544 self
._FvDir
= path
.join(self
.BuildDir
, 'FV')
547 ## Return the directory to store all intermediate and final files built
548 def _GetBuildDir(self
):
549 return self
.AutoGenObjectList
[0].BuildDir
551 ## Return the build output directory platform specifies
552 def _GetOutputDir(self
):
553 return self
.Platform
.OutputDirectory
555 ## Return platform name
557 return self
.Platform
.PlatformName
559 ## Return meta-file GUID
561 return self
.Platform
.Guid
563 ## Return platform version
564 def _GetVersion(self
):
565 return self
.Platform
.Version
567 ## Return paths of tools
568 def _GetToolDefinition(self
):
569 return self
.AutoGenObjectList
[0].ToolDefinition
571 ## Return directory of platform makefile
573 # @retval string Makefile directory
575 def _GetMakeFileDir(self
):
576 if self
._MakeFileDir
== None:
577 self
._MakeFileDir
= self
.BuildDir
578 return self
._MakeFileDir
580 ## Return build command string
582 # @retval string Build command string
584 def _GetBuildCommand(self
):
585 if self
._BuildCommand
== None:
586 # BuildCommand should be all the same. So just get one from platform AutoGen
587 self
._BuildCommand
= self
.AutoGenObjectList
[0].BuildCommand
588 return self
._BuildCommand
590 ## Check the PCDs token value conflict in each DEC file.
592 # Will cause build break and raise error message while two PCDs conflict.
596 def _CheckAllPcdsTokenValueConflict(self
):
597 for Pa
in self
.AutoGenObjectList
:
598 for Package
in Pa
.PackageList
:
599 PcdList
= Package
.Pcds
.values()
600 PcdList
.sort(lambda x
, y
: cmp(x
.TokenValue
, y
.TokenValue
))
602 while (Count
< len(PcdList
) - 1) :
603 Item
= PcdList
[Count
]
604 ItemNext
= PcdList
[Count
+ 1]
606 # Make sure in the same token space the TokenValue should be unique
608 if (Item
.TokenValue
== ItemNext
.TokenValue
):
609 SameTokenValuePcdList
= []
610 SameTokenValuePcdList
.append(Item
)
611 SameTokenValuePcdList
.append(ItemNext
)
612 RemainPcdListLength
= len(PcdList
) - Count
- 2
613 for ValueSameCount
in range(RemainPcdListLength
):
614 if PcdList
[len(PcdList
) - RemainPcdListLength
+ ValueSameCount
].TokenValue
== Item
.TokenValue
:
615 SameTokenValuePcdList
.append(PcdList
[len(PcdList
) - RemainPcdListLength
+ ValueSameCount
])
619 # Sort same token value PCD list with TokenGuid and TokenCName
621 SameTokenValuePcdList
.sort(lambda x
, y
: cmp("%s.%s"%(x
.TokenSpaceGuidCName
, x
.TokenCName
), "%s.%s"%(y
.TokenSpaceGuidCName
, y
.TokenCName
)))
622 SameTokenValuePcdListCount
= 0
623 while (SameTokenValuePcdListCount
< len(SameTokenValuePcdList
) - 1):
624 TemListItem
= SameTokenValuePcdList
[SameTokenValuePcdListCount
]
625 TemListItemNext
= SameTokenValuePcdList
[SameTokenValuePcdListCount
+ 1]
627 if (TemListItem
.TokenSpaceGuidCName
== TemListItemNext
.TokenSpaceGuidCName
) and (TemListItem
.TokenCName
!= TemListItemNext
.TokenCName
):
631 "The TokenValue [%s] of PCD [%s.%s] is conflict with: [%s.%s] in %s"\
632 % (TemListItem
.TokenValue
, TemListItem
.TokenSpaceGuidCName
, TemListItem
.TokenCName
, TemListItemNext
.TokenSpaceGuidCName
, TemListItemNext
.TokenCName
, Package
),
635 SameTokenValuePcdListCount
+= 1
636 Count
+= SameTokenValuePcdListCount
639 PcdList
= Package
.Pcds
.values()
640 PcdList
.sort(lambda x
, y
: cmp("%s.%s"%(x
.TokenSpaceGuidCName
, x
.TokenCName
), "%s.%s"%(y
.TokenSpaceGuidCName
, y
.TokenCName
)))
642 while (Count
< len(PcdList
) - 1) :
643 Item
= PcdList
[Count
]
644 ItemNext
= PcdList
[Count
+ 1]
646 # Check PCDs with same TokenSpaceGuidCName.TokenCName have same token value as well.
648 if (Item
.TokenSpaceGuidCName
== ItemNext
.TokenSpaceGuidCName
) and (Item
.TokenCName
== ItemNext
.TokenCName
) and (Item
.TokenValue
!= ItemNext
.TokenValue
):
652 "The TokenValue [%s] of PCD [%s.%s] in %s defined in two places should be same as well."\
653 % (Item
.TokenValue
, Item
.TokenSpaceGuidCName
, Item
.TokenCName
, Package
),
658 def _GenFdsCommand(self
):
659 return (GenMake
.TopLevelMakefile(self
)._TEMPLATE
_.Replace(GenMake
.TopLevelMakefile(self
)._TemplateDict
)).strip()
661 ## Create makefile for the platform and modules in it
663 # @param CreateDepsMakeFile Flag indicating if the makefile for
664 # modules will be created as well
666 def CreateMakeFile(self
, CreateDepsMakeFile
=False):
667 if CreateDepsMakeFile
:
668 for Pa
in self
.AutoGenObjectList
:
669 Pa
.CreateMakeFile(CreateDepsMakeFile
)
671 ## Create autogen code for platform and modules
673 # Since there's no autogen code for platform, this method will do nothing
674 # if CreateModuleCodeFile is set to False.
676 # @param CreateDepsCodeFile Flag indicating if creating module's
677 # autogen code file or not
679 def CreateCodeFile(self
, CreateDepsCodeFile
=False):
680 if not CreateDepsCodeFile
:
682 for Pa
in self
.AutoGenObjectList
:
683 Pa
.CreateCodeFile(CreateDepsCodeFile
)
685 ## Create AsBuilt INF file the platform
687 def CreateAsBuiltInf(self
):
690 Name
= property(_GetName
)
691 Guid
= property(_GetGuid
)
692 Version
= property(_GetVersion
)
693 OutputDir
= property(_GetOutputDir
)
695 ToolDefinition
= property(_GetToolDefinition
) # toolcode : tool path
697 BuildDir
= property(_GetBuildDir
)
698 FvDir
= property(_GetFvDir
)
699 MakeFileDir
= property(_GetMakeFileDir
)
700 BuildCommand
= property(_GetBuildCommand
)
701 GenFdsCommand
= property(_GenFdsCommand
)
703 ## AutoGen class for platform
705 # PlatformAutoGen class will process the original information in platform
706 # file in order to generate makefile for platform.
708 class PlatformAutoGen(AutoGen
):
710 # Used to store all PCDs for both PEI and DXE phase, in order to generate
711 # correct PCD database
714 _NonDynaPcdList_
= []
717 # The priority list while override build option
719 PrioList
= {"0x11111" : 16, # TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE (Highest)
720 "0x01111" : 15, # ******_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
721 "0x10111" : 14, # TARGET_*********_ARCH_COMMANDTYPE_ATTRIBUTE
722 "0x00111" : 13, # ******_*********_ARCH_COMMANDTYPE_ATTRIBUTE
723 "0x11011" : 12, # TARGET_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
724 "0x01011" : 11, # ******_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
725 "0x10011" : 10, # TARGET_*********_****_COMMANDTYPE_ATTRIBUTE
726 "0x00011" : 9, # ******_*********_****_COMMANDTYPE_ATTRIBUTE
727 "0x11101" : 8, # TARGET_TOOLCHAIN_ARCH_***********_ATTRIBUTE
728 "0x01101" : 7, # ******_TOOLCHAIN_ARCH_***********_ATTRIBUTE
729 "0x10101" : 6, # TARGET_*********_ARCH_***********_ATTRIBUTE
730 "0x00101" : 5, # ******_*********_ARCH_***********_ATTRIBUTE
731 "0x11001" : 4, # TARGET_TOOLCHAIN_****_***********_ATTRIBUTE
732 "0x01001" : 3, # ******_TOOLCHAIN_****_***********_ATTRIBUTE
733 "0x10001" : 2, # TARGET_*********_****_***********_ATTRIBUTE
734 "0x00001" : 1} # ******_*********_****_***********_ATTRIBUTE (Lowest)
736 ## The real constructor of PlatformAutoGen
738 # This method is not supposed to be called by users of PlatformAutoGen. It's
739 # only used by factory method __new__() to do real initialization work for an
740 # object of PlatformAutoGen
742 # @param Workspace WorkspaceAutoGen object
743 # @param PlatformFile Platform file (DSC file)
744 # @param Target Build target (DEBUG, RELEASE)
745 # @param Toolchain Name of tool chain
746 # @param Arch arch of the platform supports
748 def _Init(self
, Workspace
, PlatformFile
, Target
, Toolchain
, Arch
):
749 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "AutoGen platform [%s] [%s]" % (PlatformFile
, Arch
))
750 GlobalData
.gProcessingFile
= "%s [%s, %s, %s]" % (PlatformFile
, Arch
, Toolchain
, Target
)
752 self
.MetaFile
= PlatformFile
753 self
.Workspace
= Workspace
754 self
.WorkspaceDir
= Workspace
.WorkspaceDir
755 self
.ToolChain
= Toolchain
756 self
.BuildTarget
= Target
758 self
.SourceDir
= PlatformFile
.SubDir
759 self
.SourceOverrideDir
= None
760 self
.FdTargetList
= self
.Workspace
.FdTargetList
761 self
.FvTargetList
= self
.Workspace
.FvTargetList
764 # flag indicating if the makefile/C-code file has been created or not
765 self
.IsMakeFileCreated
= False
766 self
.IsCodeFileCreated
= False
768 self
._Platform
= None
773 self
._BuildRule
= None
774 self
._SourceDir
= None
775 self
._BuildDir
= None
776 self
._OutputDir
= None
778 self
._MakeFileDir
= None
781 self
._PcdTokenNumber
= None # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber
782 self
._DynamicPcdList
= None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
783 self
._NonDynamicPcdList
= None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
784 self
._NonDynamicPcdDict
= {}
786 self
._ToolDefinitions
= None
787 self
._ToolDefFile
= None # toolcode : tool path
788 self
._ToolChainFamily
= None
789 self
._BuildRuleFamily
= None
790 self
._BuildOption
= None # toolcode : option
791 self
._EdkBuildOption
= None # edktoolcode : option
792 self
._EdkIIBuildOption
= None # edkiitoolcode : option
793 self
._PackageList
= None
794 self
._ModuleAutoGenList
= None
795 self
._LibraryAutoGenList
= None
796 self
._BuildCommand
= None
798 # get library/modules for build
799 self
.LibraryBuildDirectoryList
= []
800 self
.ModuleBuildDirectoryList
= []
801 # get the original module/package/platform objects
802 self
.BuildDatabase
= Workspace
.BuildDatabase
806 return "%s [%s]" % (self
.MetaFile
, self
.Arch
)
808 ## Create autogen code for platform and modules
810 # Since there's no autogen code for platform, this method will do nothing
811 # if CreateModuleCodeFile is set to False.
813 # @param CreateModuleCodeFile Flag indicating if creating module's
814 # autogen code file or not
816 def CreateCodeFile(self
, CreateModuleCodeFile
=False):
817 # only module has code to be greated, so do nothing if CreateModuleCodeFile is False
818 if self
.IsCodeFileCreated
or not CreateModuleCodeFile
:
821 for Ma
in self
.ModuleAutoGenList
:
822 Ma
.CreateCodeFile(True)
824 # don't do this twice
825 self
.IsCodeFileCreated
= True
827 ## Generate Fds Command
828 def _GenFdsCommand(self
):
829 return self
.Workspace
.GenFdsCommand
831 ## Create makefile for the platform and mdoules in it
833 # @param CreateModuleMakeFile Flag indicating if the makefile for
834 # modules will be created as well
836 def CreateMakeFile(self
, CreateModuleMakeFile
=False):
837 if CreateModuleMakeFile
:
838 for ModuleFile
in self
.Platform
.Modules
:
839 Ma
= ModuleAutoGen(self
.Workspace
, ModuleFile
, self
.BuildTarget
,
840 self
.ToolChain
, self
.Arch
, self
.MetaFile
)
841 Ma
.CreateMakeFile(True)
842 Ma
.CreateAsBuiltInf()
844 # no need to create makefile for the platform more than once
845 if self
.IsMakeFileCreated
:
848 # create library/module build dirs for platform
849 Makefile
= GenMake
.PlatformMakefile(self
)
850 self
.LibraryBuildDirectoryList
= Makefile
.GetLibraryBuildDirectoryList()
851 self
.ModuleBuildDirectoryList
= Makefile
.GetModuleBuildDirectoryList()
853 self
.IsMakeFileCreated
= True
855 ## Deal with Shared FixedAtBuild Pcds
857 def CollectFixedAtBuildPcds(self
):
858 for LibAuto
in self
.LibraryAutoGenList
:
859 FixedAtBuildPcds
= {}
860 ShareFixedAtBuildPcdsSameValue
= {}
861 for Module
in LibAuto
._ReferenceModules
:
862 for Pcd
in Module
.FixedAtBuildPcds
+ LibAuto
.FixedAtBuildPcds
:
863 key
= ".".join((Pcd
.TokenSpaceGuidCName
,Pcd
.TokenCName
))
864 if key
not in FixedAtBuildPcds
:
865 ShareFixedAtBuildPcdsSameValue
[key
] = True
866 FixedAtBuildPcds
[key
] = Pcd
.DefaultValue
868 if FixedAtBuildPcds
[key
] != Pcd
.DefaultValue
:
869 ShareFixedAtBuildPcdsSameValue
[key
] = False
870 for Pcd
in LibAuto
.FixedAtBuildPcds
:
871 key
= ".".join((Pcd
.TokenSpaceGuidCName
,Pcd
.TokenCName
))
872 if (Pcd
.TokenCName
,Pcd
.TokenSpaceGuidCName
) not in self
.NonDynamicPcdDict
:
875 DscPcd
= self
.NonDynamicPcdDict
[(Pcd
.TokenCName
,Pcd
.TokenSpaceGuidCName
)]
876 if DscPcd
.Type
!= "FixedAtBuild":
878 if key
in ShareFixedAtBuildPcdsSameValue
and ShareFixedAtBuildPcdsSameValue
[key
]:
879 LibAuto
.ConstPcd
[key
] = Pcd
.DefaultValue
881 ## Collect dynamic PCDs
883 # Gather dynamic PCDs list from each module and their settings from platform
884 # This interface should be invoked explicitly when platform action is created.
886 def CollectPlatformDynamicPcds(self
):
887 # for gathering error information
888 NoDatumTypePcdList
= set()
891 for F
in self
.Platform
.Modules
.keys():
892 M
= ModuleAutoGen(self
.Workspace
, F
, self
.BuildTarget
, self
.ToolChain
, self
.Arch
, self
.MetaFile
)
893 #GuidValue.update(M.Guids)
895 self
.Platform
.Modules
[F
].M
= M
897 for PcdFromModule
in M
.ModulePcdList
+M
.LibraryPcdList
:
898 # make sure that the "VOID*" kind of datum has MaxDatumSize set
899 if PcdFromModule
.DatumType
== "VOID*" and PcdFromModule
.MaxDatumSize
in [None, '']:
900 NoDatumTypePcdList
.add("%s.%s [%s]" % (PcdFromModule
.TokenSpaceGuidCName
, PcdFromModule
.TokenCName
, F
))
902 if PcdFromModule
.Type
in GenC
.gDynamicPcd
or PcdFromModule
.Type
in GenC
.gDynamicExPcd
:
904 # If a dynamic PCD used by a PEM module/PEI module & DXE module,
905 # it should be stored in Pcd PEI database, If a dynamic only
906 # used by DXE module, it should be stored in DXE PCD database.
907 # The default Phase is DXE
909 if M
.ModuleType
in ["PEIM", "PEI_CORE"]:
910 PcdFromModule
.Phase
= "PEI"
911 if PcdFromModule
not in self
._DynaPcdList
_:
912 self
._DynaPcdList
_.append(PcdFromModule
)
913 elif PcdFromModule
.Phase
== 'PEI':
914 # overwrite any the same PCD existing, if Phase is PEI
915 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
916 self
._DynaPcdList
_[Index
] = PcdFromModule
917 elif PcdFromModule
not in self
._NonDynaPcdList
_:
918 self
._NonDynaPcdList
_.append(PcdFromModule
)
920 # print out error information and break the build, if error found
921 if len(NoDatumTypePcdList
) > 0:
922 NoDatumTypePcdListString
= "\n\t\t".join(NoDatumTypePcdList
)
923 EdkLogger
.error("build", AUTOGEN_ERROR
, "PCD setting error",
925 ExtraData
="\n\tPCD(s) without MaxDatumSize:\n\t\t%s\n"
926 % NoDatumTypePcdListString
)
927 self
._NonDynamicPcdList
= self
._NonDynaPcdList
_
928 self
._DynamicPcdList
= self
._DynaPcdList
_
929 self
.AllPcdList
= self
._NonDynamicPcdList
+ self
._DynamicPcdList
932 # Sort dynamic PCD list to:
933 # 1) If PCD's datum type is VOID* and value is unicode string which starts with L, the PCD item should
934 # try to be put header of dynamicd List
935 # 2) If PCD is HII type, the PCD item should be put after unicode type PCD
937 # The reason of sorting is make sure the unicode string is in double-byte alignment in string table.
943 VpdFile
= VpdInfoFile
.VpdInfoFile()
944 NeedProcessVpdMapFile
= False
946 if (self
.Workspace
.ArchList
[-1] == self
.Arch
):
947 for Pcd
in self
._DynamicPcdList
:
948 # just pick the a value to determine whether is unicode string type
949 Sku
= Pcd
.SkuInfoList
[Pcd
.SkuInfoList
.keys()[0]]
950 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
952 PcdValue
= Sku
.DefaultValue
953 if Pcd
.DatumType
== 'VOID*' and PcdValue
.startswith("L"):
954 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
955 UnicodePcdArray
.append(Pcd
)
956 elif len(Sku
.VariableName
) > 0:
957 # if found HII type PCD then insert to right of UnicodeIndex
958 HiiPcdArray
.append(Pcd
)
960 OtherPcdArray
.append(Pcd
)
961 if Pcd
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
]:
962 VpdPcdDict
[(Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
)] = Pcd
964 PlatformPcds
= self
.Platform
.Pcds
.keys()
967 # Add VPD type PCD into VpdFile and determine whether the VPD PCD need to be fixed up.
969 for PcdKey
in PlatformPcds
:
970 Pcd
= self
.Platform
.Pcds
[PcdKey
]
971 if Pcd
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
] and \
972 PcdKey
in VpdPcdDict
:
973 Pcd
= VpdPcdDict
[PcdKey
]
974 for (SkuName
,Sku
) in Pcd
.SkuInfoList
.items():
975 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
976 VpdFile
.Add(Pcd
, Sku
.VpdOffset
)
977 # if the offset of a VPD is *, then it need to be fixed up by third party tool.
978 if not NeedProcessVpdMapFile
and Sku
.VpdOffset
== "*":
979 NeedProcessVpdMapFile
= True
980 if self
.Platform
.VpdToolGuid
== None or self
.Platform
.VpdToolGuid
== '':
981 EdkLogger
.error("Build", FILE_NOT_FOUND
, \
982 "Fail to find third-party BPDG tool to process VPD PCDs. BPDG Guid tool need to be defined in tools_def.txt and VPD_TOOL_GUID need to be provided in DSC file.")
986 # Fix the PCDs define in VPD PCD section that never referenced by module.
987 # An example is PCD for signature usage.
989 for DscPcd
in PlatformPcds
:
990 DscPcdEntry
= self
.Platform
.Pcds
[DscPcd
]
991 if DscPcdEntry
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
]:
992 if not (self
.Platform
.VpdToolGuid
== None or self
.Platform
.VpdToolGuid
== ''):
994 for VpdPcd
in VpdFile
._VpdArray
.keys():
995 # This PCD has been referenced by module
996 if (VpdPcd
.TokenSpaceGuidCName
== DscPcdEntry
.TokenSpaceGuidCName
) and \
997 (VpdPcd
.TokenCName
== DscPcdEntry
.TokenCName
):
1000 # Not found, it should be signature
1002 # just pick the a value to determine whether is unicode string type
1003 for (SkuName
,Sku
) in DscPcdEntry
.SkuInfoList
.items():
1004 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1006 # Need to iterate DEC pcd information to get the value & datumtype
1007 for eachDec
in self
.PackageList
:
1008 for DecPcd
in eachDec
.Pcds
:
1009 DecPcdEntry
= eachDec
.Pcds
[DecPcd
]
1010 if (DecPcdEntry
.TokenSpaceGuidCName
== DscPcdEntry
.TokenSpaceGuidCName
) and \
1011 (DecPcdEntry
.TokenCName
== DscPcdEntry
.TokenCName
):
1012 # Print warning message to let the developer make a determine.
1013 EdkLogger
.warn("build", "Unreferenced vpd pcd used!",
1014 File
=self
.MetaFile
, \
1015 ExtraData
= "PCD: %s.%s used in the DSC file %s is unreferenced." \
1016 %(DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
, self
.Platform
.MetaFile
.Path
))
1018 DscPcdEntry
.DatumType
= DecPcdEntry
.DatumType
1019 DscPcdEntry
.DefaultValue
= DecPcdEntry
.DefaultValue
1020 DscPcdEntry
.TokenValue
= DecPcdEntry
.TokenValue
1021 DscPcdEntry
.TokenSpaceGuidValue
= eachDec
.Guids
[DecPcdEntry
.TokenSpaceGuidCName
]
1022 # Only fix the value while no value provided in DSC file.
1023 if (Sku
.DefaultValue
== "" or Sku
.DefaultValue
==None):
1024 DscPcdEntry
.SkuInfoList
[DscPcdEntry
.SkuInfoList
.keys()[0]].DefaultValue
= DecPcdEntry
.DefaultValue
1026 if DscPcdEntry
not in self
._DynamicPcdList
:
1027 self
._DynamicPcdList
.append(DscPcdEntry
)
1028 # Sku = DscPcdEntry.SkuInfoList[DscPcdEntry.SkuInfoList.keys()[0]]
1029 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1030 PcdValue
= Sku
.DefaultValue
1031 VpdFile
.Add(DscPcdEntry
, Sku
.VpdOffset
)
1032 if not NeedProcessVpdMapFile
and Sku
.VpdOffset
== "*":
1033 NeedProcessVpdMapFile
= True
1034 if DscPcdEntry
.DatumType
== 'VOID*' and PcdValue
.startswith("L"):
1035 UnicodePcdArray
.append(DscPcdEntry
)
1036 elif len(Sku
.VariableName
) > 0:
1037 HiiPcdArray
.append(DscPcdEntry
)
1039 OtherPcdArray
.append(DscPcdEntry
)
1041 # if the offset of a VPD is *, then it need to be fixed up by third party tool.
1045 if (self
.Platform
.FlashDefinition
== None or self
.Platform
.FlashDefinition
== '') and \
1046 VpdFile
.GetCount() != 0:
1047 EdkLogger
.error("build", ATTRIBUTE_NOT_AVAILABLE
,
1048 "Fail to get FLASH_DEFINITION definition in DSC file %s which is required when DSC contains VPD PCD." % str(self
.Platform
.MetaFile
))
1050 if VpdFile
.GetCount() != 0:
1051 DscTimeStamp
= self
.Platform
.MetaFile
.TimeStamp
1052 FvPath
= os
.path
.join(self
.BuildDir
, "FV")
1053 if not os
.path
.exists(FvPath
):
1057 EdkLogger
.error("build", FILE_WRITE_FAILURE
, "Fail to create FV folder under %s" % self
.BuildDir
)
1060 VpdFilePath
= os
.path
.join(FvPath
, "%s.txt" % self
.Platform
.VpdToolGuid
)
1063 if not os
.path
.exists(VpdFilePath
) or os
.path
.getmtime(VpdFilePath
) < DscTimeStamp
:
1064 VpdFile
.Write(VpdFilePath
)
1066 # retrieve BPDG tool's path from tool_def.txt according to VPD_TOOL_GUID defined in DSC file.
1068 for ToolDef
in self
.ToolDefinition
.values():
1069 if ToolDef
.has_key("GUID") and ToolDef
["GUID"] == self
.Platform
.VpdToolGuid
:
1070 if not ToolDef
.has_key("PATH"):
1071 EdkLogger
.error("build", ATTRIBUTE_NOT_AVAILABLE
, "PATH attribute was not provided for BPDG guid tool %s in tools_def.txt" % self
.Platform
.VpdToolGuid
)
1072 BPDGToolName
= ToolDef
["PATH"]
1074 # Call third party GUID BPDG tool.
1075 if BPDGToolName
!= None:
1076 VpdInfoFile
.CallExtenalBPDGTool(BPDGToolName
, VpdFilePath
)
1078 EdkLogger
.error("Build", FILE_NOT_FOUND
, "Fail to find third-party BPDG tool to process VPD PCDs. BPDG Guid tool need to be defined in tools_def.txt and VPD_TOOL_GUID need to be provided in DSC file.")
1080 # Process VPD map file generated by third party BPDG tool
1081 if NeedProcessVpdMapFile
:
1082 VpdMapFilePath
= os
.path
.join(self
.BuildDir
, "FV", "%s.map" % self
.Platform
.VpdToolGuid
)
1083 if os
.path
.exists(VpdMapFilePath
):
1084 VpdFile
.Read(VpdMapFilePath
)
1087 for Pcd
in self
._DynamicPcdList
:
1088 # just pick the a value to determine whether is unicode string type
1090 for (SkuName
,Sku
) in Pcd
.SkuInfoList
.items():
1091 if Sku
.VpdOffset
== "*":
1092 Sku
.VpdOffset
= VpdFile
.GetOffset(Pcd
)[i
].strip()
1095 EdkLogger
.error("build", FILE_READ_FAILURE
, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath
)
1097 # Delete the DynamicPcdList At the last time enter into this function
1098 del self
._DynamicPcdList
[:]
1099 self
._DynamicPcdList
.extend(UnicodePcdArray
)
1100 self
._DynamicPcdList
.extend(HiiPcdArray
)
1101 self
._DynamicPcdList
.extend(OtherPcdArray
)
1104 ## Return the platform build data object
1105 def _GetPlatform(self
):
1106 if self
._Platform
== None:
1107 self
._Platform
= self
.BuildDatabase
[self
.MetaFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1108 return self
._Platform
1110 ## Return platform name
1112 return self
.Platform
.PlatformName
1114 ## Return the meta file GUID
1116 return self
.Platform
.Guid
1118 ## Return the platform version
1119 def _GetVersion(self
):
1120 return self
.Platform
.Version
1122 ## Return the FDF file name
1123 def _GetFdfFile(self
):
1124 if self
._FdfFile
== None:
1125 if self
.Workspace
.FdfFile
!= "":
1126 self
._FdfFile
= path
.join(self
.WorkspaceDir
, self
.Workspace
.FdfFile
)
1129 return self
._FdfFile
1131 ## Return the build output directory platform specifies
1132 def _GetOutputDir(self
):
1133 return self
.Platform
.OutputDirectory
1135 ## Return the directory to store all intermediate and final files built
1136 def _GetBuildDir(self
):
1137 if self
._BuildDir
== None:
1138 if os
.path
.isabs(self
.OutputDir
):
1139 self
._BuildDir
= path
.join(
1140 path
.abspath(self
.OutputDir
),
1141 self
.BuildTarget
+ "_" + self
.ToolChain
,
1144 self
._BuildDir
= path
.join(
1147 self
.BuildTarget
+ "_" + self
.ToolChain
,
1149 return self
._BuildDir
1151 ## Return directory of platform makefile
1153 # @retval string Makefile directory
1155 def _GetMakeFileDir(self
):
1156 if self
._MakeFileDir
== None:
1157 self
._MakeFileDir
= path
.join(self
.BuildDir
, self
.Arch
)
1158 return self
._MakeFileDir
1160 ## Return build command string
1162 # @retval string Build command string
1164 def _GetBuildCommand(self
):
1165 if self
._BuildCommand
== None:
1166 self
._BuildCommand
= []
1167 if "MAKE" in self
.ToolDefinition
and "PATH" in self
.ToolDefinition
["MAKE"]:
1168 self
._BuildCommand
+= SplitOption(self
.ToolDefinition
["MAKE"]["PATH"])
1169 if "FLAGS" in self
.ToolDefinition
["MAKE"]:
1170 NewOption
= self
.ToolDefinition
["MAKE"]["FLAGS"].strip()
1172 self
._BuildCommand
+= SplitOption(NewOption
)
1173 return self
._BuildCommand
1175 ## Get tool chain definition
1177 # Get each tool defition for given tool chain from tools_def.txt and platform
1179 def _GetToolDefinition(self
):
1180 if self
._ToolDefinitions
== None:
1181 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDictionary
1182 if TAB_TOD_DEFINES_COMMAND_TYPE
not in self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
:
1183 EdkLogger
.error('build', RESOURCE_NOT_AVAILABLE
, "No tools found in configuration",
1184 ExtraData
="[%s]" % self
.MetaFile
)
1185 self
._ToolDefinitions
= {}
1187 for Def
in ToolDefinition
:
1188 Target
, Tag
, Arch
, Tool
, Attr
= Def
.split("_")
1189 if Target
!= self
.BuildTarget
or Tag
!= self
.ToolChain
or Arch
!= self
.Arch
:
1192 Value
= ToolDefinition
[Def
]
1193 # don't record the DLL
1195 DllPathList
.add(Value
)
1198 if Tool
not in self
._ToolDefinitions
:
1199 self
._ToolDefinitions
[Tool
] = {}
1200 self
._ToolDefinitions
[Tool
][Attr
] = Value
1204 if GlobalData
.gOptions
.SilentMode
and "MAKE" in self
._ToolDefinitions
:
1205 if "FLAGS" not in self
._ToolDefinitions
["MAKE"]:
1206 self
._ToolDefinitions
["MAKE"]["FLAGS"] = ""
1207 self
._ToolDefinitions
["MAKE"]["FLAGS"] += " -s"
1209 for Tool
in self
._ToolDefinitions
:
1210 for Attr
in self
._ToolDefinitions
[Tool
]:
1211 Value
= self
._ToolDefinitions
[Tool
][Attr
]
1212 if Tool
in self
.BuildOption
and Attr
in self
.BuildOption
[Tool
]:
1213 # check if override is indicated
1214 if self
.BuildOption
[Tool
][Attr
].startswith('='):
1215 Value
= self
.BuildOption
[Tool
][Attr
][1:]
1217 Value
+= " " + self
.BuildOption
[Tool
][Attr
]
1220 # Don't put MAKE definition in the file
1224 ToolsDef
+= "%s = %s\n" % (Tool
, Value
)
1226 # Don't put MAKE definition in the file
1231 ToolsDef
+= "%s_%s = %s\n" % (Tool
, Attr
, Value
)
1234 SaveFileOnChange(self
.ToolDefinitionFile
, ToolsDef
)
1235 for DllPath
in DllPathList
:
1236 os
.environ
["PATH"] = DllPath
+ os
.pathsep
+ os
.environ
["PATH"]
1237 os
.environ
["MAKE_FLAGS"] = MakeFlags
1239 return self
._ToolDefinitions
1241 ## Return the paths of tools
1242 def _GetToolDefFile(self
):
1243 if self
._ToolDefFile
== None:
1244 self
._ToolDefFile
= os
.path
.join(self
.MakeFileDir
, "TOOLS_DEF." + self
.Arch
)
1245 return self
._ToolDefFile
1247 ## Retrieve the toolchain family of given toolchain tag. Default to 'MSFT'.
1248 def _GetToolChainFamily(self
):
1249 if self
._ToolChainFamily
== None:
1250 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
1251 if TAB_TOD_DEFINES_FAMILY
not in ToolDefinition \
1252 or self
.ToolChain
not in ToolDefinition
[TAB_TOD_DEFINES_FAMILY
] \
1253 or not ToolDefinition
[TAB_TOD_DEFINES_FAMILY
][self
.ToolChain
]:
1254 EdkLogger
.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
1256 self
._ToolChainFamily
= "MSFT"
1258 self
._ToolChainFamily
= ToolDefinition
[TAB_TOD_DEFINES_FAMILY
][self
.ToolChain
]
1259 return self
._ToolChainFamily
1261 def _GetBuildRuleFamily(self
):
1262 if self
._BuildRuleFamily
== None:
1263 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
1264 if TAB_TOD_DEFINES_BUILDRULEFAMILY
not in ToolDefinition \
1265 or self
.ToolChain
not in ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
] \
1266 or not ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
][self
.ToolChain
]:
1267 EdkLogger
.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
1269 self
._BuildRuleFamily
= "MSFT"
1271 self
._BuildRuleFamily
= ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
][self
.ToolChain
]
1272 return self
._BuildRuleFamily
1274 ## Return the build options specific for all modules in this platform
1275 def _GetBuildOptions(self
):
1276 if self
._BuildOption
== None:
1277 self
._BuildOption
= self
._ExpandBuildOption
(self
.Platform
.BuildOptions
)
1278 return self
._BuildOption
1280 ## Return the build options specific for EDK modules in this platform
1281 def _GetEdkBuildOptions(self
):
1282 if self
._EdkBuildOption
== None:
1283 self
._EdkBuildOption
= self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, EDK_NAME
)
1284 return self
._EdkBuildOption
1286 ## Return the build options specific for EDKII modules in this platform
1287 def _GetEdkIIBuildOptions(self
):
1288 if self
._EdkIIBuildOption
== None:
1289 self
._EdkIIBuildOption
= self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, EDKII_NAME
)
1290 return self
._EdkIIBuildOption
1292 ## Parse build_rule.txt in $(WORKSPACE)/Conf/build_rule.txt
1294 # @retval BuildRule object
1296 def _GetBuildRule(self
):
1297 if self
._BuildRule
== None:
1298 BuildRuleFile
= None
1299 if TAB_TAT_DEFINES_BUILD_RULE_CONF
in self
.Workspace
.TargetTxt
.TargetTxtDictionary
:
1300 BuildRuleFile
= self
.Workspace
.TargetTxt
.TargetTxtDictionary
[TAB_TAT_DEFINES_BUILD_RULE_CONF
]
1301 if BuildRuleFile
in [None, '']:
1302 BuildRuleFile
= gBuildRuleFile
1303 self
._BuildRule
= BuildRule(BuildRuleFile
)
1304 if self
._BuildRule
._FileVersion
== "":
1305 self
._BuildRule
._FileVersion
= AutoGenReqBuildRuleVerNum
1307 if self
._BuildRule
._FileVersion
< AutoGenReqBuildRuleVerNum
:
1308 # If Build Rule's version is less than the version number required by the tools, halting the build.
1309 EdkLogger
.error("build", AUTOGEN_ERROR
,
1310 ExtraData
="The version number [%s] of build_rule.txt is less than the version number required by the AutoGen.(the minimum required version number is [%s])"\
1311 % (self
._BuildRule
._FileVersion
, AutoGenReqBuildRuleVerNum
))
1313 return self
._BuildRule
1315 ## Summarize the packages used by modules in this platform
1316 def _GetPackageList(self
):
1317 if self
._PackageList
== None:
1318 self
._PackageList
= set()
1319 for La
in self
.LibraryAutoGenList
:
1320 self
._PackageList
.update(La
.DependentPackageList
)
1321 for Ma
in self
.ModuleAutoGenList
:
1322 self
._PackageList
.update(Ma
.DependentPackageList
)
1323 self
._PackageList
= list(self
._PackageList
)
1324 return self
._PackageList
1326 def _GetNonDynamicPcdDict(self
):
1327 if self
._NonDynamicPcdDict
:
1328 return self
._NonDynamicPcdDict
1329 for Pcd
in self
.NonDynamicPcdList
:
1330 self
._NonDynamicPcdDict
[(Pcd
.TokenCName
,Pcd
.TokenSpaceGuidCName
)] = Pcd
1331 return self
._NonDynamicPcdDict
1333 ## Get list of non-dynamic PCDs
1334 def _GetNonDynamicPcdList(self
):
1335 if self
._NonDynamicPcdList
== None:
1336 self
.CollectPlatformDynamicPcds()
1337 return self
._NonDynamicPcdList
1339 ## Get list of dynamic PCDs
1340 def _GetDynamicPcdList(self
):
1341 if self
._DynamicPcdList
== None:
1342 self
.CollectPlatformDynamicPcds()
1343 return self
._DynamicPcdList
1345 ## Generate Token Number for all PCD
1346 def _GetPcdTokenNumbers(self
):
1347 if self
._PcdTokenNumber
== None:
1348 self
._PcdTokenNumber
= sdict()
1351 # Make the Dynamic and DynamicEx PCD use within different TokenNumber area.
1355 # TokenNumber 0 ~ 10
1357 # TokeNumber 11 ~ 20
1359 for Pcd
in self
.DynamicPcdList
:
1360 if Pcd
.Phase
== "PEI":
1361 if Pcd
.Type
in ["Dynamic", "DynamicDefault", "DynamicVpd", "DynamicHii"]:
1362 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
1363 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
1366 for Pcd
in self
.DynamicPcdList
:
1367 if Pcd
.Phase
== "PEI":
1368 if Pcd
.Type
in ["DynamicEx", "DynamicExDefault", "DynamicExVpd", "DynamicExHii"]:
1369 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
1370 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
1373 for Pcd
in self
.DynamicPcdList
:
1374 if Pcd
.Phase
== "DXE":
1375 if Pcd
.Type
in ["Dynamic", "DynamicDefault", "DynamicVpd", "DynamicHii"]:
1376 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
1377 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
1380 for Pcd
in self
.DynamicPcdList
:
1381 if Pcd
.Phase
== "DXE":
1382 if Pcd
.Type
in ["DynamicEx", "DynamicExDefault", "DynamicExVpd", "DynamicExHii"]:
1383 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
1384 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
1387 for Pcd
in self
.NonDynamicPcdList
:
1388 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
1390 return self
._PcdTokenNumber
1392 ## Summarize ModuleAutoGen objects of all modules/libraries to be built for this platform
1393 def _GetAutoGenObjectList(self
):
1394 self
._ModuleAutoGenList
= []
1395 self
._LibraryAutoGenList
= []
1396 for ModuleFile
in self
.Platform
.Modules
:
1405 if Ma
not in self
._ModuleAutoGenList
:
1406 self
._ModuleAutoGenList
.append(Ma
)
1407 for La
in Ma
.LibraryAutoGenList
:
1408 if La
not in self
._LibraryAutoGenList
:
1409 self
._LibraryAutoGenList
.append(La
)
1410 if Ma
not in La
._ReferenceModules
:
1411 La
._ReferenceModules
.append(Ma
)
1413 ## Summarize ModuleAutoGen objects of all modules to be built for this platform
1414 def _GetModuleAutoGenList(self
):
1415 if self
._ModuleAutoGenList
== None:
1416 self
._GetAutoGenObjectList
()
1417 return self
._ModuleAutoGenList
1419 ## Summarize ModuleAutoGen objects of all libraries to be built for this platform
1420 def _GetLibraryAutoGenList(self
):
1421 if self
._LibraryAutoGenList
== None:
1422 self
._GetAutoGenObjectList
()
1423 return self
._LibraryAutoGenList
1425 ## Test if a module is supported by the platform
1427 # An error will be raised directly if the module or its arch is not supported
1428 # by the platform or current configuration
1430 def ValidModule(self
, Module
):
1431 return Module
in self
.Platform
.Modules
or Module
in self
.Platform
.LibraryInstances
1433 ## Resolve the library classes in a module to library instances
1435 # This method will not only resolve library classes but also sort the library
1436 # instances according to the dependency-ship.
1438 # @param Module The module from which the library classes will be resolved
1440 # @retval library_list List of library instances sorted
1442 def ApplyLibraryInstance(self
, Module
):
1443 ModuleType
= Module
.ModuleType
1445 # for overridding library instances with module specific setting
1446 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
1448 # add forced library instances (specified under LibraryClasses sections)
1450 # If a module has a MODULE_TYPE of USER_DEFINED,
1451 # do not link in NULL library class instances from the global [LibraryClasses.*] sections.
1453 if Module
.ModuleType
!= SUP_MODULE_USER_DEFINED
:
1454 for LibraryClass
in self
.Platform
.LibraryClasses
.GetKeys():
1455 if LibraryClass
.startswith("NULL") and self
.Platform
.LibraryClasses
[LibraryClass
, Module
.ModuleType
]:
1456 Module
.LibraryClasses
[LibraryClass
] = self
.Platform
.LibraryClasses
[LibraryClass
, Module
.ModuleType
]
1458 # add forced library instances (specified in module overrides)
1459 for LibraryClass
in PlatformModule
.LibraryClasses
:
1460 if LibraryClass
.startswith("NULL"):
1461 Module
.LibraryClasses
[LibraryClass
] = PlatformModule
.LibraryClasses
[LibraryClass
]
1464 LibraryConsumerList
= [Module
]
1466 ConsumedByList
= sdict()
1467 LibraryInstance
= sdict()
1469 EdkLogger
.verbose("")
1470 EdkLogger
.verbose("Library instances of module [%s] [%s]:" % (str(Module
), self
.Arch
))
1471 while len(LibraryConsumerList
) > 0:
1472 M
= LibraryConsumerList
.pop()
1473 for LibraryClassName
in M
.LibraryClasses
:
1474 if LibraryClassName
not in LibraryInstance
:
1475 # override library instance for this module
1476 if LibraryClassName
in PlatformModule
.LibraryClasses
:
1477 LibraryPath
= PlatformModule
.LibraryClasses
[LibraryClassName
]
1479 LibraryPath
= self
.Platform
.LibraryClasses
[LibraryClassName
, ModuleType
]
1480 if LibraryPath
== None or LibraryPath
== "":
1481 LibraryPath
= M
.LibraryClasses
[LibraryClassName
]
1482 if LibraryPath
== None or LibraryPath
== "":
1483 EdkLogger
.error("build", RESOURCE_NOT_AVAILABLE
,
1484 "Instance of library class [%s] is not found" % LibraryClassName
,
1486 ExtraData
="in [%s] [%s]\n\tconsumed by module [%s]" % (str(M
), self
.Arch
, str(Module
)))
1488 LibraryModule
= self
.BuildDatabase
[LibraryPath
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1489 # for those forced library instance (NULL library), add a fake library class
1490 if LibraryClassName
.startswith("NULL"):
1491 LibraryModule
.LibraryClass
.append(LibraryClassObject(LibraryClassName
, [ModuleType
]))
1492 elif LibraryModule
.LibraryClass
== None \
1493 or len(LibraryModule
.LibraryClass
) == 0 \
1494 or (ModuleType
!= 'USER_DEFINED'
1495 and ModuleType
not in LibraryModule
.LibraryClass
[0].SupModList
):
1496 # only USER_DEFINED can link against any library instance despite of its SupModList
1497 EdkLogger
.error("build", OPTION_MISSING
,
1498 "Module type [%s] is not supported by library instance [%s]" \
1499 % (ModuleType
, LibraryPath
), File
=self
.MetaFile
,
1500 ExtraData
="consumed by [%s]" % str(Module
))
1502 LibraryInstance
[LibraryClassName
] = LibraryModule
1503 LibraryConsumerList
.append(LibraryModule
)
1504 EdkLogger
.verbose("\t" + str(LibraryClassName
) + " : " + str(LibraryModule
))
1506 LibraryModule
= LibraryInstance
[LibraryClassName
]
1508 if LibraryModule
== None:
1511 if LibraryModule
.ConstructorList
!= [] and LibraryModule
not in Constructor
:
1512 Constructor
.append(LibraryModule
)
1514 if LibraryModule
not in ConsumedByList
:
1515 ConsumedByList
[LibraryModule
] = []
1516 # don't add current module itself to consumer list
1518 if M
in ConsumedByList
[LibraryModule
]:
1520 ConsumedByList
[LibraryModule
].append(M
)
1522 # Initialize the sorted output list to the empty set
1524 SortedLibraryList
= []
1526 # Q <- Set of all nodes with no incoming edges
1528 LibraryList
= [] #LibraryInstance.values()
1530 for LibraryClassName
in LibraryInstance
:
1531 M
= LibraryInstance
[LibraryClassName
]
1532 LibraryList
.append(M
)
1533 if ConsumedByList
[M
] == []:
1537 # start the DAG algorithm
1541 while Q
== [] and EdgeRemoved
:
1543 # for each node Item with a Constructor
1544 for Item
in LibraryList
:
1545 if Item
not in Constructor
:
1547 # for each Node without a constructor with an edge e from Item to Node
1548 for Node
in ConsumedByList
[Item
]:
1549 if Node
in Constructor
:
1551 # remove edge e from the graph if Node has no constructor
1552 ConsumedByList
[Item
].remove(Node
)
1554 if ConsumedByList
[Item
] == []:
1555 # insert Item into Q
1560 # DAG is done if there's no more incoming edge for all nodes
1564 # remove node from Q
1567 SortedLibraryList
.append(Node
)
1569 # for each node Item with an edge e from Node to Item do
1570 for Item
in LibraryList
:
1571 if Node
not in ConsumedByList
[Item
]:
1573 # remove edge e from the graph
1574 ConsumedByList
[Item
].remove(Node
)
1576 if ConsumedByList
[Item
] != []:
1578 # insert Item into Q, if Item has no other incoming edges
1582 # if any remaining node Item in the graph has a constructor and an incoming edge, then the graph has a cycle
1584 for Item
in LibraryList
:
1585 if ConsumedByList
[Item
] != [] and Item
in Constructor
and len(Constructor
) > 1:
1586 ErrorMessage
= "\tconsumed by " + "\n\tconsumed by ".join([str(L
) for L
in ConsumedByList
[Item
]])
1587 EdkLogger
.error("build", BUILD_ERROR
, 'Library [%s] with constructors has a cycle' % str(Item
),
1588 ExtraData
=ErrorMessage
, File
=self
.MetaFile
)
1589 if Item
not in SortedLibraryList
:
1590 SortedLibraryList
.append(Item
)
1593 # Build the list of constructor and destructir names
1594 # The DAG Topo sort produces the destructor order, so the list of constructors must generated in the reverse order
1596 SortedLibraryList
.reverse()
1597 return SortedLibraryList
1600 ## Override PCD setting (type, value, ...)
1602 # @param ToPcd The PCD to be overrided
1603 # @param FromPcd The PCD overrideing from
1605 def _OverridePcd(self
, ToPcd
, FromPcd
, Module
=""):
1607 # in case there's PCDs coming from FDF file, which have no type given.
1608 # at this point, ToPcd.Type has the type found from dependent
1612 if ToPcd
.Pending
and FromPcd
.Type
not in [None, '']:
1613 ToPcd
.Type
= FromPcd
.Type
1614 elif (ToPcd
.Type
not in [None, '']) and (FromPcd
.Type
not in [None, ''])\
1615 and (ToPcd
.Type
!= FromPcd
.Type
) and (ToPcd
.Type
in FromPcd
.Type
):
1616 if ToPcd
.Type
.strip() == "DynamicEx":
1617 ToPcd
.Type
= FromPcd
.Type
1618 elif ToPcd
.Type
not in [None, ''] and FromPcd
.Type
not in [None, ''] \
1619 and ToPcd
.Type
!= FromPcd
.Type
:
1620 EdkLogger
.error("build", OPTION_CONFLICT
, "Mismatched PCD type",
1621 ExtraData
="%s.%s is defined as [%s] in module %s, but as [%s] in platform."\
1622 % (ToPcd
.TokenSpaceGuidCName
, ToPcd
.TokenCName
,
1623 ToPcd
.Type
, Module
, FromPcd
.Type
),
1626 if FromPcd
.MaxDatumSize
not in [None, '']:
1627 ToPcd
.MaxDatumSize
= FromPcd
.MaxDatumSize
1628 if FromPcd
.DefaultValue
not in [None, '']:
1629 ToPcd
.DefaultValue
= FromPcd
.DefaultValue
1630 if FromPcd
.TokenValue
not in [None, '']:
1631 ToPcd
.TokenValue
= FromPcd
.TokenValue
1632 if FromPcd
.MaxDatumSize
not in [None, '']:
1633 ToPcd
.MaxDatumSize
= FromPcd
.MaxDatumSize
1634 if FromPcd
.DatumType
not in [None, '']:
1635 ToPcd
.DatumType
= FromPcd
.DatumType
1636 if FromPcd
.SkuInfoList
not in [None, '', []]:
1637 ToPcd
.SkuInfoList
= FromPcd
.SkuInfoList
1639 # check the validation of datum
1640 IsValid
, Cause
= CheckPcdDatum(ToPcd
.DatumType
, ToPcd
.DefaultValue
)
1642 EdkLogger
.error('build', FORMAT_INVALID
, Cause
, File
=self
.MetaFile
,
1643 ExtraData
="%s.%s" % (ToPcd
.TokenSpaceGuidCName
, ToPcd
.TokenCName
))
1645 if ToPcd
.DatumType
== "VOID*" and ToPcd
.MaxDatumSize
in ['', None]:
1646 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "No MaxDatumSize specified for PCD %s.%s" \
1647 % (ToPcd
.TokenSpaceGuidCName
, ToPcd
.TokenCName
))
1648 Value
= ToPcd
.DefaultValue
1649 if Value
in [None, '']:
1650 ToPcd
.MaxDatumSize
= '1'
1651 elif Value
[0] == 'L':
1652 ToPcd
.MaxDatumSize
= str((len(Value
) - 2) * 2)
1653 elif Value
[0] == '{':
1654 ToPcd
.MaxDatumSize
= str(len(Value
.split(',')))
1656 ToPcd
.MaxDatumSize
= str(len(Value
) - 1)
1658 # apply default SKU for dynamic PCDS if specified one is not available
1659 if (ToPcd
.Type
in PCD_DYNAMIC_TYPE_LIST
or ToPcd
.Type
in PCD_DYNAMIC_EX_TYPE_LIST
) \
1660 and ToPcd
.SkuInfoList
in [None, {}, '']:
1661 if self
.Platform
.SkuName
in self
.Platform
.SkuIds
:
1662 SkuName
= self
.Platform
.SkuName
1665 ToPcd
.SkuInfoList
= {
1666 SkuName
: SkuInfoClass(SkuName
, self
.Platform
.SkuIds
[SkuName
], '', '', '', '', '', ToPcd
.DefaultValue
)
1669 ## Apply PCD setting defined platform to a module
1671 # @param Module The module from which the PCD setting will be overrided
1673 # @retval PCD_list The list PCDs with settings from platform
1675 def ApplyPcdSetting(self
, Module
, Pcds
):
1676 # for each PCD in module
1677 for Name
,Guid
in Pcds
:
1678 PcdInModule
= Pcds
[Name
,Guid
]
1679 # find out the PCD setting in platform
1680 if (Name
,Guid
) in self
.Platform
.Pcds
:
1681 PcdInPlatform
= self
.Platform
.Pcds
[Name
,Guid
]
1683 PcdInPlatform
= None
1684 # then override the settings if any
1685 self
._OverridePcd
(PcdInModule
, PcdInPlatform
, Module
)
1686 # resolve the VariableGuid value
1687 for SkuId
in PcdInModule
.SkuInfoList
:
1688 Sku
= PcdInModule
.SkuInfoList
[SkuId
]
1689 if Sku
.VariableGuid
== '': continue
1690 Sku
.VariableGuidValue
= GuidValue(Sku
.VariableGuid
, self
.PackageList
)
1691 if Sku
.VariableGuidValue
== None:
1692 PackageList
= "\n\t".join([str(P
) for P
in self
.PackageList
])
1695 RESOURCE_NOT_AVAILABLE
,
1696 "Value of GUID [%s] is not found in" % Sku
.VariableGuid
,
1697 ExtraData
=PackageList
+ "\n\t(used with %s.%s from module %s)" \
1698 % (Guid
, Name
, str(Module
)),
1702 # override PCD settings with module specific setting
1703 if Module
in self
.Platform
.Modules
:
1704 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
1705 for Key
in PlatformModule
.Pcds
:
1707 self
._OverridePcd
(Pcds
[Key
], PlatformModule
.Pcds
[Key
], Module
)
1708 return Pcds
.values()
1710 ## Resolve library names to library modules
1712 # (for Edk.x modules)
1714 # @param Module The module from which the library names will be resolved
1716 # @retval library_list The list of library modules
1718 def ResolveLibraryReference(self
, Module
):
1719 EdkLogger
.verbose("")
1720 EdkLogger
.verbose("Library instances of module [%s] [%s]:" % (str(Module
), self
.Arch
))
1721 LibraryConsumerList
= [Module
]
1723 # "CompilerStub" is a must for Edk modules
1724 if Module
.Libraries
:
1725 Module
.Libraries
.append("CompilerStub")
1727 while len(LibraryConsumerList
) > 0:
1728 M
= LibraryConsumerList
.pop()
1729 for LibraryName
in M
.Libraries
:
1730 Library
= self
.Platform
.LibraryClasses
[LibraryName
, ':dummy:']
1732 for Key
in self
.Platform
.LibraryClasses
.data
.keys():
1733 if LibraryName
.upper() == Key
.upper():
1734 Library
= self
.Platform
.LibraryClasses
[Key
, ':dummy:']
1737 EdkLogger
.warn("build", "Library [%s] is not found" % LibraryName
, File
=str(M
),
1738 ExtraData
="\t%s [%s]" % (str(Module
), self
.Arch
))
1741 if Library
not in LibraryList
:
1742 LibraryList
.append(Library
)
1743 LibraryConsumerList
.append(Library
)
1744 EdkLogger
.verbose("\t" + LibraryName
+ " : " + str(Library
) + ' ' + str(type(Library
)))
1747 ## Calculate the priority value of the build option
1749 # @param Key Build option definition contain: TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
1751 # @retval Value Priority value based on the priority list.
1753 def CalculatePriorityValue(self
, Key
):
1754 Target
, ToolChain
, Arch
, CommandType
, Attr
= Key
.split('_')
1755 PriorityValue
= 0x11111
1757 PriorityValue
&= 0x01111
1758 if ToolChain
== "*":
1759 PriorityValue
&= 0x10111
1761 PriorityValue
&= 0x11011
1762 if CommandType
== "*":
1763 PriorityValue
&= 0x11101
1765 PriorityValue
&= 0x11110
1767 return self
.PrioList
["0x%0.5x"%PriorityValue
]
1770 ## Expand * in build option key
1772 # @param Options Options to be expanded
1774 # @retval options Options expanded
1776 def _ExpandBuildOption(self
, Options
, ModuleStyle
=None):
1783 # Construct a list contain the build options which need override.
1787 # Key[0] -- tool family
1788 # Key[1] -- TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
1790 if Key
[0] == self
.BuildRuleFamily
:
1791 Target
, ToolChain
, Arch
, CommandType
, Attr
= Key
[1].split('_')
1792 if Target
== self
.BuildTarget
or Target
== "*":
1793 if ToolChain
== self
.ToolChain
or ToolChain
== "*":
1794 if Arch
== self
.Arch
or Arch
== "*":
1795 if Options
[Key
].startswith("="):
1796 if OverrideList
.get(Key
[1]) != None:
1797 OverrideList
.pop(Key
[1])
1798 OverrideList
[Key
[1]] = Options
[Key
]
1801 # Use the highest priority value.
1803 if (len(OverrideList
) >= 2):
1804 KeyList
= OverrideList
.keys()
1805 for Index
in range(len(KeyList
)):
1806 NowKey
= KeyList
[Index
]
1807 Target1
, ToolChain1
, Arch1
, CommandType1
, Attr1
= NowKey
.split("_")
1808 for Index1
in range(len(KeyList
) - Index
- 1):
1809 NextKey
= KeyList
[Index1
+ Index
+ 1]
1811 # Compare two Key, if one is included by another, choose the higher priority one
1813 Target2
, ToolChain2
, Arch2
, CommandType2
, Attr2
= NextKey
.split("_")
1814 if Target1
== Target2
or Target1
== "*" or Target2
== "*":
1815 if ToolChain1
== ToolChain2
or ToolChain1
== "*" or ToolChain2
== "*":
1816 if Arch1
== Arch2
or Arch1
== "*" or Arch2
== "*":
1817 if CommandType1
== CommandType2
or CommandType1
== "*" or CommandType2
== "*":
1818 if Attr1
== Attr2
or Attr1
== "*" or Attr2
== "*":
1819 if self
.CalculatePriorityValue(NowKey
) > self
.CalculatePriorityValue(NextKey
):
1820 if Options
.get((self
.BuildRuleFamily
, NextKey
)) != None:
1821 Options
.pop((self
.BuildRuleFamily
, NextKey
))
1823 if Options
.get((self
.BuildRuleFamily
, NowKey
)) != None:
1824 Options
.pop((self
.BuildRuleFamily
, NowKey
))
1828 if ModuleStyle
!= None and len (Key
) > 2:
1829 # Check Module style is EDK or EDKII.
1830 # Only append build option for the matched style module.
1831 if ModuleStyle
== EDK_NAME
and Key
[2] != EDK_NAME
:
1833 elif ModuleStyle
== EDKII_NAME
and Key
[2] != EDKII_NAME
:
1836 Target
, Tag
, Arch
, Tool
, Attr
= Key
[1].split("_")
1837 # if tool chain family doesn't match, skip it
1838 if Tool
in self
.ToolDefinition
and Family
!= "":
1839 FamilyIsNull
= False
1840 if self
.ToolDefinition
[Tool
].get(TAB_TOD_DEFINES_BUILDRULEFAMILY
, "") != "":
1841 if Family
!= self
.ToolDefinition
[Tool
][TAB_TOD_DEFINES_BUILDRULEFAMILY
]:
1843 elif Family
!= self
.ToolDefinition
[Tool
][TAB_TOD_DEFINES_FAMILY
]:
1846 # expand any wildcard
1847 if Target
== "*" or Target
== self
.BuildTarget
:
1848 if Tag
== "*" or Tag
== self
.ToolChain
:
1849 if Arch
== "*" or Arch
== self
.Arch
:
1850 if Tool
not in BuildOptions
:
1851 BuildOptions
[Tool
] = {}
1852 if Attr
!= "FLAGS" or Attr
not in BuildOptions
[Tool
]:
1853 BuildOptions
[Tool
][Attr
] = Options
[Key
]
1855 # append options for the same tool
1856 BuildOptions
[Tool
][Attr
] += " " + Options
[Key
]
1857 # Build Option Family has been checked, which need't to be checked again for family.
1858 if FamilyMatch
or FamilyIsNull
:
1862 if ModuleStyle
!= None and len (Key
) > 2:
1863 # Check Module style is EDK or EDKII.
1864 # Only append build option for the matched style module.
1865 if ModuleStyle
== EDK_NAME
and Key
[2] != EDK_NAME
:
1867 elif ModuleStyle
== EDKII_NAME
and Key
[2] != EDKII_NAME
:
1870 Target
, Tag
, Arch
, Tool
, Attr
= Key
[1].split("_")
1871 # if tool chain family doesn't match, skip it
1872 if Tool
not in self
.ToolDefinition
or Family
=="":
1874 # option has been added before
1875 if Family
!= self
.ToolDefinition
[Tool
][TAB_TOD_DEFINES_FAMILY
]:
1878 # expand any wildcard
1879 if Target
== "*" or Target
== self
.BuildTarget
:
1880 if Tag
== "*" or Tag
== self
.ToolChain
:
1881 if Arch
== "*" or Arch
== self
.Arch
:
1882 if Tool
not in BuildOptions
:
1883 BuildOptions
[Tool
] = {}
1884 if Attr
!= "FLAGS" or Attr
not in BuildOptions
[Tool
]:
1885 BuildOptions
[Tool
][Attr
] = Options
[Key
]
1887 # append options for the same tool
1888 BuildOptions
[Tool
][Attr
] += " " + Options
[Key
]
1891 ## Append build options in platform to a module
1893 # @param Module The module to which the build options will be appened
1895 # @retval options The options appended with build options in platform
1897 def ApplyBuildOption(self
, Module
):
1898 # Get the different options for the different style module
1899 if Module
.AutoGenVersion
< 0x00010005:
1900 PlatformOptions
= self
.EdkBuildOption
1902 PlatformOptions
= self
.EdkIIBuildOption
1903 ModuleOptions
= self
._ExpandBuildOption
(Module
.BuildOptions
)
1904 if Module
in self
.Platform
.Modules
:
1905 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
1906 PlatformModuleOptions
= self
._ExpandBuildOption
(PlatformModule
.BuildOptions
)
1908 PlatformModuleOptions
= {}
1910 AllTools
= set(ModuleOptions
.keys() + PlatformOptions
.keys() + PlatformModuleOptions
.keys() + self
.ToolDefinition
.keys())
1912 for Tool
in AllTools
:
1913 if Tool
not in BuildOptions
:
1914 BuildOptions
[Tool
] = {}
1916 for Options
in [self
.ToolDefinition
, ModuleOptions
, PlatformOptions
, PlatformModuleOptions
]:
1917 if Tool
not in Options
:
1919 for Attr
in Options
[Tool
]:
1920 Value
= Options
[Tool
][Attr
]
1921 if Attr
not in BuildOptions
[Tool
]:
1922 BuildOptions
[Tool
][Attr
] = ""
1923 # check if override is indicated
1924 if Value
.startswith('='):
1925 BuildOptions
[Tool
][Attr
] = Value
[1:]
1927 BuildOptions
[Tool
][Attr
] += " " + Value
1928 if Module
.AutoGenVersion
< 0x00010005 and self
.Workspace
.UniFlag
!= None:
1930 # Override UNI flag only for EDK module.
1932 if 'BUILD' not in BuildOptions
:
1933 BuildOptions
['BUILD'] = {}
1934 BuildOptions
['BUILD']['FLAGS'] = self
.Workspace
.UniFlag
1937 Platform
= property(_GetPlatform
)
1938 Name
= property(_GetName
)
1939 Guid
= property(_GetGuid
)
1940 Version
= property(_GetVersion
)
1942 OutputDir
= property(_GetOutputDir
)
1943 BuildDir
= property(_GetBuildDir
)
1944 MakeFileDir
= property(_GetMakeFileDir
)
1945 FdfFile
= property(_GetFdfFile
)
1947 PcdTokenNumber
= property(_GetPcdTokenNumbers
) # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber
1948 DynamicPcdList
= property(_GetDynamicPcdList
) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
1949 NonDynamicPcdList
= property(_GetNonDynamicPcdList
) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
1950 NonDynamicPcdDict
= property(_GetNonDynamicPcdDict
)
1951 PackageList
= property(_GetPackageList
)
1953 ToolDefinition
= property(_GetToolDefinition
) # toolcode : tool path
1954 ToolDefinitionFile
= property(_GetToolDefFile
) # toolcode : lib path
1955 ToolChainFamily
= property(_GetToolChainFamily
)
1956 BuildRuleFamily
= property(_GetBuildRuleFamily
)
1957 BuildOption
= property(_GetBuildOptions
) # toolcode : option
1958 EdkBuildOption
= property(_GetEdkBuildOptions
) # edktoolcode : option
1959 EdkIIBuildOption
= property(_GetEdkIIBuildOptions
) # edkiitoolcode : option
1961 BuildCommand
= property(_GetBuildCommand
)
1962 BuildRule
= property(_GetBuildRule
)
1963 ModuleAutoGenList
= property(_GetModuleAutoGenList
)
1964 LibraryAutoGenList
= property(_GetLibraryAutoGenList
)
1966 ## ModuleAutoGen class
1968 # This class encapsules the AutoGen behaviors for the build tools. In addition to
1969 # the generation of AutoGen.h and AutoGen.c, it will generate *.depex file according
1970 # to the [depex] section in module's inf file.
1972 class ModuleAutoGen(AutoGen
):
1973 ## The real constructor of ModuleAutoGen
1975 # This method is not supposed to be called by users of ModuleAutoGen. It's
1976 # only used by factory method __new__() to do real initialization work for an
1977 # object of ModuleAutoGen
1979 # @param Workspace EdkIIWorkspaceBuild object
1980 # @param ModuleFile The path of module file
1981 # @param Target Build target (DEBUG, RELEASE)
1982 # @param Toolchain Name of tool chain
1983 # @param Arch The arch the module supports
1984 # @param PlatformFile Platform meta-file
1986 def _Init(self
, Workspace
, ModuleFile
, Target
, Toolchain
, Arch
, PlatformFile
):
1987 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "AutoGen module [%s] [%s]" % (ModuleFile
, Arch
))
1988 GlobalData
.gProcessingFile
= "%s [%s, %s, %s]" % (ModuleFile
, Arch
, Toolchain
, Target
)
1990 self
.Workspace
= Workspace
1991 self
.WorkspaceDir
= Workspace
.WorkspaceDir
1993 self
.MetaFile
= ModuleFile
1994 self
.PlatformInfo
= PlatformAutoGen(Workspace
, PlatformFile
, Target
, Toolchain
, Arch
)
1995 # check if this module is employed by active platform
1996 if not self
.PlatformInfo
.ValidModule(self
.MetaFile
):
1997 EdkLogger
.verbose("Module [%s] for [%s] is not employed by active platform\n" \
1998 % (self
.MetaFile
, Arch
))
2001 self
.SourceDir
= self
.MetaFile
.SubDir
2002 self
.SourceOverrideDir
= None
2003 # use overrided path defined in DSC file
2004 if self
.MetaFile
.Key
in GlobalData
.gOverrideDir
:
2005 self
.SourceOverrideDir
= GlobalData
.gOverrideDir
[self
.MetaFile
.Key
]
2007 self
.ToolChain
= Toolchain
2008 self
.BuildTarget
= Target
2010 self
.ToolChainFamily
= self
.PlatformInfo
.ToolChainFamily
2011 self
.BuildRuleFamily
= self
.PlatformInfo
.BuildRuleFamily
2013 self
.IsMakeFileCreated
= False
2014 self
.IsCodeFileCreated
= False
2015 self
.IsAsBuiltInfCreated
= False
2016 self
.DepexGenerated
= False
2018 self
.BuildDatabase
= self
.Workspace
.BuildDatabase
2023 self
._Version
= None
2024 self
._ModuleType
= None
2025 self
._ComponentType
= None
2026 self
._PcdIsDriver
= None
2027 self
._AutoGenVersion
= None
2028 self
._LibraryFlag
= None
2029 self
._CustomMakefile
= None
2032 self
._BuildDir
= None
2033 self
._OutputDir
= None
2034 self
._DebugDir
= None
2035 self
._MakeFileDir
= None
2037 self
._IncludePathList
= None
2038 self
._AutoGenFileList
= None
2039 self
._UnicodeFileList
= None
2040 self
._SourceFileList
= None
2041 self
._ObjectFileList
= None
2042 self
._BinaryFileList
= None
2044 self
._DependentPackageList
= None
2045 self
._DependentLibraryList
= None
2046 self
._LibraryAutoGenList
= None
2047 self
._DerivedPackageList
= None
2048 self
._ModulePcdList
= None
2049 self
._LibraryPcdList
= None
2050 self
._PcdComments
= sdict()
2051 self
._GuidList
= None
2052 self
._GuidsUsedByPcd
= None
2053 self
._GuidComments
= sdict()
2054 self
._ProtocolList
= None
2055 self
._ProtocolComments
= sdict()
2056 self
._PpiList
= None
2057 self
._PpiComments
= sdict()
2058 self
._DepexList
= None
2059 self
._DepexExpressionList
= None
2060 self
._BuildOption
= None
2061 self
._BuildOptionIncPathList
= None
2062 self
._BuildTargets
= None
2063 self
._IntroBuildTargetList
= None
2064 self
._FinalBuildTargetList
= None
2065 self
._FileTypes
= None
2066 self
._BuildRules
= None
2068 ## The Modules referenced to this Library
2069 # Only Library has this attribute
2070 self
._ReferenceModules
= []
2072 ## Store the FixedAtBuild Pcds
2074 self
._FixedAtBuildPcds
= []
2079 return "%s [%s]" % (self
.MetaFile
, self
.Arch
)
2081 # Get FixedAtBuild Pcds of this Module
2082 def _GetFixedAtBuildPcds(self
):
2083 if self
._FixedAtBuildPcds
:
2084 return self
._FixedAtBuildPcds
2085 for Pcd
in self
.ModulePcdList
:
2087 if not (Pcd
.Pending
== False and Pcd
.Type
== "FixedAtBuild"):
2089 elif Pcd
.Type
!= "FixedAtBuild":
2091 if Pcd
not in self
._FixedAtBuildPcds
:
2092 self
._FixedAtBuildPcds
.append(Pcd
)
2094 return self
._FixedAtBuildPcds
2096 # Macros could be used in build_rule.txt (also Makefile)
2097 def _GetMacros(self
):
2098 if self
._Macro
== None:
2099 self
._Macro
= sdict()
2100 self
._Macro
["WORKSPACE" ] = self
.WorkspaceDir
2101 self
._Macro
["MODULE_NAME" ] = self
.Name
2102 self
._Macro
["MODULE_GUID" ] = self
.Guid
2103 self
._Macro
["MODULE_VERSION" ] = self
.Version
2104 self
._Macro
["MODULE_TYPE" ] = self
.ModuleType
2105 self
._Macro
["MODULE_FILE" ] = str(self
.MetaFile
)
2106 self
._Macro
["MODULE_FILE_BASE_NAME" ] = self
.MetaFile
.BaseName
2107 self
._Macro
["MODULE_RELATIVE_DIR" ] = self
.SourceDir
2108 self
._Macro
["MODULE_DIR" ] = self
.SourceDir
2110 self
._Macro
["BASE_NAME" ] = self
.Name
2112 self
._Macro
["ARCH" ] = self
.Arch
2113 self
._Macro
["TOOLCHAIN" ] = self
.ToolChain
2114 self
._Macro
["TOOLCHAIN_TAG" ] = self
.ToolChain
2115 self
._Macro
["TOOL_CHAIN_TAG" ] = self
.ToolChain
2116 self
._Macro
["TARGET" ] = self
.BuildTarget
2118 self
._Macro
["BUILD_DIR" ] = self
.PlatformInfo
.BuildDir
2119 self
._Macro
["BIN_DIR" ] = os
.path
.join(self
.PlatformInfo
.BuildDir
, self
.Arch
)
2120 self
._Macro
["LIB_DIR" ] = os
.path
.join(self
.PlatformInfo
.BuildDir
, self
.Arch
)
2121 self
._Macro
["MODULE_BUILD_DIR" ] = self
.BuildDir
2122 self
._Macro
["OUTPUT_DIR" ] = self
.OutputDir
2123 self
._Macro
["DEBUG_DIR" ] = self
.DebugDir
2126 ## Return the module build data object
2127 def _GetModule(self
):
2128 if self
._Module
== None:
2129 self
._Module
= self
.Workspace
.BuildDatabase
[self
.MetaFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
2132 ## Return the module name
2133 def _GetBaseName(self
):
2134 return self
.Module
.BaseName
2136 ## Return the module DxsFile if exist
2137 def _GetDxsFile(self
):
2138 return self
.Module
.DxsFile
2140 ## Return the module SourceOverridePath
2141 def _GetSourceOverridePath(self
):
2142 return self
.Module
.SourceOverridePath
2144 ## Return the module meta-file GUID
2146 return self
.Module
.Guid
2148 ## Return the module version
2149 def _GetVersion(self
):
2150 return self
.Module
.Version
2152 ## Return the module type
2153 def _GetModuleType(self
):
2154 return self
.Module
.ModuleType
2156 ## Return the component type (for Edk.x style of module)
2157 def _GetComponentType(self
):
2158 return self
.Module
.ComponentType
2160 ## Return the build type
2161 def _GetBuildType(self
):
2162 return self
.Module
.BuildType
2164 ## Return the PCD_IS_DRIVER setting
2165 def _GetPcdIsDriver(self
):
2166 return self
.Module
.PcdIsDriver
2168 ## Return the autogen version, i.e. module meta-file version
2169 def _GetAutoGenVersion(self
):
2170 return self
.Module
.AutoGenVersion
2172 ## Check if the module is library or not
2173 def _IsLibrary(self
):
2174 if self
._LibraryFlag
== None:
2175 if self
.Module
.LibraryClass
!= None and self
.Module
.LibraryClass
!= []:
2176 self
._LibraryFlag
= True
2178 self
._LibraryFlag
= False
2179 return self
._LibraryFlag
2181 ## Check if the module is binary module or not
2182 def _IsBinaryModule(self
):
2183 return self
.Module
.IsBinaryModule
2185 ## Return the directory to store intermediate files of the module
2186 def _GetBuildDir(self
):
2187 if self
._BuildDir
== None:
2188 self
._BuildDir
= path
.join(
2189 self
.PlatformInfo
.BuildDir
,
2192 self
.MetaFile
.BaseName
2194 CreateDirectory(self
._BuildDir
)
2195 return self
._BuildDir
2197 ## Return the directory to store the intermediate object files of the mdoule
2198 def _GetOutputDir(self
):
2199 if self
._OutputDir
== None:
2200 self
._OutputDir
= path
.join(self
.BuildDir
, "OUTPUT")
2201 CreateDirectory(self
._OutputDir
)
2202 return self
._OutputDir
2204 ## Return the directory to store auto-gened source files of the mdoule
2205 def _GetDebugDir(self
):
2206 if self
._DebugDir
== None:
2207 self
._DebugDir
= path
.join(self
.BuildDir
, "DEBUG")
2208 CreateDirectory(self
._DebugDir
)
2209 return self
._DebugDir
2211 ## Return the path of custom file
2212 def _GetCustomMakefile(self
):
2213 if self
._CustomMakefile
== None:
2214 self
._CustomMakefile
= {}
2215 for Type
in self
.Module
.CustomMakefile
:
2216 if Type
in gMakeTypeMap
:
2217 MakeType
= gMakeTypeMap
[Type
]
2220 if self
.SourceOverrideDir
!= None:
2221 File
= os
.path
.join(self
.SourceOverrideDir
, self
.Module
.CustomMakefile
[Type
])
2222 if not os
.path
.exists(File
):
2223 File
= os
.path
.join(self
.SourceDir
, self
.Module
.CustomMakefile
[Type
])
2225 File
= os
.path
.join(self
.SourceDir
, self
.Module
.CustomMakefile
[Type
])
2226 self
._CustomMakefile
[MakeType
] = File
2227 return self
._CustomMakefile
2229 ## Return the directory of the makefile
2231 # @retval string The directory string of module's makefile
2233 def _GetMakeFileDir(self
):
2234 return self
.BuildDir
2236 ## Return build command string
2238 # @retval string Build command string
2240 def _GetBuildCommand(self
):
2241 return self
.PlatformInfo
.BuildCommand
2243 ## Get object list of all packages the module and its dependent libraries belong to
2245 # @retval list The list of package object
2247 def _GetDerivedPackageList(self
):
2249 for M
in [self
.Module
] + self
.DependentLibraryList
:
2250 for Package
in M
.Packages
:
2251 if Package
in PackageList
:
2253 PackageList
.append(Package
)
2256 ## Merge dependency expression
2258 # @retval list The token list of the dependency expression after parsed
2260 def _GetDepexTokenList(self
):
2261 if self
._DepexList
== None:
2262 self
._DepexList
= {}
2263 if self
.DxsFile
or self
.IsLibrary
or TAB_DEPENDENCY_EXPRESSION_FILE
in self
.FileTypes
:
2264 return self
._DepexList
2266 self
._DepexList
[self
.ModuleType
] = []
2268 for ModuleType
in self
._DepexList
:
2269 DepexList
= self
._DepexList
[ModuleType
]
2271 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
2273 for M
in [self
.Module
] + self
.DependentLibraryList
:
2275 for D
in M
.Depex
[self
.Arch
, ModuleType
]:
2277 DepexList
.append('AND')
2278 DepexList
.append('(')
2280 if DepexList
[-1] == 'END': # no need of a END at this time
2282 DepexList
.append(')')
2285 EdkLogger
.verbose("DEPEX[%s] (+%s) = %s" % (self
.Name
, M
.BaseName
, DepexList
))
2286 if 'BEFORE' in DepexList
or 'AFTER' in DepexList
:
2288 if len(DepexList
) > 0:
2289 EdkLogger
.verbose('')
2290 return self
._DepexList
2292 ## Merge dependency expression
2294 # @retval list The token list of the dependency expression after parsed
2296 def _GetDepexExpressionTokenList(self
):
2297 if self
._DepexExpressionList
== None:
2298 self
._DepexExpressionList
= {}
2299 if self
.DxsFile
or self
.IsLibrary
or TAB_DEPENDENCY_EXPRESSION_FILE
in self
.FileTypes
:
2300 return self
._DepexExpressionList
2302 self
._DepexExpressionList
[self
.ModuleType
] = ''
2304 for ModuleType
in self
._DepexExpressionList
:
2305 DepexExpressionList
= self
._DepexExpressionList
[ModuleType
]
2307 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
2309 for M
in [self
.Module
] + self
.DependentLibraryList
:
2311 for D
in M
.DepexExpression
[self
.Arch
, ModuleType
]:
2312 if DepexExpressionList
!= '':
2313 DepexExpressionList
+= ' AND '
2314 DepexExpressionList
+= '('
2315 DepexExpressionList
+= D
2316 DepexExpressionList
= DepexExpressionList
.rstrip('END').strip()
2317 DepexExpressionList
+= ')'
2320 EdkLogger
.verbose("DEPEX[%s] (+%s) = %s" % (self
.Name
, M
.BaseName
, DepexExpressionList
))
2321 if 'BEFORE' in DepexExpressionList
or 'AFTER' in DepexExpressionList
:
2323 if len(DepexExpressionList
) > 0:
2324 EdkLogger
.verbose('')
2325 self
._DepexExpressionList
[ModuleType
] = DepexExpressionList
2326 return self
._DepexExpressionList
2328 ## Return the list of specification version required for the module
2330 # @retval list The list of specification defined in module file
2332 def _GetSpecification(self
):
2333 return self
.Module
.Specification
2335 ## Tool option for the module build
2337 # @param PlatformInfo The object of PlatformBuildInfo
2338 # @retval dict The dict containing valid options
2340 def _GetModuleBuildOption(self
):
2341 if self
._BuildOption
== None:
2342 self
._BuildOption
= self
.PlatformInfo
.ApplyBuildOption(self
.Module
)
2343 return self
._BuildOption
2345 ## Get include path list from tool option for the module build
2347 # @retval list The include path list
2349 def _GetBuildOptionIncPathList(self
):
2350 if self
._BuildOptionIncPathList
== None:
2352 # Regular expression for finding Include Directories, the difference between MSFT and INTEL/GCC/RVCT
2353 # is the former use /I , the Latter used -I to specify include directories
2355 if self
.PlatformInfo
.ToolChainFamily
in ('MSFT'):
2356 gBuildOptIncludePattern
= re
.compile(r
"(?:.*?)/I[ \t]*([^ ]*)", re
.MULTILINE|re
.DOTALL
)
2357 elif self
.PlatformInfo
.ToolChainFamily
in ('INTEL', 'GCC', 'RVCT'):
2358 gBuildOptIncludePattern
= re
.compile(r
"(?:.*?)-I[ \t]*([^ ]*)", re
.MULTILINE|re
.DOTALL
)
2361 # New ToolChainFamily, don't known whether there is option to specify include directories
2363 self
._BuildOptionIncPathList
= []
2364 return self
._BuildOptionIncPathList
2366 BuildOptionIncPathList
= []
2367 for Tool
in ('CC', 'PP', 'VFRPP', 'ASLPP', 'ASLCC', 'APP', 'ASM'):
2370 FlagOption
= self
.BuildOption
[Tool
][Attr
]
2374 if self
.PlatformInfo
.ToolChainFamily
!= 'RVCT':
2375 IncPathList
= [NormPath(Path
, self
.Macros
) for Path
in gBuildOptIncludePattern
.findall(FlagOption
)]
2378 # RVCT may specify a list of directory seperated by commas
2381 for Path
in gBuildOptIncludePattern
.findall(FlagOption
):
2382 PathList
= GetSplitList(Path
, TAB_COMMA_SPLIT
)
2383 IncPathList
+= [NormPath(PathEntry
, self
.Macros
) for PathEntry
in PathList
]
2386 # EDK II modules must not reference header files outside of the packages they depend on or
2387 # within the module's directory tree. Report error if violation.
2389 if self
.AutoGenVersion
>= 0x00010005 and len(IncPathList
) > 0:
2390 for Path
in IncPathList
:
2391 if (Path
not in self
.IncludePathList
) and (CommonPath([Path
, self
.MetaFile
.Dir
]) != self
.MetaFile
.Dir
):
2392 ErrMsg
= "The include directory for the EDK II module in this line is invalid %s specified in %s FLAGS '%s'" % (Path
, Tool
, FlagOption
)
2393 EdkLogger
.error("build",
2396 File
= str(self
.MetaFile
))
2399 BuildOptionIncPathList
+= IncPathList
2401 self
._BuildOptionIncPathList
= BuildOptionIncPathList
2403 return self
._BuildOptionIncPathList
2405 ## Return a list of files which can be built from source
2407 # What kind of files can be built is determined by build rules in
2408 # $(WORKSPACE)/Conf/build_rule.txt and toolchain family.
2410 def _GetSourceFileList(self
):
2411 if self
._SourceFileList
== None:
2412 self
._SourceFileList
= []
2413 for F
in self
.Module
.Sources
:
2415 if F
.TagName
not in ("", "*", self
.ToolChain
):
2416 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "The toolchain [%s] for processing file [%s] is found, "
2417 "but [%s] is needed" % (F
.TagName
, str(F
), self
.ToolChain
))
2419 # match tool chain family
2420 if F
.ToolChainFamily
not in ("", "*", self
.ToolChainFamily
):
2423 "The file [%s] must be built by tools of [%s], " \
2424 "but current toolchain family is [%s]" \
2425 % (str(F
), F
.ToolChainFamily
, self
.ToolChainFamily
))
2428 # add the file path into search path list for file including
2429 if F
.Dir
not in self
.IncludePathList
and self
.AutoGenVersion
>= 0x00010005:
2430 self
.IncludePathList
.insert(0, F
.Dir
)
2431 self
._SourceFileList
.append(F
)
2432 self
._ApplyBuildRule
(F
, TAB_UNKNOWN_FILE
)
2433 return self
._SourceFileList
2435 ## Return the list of unicode files
2436 def _GetUnicodeFileList(self
):
2437 if self
._UnicodeFileList
== None:
2438 if TAB_UNICODE_FILE
in self
.FileTypes
:
2439 self
._UnicodeFileList
= self
.FileTypes
[TAB_UNICODE_FILE
]
2441 self
._UnicodeFileList
= []
2442 return self
._UnicodeFileList
2444 ## Return a list of files which can be built from binary
2446 # "Build" binary files are just to copy them to build directory.
2448 # @retval list The list of files which can be built later
2450 def _GetBinaryFiles(self
):
2451 if self
._BinaryFileList
== None:
2452 self
._BinaryFileList
= []
2453 for F
in self
.Module
.Binaries
:
2454 if F
.Target
not in ['COMMON', '*'] and F
.Target
!= self
.BuildTarget
:
2456 self
._BinaryFileList
.append(F
)
2457 self
._ApplyBuildRule
(F
, F
.Type
)
2458 return self
._BinaryFileList
2460 def _GetBuildRules(self
):
2461 if self
._BuildRules
== None:
2463 BuildRuleDatabase
= self
.PlatformInfo
.BuildRule
2464 for Type
in BuildRuleDatabase
.FileTypeList
:
2465 #first try getting build rule by BuildRuleFamily
2466 RuleObject
= BuildRuleDatabase
[Type
, self
.BuildType
, self
.Arch
, self
.BuildRuleFamily
]
2468 # build type is always module type, but ...
2469 if self
.ModuleType
!= self
.BuildType
:
2470 RuleObject
= BuildRuleDatabase
[Type
, self
.ModuleType
, self
.Arch
, self
.BuildRuleFamily
]
2471 #second try getting build rule by ToolChainFamily
2473 RuleObject
= BuildRuleDatabase
[Type
, self
.BuildType
, self
.Arch
, self
.ToolChainFamily
]
2475 # build type is always module type, but ...
2476 if self
.ModuleType
!= self
.BuildType
:
2477 RuleObject
= BuildRuleDatabase
[Type
, self
.ModuleType
, self
.Arch
, self
.ToolChainFamily
]
2480 RuleObject
= RuleObject
.Instantiate(self
.Macros
)
2481 BuildRules
[Type
] = RuleObject
2482 for Ext
in RuleObject
.SourceFileExtList
:
2483 BuildRules
[Ext
] = RuleObject
2484 self
._BuildRules
= BuildRules
2485 return self
._BuildRules
2487 def _ApplyBuildRule(self
, File
, FileType
):
2488 if self
._BuildTargets
== None:
2489 self
._IntroBuildTargetList
= set()
2490 self
._FinalBuildTargetList
= set()
2491 self
._BuildTargets
= {}
2492 self
._FileTypes
= {}
2494 SubDirectory
= os
.path
.join(self
.OutputDir
, File
.SubDir
)
2495 if not os
.path
.exists(SubDirectory
):
2496 CreateDirectory(SubDirectory
)
2501 while Index
< len(SourceList
):
2502 Source
= SourceList
[Index
]
2506 CreateDirectory(Source
.Dir
)
2508 if File
.IsBinary
and File
== Source
and self
._BinaryFileList
!= None and File
in self
._BinaryFileList
:
2509 # Skip all files that are not binary libraries
2510 if not self
.IsLibrary
:
2512 RuleObject
= self
.BuildRules
[TAB_DEFAULT_BINARY_FILE
]
2513 elif FileType
in self
.BuildRules
:
2514 RuleObject
= self
.BuildRules
[FileType
]
2515 elif Source
.Ext
in self
.BuildRules
:
2516 RuleObject
= self
.BuildRules
[Source
.Ext
]
2518 # stop at no more rules
2520 self
._FinalBuildTargetList
.add(LastTarget
)
2523 FileType
= RuleObject
.SourceFileType
2524 if FileType
not in self
._FileTypes
:
2525 self
._FileTypes
[FileType
] = set()
2526 self
._FileTypes
[FileType
].add(Source
)
2528 # stop at STATIC_LIBRARY for library
2529 if self
.IsLibrary
and FileType
== TAB_STATIC_LIBRARY
:
2531 self
._FinalBuildTargetList
.add(LastTarget
)
2534 Target
= RuleObject
.Apply(Source
)
2537 self
._FinalBuildTargetList
.add(LastTarget
)
2539 elif not Target
.Outputs
:
2540 # Only do build for target with outputs
2541 self
._FinalBuildTargetList
.add(Target
)
2543 if FileType
not in self
._BuildTargets
:
2544 self
._BuildTargets
[FileType
] = set()
2545 self
._BuildTargets
[FileType
].add(Target
)
2547 if not Source
.IsBinary
and Source
== File
:
2548 self
._IntroBuildTargetList
.add(Target
)
2550 # to avoid cyclic rule
2551 if FileType
in RuleChain
:
2554 RuleChain
.append(FileType
)
2555 SourceList
.extend(Target
.Outputs
)
2557 FileType
= TAB_UNKNOWN_FILE
2559 def _GetTargets(self
):
2560 if self
._BuildTargets
== None:
2561 self
._IntroBuildTargetList
= set()
2562 self
._FinalBuildTargetList
= set()
2563 self
._BuildTargets
= {}
2564 self
._FileTypes
= {}
2566 #TRICK: call _GetSourceFileList to apply build rule for source files
2567 if self
.SourceFileList
:
2570 #TRICK: call _GetBinaryFileList to apply build rule for binary files
2571 if self
.BinaryFileList
:
2574 return self
._BuildTargets
2576 def _GetIntroTargetList(self
):
2578 return self
._IntroBuildTargetList
2580 def _GetFinalTargetList(self
):
2582 return self
._FinalBuildTargetList
2584 def _GetFileTypes(self
):
2586 return self
._FileTypes
2588 ## Get the list of package object the module depends on
2590 # @retval list The package object list
2592 def _GetDependentPackageList(self
):
2593 return self
.Module
.Packages
2595 ## Return the list of auto-generated code file
2597 # @retval list The list of auto-generated file
2599 def _GetAutoGenFileList(self
):
2600 UniStringAutoGenC
= True
2601 UniStringBinBuffer
= StringIO()
2602 if self
.BuildType
== 'UEFI_HII':
2603 UniStringAutoGenC
= False
2604 if self
._AutoGenFileList
== None:
2605 self
._AutoGenFileList
= {}
2606 AutoGenC
= TemplateString()
2607 AutoGenH
= TemplateString()
2608 StringH
= TemplateString()
2609 GenC
.CreateCode(self
, AutoGenC
, AutoGenH
, StringH
, UniStringAutoGenC
, UniStringBinBuffer
)
2611 # AutoGen.c is generated if there are library classes in inf, or there are object files
2613 if str(AutoGenC
) != "" and (len(self
.Module
.LibraryClasses
) > 0
2614 or TAB_OBJECT_FILE
in self
.FileTypes
):
2615 AutoFile
= PathClass(gAutoGenCodeFileName
, self
.DebugDir
)
2616 self
._AutoGenFileList
[AutoFile
] = str(AutoGenC
)
2617 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
2618 if str(AutoGenH
) != "":
2619 AutoFile
= PathClass(gAutoGenHeaderFileName
, self
.DebugDir
)
2620 self
._AutoGenFileList
[AutoFile
] = str(AutoGenH
)
2621 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
2622 if str(StringH
) != "":
2623 AutoFile
= PathClass(gAutoGenStringFileName
% {"module_name":self
.Name
}, self
.DebugDir
)
2624 self
._AutoGenFileList
[AutoFile
] = str(StringH
)
2625 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
2626 if UniStringBinBuffer
!= None and UniStringBinBuffer
.getvalue() != "":
2627 AutoFile
= PathClass(gAutoGenStringFormFileName
% {"module_name":self
.Name
}, self
.OutputDir
)
2628 self
._AutoGenFileList
[AutoFile
] = UniStringBinBuffer
.getvalue()
2629 AutoFile
.IsBinary
= True
2630 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
2631 if UniStringBinBuffer
!= None:
2632 UniStringBinBuffer
.close()
2633 return self
._AutoGenFileList
2635 ## Return the list of library modules explicitly or implicityly used by this module
2636 def _GetLibraryList(self
):
2637 if self
._DependentLibraryList
== None:
2638 # only merge library classes and PCD for non-library module
2640 self
._DependentLibraryList
= []
2642 if self
.AutoGenVersion
< 0x00010005:
2643 self
._DependentLibraryList
= self
.PlatformInfo
.ResolveLibraryReference(self
.Module
)
2645 self
._DependentLibraryList
= self
.PlatformInfo
.ApplyLibraryInstance(self
.Module
)
2646 return self
._DependentLibraryList
2649 def UpdateComments(Recver
, Src
):
2651 if Key
not in Recver
:
2653 Recver
[Key
].extend(Src
[Key
])
2654 ## Get the list of PCDs from current module
2656 # @retval list The list of PCD
2658 def _GetModulePcdList(self
):
2659 if self
._ModulePcdList
== None:
2660 # apply PCD settings from platform
2661 self
._ModulePcdList
= self
.PlatformInfo
.ApplyPcdSetting(self
.Module
, self
.Module
.Pcds
)
2662 self
.UpdateComments(self
._PcdComments
, self
.Module
.PcdComments
)
2663 return self
._ModulePcdList
2665 ## Get the list of PCDs from dependent libraries
2667 # @retval list The list of PCD
2669 def _GetLibraryPcdList(self
):
2670 if self
._LibraryPcdList
== None:
2672 if not self
.IsLibrary
:
2673 # get PCDs from dependent libraries
2674 for Library
in self
.DependentLibraryList
:
2675 self
.UpdateComments(self
._PcdComments
, Library
.PcdComments
)
2676 for Key
in Library
.Pcds
:
2677 # skip duplicated PCDs
2678 if Key
in self
.Module
.Pcds
or Key
in Pcds
:
2680 Pcds
[Key
] = copy
.copy(Library
.Pcds
[Key
])
2681 # apply PCD settings from platform
2682 self
._LibraryPcdList
= self
.PlatformInfo
.ApplyPcdSetting(self
.Module
, Pcds
)
2684 self
._LibraryPcdList
= []
2685 return self
._LibraryPcdList
2687 ## Get the GUID value mapping
2689 # @retval dict The mapping between GUID cname and its value
2691 def _GetGuidList(self
):
2692 if self
._GuidList
== None:
2693 self
._GuidList
= self
.Module
.Guids
2694 for Library
in self
.DependentLibraryList
:
2695 self
._GuidList
.update(Library
.Guids
)
2696 self
.UpdateComments(self
._GuidComments
, Library
.GuidComments
)
2697 self
.UpdateComments(self
._GuidComments
, self
.Module
.GuidComments
)
2698 return self
._GuidList
2700 def GetGuidsUsedByPcd(self
):
2701 if self
._GuidsUsedByPcd
== None:
2702 self
._GuidsUsedByPcd
= sdict()
2703 self
._GuidsUsedByPcd
.update(self
.Module
.GetGuidsUsedByPcd())
2704 for Library
in self
.DependentLibraryList
:
2705 self
._GuidsUsedByPcd
.update(Library
.GetGuidsUsedByPcd())
2706 return self
._GuidsUsedByPcd
2707 ## Get the protocol value mapping
2709 # @retval dict The mapping between protocol cname and its value
2711 def _GetProtocolList(self
):
2712 if self
._ProtocolList
== None:
2713 self
._ProtocolList
= self
.Module
.Protocols
2714 for Library
in self
.DependentLibraryList
:
2715 self
._ProtocolList
.update(Library
.Protocols
)
2716 self
.UpdateComments(self
._ProtocolComments
, Library
.ProtocolComments
)
2717 self
.UpdateComments(self
._ProtocolComments
, self
.Module
.ProtocolComments
)
2718 return self
._ProtocolList
2720 ## Get the PPI value mapping
2722 # @retval dict The mapping between PPI cname and its value
2724 def _GetPpiList(self
):
2725 if self
._PpiList
== None:
2726 self
._PpiList
= self
.Module
.Ppis
2727 for Library
in self
.DependentLibraryList
:
2728 self
._PpiList
.update(Library
.Ppis
)
2729 self
.UpdateComments(self
._PpiComments
, Library
.PpiComments
)
2730 self
.UpdateComments(self
._PpiComments
, self
.Module
.PpiComments
)
2731 return self
._PpiList
2733 ## Get the list of include search path
2735 # @retval list The list path
2737 def _GetIncludePathList(self
):
2738 if self
._IncludePathList
== None:
2739 self
._IncludePathList
= []
2740 if self
.AutoGenVersion
< 0x00010005:
2741 for Inc
in self
.Module
.Includes
:
2742 if Inc
not in self
._IncludePathList
:
2743 self
._IncludePathList
.append(Inc
)
2745 Inc
= path
.join(Inc
, self
.Arch
.capitalize())
2746 if os
.path
.exists(Inc
) and Inc
not in self
._IncludePathList
:
2747 self
._IncludePathList
.append(Inc
)
2748 # Edk module needs to put DEBUG_DIR at the end of search path and not to use SOURCE_DIR all the time
2749 self
._IncludePathList
.append(self
.DebugDir
)
2751 self
._IncludePathList
.append(self
.MetaFile
.Dir
)
2752 self
._IncludePathList
.append(self
.DebugDir
)
2754 for Package
in self
.Module
.Packages
:
2755 PackageDir
= path
.join(self
.WorkspaceDir
, Package
.MetaFile
.Dir
)
2756 if PackageDir
not in self
._IncludePathList
:
2757 self
._IncludePathList
.append(PackageDir
)
2758 for Inc
in Package
.Includes
:
2759 if Inc
not in self
._IncludePathList
:
2760 self
._IncludePathList
.append(str(Inc
))
2761 return self
._IncludePathList
2763 ## Create AsBuilt INF file the module
2765 def CreateAsBuiltInf(self
):
2766 if self
.IsAsBuiltInfCreated
:
2769 # Skip the following code for EDK I inf
2770 if self
.AutoGenVersion
< 0x00010005:
2773 # Skip the following code for libraries
2777 # Skip the following code for modules with no source files
2778 if self
.SourceFileList
== None or self
.SourceFileList
== []:
2781 # Skip the following code for modules without any binary files
2782 if self
.BinaryFileList
<> None and self
.BinaryFileList
<> []:
2785 ### TODO: How to handles mixed source and binary modules
2787 # Find all DynamicEx and PatchableInModule PCDs used by this module and dependent libraries
2788 # Also find all packages that the DynamicEx PCDs depend on
2793 PcdTokenSpaceList
= []
2794 for Pcd
in self
.ModulePcdList
+ self
.LibraryPcdList
:
2795 if Pcd
.Type
== TAB_PCDS_PATCHABLE_IN_MODULE
:
2796 PatchablePcds
[Pcd
.TokenCName
] = Pcd
2797 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, 'PatchableInModule'))
2798 elif Pcd
.Type
in GenC
.gDynamicExPcd
:
2801 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, 'DynamicEx'))
2802 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, 'Dynamic'))
2803 PcdTokenSpaceList
.append(Pcd
.TokenSpaceGuidCName
)
2805 GuidList
.update(self
.GuidList
)
2806 for TokenSpace
in self
.GetGuidsUsedByPcd():
2807 # If token space is not referred by patch PCD or Ex PCD, remove the GUID from GUID list
2808 # The GUIDs in GUIDs section should really be the GUIDs in source INF or referred by Ex an patch PCDs
2809 if TokenSpace
not in PcdTokenSpaceList
and TokenSpace
in GuidList
:
2810 GuidList
.pop(TokenSpace
)
2811 CheckList
= (GuidList
, self
.PpiList
, self
.ProtocolList
, PcdCheckList
)
2812 for Package
in self
.DerivedPackageList
:
2813 if Package
in Packages
:
2815 BeChecked
= (Package
.Guids
, Package
.Ppis
, Package
.Protocols
, Package
.Pcds
)
2817 for Index
in range(len(BeChecked
)):
2818 for Item
in CheckList
[Index
]:
2819 if Item
in BeChecked
[Index
]:
2820 Packages
+= [Package
]
2825 ModuleType
= self
.ModuleType
2826 if ModuleType
== 'UEFI_DRIVER' and self
.DepexGenerated
:
2827 ModuleType
= 'DXE_DRIVER'
2830 if self
.PcdIsDriver
!= '':
2831 DriverType
= self
.PcdIsDriver
2834 'module_name' : self
.Name
,
2835 'module_guid' : self
.Guid
,
2836 'module_module_type' : ModuleType
,
2837 'module_version_string' : self
.Version
,
2838 'pcd_is_driver_string' : [],
2839 'module_uefi_specification_version' : [],
2840 'module_pi_specification_version' : [],
2841 'module_arch' : self
.Arch
,
2842 'package_item' : ['%s' % (Package
.MetaFile
.File
.replace('\\','/')) for Package
in Packages
],
2844 'patchablepcd_item' : [],
2846 'protocol_item' : [],
2850 'libraryclasses_item' : []
2852 AsBuiltInfDict
['module_inf_version'] = '0x%08x' % self
.AutoGenVersion
2854 AsBuiltInfDict
['pcd_is_driver_string'] += [DriverType
]
2856 if 'UEFI_SPECIFICATION_VERSION' in self
.Specification
:
2857 AsBuiltInfDict
['module_uefi_specification_version'] += [self
.Specification
['UEFI_SPECIFICATION_VERSION']]
2858 if 'PI_SPECIFICATION_VERSION' in self
.Specification
:
2859 AsBuiltInfDict
['module_pi_specification_version'] += [self
.Specification
['PI_SPECIFICATION_VERSION']]
2861 OutputDir
= self
.OutputDir
.replace('\\','/').strip('/')
2862 if self
.ModuleType
in ['BASE', 'USER_DEFINED']:
2863 for Item
in self
.CodaTargetList
:
2864 File
= Item
.Target
.Path
.replace('\\','/').strip('/').replace(OutputDir
,'').strip('/')
2865 if Item
.Target
.Ext
.lower() == '.aml':
2866 AsBuiltInfDict
['binary_item'] += ['ASL|' + File
]
2867 elif Item
.Target
.Ext
.lower() == '.acpi':
2868 AsBuiltInfDict
['binary_item'] += ['ACPI|' + File
]
2870 AsBuiltInfDict
['binary_item'] += ['BIN|' + File
]
2872 for Item
in self
.CodaTargetList
:
2873 File
= Item
.Target
.Path
.replace('\\','/').strip('/').replace(OutputDir
,'').strip('/')
2874 if Item
.Target
.Ext
.lower() == '.efi':
2875 AsBuiltInfDict
['binary_item'] += ['PE32|' + self
.Name
+ '.efi']
2877 AsBuiltInfDict
['binary_item'] += ['BIN|' + File
]
2878 if self
.DepexGenerated
:
2879 if self
.ModuleType
in ['PEIM']:
2880 AsBuiltInfDict
['binary_item'] += ['PEI_DEPEX|' + self
.Name
+ '.depex']
2881 if self
.ModuleType
in ['DXE_DRIVER','DXE_RUNTIME_DRIVER','DXE_SAL_DRIVER','UEFI_DRIVER']:
2882 AsBuiltInfDict
['binary_item'] += ['DXE_DEPEX|' + self
.Name
+ '.depex']
2883 if self
.ModuleType
in ['DXE_SMM_DRIVER']:
2884 AsBuiltInfDict
['binary_item'] += ['SMM_DEPEX|' + self
.Name
+ '.depex']
2886 for Root
, Dirs
, Files
in os
.walk(OutputDir
):
2888 if File
.lower().endswith('.pdb'):
2889 AsBuiltInfDict
['binary_item'] += ['DISPOSABLE|' + File
]
2890 HeaderComments
= self
.Module
.HeaderComments
2892 for Index
in range(len(HeaderComments
)):
2893 if HeaderComments
[Index
].find('@BinaryHeader') != -1:
2894 HeaderComments
[Index
] = HeaderComments
[Index
].replace('@BinaryHeader', '@file')
2897 AsBuiltInfDict
['header_comments'] = '\n'.join(HeaderComments
[StartPos
:]).replace(':#', '://')
2899 (self
.ProtocolList
, self
._ProtocolComments
, 'protocol_item'),
2900 (self
.PpiList
, self
._PpiComments
, 'ppi_item'),
2901 (GuidList
, self
._GuidComments
, 'guid_item')
2903 for Item
in GenList
:
2904 for CName
in Item
[0]:
2906 if CName
in Item
[1]:
2907 Comments
= '\n '.join(Item
[1][CName
])
2910 Entry
= Comments
+ '\n ' + CName
2911 AsBuiltInfDict
[Item
[2]].append(Entry
)
2912 PatchList
= parsePcdInfoFromMapFile(
2913 os
.path
.join(self
.OutputDir
, self
.Name
+ '.map'),
2914 os
.path
.join(self
.OutputDir
, self
.Name
+ '.efi')
2917 for PatchPcd
in PatchList
:
2918 if PatchPcd
[0] not in PatchablePcds
:
2920 Pcd
= PatchablePcds
[PatchPcd
[0]]
2922 if Pcd
.DatumType
!= 'VOID*':
2923 HexFormat
= '0x%02x'
2924 if Pcd
.DatumType
== 'UINT16':
2925 HexFormat
= '0x%04x'
2926 elif Pcd
.DatumType
== 'UINT32':
2927 HexFormat
= '0x%08x'
2928 elif Pcd
.DatumType
== 'UINT64':
2929 HexFormat
= '0x%016x'
2930 PcdValue
= HexFormat
% int(Pcd
.DefaultValue
, 0)
2932 if Pcd
.MaxDatumSize
== None or Pcd
.MaxDatumSize
== '':
2933 EdkLogger
.error("build", AUTOGEN_ERROR
,
2934 "Unknown [MaxDatumSize] of PCD [%s.%s]" % (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
)
2936 ArraySize
= int(Pcd
.MaxDatumSize
, 0)
2937 PcdValue
= Pcd
.DefaultValue
2938 if PcdValue
[0] != '{':
2940 if PcdValue
[0] == 'L':
2942 PcdValue
= PcdValue
.lstrip('L')
2943 PcdValue
= eval(PcdValue
)
2945 for Index
in range(0, len(PcdValue
)):
2947 CharVal
= ord(PcdValue
[Index
])
2948 NewValue
= NewValue
+ '0x%02x' % (CharVal
& 0x00FF) + ', ' \
2949 + '0x%02x' % (CharVal
>> 8) + ', '
2951 NewValue
= NewValue
+ '0x%02x' % (ord(PcdValue
[Index
]) % 0x100) + ', '
2954 Padding
= Padding
* 2
2955 ArraySize
= ArraySize
/ 2
2956 if ArraySize
< (len(PcdValue
) + 1):
2957 EdkLogger
.error("build", AUTOGEN_ERROR
,
2958 "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
)
2960 if ArraySize
> len(PcdValue
) + 1:
2961 NewValue
= NewValue
+ Padding
* (ArraySize
- len(PcdValue
) - 1)
2962 PcdValue
= NewValue
+ Padding
.strip().rstrip(',') + '}'
2963 elif len(PcdValue
.split(',')) <= ArraySize
:
2964 PcdValue
= PcdValue
.rstrip('}') + ', 0x00' * (ArraySize
- len(PcdValue
.split(',')))
2967 EdkLogger
.error("build", AUTOGEN_ERROR
,
2968 "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
)
2970 PcdItem
= '%s.%s|%s|0x%X' % \
2971 (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
, PcdValue
, PatchPcd
[1])
2973 if (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) in self
._PcdComments
:
2974 PcdComments
= '\n '.join(self
._PcdComments
[Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
])
2976 PcdItem
= PcdComments
+ '\n ' + PcdItem
2977 AsBuiltInfDict
['patchablepcd_item'].append(PcdItem
)
2982 if Pcd
.Type
== TAB_PCDS_DYNAMIC_EX_HII
:
2983 for SkuName
in Pcd
.SkuInfoList
:
2984 SkuInfo
= Pcd
.SkuInfoList
[SkuName
]
2985 HiiInfo
= '## %s|%s|%s' % (SkuInfo
.VariableName
, SkuInfo
.VariableGuid
, SkuInfo
.VariableOffset
)
2987 if (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) in self
._PcdComments
:
2988 PcdCommentList
= self
._PcdComments
[Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
][:]
2991 for Index
, Comment
in enumerate(PcdCommentList
):
2992 for Usage
in UsageList
:
2993 if Comment
.find(Usage
) != -1:
2996 if UsageIndex
!= -1:
2997 PcdCommentList
[UsageIndex
] = PcdCommentList
[UsageIndex
] + ' ' + HiiInfo
2999 PcdCommentList
.append('## ' + HiiInfo
)
3000 PcdComments
= '\n '.join(PcdCommentList
)
3001 PcdEntry
= Pcd
.TokenSpaceGuidCName
+ '.' + Pcd
.TokenCName
3003 PcdEntry
= PcdComments
+ '\n ' + PcdEntry
3004 AsBuiltInfDict
['pcd_item'] += [PcdEntry
]
3005 for Item
in self
.BuildOption
:
3006 if 'FLAGS' in self
.BuildOption
[Item
]:
3007 AsBuiltInfDict
['flags_item'] += ['%s:%s_%s_%s_%s_FLAGS = %s' % (self
.ToolChainFamily
, self
.BuildTarget
, self
.ToolChain
, self
.Arch
, Item
, self
.BuildOption
[Item
]['FLAGS'].strip())]
3009 AsBuiltInf
= TemplateString()
3010 AsBuiltInf
.Append(gAsBuiltInfHeaderString
.Replace(AsBuiltInfDict
))
3012 SaveFileOnChange(os
.path
.join(self
.OutputDir
, self
.Name
+ '.inf'), str(AsBuiltInf
), False)
3014 self
.IsAsBuiltInfCreated
= True
3016 ## Create makefile for the module and its dependent libraries
3018 # @param CreateLibraryMakeFile Flag indicating if or not the makefiles of
3019 # dependent libraries will be created
3021 def CreateMakeFile(self
, CreateLibraryMakeFile
=True):
3022 if self
.IsMakeFileCreated
:
3025 if not self
.IsLibrary
and CreateLibraryMakeFile
:
3026 for LibraryAutoGen
in self
.LibraryAutoGenList
:
3027 LibraryAutoGen
.CreateMakeFile()
3029 if len(self
.CustomMakefile
) == 0:
3030 Makefile
= GenMake
.ModuleMakefile(self
)
3032 Makefile
= GenMake
.CustomMakefile(self
)
3033 if Makefile
.Generate():
3034 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated makefile for module %s [%s]" %
3035 (self
.Name
, self
.Arch
))
3037 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Skipped the generation of makefile for module %s [%s]" %
3038 (self
.Name
, self
.Arch
))
3040 self
.IsMakeFileCreated
= True
3042 ## Create autogen code for the module and its dependent libraries
3044 # @param CreateLibraryCodeFile Flag indicating if or not the code of
3045 # dependent libraries will be created
3047 def CreateCodeFile(self
, CreateLibraryCodeFile
=True):
3048 if self
.IsCodeFileCreated
:
3051 # Need to generate PcdDatabase even PcdDriver is binarymodule
3052 if self
.IsBinaryModule
and self
.PcdIsDriver
!= '':
3053 CreatePcdDatabaseCode(self
, TemplateString(), TemplateString())
3056 if not self
.IsLibrary
and CreateLibraryCodeFile
:
3057 for LibraryAutoGen
in self
.LibraryAutoGenList
:
3058 LibraryAutoGen
.CreateCodeFile()
3061 IgoredAutoGenList
= []
3063 for File
in self
.AutoGenFileList
:
3064 if GenC
.Generate(File
.Path
, self
.AutoGenFileList
[File
], File
.IsBinary
):
3065 #Ignore Edk AutoGen.c
3066 if self
.AutoGenVersion
< 0x00010005 and File
.Name
== 'AutoGen.c':
3069 AutoGenList
.append(str(File
))
3071 IgoredAutoGenList
.append(str(File
))
3073 # Skip the following code for EDK I inf
3074 if self
.AutoGenVersion
< 0x00010005:
3077 for ModuleType
in self
.DepexList
:
3078 # Ignore empty [depex] section or [depex] section for "USER_DEFINED" module
3079 if len(self
.DepexList
[ModuleType
]) == 0 or ModuleType
== "USER_DEFINED":
3082 Dpx
= GenDepex
.DependencyExpression(self
.DepexList
[ModuleType
], ModuleType
, True)
3083 DpxFile
= gAutoGenDepexFileName
% {"module_name" : self
.Name
}
3085 if len(Dpx
.PostfixNotation
) <> 0:
3086 self
.DepexGenerated
= True
3088 if Dpx
.Generate(path
.join(self
.OutputDir
, DpxFile
)):
3089 AutoGenList
.append(str(DpxFile
))
3091 IgoredAutoGenList
.append(str(DpxFile
))
3093 if IgoredAutoGenList
== []:
3094 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated [%s] files for module %s [%s]" %
3095 (" ".join(AutoGenList
), self
.Name
, self
.Arch
))
3096 elif AutoGenList
== []:
3097 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Skipped the generation of [%s] files for module %s [%s]" %
3098 (" ".join(IgoredAutoGenList
), self
.Name
, self
.Arch
))
3100 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated [%s] (skipped %s) files for module %s [%s]" %
3101 (" ".join(AutoGenList
), " ".join(IgoredAutoGenList
), self
.Name
, self
.Arch
))
3103 self
.IsCodeFileCreated
= True
3106 ## Summarize the ModuleAutoGen objects of all libraries used by this module
3107 def _GetLibraryAutoGenList(self
):
3108 if self
._LibraryAutoGenList
== None:
3109 self
._LibraryAutoGenList
= []
3110 for Library
in self
.DependentLibraryList
:
3117 self
.PlatformInfo
.MetaFile
3119 if La
not in self
._LibraryAutoGenList
:
3120 self
._LibraryAutoGenList
.append(La
)
3121 for Lib
in La
.CodaTargetList
:
3122 self
._ApplyBuildRule
(Lib
.Target
, TAB_UNKNOWN_FILE
)
3123 return self
._LibraryAutoGenList
3125 Module
= property(_GetModule
)
3126 Name
= property(_GetBaseName
)
3127 Guid
= property(_GetGuid
)
3128 Version
= property(_GetVersion
)
3129 ModuleType
= property(_GetModuleType
)
3130 ComponentType
= property(_GetComponentType
)
3131 BuildType
= property(_GetBuildType
)
3132 PcdIsDriver
= property(_GetPcdIsDriver
)
3133 AutoGenVersion
= property(_GetAutoGenVersion
)
3134 Macros
= property(_GetMacros
)
3135 Specification
= property(_GetSpecification
)
3137 IsLibrary
= property(_IsLibrary
)
3138 IsBinaryModule
= property(_IsBinaryModule
)
3139 BuildDir
= property(_GetBuildDir
)
3140 OutputDir
= property(_GetOutputDir
)
3141 DebugDir
= property(_GetDebugDir
)
3142 MakeFileDir
= property(_GetMakeFileDir
)
3143 CustomMakefile
= property(_GetCustomMakefile
)
3145 IncludePathList
= property(_GetIncludePathList
)
3146 AutoGenFileList
= property(_GetAutoGenFileList
)
3147 UnicodeFileList
= property(_GetUnicodeFileList
)
3148 SourceFileList
= property(_GetSourceFileList
)
3149 BinaryFileList
= property(_GetBinaryFiles
) # FileType : [File List]
3150 Targets
= property(_GetTargets
)
3151 IntroTargetList
= property(_GetIntroTargetList
)
3152 CodaTargetList
= property(_GetFinalTargetList
)
3153 FileTypes
= property(_GetFileTypes
)
3154 BuildRules
= property(_GetBuildRules
)
3156 DependentPackageList
= property(_GetDependentPackageList
)
3157 DependentLibraryList
= property(_GetLibraryList
)
3158 LibraryAutoGenList
= property(_GetLibraryAutoGenList
)
3159 DerivedPackageList
= property(_GetDerivedPackageList
)
3161 ModulePcdList
= property(_GetModulePcdList
)
3162 LibraryPcdList
= property(_GetLibraryPcdList
)
3163 GuidList
= property(_GetGuidList
)
3164 ProtocolList
= property(_GetProtocolList
)
3165 PpiList
= property(_GetPpiList
)
3166 DepexList
= property(_GetDepexTokenList
)
3167 DxsFile
= property(_GetDxsFile
)
3168 DepexExpressionList
= property(_GetDepexExpressionTokenList
)
3169 BuildOption
= property(_GetModuleBuildOption
)
3170 BuildOptionIncPathList
= property(_GetBuildOptionIncPathList
)
3171 BuildCommand
= property(_GetBuildCommand
)
3173 FixedAtBuildPcds
= property(_GetFixedAtBuildPcds
)
3175 # This acts like the main() function for the script, unless it is 'import'ed into another script.
3176 if __name__
== '__main__':