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
),
659 ## Create makefile for the platform and modules in it
661 # @param CreateDepsMakeFile Flag indicating if the makefile for
662 # modules will be created as well
664 def CreateMakeFile(self
, CreateDepsMakeFile
=False):
665 # create makefile for platform
666 Makefile
= GenMake
.TopLevelMakefile(self
)
667 if Makefile
.Generate():
668 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated makefile for platform [%s] %s\n" %
669 (self
.MetaFile
, self
.ArchList
))
671 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Skipped the generation of makefile for platform [%s] %s\n" %
672 (self
.MetaFile
, self
.ArchList
))
674 if CreateDepsMakeFile
:
675 for Pa
in self
.AutoGenObjectList
:
676 Pa
.CreateMakeFile(CreateDepsMakeFile
)
678 ## Create autogen code for platform and modules
680 # Since there's no autogen code for platform, this method will do nothing
681 # if CreateModuleCodeFile is set to False.
683 # @param CreateDepsCodeFile Flag indicating if creating module's
684 # autogen code file or not
686 def CreateCodeFile(self
, CreateDepsCodeFile
=False):
687 if not CreateDepsCodeFile
:
689 for Pa
in self
.AutoGenObjectList
:
690 Pa
.CreateCodeFile(CreateDepsCodeFile
)
692 ## Create AsBuilt INF file the platform
694 def CreateAsBuiltInf(self
):
697 Name
= property(_GetName
)
698 Guid
= property(_GetGuid
)
699 Version
= property(_GetVersion
)
700 OutputDir
= property(_GetOutputDir
)
702 ToolDefinition
= property(_GetToolDefinition
) # toolcode : tool path
704 BuildDir
= property(_GetBuildDir
)
705 FvDir
= property(_GetFvDir
)
706 MakeFileDir
= property(_GetMakeFileDir
)
707 BuildCommand
= property(_GetBuildCommand
)
709 ## AutoGen class for platform
711 # PlatformAutoGen class will process the original information in platform
712 # file in order to generate makefile for platform.
714 class PlatformAutoGen(AutoGen
):
716 # Used to store all PCDs for both PEI and DXE phase, in order to generate
717 # correct PCD database
720 _NonDynaPcdList_
= []
723 # The priority list while override build option
725 PrioList
= {"0x11111" : 16, # TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE (Highest)
726 "0x01111" : 15, # ******_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
727 "0x10111" : 14, # TARGET_*********_ARCH_COMMANDTYPE_ATTRIBUTE
728 "0x00111" : 13, # ******_*********_ARCH_COMMANDTYPE_ATTRIBUTE
729 "0x11011" : 12, # TARGET_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
730 "0x01011" : 11, # ******_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
731 "0x10011" : 10, # TARGET_*********_****_COMMANDTYPE_ATTRIBUTE
732 "0x00011" : 9, # ******_*********_****_COMMANDTYPE_ATTRIBUTE
733 "0x11101" : 8, # TARGET_TOOLCHAIN_ARCH_***********_ATTRIBUTE
734 "0x01101" : 7, # ******_TOOLCHAIN_ARCH_***********_ATTRIBUTE
735 "0x10101" : 6, # TARGET_*********_ARCH_***********_ATTRIBUTE
736 "0x00101" : 5, # ******_*********_ARCH_***********_ATTRIBUTE
737 "0x11001" : 4, # TARGET_TOOLCHAIN_****_***********_ATTRIBUTE
738 "0x01001" : 3, # ******_TOOLCHAIN_****_***********_ATTRIBUTE
739 "0x10001" : 2, # TARGET_*********_****_***********_ATTRIBUTE
740 "0x00001" : 1} # ******_*********_****_***********_ATTRIBUTE (Lowest)
742 ## The real constructor of PlatformAutoGen
744 # This method is not supposed to be called by users of PlatformAutoGen. It's
745 # only used by factory method __new__() to do real initialization work for an
746 # object of PlatformAutoGen
748 # @param Workspace WorkspaceAutoGen object
749 # @param PlatformFile Platform file (DSC file)
750 # @param Target Build target (DEBUG, RELEASE)
751 # @param Toolchain Name of tool chain
752 # @param Arch arch of the platform supports
754 def _Init(self
, Workspace
, PlatformFile
, Target
, Toolchain
, Arch
):
755 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "AutoGen platform [%s] [%s]" % (PlatformFile
, Arch
))
756 GlobalData
.gProcessingFile
= "%s [%s, %s, %s]" % (PlatformFile
, Arch
, Toolchain
, Target
)
758 self
.MetaFile
= PlatformFile
759 self
.Workspace
= Workspace
760 self
.WorkspaceDir
= Workspace
.WorkspaceDir
761 self
.ToolChain
= Toolchain
762 self
.BuildTarget
= Target
764 self
.SourceDir
= PlatformFile
.SubDir
765 self
.SourceOverrideDir
= None
766 self
.FdTargetList
= self
.Workspace
.FdTargetList
767 self
.FvTargetList
= self
.Workspace
.FvTargetList
770 # flag indicating if the makefile/C-code file has been created or not
771 self
.IsMakeFileCreated
= False
772 self
.IsCodeFileCreated
= False
774 self
._Platform
= None
779 self
._BuildRule
= None
780 self
._SourceDir
= None
781 self
._BuildDir
= None
782 self
._OutputDir
= None
784 self
._MakeFileDir
= None
787 self
._PcdTokenNumber
= None # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber
788 self
._DynamicPcdList
= None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
789 self
._NonDynamicPcdList
= None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
790 self
._NonDynamicPcdDict
= {}
792 self
._ToolDefinitions
= None
793 self
._ToolDefFile
= None # toolcode : tool path
794 self
._ToolChainFamily
= None
795 self
._BuildRuleFamily
= None
796 self
._BuildOption
= None # toolcode : option
797 self
._EdkBuildOption
= None # edktoolcode : option
798 self
._EdkIIBuildOption
= None # edkiitoolcode : option
799 self
._PackageList
= None
800 self
._ModuleAutoGenList
= None
801 self
._LibraryAutoGenList
= None
802 self
._BuildCommand
= None
804 # get the original module/package/platform objects
805 self
.BuildDatabase
= Workspace
.BuildDatabase
809 return "%s [%s]" % (self
.MetaFile
, self
.Arch
)
811 ## Create autogen code for platform and modules
813 # Since there's no autogen code for platform, this method will do nothing
814 # if CreateModuleCodeFile is set to False.
816 # @param CreateModuleCodeFile Flag indicating if creating module's
817 # autogen code file or not
819 def CreateCodeFile(self
, CreateModuleCodeFile
=False):
820 # only module has code to be greated, so do nothing if CreateModuleCodeFile is False
821 if self
.IsCodeFileCreated
or not CreateModuleCodeFile
:
824 for Ma
in self
.ModuleAutoGenList
:
825 Ma
.CreateCodeFile(True)
827 # don't do this twice
828 self
.IsCodeFileCreated
= True
830 ## Create makefile for the platform and mdoules in it
832 # @param CreateModuleMakeFile Flag indicating if the makefile for
833 # modules will be created as well
835 def CreateMakeFile(self
, CreateModuleMakeFile
=False):
836 if CreateModuleMakeFile
:
837 for ModuleFile
in self
.Platform
.Modules
:
838 Ma
= ModuleAutoGen(self
.Workspace
, ModuleFile
, self
.BuildTarget
,
839 self
.ToolChain
, self
.Arch
, self
.MetaFile
)
840 Ma
.CreateMakeFile(True)
841 Ma
.CreateAsBuiltInf()
843 # no need to create makefile for the platform more than once
844 if self
.IsMakeFileCreated
:
847 # create makefile for platform
848 Makefile
= GenMake
.PlatformMakefile(self
)
849 if Makefile
.Generate():
850 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated makefile for platform [%s] [%s]\n" %
851 (self
.MetaFile
, self
.Arch
))
853 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Skipped the generation of makefile for platform [%s] [%s]\n" %
854 (self
.MetaFile
, self
.Arch
))
855 self
.IsMakeFileCreated
= True
857 ## Deal with Shared FixedAtBuild Pcds
859 def CollectFixedAtBuildPcds(self
):
860 for LibAuto
in self
.LibraryAutoGenList
:
861 FixedAtBuildPcds
= {}
862 ShareFixedAtBuildPcdsSameValue
= {}
863 for Module
in LibAuto
._ReferenceModules
:
864 for Pcd
in Module
.FixedAtBuildPcds
+ LibAuto
.FixedAtBuildPcds
:
865 key
= ".".join((Pcd
.TokenSpaceGuidCName
,Pcd
.TokenCName
))
866 if key
not in FixedAtBuildPcds
:
867 ShareFixedAtBuildPcdsSameValue
[key
] = True
868 FixedAtBuildPcds
[key
] = Pcd
.DefaultValue
870 if FixedAtBuildPcds
[key
] != Pcd
.DefaultValue
:
871 ShareFixedAtBuildPcdsSameValue
[key
] = False
872 for Pcd
in LibAuto
.FixedAtBuildPcds
:
873 key
= ".".join((Pcd
.TokenSpaceGuidCName
,Pcd
.TokenCName
))
874 if (Pcd
.TokenCName
,Pcd
.TokenSpaceGuidCName
) not in self
.NonDynamicPcdDict
:
877 DscPcd
= self
.NonDynamicPcdDict
[(Pcd
.TokenCName
,Pcd
.TokenSpaceGuidCName
)]
878 if DscPcd
.Type
!= "FixedAtBuild":
880 if key
in ShareFixedAtBuildPcdsSameValue
and ShareFixedAtBuildPcdsSameValue
[key
]:
881 LibAuto
.ConstPcd
[key
] = Pcd
.DefaultValue
883 ## Collect dynamic PCDs
885 # Gather dynamic PCDs list from each module and their settings from platform
886 # This interface should be invoked explicitly when platform action is created.
888 def CollectPlatformDynamicPcds(self
):
889 # for gathering error information
890 NoDatumTypePcdList
= set()
893 for F
in self
.Platform
.Modules
.keys():
894 M
= ModuleAutoGen(self
.Workspace
, F
, self
.BuildTarget
, self
.ToolChain
, self
.Arch
, self
.MetaFile
)
895 #GuidValue.update(M.Guids)
897 self
.Platform
.Modules
[F
].M
= M
899 for PcdFromModule
in M
.ModulePcdList
+M
.LibraryPcdList
:
900 # make sure that the "VOID*" kind of datum has MaxDatumSize set
901 if PcdFromModule
.DatumType
== "VOID*" and PcdFromModule
.MaxDatumSize
in [None, '']:
902 NoDatumTypePcdList
.add("%s.%s [%s]" % (PcdFromModule
.TokenSpaceGuidCName
, PcdFromModule
.TokenCName
, F
))
904 if PcdFromModule
.Type
in GenC
.gDynamicPcd
or PcdFromModule
.Type
in GenC
.gDynamicExPcd
:
906 # If a dynamic PCD used by a PEM module/PEI module & DXE module,
907 # it should be stored in Pcd PEI database, If a dynamic only
908 # used by DXE module, it should be stored in DXE PCD database.
909 # The default Phase is DXE
911 if M
.ModuleType
in ["PEIM", "PEI_CORE"]:
912 PcdFromModule
.Phase
= "PEI"
913 if PcdFromModule
not in self
._DynaPcdList
_:
914 self
._DynaPcdList
_.append(PcdFromModule
)
915 elif PcdFromModule
.Phase
== 'PEI':
916 # overwrite any the same PCD existing, if Phase is PEI
917 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
918 self
._DynaPcdList
_[Index
] = PcdFromModule
919 elif PcdFromModule
not in self
._NonDynaPcdList
_:
920 self
._NonDynaPcdList
_.append(PcdFromModule
)
922 # print out error information and break the build, if error found
923 if len(NoDatumTypePcdList
) > 0:
924 NoDatumTypePcdListString
= "\n\t\t".join(NoDatumTypePcdList
)
925 EdkLogger
.error("build", AUTOGEN_ERROR
, "PCD setting error",
927 ExtraData
="\n\tPCD(s) without MaxDatumSize:\n\t\t%s\n"
928 % NoDatumTypePcdListString
)
929 self
._NonDynamicPcdList
= self
._NonDynaPcdList
_
930 self
._DynamicPcdList
= self
._DynaPcdList
_
931 self
.AllPcdList
= self
._NonDynamicPcdList
+ self
._DynamicPcdList
934 # Sort dynamic PCD list to:
935 # 1) If PCD's datum type is VOID* and value is unicode string which starts with L, the PCD item should
936 # try to be put header of dynamicd List
937 # 2) If PCD is HII type, the PCD item should be put after unicode type PCD
939 # The reason of sorting is make sure the unicode string is in double-byte alignment in string table.
945 VpdFile
= VpdInfoFile
.VpdInfoFile()
946 NeedProcessVpdMapFile
= False
948 if (self
.Workspace
.ArchList
[-1] == self
.Arch
):
949 for Pcd
in self
._DynamicPcdList
:
950 # just pick the a value to determine whether is unicode string type
951 Sku
= Pcd
.SkuInfoList
[Pcd
.SkuInfoList
.keys()[0]]
952 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
954 PcdValue
= Sku
.DefaultValue
955 if Pcd
.DatumType
== 'VOID*' and PcdValue
.startswith("L"):
956 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
957 UnicodePcdArray
.append(Pcd
)
958 elif len(Sku
.VariableName
) > 0:
959 # if found HII type PCD then insert to right of UnicodeIndex
960 HiiPcdArray
.append(Pcd
)
962 OtherPcdArray
.append(Pcd
)
963 if Pcd
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
]:
964 VpdPcdDict
[(Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
)] = Pcd
966 PlatformPcds
= self
.Platform
.Pcds
.keys()
969 # Add VPD type PCD into VpdFile and determine whether the VPD PCD need to be fixed up.
971 for PcdKey
in PlatformPcds
:
972 Pcd
= self
.Platform
.Pcds
[PcdKey
]
973 if Pcd
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
] and \
974 PcdKey
in VpdPcdDict
:
975 Pcd
= VpdPcdDict
[PcdKey
]
976 for (SkuName
,Sku
) in Pcd
.SkuInfoList
.items():
977 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
978 VpdFile
.Add(Pcd
, Sku
.VpdOffset
)
979 # if the offset of a VPD is *, then it need to be fixed up by third party tool.
980 if not NeedProcessVpdMapFile
and Sku
.VpdOffset
== "*":
981 NeedProcessVpdMapFile
= True
982 if self
.Platform
.VpdToolGuid
== None or self
.Platform
.VpdToolGuid
== '':
983 EdkLogger
.error("Build", FILE_NOT_FOUND
, \
984 "Fail to find third-party BPDG tool to process VPD PCDs. BPDG Guid tool need to be defined in tools_def.txt and VPD_TOOL_GUID need to be provided in DSC file.")
988 # Fix the PCDs define in VPD PCD section that never referenced by module.
989 # An example is PCD for signature usage.
991 for DscPcd
in PlatformPcds
:
992 DscPcdEntry
= self
.Platform
.Pcds
[DscPcd
]
993 if DscPcdEntry
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
]:
994 if not (self
.Platform
.VpdToolGuid
== None or self
.Platform
.VpdToolGuid
== ''):
996 for VpdPcd
in VpdFile
._VpdArray
.keys():
997 # This PCD has been referenced by module
998 if (VpdPcd
.TokenSpaceGuidCName
== DscPcdEntry
.TokenSpaceGuidCName
) and \
999 (VpdPcd
.TokenCName
== DscPcdEntry
.TokenCName
):
1002 # Not found, it should be signature
1004 # just pick the a value to determine whether is unicode string type
1005 for (SkuName
,Sku
) in DscPcdEntry
.SkuInfoList
.items():
1006 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1008 # Need to iterate DEC pcd information to get the value & datumtype
1009 for eachDec
in self
.PackageList
:
1010 for DecPcd
in eachDec
.Pcds
:
1011 DecPcdEntry
= eachDec
.Pcds
[DecPcd
]
1012 if (DecPcdEntry
.TokenSpaceGuidCName
== DscPcdEntry
.TokenSpaceGuidCName
) and \
1013 (DecPcdEntry
.TokenCName
== DscPcdEntry
.TokenCName
):
1014 # Print warning message to let the developer make a determine.
1015 EdkLogger
.warn("build", "Unreferenced vpd pcd used!",
1016 File
=self
.MetaFile
, \
1017 ExtraData
= "PCD: %s.%s used in the DSC file %s is unreferenced." \
1018 %(DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
, self
.Platform
.MetaFile
.Path
))
1020 DscPcdEntry
.DatumType
= DecPcdEntry
.DatumType
1021 DscPcdEntry
.DefaultValue
= DecPcdEntry
.DefaultValue
1022 DscPcdEntry
.TokenValue
= DecPcdEntry
.TokenValue
1023 DscPcdEntry
.TokenSpaceGuidValue
= eachDec
.Guids
[DecPcdEntry
.TokenSpaceGuidCName
]
1024 # Only fix the value while no value provided in DSC file.
1025 if (Sku
.DefaultValue
== "" or Sku
.DefaultValue
==None):
1026 DscPcdEntry
.SkuInfoList
[DscPcdEntry
.SkuInfoList
.keys()[0]].DefaultValue
= DecPcdEntry
.DefaultValue
1028 if DscPcdEntry
not in self
._DynamicPcdList
:
1029 self
._DynamicPcdList
.append(DscPcdEntry
)
1030 # Sku = DscPcdEntry.SkuInfoList[DscPcdEntry.SkuInfoList.keys()[0]]
1031 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1032 PcdValue
= Sku
.DefaultValue
1033 VpdFile
.Add(DscPcdEntry
, Sku
.VpdOffset
)
1034 if not NeedProcessVpdMapFile
and Sku
.VpdOffset
== "*":
1035 NeedProcessVpdMapFile
= True
1036 if DscPcdEntry
.DatumType
== 'VOID*' and PcdValue
.startswith("L"):
1037 UnicodePcdArray
.append(DscPcdEntry
)
1038 elif len(Sku
.VariableName
) > 0:
1039 HiiPcdArray
.append(DscPcdEntry
)
1041 OtherPcdArray
.append(DscPcdEntry
)
1043 # if the offset of a VPD is *, then it need to be fixed up by third party tool.
1047 if (self
.Platform
.FlashDefinition
== None or self
.Platform
.FlashDefinition
== '') and \
1048 VpdFile
.GetCount() != 0:
1049 EdkLogger
.error("build", ATTRIBUTE_NOT_AVAILABLE
,
1050 "Fail to get FLASH_DEFINITION definition in DSC file %s which is required when DSC contains VPD PCD." % str(self
.Platform
.MetaFile
))
1052 if VpdFile
.GetCount() != 0:
1053 DscTimeStamp
= self
.Platform
.MetaFile
.TimeStamp
1054 FvPath
= os
.path
.join(self
.BuildDir
, "FV")
1055 if not os
.path
.exists(FvPath
):
1059 EdkLogger
.error("build", FILE_WRITE_FAILURE
, "Fail to create FV folder under %s" % self
.BuildDir
)
1062 VpdFilePath
= os
.path
.join(FvPath
, "%s.txt" % self
.Platform
.VpdToolGuid
)
1065 if not os
.path
.exists(VpdFilePath
) or os
.path
.getmtime(VpdFilePath
) < DscTimeStamp
:
1066 VpdFile
.Write(VpdFilePath
)
1068 # retrieve BPDG tool's path from tool_def.txt according to VPD_TOOL_GUID defined in DSC file.
1070 for ToolDef
in self
.ToolDefinition
.values():
1071 if ToolDef
.has_key("GUID") and ToolDef
["GUID"] == self
.Platform
.VpdToolGuid
:
1072 if not ToolDef
.has_key("PATH"):
1073 EdkLogger
.error("build", ATTRIBUTE_NOT_AVAILABLE
, "PATH attribute was not provided for BPDG guid tool %s in tools_def.txt" % self
.Platform
.VpdToolGuid
)
1074 BPDGToolName
= ToolDef
["PATH"]
1076 # Call third party GUID BPDG tool.
1077 if BPDGToolName
!= None:
1078 VpdInfoFile
.CallExtenalBPDGTool(BPDGToolName
, VpdFilePath
)
1080 EdkLogger
.error("Build", FILE_NOT_FOUND
, "Fail to find third-party BPDG tool to process VPD PCDs. BPDG Guid tool need to be defined in tools_def.txt and VPD_TOOL_GUID need to be provided in DSC file.")
1082 # Process VPD map file generated by third party BPDG tool
1083 if NeedProcessVpdMapFile
:
1084 VpdMapFilePath
= os
.path
.join(self
.BuildDir
, "FV", "%s.map" % self
.Platform
.VpdToolGuid
)
1085 if os
.path
.exists(VpdMapFilePath
):
1086 VpdFile
.Read(VpdMapFilePath
)
1089 for Pcd
in self
._DynamicPcdList
:
1090 # just pick the a value to determine whether is unicode string type
1092 for (SkuName
,Sku
) in Pcd
.SkuInfoList
.items():
1093 if Sku
.VpdOffset
== "*":
1094 Sku
.VpdOffset
= VpdFile
.GetOffset(Pcd
)[i
].strip()
1097 EdkLogger
.error("build", FILE_READ_FAILURE
, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath
)
1099 # Delete the DynamicPcdList At the last time enter into this function
1100 del self
._DynamicPcdList
[:]
1101 self
._DynamicPcdList
.extend(UnicodePcdArray
)
1102 self
._DynamicPcdList
.extend(HiiPcdArray
)
1103 self
._DynamicPcdList
.extend(OtherPcdArray
)
1106 ## Return the platform build data object
1107 def _GetPlatform(self
):
1108 if self
._Platform
== None:
1109 self
._Platform
= self
.BuildDatabase
[self
.MetaFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1110 return self
._Platform
1112 ## Return platform name
1114 return self
.Platform
.PlatformName
1116 ## Return the meta file GUID
1118 return self
.Platform
.Guid
1120 ## Return the platform version
1121 def _GetVersion(self
):
1122 return self
.Platform
.Version
1124 ## Return the FDF file name
1125 def _GetFdfFile(self
):
1126 if self
._FdfFile
== None:
1127 if self
.Workspace
.FdfFile
!= "":
1128 self
._FdfFile
= path
.join(self
.WorkspaceDir
, self
.Workspace
.FdfFile
)
1131 return self
._FdfFile
1133 ## Return the build output directory platform specifies
1134 def _GetOutputDir(self
):
1135 return self
.Platform
.OutputDirectory
1137 ## Return the directory to store all intermediate and final files built
1138 def _GetBuildDir(self
):
1139 if self
._BuildDir
== None:
1140 if os
.path
.isabs(self
.OutputDir
):
1141 self
._BuildDir
= path
.join(
1142 path
.abspath(self
.OutputDir
),
1143 self
.BuildTarget
+ "_" + self
.ToolChain
,
1146 self
._BuildDir
= path
.join(
1149 self
.BuildTarget
+ "_" + self
.ToolChain
,
1151 return self
._BuildDir
1153 ## Return directory of platform makefile
1155 # @retval string Makefile directory
1157 def _GetMakeFileDir(self
):
1158 if self
._MakeFileDir
== None:
1159 self
._MakeFileDir
= path
.join(self
.BuildDir
, self
.Arch
)
1160 return self
._MakeFileDir
1162 ## Return build command string
1164 # @retval string Build command string
1166 def _GetBuildCommand(self
):
1167 if self
._BuildCommand
== None:
1168 self
._BuildCommand
= []
1169 if "MAKE" in self
.ToolDefinition
and "PATH" in self
.ToolDefinition
["MAKE"]:
1170 self
._BuildCommand
+= SplitOption(self
.ToolDefinition
["MAKE"]["PATH"])
1171 if "FLAGS" in self
.ToolDefinition
["MAKE"]:
1172 NewOption
= self
.ToolDefinition
["MAKE"]["FLAGS"].strip()
1174 self
._BuildCommand
+= SplitOption(NewOption
)
1175 return self
._BuildCommand
1177 ## Get tool chain definition
1179 # Get each tool defition for given tool chain from tools_def.txt and platform
1181 def _GetToolDefinition(self
):
1182 if self
._ToolDefinitions
== None:
1183 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDictionary
1184 if TAB_TOD_DEFINES_COMMAND_TYPE
not in self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
:
1185 EdkLogger
.error('build', RESOURCE_NOT_AVAILABLE
, "No tools found in configuration",
1186 ExtraData
="[%s]" % self
.MetaFile
)
1187 self
._ToolDefinitions
= {}
1189 for Def
in ToolDefinition
:
1190 Target
, Tag
, Arch
, Tool
, Attr
= Def
.split("_")
1191 if Target
!= self
.BuildTarget
or Tag
!= self
.ToolChain
or Arch
!= self
.Arch
:
1194 Value
= ToolDefinition
[Def
]
1195 # don't record the DLL
1197 DllPathList
.add(Value
)
1200 if Tool
not in self
._ToolDefinitions
:
1201 self
._ToolDefinitions
[Tool
] = {}
1202 self
._ToolDefinitions
[Tool
][Attr
] = Value
1206 if GlobalData
.gOptions
.SilentMode
and "MAKE" in self
._ToolDefinitions
:
1207 if "FLAGS" not in self
._ToolDefinitions
["MAKE"]:
1208 self
._ToolDefinitions
["MAKE"]["FLAGS"] = ""
1209 self
._ToolDefinitions
["MAKE"]["FLAGS"] += " -s"
1211 for Tool
in self
._ToolDefinitions
:
1212 for Attr
in self
._ToolDefinitions
[Tool
]:
1213 Value
= self
._ToolDefinitions
[Tool
][Attr
]
1214 if Tool
in self
.BuildOption
and Attr
in self
.BuildOption
[Tool
]:
1215 # check if override is indicated
1216 if self
.BuildOption
[Tool
][Attr
].startswith('='):
1217 Value
= self
.BuildOption
[Tool
][Attr
][1:]
1219 Value
+= " " + self
.BuildOption
[Tool
][Attr
]
1222 # Don't put MAKE definition in the file
1226 ToolsDef
+= "%s = %s\n" % (Tool
, Value
)
1228 # Don't put MAKE definition in the file
1233 ToolsDef
+= "%s_%s = %s\n" % (Tool
, Attr
, Value
)
1236 SaveFileOnChange(self
.ToolDefinitionFile
, ToolsDef
)
1237 for DllPath
in DllPathList
:
1238 os
.environ
["PATH"] = DllPath
+ os
.pathsep
+ os
.environ
["PATH"]
1239 os
.environ
["MAKE_FLAGS"] = MakeFlags
1241 return self
._ToolDefinitions
1243 ## Return the paths of tools
1244 def _GetToolDefFile(self
):
1245 if self
._ToolDefFile
== None:
1246 self
._ToolDefFile
= os
.path
.join(self
.MakeFileDir
, "TOOLS_DEF." + self
.Arch
)
1247 return self
._ToolDefFile
1249 ## Retrieve the toolchain family of given toolchain tag. Default to 'MSFT'.
1250 def _GetToolChainFamily(self
):
1251 if self
._ToolChainFamily
== None:
1252 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
1253 if TAB_TOD_DEFINES_FAMILY
not in ToolDefinition \
1254 or self
.ToolChain
not in ToolDefinition
[TAB_TOD_DEFINES_FAMILY
] \
1255 or not ToolDefinition
[TAB_TOD_DEFINES_FAMILY
][self
.ToolChain
]:
1256 EdkLogger
.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
1258 self
._ToolChainFamily
= "MSFT"
1260 self
._ToolChainFamily
= ToolDefinition
[TAB_TOD_DEFINES_FAMILY
][self
.ToolChain
]
1261 return self
._ToolChainFamily
1263 def _GetBuildRuleFamily(self
):
1264 if self
._BuildRuleFamily
== None:
1265 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
1266 if TAB_TOD_DEFINES_BUILDRULEFAMILY
not in ToolDefinition \
1267 or self
.ToolChain
not in ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
] \
1268 or not ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
][self
.ToolChain
]:
1269 EdkLogger
.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
1271 self
._BuildRuleFamily
= "MSFT"
1273 self
._BuildRuleFamily
= ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
][self
.ToolChain
]
1274 return self
._BuildRuleFamily
1276 ## Return the build options specific for all modules in this platform
1277 def _GetBuildOptions(self
):
1278 if self
._BuildOption
== None:
1279 self
._BuildOption
= self
._ExpandBuildOption
(self
.Platform
.BuildOptions
)
1280 return self
._BuildOption
1282 ## Return the build options specific for EDK modules in this platform
1283 def _GetEdkBuildOptions(self
):
1284 if self
._EdkBuildOption
== None:
1285 self
._EdkBuildOption
= self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, EDK_NAME
)
1286 return self
._EdkBuildOption
1288 ## Return the build options specific for EDKII modules in this platform
1289 def _GetEdkIIBuildOptions(self
):
1290 if self
._EdkIIBuildOption
== None:
1291 self
._EdkIIBuildOption
= self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, EDKII_NAME
)
1292 return self
._EdkIIBuildOption
1294 ## Parse build_rule.txt in $(WORKSPACE)/Conf/build_rule.txt
1296 # @retval BuildRule object
1298 def _GetBuildRule(self
):
1299 if self
._BuildRule
== None:
1300 BuildRuleFile
= None
1301 if TAB_TAT_DEFINES_BUILD_RULE_CONF
in self
.Workspace
.TargetTxt
.TargetTxtDictionary
:
1302 BuildRuleFile
= self
.Workspace
.TargetTxt
.TargetTxtDictionary
[TAB_TAT_DEFINES_BUILD_RULE_CONF
]
1303 if BuildRuleFile
in [None, '']:
1304 BuildRuleFile
= gBuildRuleFile
1305 self
._BuildRule
= BuildRule(BuildRuleFile
)
1306 if self
._BuildRule
._FileVersion
== "":
1307 self
._BuildRule
._FileVersion
= AutoGenReqBuildRuleVerNum
1309 if self
._BuildRule
._FileVersion
< AutoGenReqBuildRuleVerNum
:
1310 # If Build Rule's version is less than the version number required by the tools, halting the build.
1311 EdkLogger
.error("build", AUTOGEN_ERROR
,
1312 ExtraData
="The version number [%s] of build_rule.txt is less than the version number required by the AutoGen.(the minimum required version number is [%s])"\
1313 % (self
._BuildRule
._FileVersion
, AutoGenReqBuildRuleVerNum
))
1315 return self
._BuildRule
1317 ## Summarize the packages used by modules in this platform
1318 def _GetPackageList(self
):
1319 if self
._PackageList
== None:
1320 self
._PackageList
= set()
1321 for La
in self
.LibraryAutoGenList
:
1322 self
._PackageList
.update(La
.DependentPackageList
)
1323 for Ma
in self
.ModuleAutoGenList
:
1324 self
._PackageList
.update(Ma
.DependentPackageList
)
1325 self
._PackageList
= list(self
._PackageList
)
1326 return self
._PackageList
1328 def _GetNonDynamicPcdDict(self
):
1329 if self
._NonDynamicPcdDict
:
1330 return self
._NonDynamicPcdDict
1331 for Pcd
in self
.NonDynamicPcdList
:
1332 self
._NonDynamicPcdDict
[(Pcd
.TokenCName
,Pcd
.TokenSpaceGuidCName
)] = Pcd
1333 return self
._NonDynamicPcdDict
1335 ## Get list of non-dynamic PCDs
1336 def _GetNonDynamicPcdList(self
):
1337 if self
._NonDynamicPcdList
== None:
1338 self
.CollectPlatformDynamicPcds()
1339 return self
._NonDynamicPcdList
1341 ## Get list of dynamic PCDs
1342 def _GetDynamicPcdList(self
):
1343 if self
._DynamicPcdList
== None:
1344 self
.CollectPlatformDynamicPcds()
1345 return self
._DynamicPcdList
1347 ## Generate Token Number for all PCD
1348 def _GetPcdTokenNumbers(self
):
1349 if self
._PcdTokenNumber
== None:
1350 self
._PcdTokenNumber
= sdict()
1353 # Make the Dynamic and DynamicEx PCD use within different TokenNumber area.
1357 # TokenNumber 0 ~ 10
1359 # TokeNumber 11 ~ 20
1361 for Pcd
in self
.DynamicPcdList
:
1362 if Pcd
.Phase
== "PEI":
1363 if Pcd
.Type
in ["Dynamic", "DynamicDefault", "DynamicVpd", "DynamicHii"]:
1364 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
1365 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
1368 for Pcd
in self
.DynamicPcdList
:
1369 if Pcd
.Phase
== "PEI":
1370 if Pcd
.Type
in ["DynamicEx", "DynamicExDefault", "DynamicExVpd", "DynamicExHii"]:
1371 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
1372 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
1375 for Pcd
in self
.DynamicPcdList
:
1376 if Pcd
.Phase
== "DXE":
1377 if Pcd
.Type
in ["Dynamic", "DynamicDefault", "DynamicVpd", "DynamicHii"]:
1378 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
1379 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
1382 for Pcd
in self
.DynamicPcdList
:
1383 if Pcd
.Phase
== "DXE":
1384 if Pcd
.Type
in ["DynamicEx", "DynamicExDefault", "DynamicExVpd", "DynamicExHii"]:
1385 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
1386 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
1389 for Pcd
in self
.NonDynamicPcdList
:
1390 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
1392 return self
._PcdTokenNumber
1394 ## Summarize ModuleAutoGen objects of all modules/libraries to be built for this platform
1395 def _GetAutoGenObjectList(self
):
1396 self
._ModuleAutoGenList
= []
1397 self
._LibraryAutoGenList
= []
1398 for ModuleFile
in self
.Platform
.Modules
:
1407 if Ma
not in self
._ModuleAutoGenList
:
1408 self
._ModuleAutoGenList
.append(Ma
)
1409 for La
in Ma
.LibraryAutoGenList
:
1410 if La
not in self
._LibraryAutoGenList
:
1411 self
._LibraryAutoGenList
.append(La
)
1412 if Ma
not in La
._ReferenceModules
:
1413 La
._ReferenceModules
.append(Ma
)
1415 ## Summarize ModuleAutoGen objects of all modules to be built for this platform
1416 def _GetModuleAutoGenList(self
):
1417 if self
._ModuleAutoGenList
== None:
1418 self
._GetAutoGenObjectList
()
1419 return self
._ModuleAutoGenList
1421 ## Summarize ModuleAutoGen objects of all libraries to be built for this platform
1422 def _GetLibraryAutoGenList(self
):
1423 if self
._LibraryAutoGenList
== None:
1424 self
._GetAutoGenObjectList
()
1425 return self
._LibraryAutoGenList
1427 ## Test if a module is supported by the platform
1429 # An error will be raised directly if the module or its arch is not supported
1430 # by the platform or current configuration
1432 def ValidModule(self
, Module
):
1433 return Module
in self
.Platform
.Modules
or Module
in self
.Platform
.LibraryInstances
1435 ## Resolve the library classes in a module to library instances
1437 # This method will not only resolve library classes but also sort the library
1438 # instances according to the dependency-ship.
1440 # @param Module The module from which the library classes will be resolved
1442 # @retval library_list List of library instances sorted
1444 def ApplyLibraryInstance(self
, Module
):
1445 ModuleType
= Module
.ModuleType
1447 # for overridding library instances with module specific setting
1448 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
1450 # add forced library instances (specified under LibraryClasses sections)
1452 # If a module has a MODULE_TYPE of USER_DEFINED,
1453 # do not link in NULL library class instances from the global [LibraryClasses.*] sections.
1455 if Module
.ModuleType
!= SUP_MODULE_USER_DEFINED
:
1456 for LibraryClass
in self
.Platform
.LibraryClasses
.GetKeys():
1457 if LibraryClass
.startswith("NULL") and self
.Platform
.LibraryClasses
[LibraryClass
, Module
.ModuleType
]:
1458 Module
.LibraryClasses
[LibraryClass
] = self
.Platform
.LibraryClasses
[LibraryClass
, Module
.ModuleType
]
1460 # add forced library instances (specified in module overrides)
1461 for LibraryClass
in PlatformModule
.LibraryClasses
:
1462 if LibraryClass
.startswith("NULL"):
1463 Module
.LibraryClasses
[LibraryClass
] = PlatformModule
.LibraryClasses
[LibraryClass
]
1466 LibraryConsumerList
= [Module
]
1468 ConsumedByList
= sdict()
1469 LibraryInstance
= sdict()
1471 EdkLogger
.verbose("")
1472 EdkLogger
.verbose("Library instances of module [%s] [%s]:" % (str(Module
), self
.Arch
))
1473 while len(LibraryConsumerList
) > 0:
1474 M
= LibraryConsumerList
.pop()
1475 for LibraryClassName
in M
.LibraryClasses
:
1476 if LibraryClassName
not in LibraryInstance
:
1477 # override library instance for this module
1478 if LibraryClassName
in PlatformModule
.LibraryClasses
:
1479 LibraryPath
= PlatformModule
.LibraryClasses
[LibraryClassName
]
1481 LibraryPath
= self
.Platform
.LibraryClasses
[LibraryClassName
, ModuleType
]
1482 if LibraryPath
== None or LibraryPath
== "":
1483 LibraryPath
= M
.LibraryClasses
[LibraryClassName
]
1484 if LibraryPath
== None or LibraryPath
== "":
1485 EdkLogger
.error("build", RESOURCE_NOT_AVAILABLE
,
1486 "Instance of library class [%s] is not found" % LibraryClassName
,
1488 ExtraData
="in [%s] [%s]\n\tconsumed by module [%s]" % (str(M
), self
.Arch
, str(Module
)))
1490 LibraryModule
= self
.BuildDatabase
[LibraryPath
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1491 # for those forced library instance (NULL library), add a fake library class
1492 if LibraryClassName
.startswith("NULL"):
1493 LibraryModule
.LibraryClass
.append(LibraryClassObject(LibraryClassName
, [ModuleType
]))
1494 elif LibraryModule
.LibraryClass
== None \
1495 or len(LibraryModule
.LibraryClass
) == 0 \
1496 or (ModuleType
!= 'USER_DEFINED'
1497 and ModuleType
not in LibraryModule
.LibraryClass
[0].SupModList
):
1498 # only USER_DEFINED can link against any library instance despite of its SupModList
1499 EdkLogger
.error("build", OPTION_MISSING
,
1500 "Module type [%s] is not supported by library instance [%s]" \
1501 % (ModuleType
, LibraryPath
), File
=self
.MetaFile
,
1502 ExtraData
="consumed by [%s]" % str(Module
))
1504 LibraryInstance
[LibraryClassName
] = LibraryModule
1505 LibraryConsumerList
.append(LibraryModule
)
1506 EdkLogger
.verbose("\t" + str(LibraryClassName
) + " : " + str(LibraryModule
))
1508 LibraryModule
= LibraryInstance
[LibraryClassName
]
1510 if LibraryModule
== None:
1513 if LibraryModule
.ConstructorList
!= [] and LibraryModule
not in Constructor
:
1514 Constructor
.append(LibraryModule
)
1516 if LibraryModule
not in ConsumedByList
:
1517 ConsumedByList
[LibraryModule
] = []
1518 # don't add current module itself to consumer list
1520 if M
in ConsumedByList
[LibraryModule
]:
1522 ConsumedByList
[LibraryModule
].append(M
)
1524 # Initialize the sorted output list to the empty set
1526 SortedLibraryList
= []
1528 # Q <- Set of all nodes with no incoming edges
1530 LibraryList
= [] #LibraryInstance.values()
1532 for LibraryClassName
in LibraryInstance
:
1533 M
= LibraryInstance
[LibraryClassName
]
1534 LibraryList
.append(M
)
1535 if ConsumedByList
[M
] == []:
1539 # start the DAG algorithm
1543 while Q
== [] and EdgeRemoved
:
1545 # for each node Item with a Constructor
1546 for Item
in LibraryList
:
1547 if Item
not in Constructor
:
1549 # for each Node without a constructor with an edge e from Item to Node
1550 for Node
in ConsumedByList
[Item
]:
1551 if Node
in Constructor
:
1553 # remove edge e from the graph if Node has no constructor
1554 ConsumedByList
[Item
].remove(Node
)
1556 if ConsumedByList
[Item
] == []:
1557 # insert Item into Q
1562 # DAG is done if there's no more incoming edge for all nodes
1566 # remove node from Q
1569 SortedLibraryList
.append(Node
)
1571 # for each node Item with an edge e from Node to Item do
1572 for Item
in LibraryList
:
1573 if Node
not in ConsumedByList
[Item
]:
1575 # remove edge e from the graph
1576 ConsumedByList
[Item
].remove(Node
)
1578 if ConsumedByList
[Item
] != []:
1580 # insert Item into Q, if Item has no other incoming edges
1584 # if any remaining node Item in the graph has a constructor and an incoming edge, then the graph has a cycle
1586 for Item
in LibraryList
:
1587 if ConsumedByList
[Item
] != [] and Item
in Constructor
and len(Constructor
) > 1:
1588 ErrorMessage
= "\tconsumed by " + "\n\tconsumed by ".join([str(L
) for L
in ConsumedByList
[Item
]])
1589 EdkLogger
.error("build", BUILD_ERROR
, 'Library [%s] with constructors has a cycle' % str(Item
),
1590 ExtraData
=ErrorMessage
, File
=self
.MetaFile
)
1591 if Item
not in SortedLibraryList
:
1592 SortedLibraryList
.append(Item
)
1595 # Build the list of constructor and destructir names
1596 # The DAG Topo sort produces the destructor order, so the list of constructors must generated in the reverse order
1598 SortedLibraryList
.reverse()
1599 return SortedLibraryList
1602 ## Override PCD setting (type, value, ...)
1604 # @param ToPcd The PCD to be overrided
1605 # @param FromPcd The PCD overrideing from
1607 def _OverridePcd(self
, ToPcd
, FromPcd
, Module
=""):
1609 # in case there's PCDs coming from FDF file, which have no type given.
1610 # at this point, ToPcd.Type has the type found from dependent
1614 if ToPcd
.Pending
and FromPcd
.Type
not in [None, '']:
1615 ToPcd
.Type
= FromPcd
.Type
1616 elif (ToPcd
.Type
not in [None, '']) and (FromPcd
.Type
not in [None, ''])\
1617 and (ToPcd
.Type
!= FromPcd
.Type
) and (ToPcd
.Type
in FromPcd
.Type
):
1618 if ToPcd
.Type
.strip() == "DynamicEx":
1619 ToPcd
.Type
= FromPcd
.Type
1620 elif ToPcd
.Type
not in [None, ''] and FromPcd
.Type
not in [None, ''] \
1621 and ToPcd
.Type
!= FromPcd
.Type
:
1622 EdkLogger
.error("build", OPTION_CONFLICT
, "Mismatched PCD type",
1623 ExtraData
="%s.%s is defined as [%s] in module %s, but as [%s] in platform."\
1624 % (ToPcd
.TokenSpaceGuidCName
, ToPcd
.TokenCName
,
1625 ToPcd
.Type
, Module
, FromPcd
.Type
),
1628 if FromPcd
.MaxDatumSize
not in [None, '']:
1629 ToPcd
.MaxDatumSize
= FromPcd
.MaxDatumSize
1630 if FromPcd
.DefaultValue
not in [None, '']:
1631 ToPcd
.DefaultValue
= FromPcd
.DefaultValue
1632 if FromPcd
.TokenValue
not in [None, '']:
1633 ToPcd
.TokenValue
= FromPcd
.TokenValue
1634 if FromPcd
.MaxDatumSize
not in [None, '']:
1635 ToPcd
.MaxDatumSize
= FromPcd
.MaxDatumSize
1636 if FromPcd
.DatumType
not in [None, '']:
1637 ToPcd
.DatumType
= FromPcd
.DatumType
1638 if FromPcd
.SkuInfoList
not in [None, '', []]:
1639 ToPcd
.SkuInfoList
= FromPcd
.SkuInfoList
1641 # check the validation of datum
1642 IsValid
, Cause
= CheckPcdDatum(ToPcd
.DatumType
, ToPcd
.DefaultValue
)
1644 EdkLogger
.error('build', FORMAT_INVALID
, Cause
, File
=self
.MetaFile
,
1645 ExtraData
="%s.%s" % (ToPcd
.TokenSpaceGuidCName
, ToPcd
.TokenCName
))
1647 if ToPcd
.DatumType
== "VOID*" and ToPcd
.MaxDatumSize
in ['', None]:
1648 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "No MaxDatumSize specified for PCD %s.%s" \
1649 % (ToPcd
.TokenSpaceGuidCName
, ToPcd
.TokenCName
))
1650 Value
= ToPcd
.DefaultValue
1651 if Value
in [None, '']:
1652 ToPcd
.MaxDatumSize
= '1'
1653 elif Value
[0] == 'L':
1654 ToPcd
.MaxDatumSize
= str((len(Value
) - 2) * 2)
1655 elif Value
[0] == '{':
1656 ToPcd
.MaxDatumSize
= str(len(Value
.split(',')))
1658 ToPcd
.MaxDatumSize
= str(len(Value
) - 1)
1660 # apply default SKU for dynamic PCDS if specified one is not available
1661 if (ToPcd
.Type
in PCD_DYNAMIC_TYPE_LIST
or ToPcd
.Type
in PCD_DYNAMIC_EX_TYPE_LIST
) \
1662 and ToPcd
.SkuInfoList
in [None, {}, '']:
1663 if self
.Platform
.SkuName
in self
.Platform
.SkuIds
:
1664 SkuName
= self
.Platform
.SkuName
1667 ToPcd
.SkuInfoList
= {
1668 SkuName
: SkuInfoClass(SkuName
, self
.Platform
.SkuIds
[SkuName
], '', '', '', '', '', ToPcd
.DefaultValue
)
1671 ## Apply PCD setting defined platform to a module
1673 # @param Module The module from which the PCD setting will be overrided
1675 # @retval PCD_list The list PCDs with settings from platform
1677 def ApplyPcdSetting(self
, Module
, Pcds
):
1678 # for each PCD in module
1679 for Name
,Guid
in Pcds
:
1680 PcdInModule
= Pcds
[Name
,Guid
]
1681 # find out the PCD setting in platform
1682 if (Name
,Guid
) in self
.Platform
.Pcds
:
1683 PcdInPlatform
= self
.Platform
.Pcds
[Name
,Guid
]
1685 PcdInPlatform
= None
1686 # then override the settings if any
1687 self
._OverridePcd
(PcdInModule
, PcdInPlatform
, Module
)
1688 # resolve the VariableGuid value
1689 for SkuId
in PcdInModule
.SkuInfoList
:
1690 Sku
= PcdInModule
.SkuInfoList
[SkuId
]
1691 if Sku
.VariableGuid
== '': continue
1692 Sku
.VariableGuidValue
= GuidValue(Sku
.VariableGuid
, self
.PackageList
)
1693 if Sku
.VariableGuidValue
== None:
1694 PackageList
= "\n\t".join([str(P
) for P
in self
.PackageList
])
1697 RESOURCE_NOT_AVAILABLE
,
1698 "Value of GUID [%s] is not found in" % Sku
.VariableGuid
,
1699 ExtraData
=PackageList
+ "\n\t(used with %s.%s from module %s)" \
1700 % (Guid
, Name
, str(Module
)),
1704 # override PCD settings with module specific setting
1705 if Module
in self
.Platform
.Modules
:
1706 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
1707 for Key
in PlatformModule
.Pcds
:
1709 self
._OverridePcd
(Pcds
[Key
], PlatformModule
.Pcds
[Key
], Module
)
1710 return Pcds
.values()
1712 ## Resolve library names to library modules
1714 # (for Edk.x modules)
1716 # @param Module The module from which the library names will be resolved
1718 # @retval library_list The list of library modules
1720 def ResolveLibraryReference(self
, Module
):
1721 EdkLogger
.verbose("")
1722 EdkLogger
.verbose("Library instances of module [%s] [%s]:" % (str(Module
), self
.Arch
))
1723 LibraryConsumerList
= [Module
]
1725 # "CompilerStub" is a must for Edk modules
1726 if Module
.Libraries
:
1727 Module
.Libraries
.append("CompilerStub")
1729 while len(LibraryConsumerList
) > 0:
1730 M
= LibraryConsumerList
.pop()
1731 for LibraryName
in M
.Libraries
:
1732 Library
= self
.Platform
.LibraryClasses
[LibraryName
, ':dummy:']
1734 for Key
in self
.Platform
.LibraryClasses
.data
.keys():
1735 if LibraryName
.upper() == Key
.upper():
1736 Library
= self
.Platform
.LibraryClasses
[Key
, ':dummy:']
1739 EdkLogger
.warn("build", "Library [%s] is not found" % LibraryName
, File
=str(M
),
1740 ExtraData
="\t%s [%s]" % (str(Module
), self
.Arch
))
1743 if Library
not in LibraryList
:
1744 LibraryList
.append(Library
)
1745 LibraryConsumerList
.append(Library
)
1746 EdkLogger
.verbose("\t" + LibraryName
+ " : " + str(Library
) + ' ' + str(type(Library
)))
1749 ## Calculate the priority value of the build option
1751 # @param Key Build option definition contain: TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
1753 # @retval Value Priority value based on the priority list.
1755 def CalculatePriorityValue(self
, Key
):
1756 Target
, ToolChain
, Arch
, CommandType
, Attr
= Key
.split('_')
1757 PriorityValue
= 0x11111
1759 PriorityValue
&= 0x01111
1760 if ToolChain
== "*":
1761 PriorityValue
&= 0x10111
1763 PriorityValue
&= 0x11011
1764 if CommandType
== "*":
1765 PriorityValue
&= 0x11101
1767 PriorityValue
&= 0x11110
1769 return self
.PrioList
["0x%0.5x"%PriorityValue
]
1772 ## Expand * in build option key
1774 # @param Options Options to be expanded
1776 # @retval options Options expanded
1778 def _ExpandBuildOption(self
, Options
, ModuleStyle
=None):
1785 # Construct a list contain the build options which need override.
1789 # Key[0] -- tool family
1790 # Key[1] -- TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
1792 if Key
[0] == self
.BuildRuleFamily
:
1793 Target
, ToolChain
, Arch
, CommandType
, Attr
= Key
[1].split('_')
1794 if Target
== self
.BuildTarget
or Target
== "*":
1795 if ToolChain
== self
.ToolChain
or ToolChain
== "*":
1796 if Arch
== self
.Arch
or Arch
== "*":
1797 if Options
[Key
].startswith("="):
1798 if OverrideList
.get(Key
[1]) != None:
1799 OverrideList
.pop(Key
[1])
1800 OverrideList
[Key
[1]] = Options
[Key
]
1803 # Use the highest priority value.
1805 if (len(OverrideList
) >= 2):
1806 KeyList
= OverrideList
.keys()
1807 for Index
in range(len(KeyList
)):
1808 NowKey
= KeyList
[Index
]
1809 Target1
, ToolChain1
, Arch1
, CommandType1
, Attr1
= NowKey
.split("_")
1810 for Index1
in range(len(KeyList
) - Index
- 1):
1811 NextKey
= KeyList
[Index1
+ Index
+ 1]
1813 # Compare two Key, if one is included by another, choose the higher priority one
1815 Target2
, ToolChain2
, Arch2
, CommandType2
, Attr2
= NextKey
.split("_")
1816 if Target1
== Target2
or Target1
== "*" or Target2
== "*":
1817 if ToolChain1
== ToolChain2
or ToolChain1
== "*" or ToolChain2
== "*":
1818 if Arch1
== Arch2
or Arch1
== "*" or Arch2
== "*":
1819 if CommandType1
== CommandType2
or CommandType1
== "*" or CommandType2
== "*":
1820 if Attr1
== Attr2
or Attr1
== "*" or Attr2
== "*":
1821 if self
.CalculatePriorityValue(NowKey
) > self
.CalculatePriorityValue(NextKey
):
1822 if Options
.get((self
.BuildRuleFamily
, NextKey
)) != None:
1823 Options
.pop((self
.BuildRuleFamily
, NextKey
))
1825 if Options
.get((self
.BuildRuleFamily
, NowKey
)) != None:
1826 Options
.pop((self
.BuildRuleFamily
, NowKey
))
1830 if ModuleStyle
!= None and len (Key
) > 2:
1831 # Check Module style is EDK or EDKII.
1832 # Only append build option for the matched style module.
1833 if ModuleStyle
== EDK_NAME
and Key
[2] != EDK_NAME
:
1835 elif ModuleStyle
== EDKII_NAME
and Key
[2] != EDKII_NAME
:
1838 Target
, Tag
, Arch
, Tool
, Attr
= Key
[1].split("_")
1839 # if tool chain family doesn't match, skip it
1840 if Tool
in self
.ToolDefinition
and Family
!= "":
1841 FamilyIsNull
= False
1842 if self
.ToolDefinition
[Tool
].get(TAB_TOD_DEFINES_BUILDRULEFAMILY
, "") != "":
1843 if Family
!= self
.ToolDefinition
[Tool
][TAB_TOD_DEFINES_BUILDRULEFAMILY
]:
1845 elif Family
!= self
.ToolDefinition
[Tool
][TAB_TOD_DEFINES_FAMILY
]:
1848 # expand any wildcard
1849 if Target
== "*" or Target
== self
.BuildTarget
:
1850 if Tag
== "*" or Tag
== self
.ToolChain
:
1851 if Arch
== "*" or Arch
== self
.Arch
:
1852 if Tool
not in BuildOptions
:
1853 BuildOptions
[Tool
] = {}
1854 if Attr
!= "FLAGS" or Attr
not in BuildOptions
[Tool
]:
1855 BuildOptions
[Tool
][Attr
] = Options
[Key
]
1857 # append options for the same tool
1858 BuildOptions
[Tool
][Attr
] += " " + Options
[Key
]
1859 # Build Option Family has been checked, which need't to be checked again for family.
1860 if FamilyMatch
or FamilyIsNull
:
1864 if ModuleStyle
!= None and len (Key
) > 2:
1865 # Check Module style is EDK or EDKII.
1866 # Only append build option for the matched style module.
1867 if ModuleStyle
== EDK_NAME
and Key
[2] != EDK_NAME
:
1869 elif ModuleStyle
== EDKII_NAME
and Key
[2] != EDKII_NAME
:
1872 Target
, Tag
, Arch
, Tool
, Attr
= Key
[1].split("_")
1873 # if tool chain family doesn't match, skip it
1874 if Tool
not in self
.ToolDefinition
or Family
=="":
1876 # option has been added before
1877 if Family
!= self
.ToolDefinition
[Tool
][TAB_TOD_DEFINES_FAMILY
]:
1880 # expand any wildcard
1881 if Target
== "*" or Target
== self
.BuildTarget
:
1882 if Tag
== "*" or Tag
== self
.ToolChain
:
1883 if Arch
== "*" or Arch
== self
.Arch
:
1884 if Tool
not in BuildOptions
:
1885 BuildOptions
[Tool
] = {}
1886 if Attr
!= "FLAGS" or Attr
not in BuildOptions
[Tool
]:
1887 BuildOptions
[Tool
][Attr
] = Options
[Key
]
1889 # append options for the same tool
1890 BuildOptions
[Tool
][Attr
] += " " + Options
[Key
]
1893 ## Append build options in platform to a module
1895 # @param Module The module to which the build options will be appened
1897 # @retval options The options appended with build options in platform
1899 def ApplyBuildOption(self
, Module
):
1900 # Get the different options for the different style module
1901 if Module
.AutoGenVersion
< 0x00010005:
1902 PlatformOptions
= self
.EdkBuildOption
1904 PlatformOptions
= self
.EdkIIBuildOption
1905 ModuleOptions
= self
._ExpandBuildOption
(Module
.BuildOptions
)
1906 if Module
in self
.Platform
.Modules
:
1907 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
1908 PlatformModuleOptions
= self
._ExpandBuildOption
(PlatformModule
.BuildOptions
)
1910 PlatformModuleOptions
= {}
1912 AllTools
= set(ModuleOptions
.keys() + PlatformOptions
.keys() + PlatformModuleOptions
.keys() + self
.ToolDefinition
.keys())
1914 for Tool
in AllTools
:
1915 if Tool
not in BuildOptions
:
1916 BuildOptions
[Tool
] = {}
1918 for Options
in [self
.ToolDefinition
, ModuleOptions
, PlatformOptions
, PlatformModuleOptions
]:
1919 if Tool
not in Options
:
1921 for Attr
in Options
[Tool
]:
1922 Value
= Options
[Tool
][Attr
]
1923 if Attr
not in BuildOptions
[Tool
]:
1924 BuildOptions
[Tool
][Attr
] = ""
1925 # check if override is indicated
1926 if Value
.startswith('='):
1927 BuildOptions
[Tool
][Attr
] = Value
[1:]
1929 BuildOptions
[Tool
][Attr
] += " " + Value
1930 if Module
.AutoGenVersion
< 0x00010005 and self
.Workspace
.UniFlag
!= None:
1932 # Override UNI flag only for EDK module.
1934 if 'BUILD' not in BuildOptions
:
1935 BuildOptions
['BUILD'] = {}
1936 BuildOptions
['BUILD']['FLAGS'] = self
.Workspace
.UniFlag
1939 Platform
= property(_GetPlatform
)
1940 Name
= property(_GetName
)
1941 Guid
= property(_GetGuid
)
1942 Version
= property(_GetVersion
)
1944 OutputDir
= property(_GetOutputDir
)
1945 BuildDir
= property(_GetBuildDir
)
1946 MakeFileDir
= property(_GetMakeFileDir
)
1947 FdfFile
= property(_GetFdfFile
)
1949 PcdTokenNumber
= property(_GetPcdTokenNumbers
) # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber
1950 DynamicPcdList
= property(_GetDynamicPcdList
) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
1951 NonDynamicPcdList
= property(_GetNonDynamicPcdList
) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
1952 NonDynamicPcdDict
= property(_GetNonDynamicPcdDict
)
1953 PackageList
= property(_GetPackageList
)
1955 ToolDefinition
= property(_GetToolDefinition
) # toolcode : tool path
1956 ToolDefinitionFile
= property(_GetToolDefFile
) # toolcode : lib path
1957 ToolChainFamily
= property(_GetToolChainFamily
)
1958 BuildRuleFamily
= property(_GetBuildRuleFamily
)
1959 BuildOption
= property(_GetBuildOptions
) # toolcode : option
1960 EdkBuildOption
= property(_GetEdkBuildOptions
) # edktoolcode : option
1961 EdkIIBuildOption
= property(_GetEdkIIBuildOptions
) # edkiitoolcode : option
1963 BuildCommand
= property(_GetBuildCommand
)
1964 BuildRule
= property(_GetBuildRule
)
1965 ModuleAutoGenList
= property(_GetModuleAutoGenList
)
1966 LibraryAutoGenList
= property(_GetLibraryAutoGenList
)
1968 ## ModuleAutoGen class
1970 # This class encapsules the AutoGen behaviors for the build tools. In addition to
1971 # the generation of AutoGen.h and AutoGen.c, it will generate *.depex file according
1972 # to the [depex] section in module's inf file.
1974 class ModuleAutoGen(AutoGen
):
1975 ## The real constructor of ModuleAutoGen
1977 # This method is not supposed to be called by users of ModuleAutoGen. It's
1978 # only used by factory method __new__() to do real initialization work for an
1979 # object of ModuleAutoGen
1981 # @param Workspace EdkIIWorkspaceBuild object
1982 # @param ModuleFile The path of module file
1983 # @param Target Build target (DEBUG, RELEASE)
1984 # @param Toolchain Name of tool chain
1985 # @param Arch The arch the module supports
1986 # @param PlatformFile Platform meta-file
1988 def _Init(self
, Workspace
, ModuleFile
, Target
, Toolchain
, Arch
, PlatformFile
):
1989 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "AutoGen module [%s] [%s]" % (ModuleFile
, Arch
))
1990 GlobalData
.gProcessingFile
= "%s [%s, %s, %s]" % (ModuleFile
, Arch
, Toolchain
, Target
)
1992 self
.Workspace
= Workspace
1993 self
.WorkspaceDir
= Workspace
.WorkspaceDir
1995 self
.MetaFile
= ModuleFile
1996 self
.PlatformInfo
= PlatformAutoGen(Workspace
, PlatformFile
, Target
, Toolchain
, Arch
)
1997 # check if this module is employed by active platform
1998 if not self
.PlatformInfo
.ValidModule(self
.MetaFile
):
1999 EdkLogger
.verbose("Module [%s] for [%s] is not employed by active platform\n" \
2000 % (self
.MetaFile
, Arch
))
2003 self
.SourceDir
= self
.MetaFile
.SubDir
2004 self
.SourceOverrideDir
= None
2005 # use overrided path defined in DSC file
2006 if self
.MetaFile
.Key
in GlobalData
.gOverrideDir
:
2007 self
.SourceOverrideDir
= GlobalData
.gOverrideDir
[self
.MetaFile
.Key
]
2009 self
.ToolChain
= Toolchain
2010 self
.BuildTarget
= Target
2012 self
.ToolChainFamily
= self
.PlatformInfo
.ToolChainFamily
2013 self
.BuildRuleFamily
= self
.PlatformInfo
.BuildRuleFamily
2015 self
.IsMakeFileCreated
= False
2016 self
.IsCodeFileCreated
= False
2017 self
.IsAsBuiltInfCreated
= False
2018 self
.DepexGenerated
= False
2020 self
.BuildDatabase
= self
.Workspace
.BuildDatabase
2025 self
._Version
= None
2026 self
._ModuleType
= None
2027 self
._ComponentType
= None
2028 self
._PcdIsDriver
= None
2029 self
._AutoGenVersion
= None
2030 self
._LibraryFlag
= None
2031 self
._CustomMakefile
= None
2034 self
._BuildDir
= None
2035 self
._OutputDir
= None
2036 self
._DebugDir
= None
2037 self
._MakeFileDir
= None
2039 self
._IncludePathList
= None
2040 self
._AutoGenFileList
= None
2041 self
._UnicodeFileList
= None
2042 self
._SourceFileList
= None
2043 self
._ObjectFileList
= None
2044 self
._BinaryFileList
= None
2046 self
._DependentPackageList
= None
2047 self
._DependentLibraryList
= None
2048 self
._LibraryAutoGenList
= None
2049 self
._DerivedPackageList
= None
2050 self
._ModulePcdList
= None
2051 self
._LibraryPcdList
= None
2052 self
._PcdComments
= sdict()
2053 self
._GuidList
= None
2054 self
._GuidsUsedByPcd
= None
2055 self
._GuidComments
= sdict()
2056 self
._ProtocolList
= None
2057 self
._ProtocolComments
= sdict()
2058 self
._PpiList
= None
2059 self
._PpiComments
= sdict()
2060 self
._DepexList
= None
2061 self
._DepexExpressionList
= None
2062 self
._BuildOption
= None
2063 self
._BuildOptionIncPathList
= None
2064 self
._BuildTargets
= None
2065 self
._IntroBuildTargetList
= None
2066 self
._FinalBuildTargetList
= None
2067 self
._FileTypes
= None
2068 self
._BuildRules
= None
2070 ## The Modules referenced to this Library
2071 # Only Library has this attribute
2072 self
._ReferenceModules
= []
2074 ## Store the FixedAtBuild Pcds
2076 self
._FixedAtBuildPcds
= []
2081 return "%s [%s]" % (self
.MetaFile
, self
.Arch
)
2083 # Get FixedAtBuild Pcds of this Module
2084 def _GetFixedAtBuildPcds(self
):
2085 if self
._FixedAtBuildPcds
:
2086 return self
._FixedAtBuildPcds
2087 for Pcd
in self
.ModulePcdList
:
2089 if not (Pcd
.Pending
== False and Pcd
.Type
== "FixedAtBuild"):
2091 elif Pcd
.Type
!= "FixedAtBuild":
2093 if Pcd
not in self
._FixedAtBuildPcds
:
2094 self
._FixedAtBuildPcds
.append(Pcd
)
2096 return self
._FixedAtBuildPcds
2098 # Macros could be used in build_rule.txt (also Makefile)
2099 def _GetMacros(self
):
2100 if self
._Macro
== None:
2101 self
._Macro
= sdict()
2102 self
._Macro
["WORKSPACE" ] = self
.WorkspaceDir
2103 self
._Macro
["MODULE_NAME" ] = self
.Name
2104 self
._Macro
["MODULE_GUID" ] = self
.Guid
2105 self
._Macro
["MODULE_VERSION" ] = self
.Version
2106 self
._Macro
["MODULE_TYPE" ] = self
.ModuleType
2107 self
._Macro
["MODULE_FILE" ] = str(self
.MetaFile
)
2108 self
._Macro
["MODULE_FILE_BASE_NAME" ] = self
.MetaFile
.BaseName
2109 self
._Macro
["MODULE_RELATIVE_DIR" ] = self
.SourceDir
2110 self
._Macro
["MODULE_DIR" ] = self
.SourceDir
2112 self
._Macro
["BASE_NAME" ] = self
.Name
2114 self
._Macro
["ARCH" ] = self
.Arch
2115 self
._Macro
["TOOLCHAIN" ] = self
.ToolChain
2116 self
._Macro
["TOOLCHAIN_TAG" ] = self
.ToolChain
2117 self
._Macro
["TOOL_CHAIN_TAG" ] = self
.ToolChain
2118 self
._Macro
["TARGET" ] = self
.BuildTarget
2120 self
._Macro
["BUILD_DIR" ] = self
.PlatformInfo
.BuildDir
2121 self
._Macro
["BIN_DIR" ] = os
.path
.join(self
.PlatformInfo
.BuildDir
, self
.Arch
)
2122 self
._Macro
["LIB_DIR" ] = os
.path
.join(self
.PlatformInfo
.BuildDir
, self
.Arch
)
2123 self
._Macro
["MODULE_BUILD_DIR" ] = self
.BuildDir
2124 self
._Macro
["OUTPUT_DIR" ] = self
.OutputDir
2125 self
._Macro
["DEBUG_DIR" ] = self
.DebugDir
2128 ## Return the module build data object
2129 def _GetModule(self
):
2130 if self
._Module
== None:
2131 self
._Module
= self
.Workspace
.BuildDatabase
[self
.MetaFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
2134 ## Return the module name
2135 def _GetBaseName(self
):
2136 return self
.Module
.BaseName
2138 ## Return the module DxsFile if exist
2139 def _GetDxsFile(self
):
2140 return self
.Module
.DxsFile
2142 ## Return the module SourceOverridePath
2143 def _GetSourceOverridePath(self
):
2144 return self
.Module
.SourceOverridePath
2146 ## Return the module meta-file GUID
2148 return self
.Module
.Guid
2150 ## Return the module version
2151 def _GetVersion(self
):
2152 return self
.Module
.Version
2154 ## Return the module type
2155 def _GetModuleType(self
):
2156 return self
.Module
.ModuleType
2158 ## Return the component type (for Edk.x style of module)
2159 def _GetComponentType(self
):
2160 return self
.Module
.ComponentType
2162 ## Return the build type
2163 def _GetBuildType(self
):
2164 return self
.Module
.BuildType
2166 ## Return the PCD_IS_DRIVER setting
2167 def _GetPcdIsDriver(self
):
2168 return self
.Module
.PcdIsDriver
2170 ## Return the autogen version, i.e. module meta-file version
2171 def _GetAutoGenVersion(self
):
2172 return self
.Module
.AutoGenVersion
2174 ## Check if the module is library or not
2175 def _IsLibrary(self
):
2176 if self
._LibraryFlag
== None:
2177 if self
.Module
.LibraryClass
!= None and self
.Module
.LibraryClass
!= []:
2178 self
._LibraryFlag
= True
2180 self
._LibraryFlag
= False
2181 return self
._LibraryFlag
2183 ## Check if the module is binary module or not
2184 def _IsBinaryModule(self
):
2185 return self
.Module
.IsBinaryModule
2187 ## Return the directory to store intermediate files of the module
2188 def _GetBuildDir(self
):
2189 if self
._BuildDir
== None:
2190 self
._BuildDir
= path
.join(
2191 self
.PlatformInfo
.BuildDir
,
2194 self
.MetaFile
.BaseName
2196 CreateDirectory(self
._BuildDir
)
2197 return self
._BuildDir
2199 ## Return the directory to store the intermediate object files of the mdoule
2200 def _GetOutputDir(self
):
2201 if self
._OutputDir
== None:
2202 self
._OutputDir
= path
.join(self
.BuildDir
, "OUTPUT")
2203 CreateDirectory(self
._OutputDir
)
2204 return self
._OutputDir
2206 ## Return the directory to store auto-gened source files of the mdoule
2207 def _GetDebugDir(self
):
2208 if self
._DebugDir
== None:
2209 self
._DebugDir
= path
.join(self
.BuildDir
, "DEBUG")
2210 CreateDirectory(self
._DebugDir
)
2211 return self
._DebugDir
2213 ## Return the path of custom file
2214 def _GetCustomMakefile(self
):
2215 if self
._CustomMakefile
== None:
2216 self
._CustomMakefile
= {}
2217 for Type
in self
.Module
.CustomMakefile
:
2218 if Type
in gMakeTypeMap
:
2219 MakeType
= gMakeTypeMap
[Type
]
2222 if self
.SourceOverrideDir
!= None:
2223 File
= os
.path
.join(self
.SourceOverrideDir
, self
.Module
.CustomMakefile
[Type
])
2224 if not os
.path
.exists(File
):
2225 File
= os
.path
.join(self
.SourceDir
, self
.Module
.CustomMakefile
[Type
])
2227 File
= os
.path
.join(self
.SourceDir
, self
.Module
.CustomMakefile
[Type
])
2228 self
._CustomMakefile
[MakeType
] = File
2229 return self
._CustomMakefile
2231 ## Return the directory of the makefile
2233 # @retval string The directory string of module's makefile
2235 def _GetMakeFileDir(self
):
2236 return self
.BuildDir
2238 ## Return build command string
2240 # @retval string Build command string
2242 def _GetBuildCommand(self
):
2243 return self
.PlatformInfo
.BuildCommand
2245 ## Get object list of all packages the module and its dependent libraries belong to
2247 # @retval list The list of package object
2249 def _GetDerivedPackageList(self
):
2251 for M
in [self
.Module
] + self
.DependentLibraryList
:
2252 for Package
in M
.Packages
:
2253 if Package
in PackageList
:
2255 PackageList
.append(Package
)
2258 ## Merge dependency expression
2260 # @retval list The token list of the dependency expression after parsed
2262 def _GetDepexTokenList(self
):
2263 if self
._DepexList
== None:
2264 self
._DepexList
= {}
2265 if self
.DxsFile
or self
.IsLibrary
or TAB_DEPENDENCY_EXPRESSION_FILE
in self
.FileTypes
:
2266 return self
._DepexList
2268 self
._DepexList
[self
.ModuleType
] = []
2270 for ModuleType
in self
._DepexList
:
2271 DepexList
= self
._DepexList
[ModuleType
]
2273 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
2275 for M
in [self
.Module
] + self
.DependentLibraryList
:
2277 for D
in M
.Depex
[self
.Arch
, ModuleType
]:
2279 DepexList
.append('AND')
2280 DepexList
.append('(')
2282 if DepexList
[-1] == 'END': # no need of a END at this time
2284 DepexList
.append(')')
2287 EdkLogger
.verbose("DEPEX[%s] (+%s) = %s" % (self
.Name
, M
.BaseName
, DepexList
))
2288 if 'BEFORE' in DepexList
or 'AFTER' in DepexList
:
2290 if len(DepexList
) > 0:
2291 EdkLogger
.verbose('')
2292 return self
._DepexList
2294 ## Merge dependency expression
2296 # @retval list The token list of the dependency expression after parsed
2298 def _GetDepexExpressionTokenList(self
):
2299 if self
._DepexExpressionList
== None:
2300 self
._DepexExpressionList
= {}
2301 if self
.DxsFile
or self
.IsLibrary
or TAB_DEPENDENCY_EXPRESSION_FILE
in self
.FileTypes
:
2302 return self
._DepexExpressionList
2304 self
._DepexExpressionList
[self
.ModuleType
] = ''
2306 for ModuleType
in self
._DepexExpressionList
:
2307 DepexExpressionList
= self
._DepexExpressionList
[ModuleType
]
2309 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
2311 for M
in [self
.Module
] + self
.DependentLibraryList
:
2313 for D
in M
.DepexExpression
[self
.Arch
, ModuleType
]:
2314 if DepexExpressionList
!= '':
2315 DepexExpressionList
+= ' AND '
2316 DepexExpressionList
+= '('
2317 DepexExpressionList
+= D
2318 DepexExpressionList
= DepexExpressionList
.rstrip('END').strip()
2319 DepexExpressionList
+= ')'
2322 EdkLogger
.verbose("DEPEX[%s] (+%s) = %s" % (self
.Name
, M
.BaseName
, DepexExpressionList
))
2323 if 'BEFORE' in DepexExpressionList
or 'AFTER' in DepexExpressionList
:
2325 if len(DepexExpressionList
) > 0:
2326 EdkLogger
.verbose('')
2327 self
._DepexExpressionList
[ModuleType
] = DepexExpressionList
2328 return self
._DepexExpressionList
2330 ## Return the list of specification version required for the module
2332 # @retval list The list of specification defined in module file
2334 def _GetSpecification(self
):
2335 return self
.Module
.Specification
2337 ## Tool option for the module build
2339 # @param PlatformInfo The object of PlatformBuildInfo
2340 # @retval dict The dict containing valid options
2342 def _GetModuleBuildOption(self
):
2343 if self
._BuildOption
== None:
2344 self
._BuildOption
= self
.PlatformInfo
.ApplyBuildOption(self
.Module
)
2345 return self
._BuildOption
2347 ## Get include path list from tool option for the module build
2349 # @retval list The include path list
2351 def _GetBuildOptionIncPathList(self
):
2352 if self
._BuildOptionIncPathList
== None:
2354 # Regular expression for finding Include Directories, the difference between MSFT and INTEL/GCC/RVCT
2355 # is the former use /I , the Latter used -I to specify include directories
2357 if self
.PlatformInfo
.ToolChainFamily
in ('MSFT'):
2358 gBuildOptIncludePattern
= re
.compile(r
"(?:.*?)/I[ \t]*([^ ]*)", re
.MULTILINE|re
.DOTALL
)
2359 elif self
.PlatformInfo
.ToolChainFamily
in ('INTEL', 'GCC', 'RVCT'):
2360 gBuildOptIncludePattern
= re
.compile(r
"(?:.*?)-I[ \t]*([^ ]*)", re
.MULTILINE|re
.DOTALL
)
2363 # New ToolChainFamily, don't known whether there is option to specify include directories
2365 self
._BuildOptionIncPathList
= []
2366 return self
._BuildOptionIncPathList
2368 BuildOptionIncPathList
= []
2369 for Tool
in ('CC', 'PP', 'VFRPP', 'ASLPP', 'ASLCC', 'APP', 'ASM'):
2372 FlagOption
= self
.BuildOption
[Tool
][Attr
]
2376 if self
.PlatformInfo
.ToolChainFamily
!= 'RVCT':
2377 IncPathList
= [NormPath(Path
, self
.Macros
) for Path
in gBuildOptIncludePattern
.findall(FlagOption
)]
2380 # RVCT may specify a list of directory seperated by commas
2383 for Path
in gBuildOptIncludePattern
.findall(FlagOption
):
2384 PathList
= GetSplitList(Path
, TAB_COMMA_SPLIT
)
2385 IncPathList
+= [NormPath(PathEntry
, self
.Macros
) for PathEntry
in PathList
]
2388 # EDK II modules must not reference header files outside of the packages they depend on or
2389 # within the module's directory tree. Report error if violation.
2391 if self
.AutoGenVersion
>= 0x00010005 and len(IncPathList
) > 0:
2392 for Path
in IncPathList
:
2393 if (Path
not in self
.IncludePathList
) and (CommonPath([Path
, self
.MetaFile
.Dir
]) != self
.MetaFile
.Dir
):
2394 ErrMsg
= "The include directory for the EDK II module in this line is invalid %s specified in %s FLAGS '%s'" % (Path
, Tool
, FlagOption
)
2395 EdkLogger
.error("build",
2398 File
= str(self
.MetaFile
))
2401 BuildOptionIncPathList
+= IncPathList
2403 self
._BuildOptionIncPathList
= BuildOptionIncPathList
2405 return self
._BuildOptionIncPathList
2407 ## Return a list of files which can be built from source
2409 # What kind of files can be built is determined by build rules in
2410 # $(WORKSPACE)/Conf/build_rule.txt and toolchain family.
2412 def _GetSourceFileList(self
):
2413 if self
._SourceFileList
== None:
2414 self
._SourceFileList
= []
2415 for F
in self
.Module
.Sources
:
2417 if F
.TagName
not in ("", "*", self
.ToolChain
):
2418 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "The toolchain [%s] for processing file [%s] is found, "
2419 "but [%s] is needed" % (F
.TagName
, str(F
), self
.ToolChain
))
2421 # match tool chain family
2422 if F
.ToolChainFamily
not in ("", "*", self
.ToolChainFamily
):
2425 "The file [%s] must be built by tools of [%s], " \
2426 "but current toolchain family is [%s]" \
2427 % (str(F
), F
.ToolChainFamily
, self
.ToolChainFamily
))
2430 # add the file path into search path list for file including
2431 if F
.Dir
not in self
.IncludePathList
and self
.AutoGenVersion
>= 0x00010005:
2432 self
.IncludePathList
.insert(0, F
.Dir
)
2433 self
._SourceFileList
.append(F
)
2434 self
._ApplyBuildRule
(F
, TAB_UNKNOWN_FILE
)
2435 return self
._SourceFileList
2437 ## Return the list of unicode files
2438 def _GetUnicodeFileList(self
):
2439 if self
._UnicodeFileList
== None:
2440 if TAB_UNICODE_FILE
in self
.FileTypes
:
2441 self
._UnicodeFileList
= self
.FileTypes
[TAB_UNICODE_FILE
]
2443 self
._UnicodeFileList
= []
2444 return self
._UnicodeFileList
2446 ## Return a list of files which can be built from binary
2448 # "Build" binary files are just to copy them to build directory.
2450 # @retval list The list of files which can be built later
2452 def _GetBinaryFiles(self
):
2453 if self
._BinaryFileList
== None:
2454 self
._BinaryFileList
= []
2455 for F
in self
.Module
.Binaries
:
2456 if F
.Target
not in ['COMMON', '*'] and F
.Target
!= self
.BuildTarget
:
2458 self
._BinaryFileList
.append(F
)
2459 self
._ApplyBuildRule
(F
, F
.Type
)
2460 return self
._BinaryFileList
2462 def _GetBuildRules(self
):
2463 if self
._BuildRules
== None:
2465 BuildRuleDatabase
= self
.PlatformInfo
.BuildRule
2466 for Type
in BuildRuleDatabase
.FileTypeList
:
2467 #first try getting build rule by BuildRuleFamily
2468 RuleObject
= BuildRuleDatabase
[Type
, self
.BuildType
, self
.Arch
, self
.BuildRuleFamily
]
2470 # build type is always module type, but ...
2471 if self
.ModuleType
!= self
.BuildType
:
2472 RuleObject
= BuildRuleDatabase
[Type
, self
.ModuleType
, self
.Arch
, self
.BuildRuleFamily
]
2473 #second try getting build rule by ToolChainFamily
2475 RuleObject
= BuildRuleDatabase
[Type
, self
.BuildType
, self
.Arch
, self
.ToolChainFamily
]
2477 # build type is always module type, but ...
2478 if self
.ModuleType
!= self
.BuildType
:
2479 RuleObject
= BuildRuleDatabase
[Type
, self
.ModuleType
, self
.Arch
, self
.ToolChainFamily
]
2482 RuleObject
= RuleObject
.Instantiate(self
.Macros
)
2483 BuildRules
[Type
] = RuleObject
2484 for Ext
in RuleObject
.SourceFileExtList
:
2485 BuildRules
[Ext
] = RuleObject
2486 self
._BuildRules
= BuildRules
2487 return self
._BuildRules
2489 def _ApplyBuildRule(self
, File
, FileType
):
2490 if self
._BuildTargets
== None:
2491 self
._IntroBuildTargetList
= set()
2492 self
._FinalBuildTargetList
= set()
2493 self
._BuildTargets
= {}
2494 self
._FileTypes
= {}
2500 while Index
< len(SourceList
):
2501 Source
= SourceList
[Index
]
2505 CreateDirectory(Source
.Dir
)
2507 if File
.IsBinary
and File
== Source
and self
._BinaryFileList
!= None and File
in self
._BinaryFileList
:
2508 # Skip all files that are not binary libraries
2509 if not self
.IsLibrary
:
2511 RuleObject
= self
.BuildRules
[TAB_DEFAULT_BINARY_FILE
]
2512 elif FileType
in self
.BuildRules
:
2513 RuleObject
= self
.BuildRules
[FileType
]
2514 elif Source
.Ext
in self
.BuildRules
:
2515 RuleObject
= self
.BuildRules
[Source
.Ext
]
2517 # stop at no more rules
2519 self
._FinalBuildTargetList
.add(LastTarget
)
2522 FileType
= RuleObject
.SourceFileType
2523 if FileType
not in self
._FileTypes
:
2524 self
._FileTypes
[FileType
] = set()
2525 self
._FileTypes
[FileType
].add(Source
)
2527 # stop at STATIC_LIBRARY for library
2528 if self
.IsLibrary
and FileType
== TAB_STATIC_LIBRARY
:
2530 self
._FinalBuildTargetList
.add(LastTarget
)
2533 Target
= RuleObject
.Apply(Source
)
2536 self
._FinalBuildTargetList
.add(LastTarget
)
2538 elif not Target
.Outputs
:
2539 # Only do build for target with outputs
2540 self
._FinalBuildTargetList
.add(Target
)
2542 if FileType
not in self
._BuildTargets
:
2543 self
._BuildTargets
[FileType
] = set()
2544 self
._BuildTargets
[FileType
].add(Target
)
2546 if not Source
.IsBinary
and Source
== File
:
2547 self
._IntroBuildTargetList
.add(Target
)
2549 # to avoid cyclic rule
2550 if FileType
in RuleChain
:
2553 RuleChain
.append(FileType
)
2554 SourceList
.extend(Target
.Outputs
)
2556 FileType
= TAB_UNKNOWN_FILE
2558 def _GetTargets(self
):
2559 if self
._BuildTargets
== None:
2560 self
._IntroBuildTargetList
= set()
2561 self
._FinalBuildTargetList
= set()
2562 self
._BuildTargets
= {}
2563 self
._FileTypes
= {}
2565 #TRICK: call _GetSourceFileList to apply build rule for source files
2566 if self
.SourceFileList
:
2569 #TRICK: call _GetBinaryFileList to apply build rule for binary files
2570 if self
.BinaryFileList
:
2573 return self
._BuildTargets
2575 def _GetIntroTargetList(self
):
2577 return self
._IntroBuildTargetList
2579 def _GetFinalTargetList(self
):
2581 return self
._FinalBuildTargetList
2583 def _GetFileTypes(self
):
2585 return self
._FileTypes
2587 ## Get the list of package object the module depends on
2589 # @retval list The package object list
2591 def _GetDependentPackageList(self
):
2592 return self
.Module
.Packages
2594 ## Return the list of auto-generated code file
2596 # @retval list The list of auto-generated file
2598 def _GetAutoGenFileList(self
):
2599 UniStringAutoGenC
= True
2600 UniStringBinBuffer
= StringIO()
2601 if self
.BuildType
== 'UEFI_HII':
2602 UniStringAutoGenC
= False
2603 if self
._AutoGenFileList
== None:
2604 self
._AutoGenFileList
= {}
2605 AutoGenC
= TemplateString()
2606 AutoGenH
= TemplateString()
2607 StringH
= TemplateString()
2608 GenC
.CreateCode(self
, AutoGenC
, AutoGenH
, StringH
, UniStringAutoGenC
, UniStringBinBuffer
)
2609 if str(AutoGenC
) != "" and TAB_C_CODE_FILE
in self
.FileTypes
:
2610 AutoFile
= PathClass(gAutoGenCodeFileName
, self
.DebugDir
)
2611 self
._AutoGenFileList
[AutoFile
] = str(AutoGenC
)
2612 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
2613 if str(AutoGenH
) != "":
2614 AutoFile
= PathClass(gAutoGenHeaderFileName
, self
.DebugDir
)
2615 self
._AutoGenFileList
[AutoFile
] = str(AutoGenH
)
2616 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
2617 if str(StringH
) != "":
2618 AutoFile
= PathClass(gAutoGenStringFileName
% {"module_name":self
.Name
}, self
.DebugDir
)
2619 self
._AutoGenFileList
[AutoFile
] = str(StringH
)
2620 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
2621 if UniStringBinBuffer
!= None and UniStringBinBuffer
.getvalue() != "":
2622 AutoFile
= PathClass(gAutoGenStringFormFileName
% {"module_name":self
.Name
}, self
.OutputDir
)
2623 self
._AutoGenFileList
[AutoFile
] = UniStringBinBuffer
.getvalue()
2624 AutoFile
.IsBinary
= True
2625 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
2626 if UniStringBinBuffer
!= None:
2627 UniStringBinBuffer
.close()
2628 return self
._AutoGenFileList
2630 ## Return the list of library modules explicitly or implicityly used by this module
2631 def _GetLibraryList(self
):
2632 if self
._DependentLibraryList
== None:
2633 # only merge library classes and PCD for non-library module
2635 self
._DependentLibraryList
= []
2637 if self
.AutoGenVersion
< 0x00010005:
2638 self
._DependentLibraryList
= self
.PlatformInfo
.ResolveLibraryReference(self
.Module
)
2640 self
._DependentLibraryList
= self
.PlatformInfo
.ApplyLibraryInstance(self
.Module
)
2641 return self
._DependentLibraryList
2644 def UpdateComments(Recver
, Src
):
2646 if Key
not in Recver
:
2648 Recver
[Key
].extend(Src
[Key
])
2649 ## Get the list of PCDs from current module
2651 # @retval list The list of PCD
2653 def _GetModulePcdList(self
):
2654 if self
._ModulePcdList
== None:
2655 # apply PCD settings from platform
2656 self
._ModulePcdList
= self
.PlatformInfo
.ApplyPcdSetting(self
.Module
, self
.Module
.Pcds
)
2657 self
.UpdateComments(self
._PcdComments
, self
.Module
.PcdComments
)
2658 return self
._ModulePcdList
2660 ## Get the list of PCDs from dependent libraries
2662 # @retval list The list of PCD
2664 def _GetLibraryPcdList(self
):
2665 if self
._LibraryPcdList
== None:
2667 if not self
.IsLibrary
:
2668 # get PCDs from dependent libraries
2669 for Library
in self
.DependentLibraryList
:
2670 self
.UpdateComments(self
._PcdComments
, Library
.PcdComments
)
2671 for Key
in Library
.Pcds
:
2672 # skip duplicated PCDs
2673 if Key
in self
.Module
.Pcds
or Key
in Pcds
:
2675 Pcds
[Key
] = copy
.copy(Library
.Pcds
[Key
])
2676 # apply PCD settings from platform
2677 self
._LibraryPcdList
= self
.PlatformInfo
.ApplyPcdSetting(self
.Module
, Pcds
)
2679 self
._LibraryPcdList
= []
2680 return self
._LibraryPcdList
2682 ## Get the GUID value mapping
2684 # @retval dict The mapping between GUID cname and its value
2686 def _GetGuidList(self
):
2687 if self
._GuidList
== None:
2688 self
._GuidList
= self
.Module
.Guids
2689 for Library
in self
.DependentLibraryList
:
2690 self
._GuidList
.update(Library
.Guids
)
2691 self
.UpdateComments(self
._GuidComments
, Library
.GuidComments
)
2692 self
.UpdateComments(self
._GuidComments
, self
.Module
.GuidComments
)
2693 return self
._GuidList
2695 def GetGuidsUsedByPcd(self
):
2696 if self
._GuidsUsedByPcd
== None:
2697 self
._GuidsUsedByPcd
= sdict()
2698 self
._GuidsUsedByPcd
.update(self
.Module
.GetGuidsUsedByPcd())
2699 for Library
in self
.DependentLibraryList
:
2700 self
._GuidsUsedByPcd
.update(Library
.GetGuidsUsedByPcd())
2701 return self
._GuidsUsedByPcd
2702 ## Get the protocol value mapping
2704 # @retval dict The mapping between protocol cname and its value
2706 def _GetProtocolList(self
):
2707 if self
._ProtocolList
== None:
2708 self
._ProtocolList
= self
.Module
.Protocols
2709 for Library
in self
.DependentLibraryList
:
2710 self
._ProtocolList
.update(Library
.Protocols
)
2711 self
.UpdateComments(self
._ProtocolComments
, Library
.ProtocolComments
)
2712 self
.UpdateComments(self
._ProtocolComments
, self
.Module
.ProtocolComments
)
2713 return self
._ProtocolList
2715 ## Get the PPI value mapping
2717 # @retval dict The mapping between PPI cname and its value
2719 def _GetPpiList(self
):
2720 if self
._PpiList
== None:
2721 self
._PpiList
= self
.Module
.Ppis
2722 for Library
in self
.DependentLibraryList
:
2723 self
._PpiList
.update(Library
.Ppis
)
2724 self
.UpdateComments(self
._PpiComments
, Library
.PpiComments
)
2725 self
.UpdateComments(self
._PpiComments
, self
.Module
.PpiComments
)
2726 return self
._PpiList
2728 ## Get the list of include search path
2730 # @retval list The list path
2732 def _GetIncludePathList(self
):
2733 if self
._IncludePathList
== None:
2734 self
._IncludePathList
= []
2735 if self
.AutoGenVersion
< 0x00010005:
2736 for Inc
in self
.Module
.Includes
:
2737 if Inc
not in self
._IncludePathList
:
2738 self
._IncludePathList
.append(Inc
)
2740 Inc
= path
.join(Inc
, self
.Arch
.capitalize())
2741 if os
.path
.exists(Inc
) and Inc
not in self
._IncludePathList
:
2742 self
._IncludePathList
.append(Inc
)
2743 # Edk module needs to put DEBUG_DIR at the end of search path and not to use SOURCE_DIR all the time
2744 self
._IncludePathList
.append(self
.DebugDir
)
2746 self
._IncludePathList
.append(self
.MetaFile
.Dir
)
2747 self
._IncludePathList
.append(self
.DebugDir
)
2749 for Package
in self
.Module
.Packages
:
2750 PackageDir
= path
.join(self
.WorkspaceDir
, Package
.MetaFile
.Dir
)
2751 if PackageDir
not in self
._IncludePathList
:
2752 self
._IncludePathList
.append(PackageDir
)
2753 for Inc
in Package
.Includes
:
2754 if Inc
not in self
._IncludePathList
:
2755 self
._IncludePathList
.append(str(Inc
))
2756 return self
._IncludePathList
2758 ## Create AsBuilt INF file the module
2760 def CreateAsBuiltInf(self
):
2761 if self
.IsAsBuiltInfCreated
:
2764 # Skip the following code for EDK I inf
2765 if self
.AutoGenVersion
< 0x00010005:
2768 # Skip the following code for libraries
2772 # Skip the following code for modules with no source files
2773 if self
.SourceFileList
== None or self
.SourceFileList
== []:
2776 # Skip the following code for modules without any binary files
2777 if self
.BinaryFileList
<> None and self
.BinaryFileList
<> []:
2780 ### TODO: How to handles mixed source and binary modules
2782 # Find all DynamicEx and PatchableInModule PCDs used by this module and dependent libraries
2783 # Also find all packages that the DynamicEx PCDs depend on
2788 PcdTokenSpaceList
= []
2789 for Pcd
in self
.ModulePcdList
+ self
.LibraryPcdList
:
2790 if Pcd
.Type
== TAB_PCDS_PATCHABLE_IN_MODULE
:
2791 PatchablePcds
[Pcd
.TokenCName
] = Pcd
2792 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, 'PatchableInModule'))
2793 elif Pcd
.Type
in GenC
.gDynamicExPcd
:
2796 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, 'DynamicEx'))
2797 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, 'Dynamic'))
2798 PcdTokenSpaceList
.append(Pcd
.TokenSpaceGuidCName
)
2800 GuidList
.update(self
.GuidList
)
2801 for TokenSpace
in self
.GetGuidsUsedByPcd():
2802 # If token space is not referred by patch PCD or Ex PCD, remove the GUID from GUID list
2803 # The GUIDs in GUIDs section should really be the GUIDs in source INF or referred by Ex an patch PCDs
2804 if TokenSpace
not in PcdTokenSpaceList
and TokenSpace
in GuidList
:
2805 GuidList
.pop(TokenSpace
)
2806 CheckList
= (GuidList
, self
.PpiList
, self
.ProtocolList
, PcdCheckList
)
2807 for Package
in self
.DerivedPackageList
:
2808 if Package
in Packages
:
2810 BeChecked
= (Package
.Guids
, Package
.Ppis
, Package
.Protocols
, Package
.Pcds
)
2812 for Index
in range(len(BeChecked
)):
2813 for Item
in CheckList
[Index
]:
2814 if Item
in BeChecked
[Index
]:
2815 Packages
+= [Package
]
2820 ModuleType
= self
.ModuleType
2821 if ModuleType
== 'UEFI_DRIVER' and self
.DepexGenerated
:
2822 ModuleType
= 'DXE_DRIVER'
2825 if self
.PcdIsDriver
!= '':
2826 DriverType
= self
.PcdIsDriver
2829 'module_name' : self
.Name
,
2830 'module_guid' : self
.Guid
,
2831 'module_module_type' : ModuleType
,
2832 'module_version_string' : self
.Version
,
2833 'pcd_is_driver_string' : [],
2834 'module_uefi_specification_version' : [],
2835 'module_pi_specification_version' : [],
2836 'module_arch' : self
.Arch
,
2837 'package_item' : ['%s' % (Package
.MetaFile
.File
.replace('\\','/')) for Package
in Packages
],
2839 'patchablepcd_item' : [],
2841 'protocol_item' : [],
2845 'libraryclasses_item' : []
2847 AsBuiltInfDict
['module_inf_version'] = '0x%08x' % self
.AutoGenVersion
2849 AsBuiltInfDict
['pcd_is_driver_string'] += [DriverType
]
2851 if 'UEFI_SPECIFICATION_VERSION' in self
.Specification
:
2852 AsBuiltInfDict
['module_uefi_specification_version'] += [self
.Specification
['UEFI_SPECIFICATION_VERSION']]
2853 if 'PI_SPECIFICATION_VERSION' in self
.Specification
:
2854 AsBuiltInfDict
['module_pi_specification_version'] += [self
.Specification
['PI_SPECIFICATION_VERSION']]
2856 OutputDir
= self
.OutputDir
.replace('\\','/').strip('/')
2857 if self
.ModuleType
in ['BASE', 'USER_DEFINED']:
2858 for Item
in self
.CodaTargetList
:
2859 File
= Item
.Target
.Path
.replace('\\','/').strip('/').replace(OutputDir
,'').strip('/')
2860 if Item
.Target
.Ext
.lower() == '.aml':
2861 AsBuiltInfDict
['binary_item'] += ['ASL|' + File
]
2862 elif Item
.Target
.Ext
.lower() == '.acpi':
2863 AsBuiltInfDict
['binary_item'] += ['ACPI|' + File
]
2865 AsBuiltInfDict
['binary_item'] += ['BIN|' + File
]
2867 for Item
in self
.CodaTargetList
:
2868 File
= Item
.Target
.Path
.replace('\\','/').strip('/').replace(OutputDir
,'').strip('/')
2869 if Item
.Target
.Ext
.lower() == '.efi':
2870 AsBuiltInfDict
['binary_item'] += ['PE32|' + self
.Name
+ '.efi']
2872 AsBuiltInfDict
['binary_item'] += ['BIN|' + File
]
2873 if self
.DepexGenerated
:
2874 if self
.ModuleType
in ['PEIM']:
2875 AsBuiltInfDict
['binary_item'] += ['PEI_DEPEX|' + self
.Name
+ '.depex']
2876 if self
.ModuleType
in ['DXE_DRIVER','DXE_RUNTIME_DRIVER','DXE_SAL_DRIVER','UEFI_DRIVER']:
2877 AsBuiltInfDict
['binary_item'] += ['DXE_DEPEX|' + self
.Name
+ '.depex']
2878 if self
.ModuleType
in ['DXE_SMM_DRIVER']:
2879 AsBuiltInfDict
['binary_item'] += ['SMM_DEPEX|' + self
.Name
+ '.depex']
2881 for Root
, Dirs
, Files
in os
.walk(OutputDir
):
2883 if File
.lower().endswith('.pdb'):
2884 AsBuiltInfDict
['binary_item'] += ['DISPOSABLE|' + File
]
2885 HeaderComments
= self
.Module
.HeaderComments
2887 for Index
in range(len(HeaderComments
)):
2888 if HeaderComments
[Index
].find('@BinaryHeader') != -1:
2889 HeaderComments
[Index
] = HeaderComments
[Index
].replace('@BinaryHeader', '@file')
2892 AsBuiltInfDict
['header_comments'] = '\n'.join(HeaderComments
[StartPos
:]).replace(':#', '://')
2894 (self
.ProtocolList
, self
._ProtocolComments
, 'protocol_item'),
2895 (self
.PpiList
, self
._PpiComments
, 'ppi_item'),
2896 (GuidList
, self
._GuidComments
, 'guid_item')
2898 for Item
in GenList
:
2899 for CName
in Item
[0]:
2901 if CName
in Item
[1]:
2902 Comments
= '\n '.join(Item
[1][CName
])
2905 Entry
= Comments
+ '\n ' + CName
2906 AsBuiltInfDict
[Item
[2]].append(Entry
)
2907 PatchList
= parsePcdInfoFromMapFile(
2908 os
.path
.join(self
.OutputDir
, self
.Name
+ '.map'),
2909 os
.path
.join(self
.OutputDir
, self
.Name
+ '.efi')
2912 for PatchPcd
in PatchList
:
2913 if PatchPcd
[0] not in PatchablePcds
:
2915 Pcd
= PatchablePcds
[PatchPcd
[0]]
2917 if Pcd
.DatumType
!= 'VOID*':
2918 HexFormat
= '0x%02x'
2919 if Pcd
.DatumType
== 'UINT16':
2920 HexFormat
= '0x%04x'
2921 elif Pcd
.DatumType
== 'UINT32':
2922 HexFormat
= '0x%08x'
2923 elif Pcd
.DatumType
== 'UINT64':
2924 HexFormat
= '0x%016x'
2925 PcdValue
= HexFormat
% int(Pcd
.DefaultValue
, 0)
2927 if Pcd
.MaxDatumSize
== None or Pcd
.MaxDatumSize
== '':
2928 EdkLogger
.error("build", AUTOGEN_ERROR
,
2929 "Unknown [MaxDatumSize] of PCD [%s.%s]" % (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
)
2931 ArraySize
= int(Pcd
.MaxDatumSize
, 0)
2932 PcdValue
= Pcd
.DefaultValue
2933 if PcdValue
[0] != '{':
2935 if PcdValue
[0] == 'L':
2937 PcdValue
= PcdValue
.lstrip('L')
2938 PcdValue
= eval(PcdValue
)
2940 for Index
in range(0, len(PcdValue
)):
2942 CharVal
= ord(PcdValue
[Index
])
2943 NewValue
= NewValue
+ '0x%02x' % (CharVal
& 0x00FF) + ', ' \
2944 + '0x%02x' % (CharVal
>> 8) + ', '
2946 NewValue
= NewValue
+ '0x%02x' % (ord(PcdValue
[Index
]) % 0x100) + ', '
2949 Padding
= Padding
* 2
2950 ArraySize
= ArraySize
/ 2
2951 if ArraySize
< (len(PcdValue
) + 1):
2952 EdkLogger
.error("build", AUTOGEN_ERROR
,
2953 "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
)
2955 if ArraySize
> len(PcdValue
) + 1:
2956 NewValue
= NewValue
+ Padding
* (ArraySize
- len(PcdValue
) - 1)
2957 PcdValue
= NewValue
+ Padding
.strip().rstrip(',') + '}'
2958 elif len(PcdValue
.split(',')) <= ArraySize
:
2959 PcdValue
= PcdValue
.rstrip('}') + ', 0x00' * (ArraySize
- len(PcdValue
.split(',')))
2962 EdkLogger
.error("build", AUTOGEN_ERROR
,
2963 "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
)
2965 PcdItem
= '%s.%s|%s|0x%X' % \
2966 (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
, PcdValue
, PatchPcd
[1])
2968 if (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) in self
._PcdComments
:
2969 PcdComments
= '\n '.join(self
._PcdComments
[Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
])
2971 PcdItem
= PcdComments
+ '\n ' + PcdItem
2972 AsBuiltInfDict
['patchablepcd_item'].append(PcdItem
)
2977 if Pcd
.Type
== TAB_PCDS_DYNAMIC_EX_HII
:
2978 for SkuName
in Pcd
.SkuInfoList
:
2979 SkuInfo
= Pcd
.SkuInfoList
[SkuName
]
2980 HiiInfo
= '## %s|%s|%s' % (SkuInfo
.VariableName
, SkuInfo
.VariableGuid
, SkuInfo
.VariableOffset
)
2982 if (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) in self
._PcdComments
:
2983 PcdCommentList
= self
._PcdComments
[Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
][:]
2986 for Index
, Comment
in enumerate(PcdCommentList
):
2987 for Usage
in UsageList
:
2988 if Comment
.find(Usage
) != -1:
2991 if UsageIndex
!= -1:
2992 PcdCommentList
[UsageIndex
] = PcdCommentList
[UsageIndex
] + ' ' + HiiInfo
2994 PcdCommentList
.append('## ' + HiiInfo
)
2995 PcdComments
= '\n '.join(PcdCommentList
)
2996 PcdEntry
= Pcd
.TokenSpaceGuidCName
+ '.' + Pcd
.TokenCName
2998 PcdEntry
= PcdComments
+ '\n ' + PcdEntry
2999 AsBuiltInfDict
['pcd_item'] += [PcdEntry
]
3000 for Item
in self
.BuildOption
:
3001 if 'FLAGS' in self
.BuildOption
[Item
]:
3002 AsBuiltInfDict
['flags_item'] += ['%s:%s_%s_%s_%s_FLAGS = %s' % (self
.ToolChainFamily
, self
.BuildTarget
, self
.ToolChain
, self
.Arch
, Item
, self
.BuildOption
[Item
]['FLAGS'].strip())]
3004 AsBuiltInf
= TemplateString()
3005 AsBuiltInf
.Append(gAsBuiltInfHeaderString
.Replace(AsBuiltInfDict
))
3007 SaveFileOnChange(os
.path
.join(self
.OutputDir
, self
.Name
+ '.inf'), str(AsBuiltInf
), False)
3009 self
.IsAsBuiltInfCreated
= True
3011 ## Create makefile for the module and its dependent libraries
3013 # @param CreateLibraryMakeFile Flag indicating if or not the makefiles of
3014 # dependent libraries will be created
3016 def CreateMakeFile(self
, CreateLibraryMakeFile
=True):
3017 if self
.IsMakeFileCreated
:
3020 if not self
.IsLibrary
and CreateLibraryMakeFile
:
3021 for LibraryAutoGen
in self
.LibraryAutoGenList
:
3022 LibraryAutoGen
.CreateMakeFile()
3024 if len(self
.CustomMakefile
) == 0:
3025 Makefile
= GenMake
.ModuleMakefile(self
)
3027 Makefile
= GenMake
.CustomMakefile(self
)
3028 if Makefile
.Generate():
3029 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated makefile for module %s [%s]" %
3030 (self
.Name
, self
.Arch
))
3032 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Skipped the generation of makefile for module %s [%s]" %
3033 (self
.Name
, self
.Arch
))
3035 self
.IsMakeFileCreated
= True
3037 ## Create autogen code for the module and its dependent libraries
3039 # @param CreateLibraryCodeFile Flag indicating if or not the code of
3040 # dependent libraries will be created
3042 def CreateCodeFile(self
, CreateLibraryCodeFile
=True):
3043 if self
.IsCodeFileCreated
:
3046 # Need to generate PcdDatabase even PcdDriver is binarymodule
3047 if self
.IsBinaryModule
and self
.PcdIsDriver
!= '':
3048 CreatePcdDatabaseCode(self
, TemplateString(), TemplateString())
3051 if not self
.IsLibrary
and CreateLibraryCodeFile
:
3052 for LibraryAutoGen
in self
.LibraryAutoGenList
:
3053 LibraryAutoGen
.CreateCodeFile()
3056 IgoredAutoGenList
= []
3058 for File
in self
.AutoGenFileList
:
3059 if GenC
.Generate(File
.Path
, self
.AutoGenFileList
[File
], File
.IsBinary
):
3060 #Ignore Edk AutoGen.c
3061 if self
.AutoGenVersion
< 0x00010005 and File
.Name
== 'AutoGen.c':
3064 AutoGenList
.append(str(File
))
3066 IgoredAutoGenList
.append(str(File
))
3068 # Skip the following code for EDK I inf
3069 if self
.AutoGenVersion
< 0x00010005:
3072 for ModuleType
in self
.DepexList
:
3073 # Ignore empty [depex] section or [depex] section for "USER_DEFINED" module
3074 if len(self
.DepexList
[ModuleType
]) == 0 or ModuleType
== "USER_DEFINED":
3077 Dpx
= GenDepex
.DependencyExpression(self
.DepexList
[ModuleType
], ModuleType
, True)
3078 DpxFile
= gAutoGenDepexFileName
% {"module_name" : self
.Name
}
3080 if len(Dpx
.PostfixNotation
) <> 0:
3081 self
.DepexGenerated
= True
3083 if Dpx
.Generate(path
.join(self
.OutputDir
, DpxFile
)):
3084 AutoGenList
.append(str(DpxFile
))
3086 IgoredAutoGenList
.append(str(DpxFile
))
3088 if IgoredAutoGenList
== []:
3089 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated [%s] files for module %s [%s]" %
3090 (" ".join(AutoGenList
), self
.Name
, self
.Arch
))
3091 elif AutoGenList
== []:
3092 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Skipped the generation of [%s] files for module %s [%s]" %
3093 (" ".join(IgoredAutoGenList
), self
.Name
, self
.Arch
))
3095 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated [%s] (skipped %s) files for module %s [%s]" %
3096 (" ".join(AutoGenList
), " ".join(IgoredAutoGenList
), self
.Name
, self
.Arch
))
3098 self
.IsCodeFileCreated
= True
3101 ## Summarize the ModuleAutoGen objects of all libraries used by this module
3102 def _GetLibraryAutoGenList(self
):
3103 if self
._LibraryAutoGenList
== None:
3104 self
._LibraryAutoGenList
= []
3105 for Library
in self
.DependentLibraryList
:
3112 self
.PlatformInfo
.MetaFile
3114 if La
not in self
._LibraryAutoGenList
:
3115 self
._LibraryAutoGenList
.append(La
)
3116 for Lib
in La
.CodaTargetList
:
3117 self
._ApplyBuildRule
(Lib
.Target
, TAB_UNKNOWN_FILE
)
3118 return self
._LibraryAutoGenList
3120 Module
= property(_GetModule
)
3121 Name
= property(_GetBaseName
)
3122 Guid
= property(_GetGuid
)
3123 Version
= property(_GetVersion
)
3124 ModuleType
= property(_GetModuleType
)
3125 ComponentType
= property(_GetComponentType
)
3126 BuildType
= property(_GetBuildType
)
3127 PcdIsDriver
= property(_GetPcdIsDriver
)
3128 AutoGenVersion
= property(_GetAutoGenVersion
)
3129 Macros
= property(_GetMacros
)
3130 Specification
= property(_GetSpecification
)
3132 IsLibrary
= property(_IsLibrary
)
3133 IsBinaryModule
= property(_IsBinaryModule
)
3134 BuildDir
= property(_GetBuildDir
)
3135 OutputDir
= property(_GetOutputDir
)
3136 DebugDir
= property(_GetDebugDir
)
3137 MakeFileDir
= property(_GetMakeFileDir
)
3138 CustomMakefile
= property(_GetCustomMakefile
)
3140 IncludePathList
= property(_GetIncludePathList
)
3141 AutoGenFileList
= property(_GetAutoGenFileList
)
3142 UnicodeFileList
= property(_GetUnicodeFileList
)
3143 SourceFileList
= property(_GetSourceFileList
)
3144 BinaryFileList
= property(_GetBinaryFiles
) # FileType : [File List]
3145 Targets
= property(_GetTargets
)
3146 IntroTargetList
= property(_GetIntroTargetList
)
3147 CodaTargetList
= property(_GetFinalTargetList
)
3148 FileTypes
= property(_GetFileTypes
)
3149 BuildRules
= property(_GetBuildRules
)
3151 DependentPackageList
= property(_GetDependentPackageList
)
3152 DependentLibraryList
= property(_GetLibraryList
)
3153 LibraryAutoGenList
= property(_GetLibraryAutoGenList
)
3154 DerivedPackageList
= property(_GetDerivedPackageList
)
3156 ModulePcdList
= property(_GetModulePcdList
)
3157 LibraryPcdList
= property(_GetLibraryPcdList
)
3158 GuidList
= property(_GetGuidList
)
3159 ProtocolList
= property(_GetProtocolList
)
3160 PpiList
= property(_GetPpiList
)
3161 DepexList
= property(_GetDepexTokenList
)
3162 DxsFile
= property(_GetDxsFile
)
3163 DepexExpressionList
= property(_GetDepexExpressionTokenList
)
3164 BuildOption
= property(_GetModuleBuildOption
)
3165 BuildOptionIncPathList
= property(_GetBuildOptionIncPathList
)
3166 BuildCommand
= property(_GetBuildCommand
)
3168 FixedAtBuildPcds
= property(_GetFixedAtBuildPcds
)
3170 # This acts like the main() function for the script, unless it is 'import'ed into another script.
3171 if __name__
== '__main__':