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.
18 import os
.path
as path
24 from StringIO
import StringIO
26 from StrGather
import *
27 from BuildEngine
import BuildRule
29 from Common
.BuildToolError
import *
30 from Common
.DataType
import *
31 from Common
.Misc
import *
32 from Common
.String
import *
33 import Common
.GlobalData
as GlobalData
34 from GenFds
.FdfParser
import *
35 from CommonDataClass
.CommonClass
import SkuInfoClass
36 from Workspace
.BuildClassObject
import *
37 from GenPatchPcdTable
.GenPatchPcdTable
import parsePcdInfoFromMapFile
38 import Common
.VpdInfoFile
as VpdInfoFile
39 from GenPcdDb
import CreatePcdDatabaseCode
40 from Workspace
.MetaFileCommentParser
import UsageList
42 ## Regular expression for splitting Dependency Expression string into tokens
43 gDepexTokenPattern
= re
.compile("(\(|\)|\w+| \S+\.inf)")
45 ## Mapping Makefile type
46 gMakeTypeMap
= {"MSFT":"nmake", "GCC":"gmake"}
49 ## Build rule configuration file
50 gBuildRuleFile
= 'Conf/build_rule.txt'
52 ## Build rule default version
53 AutoGenReqBuildRuleVerNum
= "0.1"
55 ## default file name for AutoGen
56 gAutoGenCodeFileName
= "AutoGen.c"
57 gAutoGenHeaderFileName
= "AutoGen.h"
58 gAutoGenStringFileName
= "%(module_name)sStrDefs.h"
59 gAutoGenStringFormFileName
= "%(module_name)sStrDefs.hpk"
60 gAutoGenDepexFileName
= "%(module_name)s.depex"
63 # Template string to generic AsBuilt INF
65 gAsBuiltInfHeaderString
= TemplateString("""${header_comments}
68 INF_VERSION = 0x00010016
69 BASE_NAME = ${module_name}
70 FILE_GUID = ${module_guid}
71 MODULE_TYPE = ${module_module_type}
72 VERSION_STRING = ${module_version_string}${BEGIN}
73 PCD_IS_DRIVER = ${pcd_is_driver_string}${END}${BEGIN}
74 UEFI_SPECIFICATION_VERSION = ${module_uefi_specification_version}${END}${BEGIN}
75 PI_SPECIFICATION_VERSION = ${module_pi_specification_version}${END}
80 [Binaries.${module_arch}]${BEGIN}
83 [PatchPcd.${module_arch}]${BEGIN}
86 [Protocols.${module_arch}]${BEGIN}
89 [Ppis.${module_arch}]${BEGIN}
92 [Guids.${module_arch}]${BEGIN}
95 [PcdEx.${module_arch}]${BEGIN}
100 ## ${flags_item}${END}
103 ## Base class for AutoGen
105 # This class just implements the cache mechanism of AutoGen objects.
107 class AutoGen(object):
108 # database to maintain the objects of xxxAutoGen
109 _CACHE_
= {} # (BuildTarget, ToolChain) : {ARCH : {platform file: AutoGen object}}}
113 # @param Class class object of real AutoGen class
114 # (WorkspaceAutoGen, ModuleAutoGen or PlatformAutoGen)
115 # @param Workspace Workspace directory or WorkspaceAutoGen object
116 # @param MetaFile The path of meta file
117 # @param Target Build target
118 # @param Toolchain Tool chain name
119 # @param Arch Target arch
120 # @param *args The specific class related parameters
121 # @param **kwargs The specific class related dict parameters
123 def __new__(Class
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
124 # check if the object has been created
125 Key
= (Target
, Toolchain
)
126 if Key
not in Class
._CACHE
_ or Arch
not in Class
._CACHE
_[Key
] \
127 or MetaFile
not in Class
._CACHE
_[Key
][Arch
]:
128 AutoGenObject
= super(AutoGen
, Class
).__new
__(Class
)
129 # call real constructor
130 if not AutoGenObject
._Init
(Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
132 if Key
not in Class
._CACHE
_:
133 Class
._CACHE
_[Key
] = {}
134 if Arch
not in Class
._CACHE
_[Key
]:
135 Class
._CACHE
_[Key
][Arch
] = {}
136 Class
._CACHE
_[Key
][Arch
][MetaFile
] = AutoGenObject
138 AutoGenObject
= Class
._CACHE
_[Key
][Arch
][MetaFile
]
144 # The file path of platform file will be used to represent hash value of this object
146 # @retval int Hash value of the file path of platform file
149 return hash(self
.MetaFile
)
153 # The file path of platform file will be used to represent this object
155 # @retval string String of platform file path
158 return str(self
.MetaFile
)
161 def __eq__(self
, Other
):
162 return Other
and self
.MetaFile
== Other
164 ## Workspace AutoGen class
166 # This class is used mainly to control the whole platform build for different
167 # architecture. This class will generate top level makefile.
169 class WorkspaceAutoGen(AutoGen
):
170 ## Real constructor of WorkspaceAutoGen
172 # This method behaves the same as __init__ except that it needs explicit invoke
173 # (in super class's __new__ method)
175 # @param WorkspaceDir Root directory of workspace
176 # @param ActivePlatform Meta-file of active platform
177 # @param Target Build target
178 # @param Toolchain Tool chain name
179 # @param ArchList List of architecture of current build
180 # @param MetaFileDb Database containing meta-files
181 # @param BuildConfig Configuration of build
182 # @param ToolDefinition Tool chain definitions
183 # @param FlashDefinitionFile File of flash definition
184 # @param Fds FD list to be generated
185 # @param Fvs FV list to be generated
186 # @param Caps Capsule list to be generated
187 # @param SkuId SKU id from command line
189 def _Init(self
, WorkspaceDir
, ActivePlatform
, Target
, Toolchain
, ArchList
, MetaFileDb
,
190 BuildConfig
, ToolDefinition
, FlashDefinitionFile
='', Fds
=None, Fvs
=None, Caps
=None, SkuId
='', UniFlag
=None,
191 Progress
=None, BuildModule
=None):
198 self
.BuildDatabase
= MetaFileDb
199 self
.MetaFile
= ActivePlatform
200 self
.WorkspaceDir
= WorkspaceDir
201 self
.Platform
= self
.BuildDatabase
[self
.MetaFile
, 'COMMON', Target
, Toolchain
]
202 GlobalData
.gActivePlatform
= self
.Platform
203 self
.BuildTarget
= Target
204 self
.ToolChain
= Toolchain
205 self
.ArchList
= ArchList
207 self
.UniFlag
= UniFlag
209 self
.TargetTxt
= BuildConfig
210 self
.ToolDef
= ToolDefinition
211 self
.FdfFile
= FlashDefinitionFile
212 self
.FdTargetList
= Fds
213 self
.FvTargetList
= Fvs
214 self
.CapTargetList
= Caps
215 self
.AutoGenObjectList
= []
217 # there's many relative directory operations, so ...
218 os
.chdir(self
.WorkspaceDir
)
223 if not self
.ArchList
:
224 ArchList
= set(self
.Platform
.SupArchList
)
226 ArchList
= set(self
.ArchList
) & set(self
.Platform
.SupArchList
)
228 EdkLogger
.error("build", PARAMETER_INVALID
,
229 ExtraData
= "Invalid ARCH specified. [Valid ARCH: %s]" % (" ".join(self
.Platform
.SupArchList
)))
230 elif self
.ArchList
and len(ArchList
) != len(self
.ArchList
):
231 SkippedArchList
= set(self
.ArchList
).symmetric_difference(set(self
.Platform
.SupArchList
))
232 EdkLogger
.verbose("\nArch [%s] is ignored because the platform supports [%s] only!"
233 % (" ".join(SkippedArchList
), " ".join(self
.Platform
.SupArchList
)))
234 self
.ArchList
= tuple(ArchList
)
236 # Validate build target
237 if self
.BuildTarget
not in self
.Platform
.BuildTargets
:
238 EdkLogger
.error("build", PARAMETER_INVALID
,
239 ExtraData
="Build target [%s] is not supported by the platform. [Valid target: %s]"
240 % (self
.BuildTarget
, " ".join(self
.Platform
.BuildTargets
)))
242 # parse FDF file to get PCDs in it, if any
244 self
.FdfFile
= self
.Platform
.FlashDefinition
248 EdkLogger
.info('%-16s = %s' % ("Architecture(s)", ' '.join(self
.ArchList
)))
249 EdkLogger
.info('%-16s = %s' % ("Build target", self
.BuildTarget
))
250 EdkLogger
.info('%-16s = %s' % ("Toolchain",self
.ToolChain
))
252 EdkLogger
.info('\n%-24s = %s' % ("Active Platform", self
.Platform
))
254 EdkLogger
.info('%-24s = %s' % ("Active Module", BuildModule
))
257 EdkLogger
.info('%-24s = %s' % ("Flash Image Definition", self
.FdfFile
))
259 EdkLogger
.verbose("\nFLASH_DEFINITION = %s" % self
.FdfFile
)
262 Progress
.Start("\nProcessing meta-data")
266 # Mark now build in AutoGen Phase
268 GlobalData
.gAutoGenPhase
= True
269 Fdf
= FdfParser(self
.FdfFile
.Path
)
271 GlobalData
.gAutoGenPhase
= False
272 PcdSet
= Fdf
.Profile
.PcdDict
273 ModuleList
= Fdf
.Profile
.InfList
274 self
.FdfProfile
= Fdf
.Profile
275 for fvname
in self
.FvTargetList
:
276 if fvname
.upper() not in self
.FdfProfile
.FvDict
:
277 EdkLogger
.error("build", OPTION_VALUE_INVALID
,
278 "No such an FV in FDF file: %s" % fvname
)
282 self
.FdfProfile
= None
283 if self
.FdTargetList
:
284 EdkLogger
.info("No flash definition file found. FD [%s] will be ignored." % " ".join(self
.FdTargetList
))
285 self
.FdTargetList
= []
286 if self
.FvTargetList
:
287 EdkLogger
.info("No flash definition file found. FV [%s] will be ignored." % " ".join(self
.FvTargetList
))
288 self
.FvTargetList
= []
289 if self
.CapTargetList
:
290 EdkLogger
.info("No flash definition file found. Capsule [%s] will be ignored." % " ".join(self
.CapTargetList
))
291 self
.CapTargetList
= []
293 # apply SKU and inject PCDs from Flash Definition file
294 for Arch
in self
.ArchList
:
295 Platform
= self
.BuildDatabase
[self
.MetaFile
, Arch
, Target
, Toolchain
]
299 PGen
= PlatformAutoGen(self
, self
.MetaFile
, Target
, Toolchain
, Arch
)
300 Pkgs
= PGen
.PackageList
303 DecPcds
[Pcd
[0], Pcd
[1]] = Pkg
.Pcds
[Pcd
]
304 DecPcdsKey
.add((Pcd
[0], Pcd
[1], Pcd
[2]))
306 Platform
.SkuName
= self
.SkuId
307 for Name
, Guid
in PcdSet
:
308 if (Name
, Guid
) not in DecPcds
:
312 "PCD (%s.%s) used in FDF is not declared in DEC files." % (Guid
, Name
),
313 File
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
][0],
314 Line
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
][1]
317 # Check whether Dynamic or DynamicEx PCD used in FDF file. If used, build break and give a error message.
318 if (Name
, Guid
, TAB_PCDS_FIXED_AT_BUILD
) in DecPcdsKey \
319 or (Name
, Guid
, TAB_PCDS_PATCHABLE_IN_MODULE
) in DecPcdsKey \
320 or (Name
, Guid
, TAB_PCDS_FEATURE_FLAG
) in DecPcdsKey
:
321 Platform
.AddPcd(Name
, Guid
, PcdSet
[Name
, Guid
])
323 elif (Name
, Guid
, TAB_PCDS_DYNAMIC
) in DecPcdsKey
or (Name
, Guid
, TAB_PCDS_DYNAMIC_EX
) in DecPcdsKey
:
327 "Using Dynamic or DynamicEx type of PCD [%s.%s] in FDF file is not allowed." % (Guid
, Name
),
328 File
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
][0],
329 Line
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
][1]
332 Pa
= PlatformAutoGen(self
, self
.MetaFile
, Target
, Toolchain
, Arch
)
334 # Explicitly collect platform's dynamic PCDs
336 Pa
.CollectPlatformDynamicPcds()
337 Pa
.CollectFixedAtBuildPcds()
338 self
.AutoGenObjectList
.append(Pa
)
341 # Check PCDs token value conflict in each DEC file.
343 self
._CheckAllPcdsTokenValueConflict
()
346 # Check PCD type and definition between DSC and DEC
348 self
._CheckPcdDefineAndType
()
351 self
._CheckDuplicateInFV
(Fdf
)
353 self
._BuildDir
= None
355 self
._MakeFileDir
= None
356 self
._BuildCommand
= None
360 ## _CheckDuplicateInFV() method
362 # Check whether there is duplicate modules/files exist in FV section.
363 # The check base on the file GUID;
365 def _CheckDuplicateInFV(self
, Fdf
):
366 for Fv
in Fdf
.Profile
.FvDict
:
368 for FfsFile
in Fdf
.Profile
.FvDict
[Fv
].FfsList
:
369 if FfsFile
.InfFileName
and FfsFile
.NameGuid
== None:
374 for Pa
in self
.AutoGenObjectList
:
377 for Module
in Pa
.ModuleAutoGenList
:
378 if path
.normpath(Module
.MetaFile
.File
) == path
.normpath(FfsFile
.InfFileName
):
380 if not Module
.Guid
.upper() in _GuidDict
.keys():
381 _GuidDict
[Module
.Guid
.upper()] = FfsFile
384 EdkLogger
.error("build",
386 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s"%(FfsFile
.CurrentLineNum
,
387 FfsFile
.CurrentLineContent
,
388 _GuidDict
[Module
.Guid
.upper()].CurrentLineNum
,
389 _GuidDict
[Module
.Guid
.upper()].CurrentLineContent
,
390 Module
.Guid
.upper()),
391 ExtraData
=self
.FdfFile
)
393 # Some INF files not have entity in DSC file.
396 if FfsFile
.InfFileName
.find('$') == -1:
397 InfPath
= NormPath(FfsFile
.InfFileName
)
398 if not os
.path
.exists(InfPath
):
399 EdkLogger
.error('build', GENFDS_ERROR
, "Non-existant Module %s !" % (FfsFile
.InfFileName
))
401 PathClassObj
= PathClass(FfsFile
.InfFileName
, self
.WorkspaceDir
)
403 # Here we just need to get FILE_GUID from INF file, use 'COMMON' as ARCH attribute. and use
404 # BuildObject from one of AutoGenObjectList is enough.
406 InfObj
= self
.AutoGenObjectList
[0].BuildDatabase
.WorkspaceDb
.BuildObject
[PathClassObj
, 'COMMON', self
.BuildTarget
, self
.ToolChain
]
407 if not InfObj
.Guid
.upper() in _GuidDict
.keys():
408 _GuidDict
[InfObj
.Guid
.upper()] = FfsFile
410 EdkLogger
.error("build",
412 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s"%(FfsFile
.CurrentLineNum
,
413 FfsFile
.CurrentLineContent
,
414 _GuidDict
[InfObj
.Guid
.upper()].CurrentLineNum
,
415 _GuidDict
[InfObj
.Guid
.upper()].CurrentLineContent
,
416 InfObj
.Guid
.upper()),
417 ExtraData
=self
.FdfFile
)
420 if FfsFile
.NameGuid
!= None:
421 _CheckPCDAsGuidPattern
= re
.compile("^PCD\(.+\..+\)$")
424 # If the NameGuid reference a PCD name.
425 # The style must match: PCD(xxxx.yyy)
427 if _CheckPCDAsGuidPattern
.match(FfsFile
.NameGuid
):
429 # Replace the PCD value.
431 _PcdName
= FfsFile
.NameGuid
.lstrip("PCD(").rstrip(")")
433 for Pa
in self
.AutoGenObjectList
:
435 for PcdItem
in Pa
.AllPcdList
:
436 if (PcdItem
.TokenSpaceGuidCName
+ "." + PcdItem
.TokenCName
) == _PcdName
:
438 # First convert from CFormatGuid to GUID string
440 _PcdGuidString
= GuidStructureStringToGuidString(PcdItem
.DefaultValue
)
442 if not _PcdGuidString
:
444 # Then try Byte array.
446 _PcdGuidString
= GuidStructureByteArrayToGuidString(PcdItem
.DefaultValue
)
448 if not _PcdGuidString
:
450 # Not Byte array or CFormat GUID, raise error.
452 EdkLogger
.error("build",
454 "The format of PCD value is incorrect. PCD: %s , Value: %s\n"%(_PcdName
, PcdItem
.DefaultValue
),
455 ExtraData
=self
.FdfFile
)
457 if not _PcdGuidString
.upper() in _GuidDict
.keys():
458 _GuidDict
[_PcdGuidString
.upper()] = FfsFile
462 EdkLogger
.error("build",
464 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s"%(FfsFile
.CurrentLineNum
,
465 FfsFile
.CurrentLineContent
,
466 _GuidDict
[_PcdGuidString
.upper()].CurrentLineNum
,
467 _GuidDict
[_PcdGuidString
.upper()].CurrentLineContent
,
468 FfsFile
.NameGuid
.upper()),
469 ExtraData
=self
.FdfFile
)
471 if not FfsFile
.NameGuid
.upper() in _GuidDict
.keys():
472 _GuidDict
[FfsFile
.NameGuid
.upper()] = FfsFile
475 # Two raw file GUID conflict.
477 EdkLogger
.error("build",
479 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s"%(FfsFile
.CurrentLineNum
,
480 FfsFile
.CurrentLineContent
,
481 _GuidDict
[FfsFile
.NameGuid
.upper()].CurrentLineNum
,
482 _GuidDict
[FfsFile
.NameGuid
.upper()].CurrentLineContent
,
483 FfsFile
.NameGuid
.upper()),
484 ExtraData
=self
.FdfFile
)
487 def _CheckPcdDefineAndType(self
):
489 "FixedAtBuild", "PatchableInModule", "FeatureFlag",
490 "Dynamic", #"DynamicHii", "DynamicVpd",
491 "DynamicEx", # "DynamicExHii", "DynamicExVpd"
494 # This dict store PCDs which are not used by any modules with specified arches
496 for Pa
in self
.AutoGenObjectList
:
497 # Key of DSC's Pcds dictionary is PcdCName, TokenSpaceGuid
498 for Pcd
in Pa
.Platform
.Pcds
:
499 PcdType
= Pa
.Platform
.Pcds
[Pcd
].Type
501 # If no PCD type, this PCD comes from FDF
505 # Try to remove Hii and Vpd suffix
506 if PcdType
.startswith("DynamicEx"):
507 PcdType
= "DynamicEx"
508 elif PcdType
.startswith("Dynamic"):
511 for Package
in Pa
.PackageList
:
512 # Key of DEC's Pcds dictionary is PcdCName, TokenSpaceGuid, PcdType
513 if (Pcd
[0], Pcd
[1], PcdType
) in Package
.Pcds
:
515 for Type
in PcdTypeList
:
516 if (Pcd
[0], Pcd
[1], Type
) in Package
.Pcds
:
520 "Type [%s] of PCD [%s.%s] in DSC file doesn't match the type [%s] defined in DEC file." \
521 % (Pa
.Platform
.Pcds
[Pcd
].Type
, Pcd
[1], Pcd
[0], Type
),
526 UnusedPcd
.setdefault(Pcd
, []).append(Pa
.Arch
)
528 for Pcd
in UnusedPcd
:
531 "The PCD was not specified by any INF module in the platform for the given architecture.\n"
532 "\tPCD: [%s.%s]\n\tPlatform: [%s]\n\tArch: %s"
533 % (Pcd
[1], Pcd
[0], os
.path
.basename(str(self
.MetaFile
)), str(UnusedPcd
[Pcd
])),
538 return "%s [%s]" % (self
.MetaFile
, ", ".join(self
.ArchList
))
540 ## Return the directory to store FV files
542 if self
._FvDir
== None:
543 self
._FvDir
= path
.join(self
.BuildDir
, 'FV')
546 ## Return the directory to store all intermediate and final files built
547 def _GetBuildDir(self
):
548 return self
.AutoGenObjectList
[0].BuildDir
550 ## Return the build output directory platform specifies
551 def _GetOutputDir(self
):
552 return self
.Platform
.OutputDirectory
554 ## Return platform name
556 return self
.Platform
.PlatformName
558 ## Return meta-file GUID
560 return self
.Platform
.Guid
562 ## Return platform version
563 def _GetVersion(self
):
564 return self
.Platform
.Version
566 ## Return paths of tools
567 def _GetToolDefinition(self
):
568 return self
.AutoGenObjectList
[0].ToolDefinition
570 ## Return directory of platform makefile
572 # @retval string Makefile directory
574 def _GetMakeFileDir(self
):
575 if self
._MakeFileDir
== None:
576 self
._MakeFileDir
= self
.BuildDir
577 return self
._MakeFileDir
579 ## Return build command string
581 # @retval string Build command string
583 def _GetBuildCommand(self
):
584 if self
._BuildCommand
== None:
585 # BuildCommand should be all the same. So just get one from platform AutoGen
586 self
._BuildCommand
= self
.AutoGenObjectList
[0].BuildCommand
587 return self
._BuildCommand
589 ## Check the PCDs token value conflict in each DEC file.
591 # Will cause build break and raise error message while two PCDs conflict.
595 def _CheckAllPcdsTokenValueConflict(self
):
596 for Pa
in self
.AutoGenObjectList
:
597 for Package
in Pa
.PackageList
:
598 PcdList
= Package
.Pcds
.values()
599 PcdList
.sort(lambda x
, y
: cmp(x
.TokenValue
, y
.TokenValue
))
601 while (Count
< len(PcdList
) - 1) :
602 Item
= PcdList
[Count
]
603 ItemNext
= PcdList
[Count
+ 1]
605 # Make sure in the same token space the TokenValue should be unique
607 if (Item
.TokenValue
== ItemNext
.TokenValue
):
608 SameTokenValuePcdList
= []
609 SameTokenValuePcdList
.append(Item
)
610 SameTokenValuePcdList
.append(ItemNext
)
611 RemainPcdListLength
= len(PcdList
) - Count
- 2
612 for ValueSameCount
in range(RemainPcdListLength
):
613 if PcdList
[len(PcdList
) - RemainPcdListLength
+ ValueSameCount
].TokenValue
== Item
.TokenValue
:
614 SameTokenValuePcdList
.append(PcdList
[len(PcdList
) - RemainPcdListLength
+ ValueSameCount
])
618 # Sort same token value PCD list with TokenGuid and TokenCName
620 SameTokenValuePcdList
.sort(lambda x
, y
: cmp("%s.%s"%(x
.TokenSpaceGuidCName
, x
.TokenCName
), "%s.%s"%(y
.TokenSpaceGuidCName
, y
.TokenCName
)))
621 SameTokenValuePcdListCount
= 0
622 while (SameTokenValuePcdListCount
< len(SameTokenValuePcdList
) - 1):
623 TemListItem
= SameTokenValuePcdList
[SameTokenValuePcdListCount
]
624 TemListItemNext
= SameTokenValuePcdList
[SameTokenValuePcdListCount
+ 1]
626 if (TemListItem
.TokenSpaceGuidCName
== TemListItemNext
.TokenSpaceGuidCName
) and (TemListItem
.TokenCName
!= TemListItemNext
.TokenCName
):
630 "The TokenValue [%s] of PCD [%s.%s] is conflict with: [%s.%s] in %s"\
631 % (TemListItem
.TokenValue
, TemListItem
.TokenSpaceGuidCName
, TemListItem
.TokenCName
, TemListItemNext
.TokenSpaceGuidCName
, TemListItemNext
.TokenCName
, Package
),
634 SameTokenValuePcdListCount
+= 1
635 Count
+= SameTokenValuePcdListCount
638 PcdList
= Package
.Pcds
.values()
639 PcdList
.sort(lambda x
, y
: cmp("%s.%s"%(x
.TokenSpaceGuidCName
, x
.TokenCName
), "%s.%s"%(y
.TokenSpaceGuidCName
, y
.TokenCName
)))
641 while (Count
< len(PcdList
) - 1) :
642 Item
= PcdList
[Count
]
643 ItemNext
= PcdList
[Count
+ 1]
645 # Check PCDs with same TokenSpaceGuidCName.TokenCName have same token value as well.
647 if (Item
.TokenSpaceGuidCName
== ItemNext
.TokenSpaceGuidCName
) and (Item
.TokenCName
== ItemNext
.TokenCName
) and (Item
.TokenValue
!= ItemNext
.TokenValue
):
651 "The TokenValue [%s] of PCD [%s.%s] in %s defined in two places should be same as well."\
652 % (Item
.TokenValue
, Item
.TokenSpaceGuidCName
, Item
.TokenCName
, Package
),
658 ## Create makefile for the platform and modules in it
660 # @param CreateDepsMakeFile Flag indicating if the makefile for
661 # modules will be created as well
663 def CreateMakeFile(self
, CreateDepsMakeFile
=False):
664 # create makefile for platform
665 Makefile
= GenMake
.TopLevelMakefile(self
)
666 if Makefile
.Generate():
667 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated makefile for platform [%s] %s\n" %
668 (self
.MetaFile
, self
.ArchList
))
670 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Skipped the generation of makefile for platform [%s] %s\n" %
671 (self
.MetaFile
, self
.ArchList
))
673 if CreateDepsMakeFile
:
674 for Pa
in self
.AutoGenObjectList
:
675 Pa
.CreateMakeFile(CreateDepsMakeFile
)
677 ## Create autogen code for platform and modules
679 # Since there's no autogen code for platform, this method will do nothing
680 # if CreateModuleCodeFile is set to False.
682 # @param CreateDepsCodeFile Flag indicating if creating module's
683 # autogen code file or not
685 def CreateCodeFile(self
, CreateDepsCodeFile
=False):
686 if not CreateDepsCodeFile
:
688 for Pa
in self
.AutoGenObjectList
:
689 Pa
.CreateCodeFile(CreateDepsCodeFile
)
691 ## Create AsBuilt INF file the platform
693 def CreateAsBuiltInf(self
):
696 Name
= property(_GetName
)
697 Guid
= property(_GetGuid
)
698 Version
= property(_GetVersion
)
699 OutputDir
= property(_GetOutputDir
)
701 ToolDefinition
= property(_GetToolDefinition
) # toolcode : tool path
703 BuildDir
= property(_GetBuildDir
)
704 FvDir
= property(_GetFvDir
)
705 MakeFileDir
= property(_GetMakeFileDir
)
706 BuildCommand
= property(_GetBuildCommand
)
708 ## AutoGen class for platform
710 # PlatformAutoGen class will process the original information in platform
711 # file in order to generate makefile for platform.
713 class PlatformAutoGen(AutoGen
):
715 # Used to store all PCDs for both PEI and DXE phase, in order to generate
716 # correct PCD database
719 _NonDynaPcdList_
= []
722 # The priority list while override build option
724 PrioList
= {"0x11111" : 16, # TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE (Highest)
725 "0x01111" : 15, # ******_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
726 "0x10111" : 14, # TARGET_*********_ARCH_COMMANDTYPE_ATTRIBUTE
727 "0x00111" : 13, # ******_*********_ARCH_COMMANDTYPE_ATTRIBUTE
728 "0x11011" : 12, # TARGET_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
729 "0x01011" : 11, # ******_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
730 "0x10011" : 10, # TARGET_*********_****_COMMANDTYPE_ATTRIBUTE
731 "0x00011" : 9, # ******_*********_****_COMMANDTYPE_ATTRIBUTE
732 "0x11101" : 8, # TARGET_TOOLCHAIN_ARCH_***********_ATTRIBUTE
733 "0x01101" : 7, # ******_TOOLCHAIN_ARCH_***********_ATTRIBUTE
734 "0x10101" : 6, # TARGET_*********_ARCH_***********_ATTRIBUTE
735 "0x00101" : 5, # ******_*********_ARCH_***********_ATTRIBUTE
736 "0x11001" : 4, # TARGET_TOOLCHAIN_****_***********_ATTRIBUTE
737 "0x01001" : 3, # ******_TOOLCHAIN_****_***********_ATTRIBUTE
738 "0x10001" : 2, # TARGET_*********_****_***********_ATTRIBUTE
739 "0x00001" : 1} # ******_*********_****_***********_ATTRIBUTE (Lowest)
741 ## The real constructor of PlatformAutoGen
743 # This method is not supposed to be called by users of PlatformAutoGen. It's
744 # only used by factory method __new__() to do real initialization work for an
745 # object of PlatformAutoGen
747 # @param Workspace WorkspaceAutoGen object
748 # @param PlatformFile Platform file (DSC file)
749 # @param Target Build target (DEBUG, RELEASE)
750 # @param Toolchain Name of tool chain
751 # @param Arch arch of the platform supports
753 def _Init(self
, Workspace
, PlatformFile
, Target
, Toolchain
, Arch
):
754 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "AutoGen platform [%s] [%s]" % (PlatformFile
, Arch
))
755 GlobalData
.gProcessingFile
= "%s [%s, %s, %s]" % (PlatformFile
, Arch
, Toolchain
, Target
)
757 self
.MetaFile
= PlatformFile
758 self
.Workspace
= Workspace
759 self
.WorkspaceDir
= Workspace
.WorkspaceDir
760 self
.ToolChain
= Toolchain
761 self
.BuildTarget
= Target
763 self
.SourceDir
= PlatformFile
.SubDir
764 self
.SourceOverrideDir
= None
765 self
.FdTargetList
= self
.Workspace
.FdTargetList
766 self
.FvTargetList
= self
.Workspace
.FvTargetList
769 # flag indicating if the makefile/C-code file has been created or not
770 self
.IsMakeFileCreated
= False
771 self
.IsCodeFileCreated
= False
773 self
._Platform
= None
778 self
._BuildRule
= None
779 self
._SourceDir
= None
780 self
._BuildDir
= None
781 self
._OutputDir
= None
783 self
._MakeFileDir
= None
786 self
._PcdTokenNumber
= None # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber
787 self
._DynamicPcdList
= None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
788 self
._NonDynamicPcdList
= None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
789 self
._NonDynamicPcdDict
= {}
791 self
._ToolDefinitions
= None
792 self
._ToolDefFile
= None # toolcode : tool path
793 self
._ToolChainFamily
= None
794 self
._BuildRuleFamily
= None
795 self
._BuildOption
= None # toolcode : option
796 self
._EdkBuildOption
= None # edktoolcode : option
797 self
._EdkIIBuildOption
= None # edkiitoolcode : option
798 self
._PackageList
= None
799 self
._ModuleAutoGenList
= None
800 self
._LibraryAutoGenList
= None
801 self
._BuildCommand
= None
803 # get the original module/package/platform objects
804 self
.BuildDatabase
= Workspace
.BuildDatabase
808 return "%s [%s]" % (self
.MetaFile
, self
.Arch
)
810 ## Create autogen code for platform and modules
812 # Since there's no autogen code for platform, this method will do nothing
813 # if CreateModuleCodeFile is set to False.
815 # @param CreateModuleCodeFile Flag indicating if creating module's
816 # autogen code file or not
818 def CreateCodeFile(self
, CreateModuleCodeFile
=False):
819 # only module has code to be greated, so do nothing if CreateModuleCodeFile is False
820 if self
.IsCodeFileCreated
or not CreateModuleCodeFile
:
823 for Ma
in self
.ModuleAutoGenList
:
824 Ma
.CreateCodeFile(True)
826 # don't do this twice
827 self
.IsCodeFileCreated
= True
829 ## Create makefile for the platform and mdoules in it
831 # @param CreateModuleMakeFile Flag indicating if the makefile for
832 # modules will be created as well
834 def CreateMakeFile(self
, CreateModuleMakeFile
=False):
835 if CreateModuleMakeFile
:
836 for ModuleFile
in self
.Platform
.Modules
:
837 Ma
= ModuleAutoGen(self
.Workspace
, ModuleFile
, self
.BuildTarget
,
838 self
.ToolChain
, self
.Arch
, self
.MetaFile
)
839 Ma
.CreateMakeFile(True)
840 Ma
.CreateAsBuiltInf()
842 # no need to create makefile for the platform more than once
843 if self
.IsMakeFileCreated
:
846 # create makefile for platform
847 Makefile
= GenMake
.PlatformMakefile(self
)
848 if Makefile
.Generate():
849 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated makefile for platform [%s] [%s]\n" %
850 (self
.MetaFile
, self
.Arch
))
852 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Skipped the generation of makefile for platform [%s] [%s]\n" %
853 (self
.MetaFile
, self
.Arch
))
854 self
.IsMakeFileCreated
= True
856 ## Deal with Shared FixedAtBuild Pcds
858 def CollectFixedAtBuildPcds(self
):
859 for LibAuto
in self
.LibraryAutoGenList
:
860 FixedAtBuildPcds
= {}
861 ShareFixedAtBuildPcdsSameValue
= {}
862 for Module
in LibAuto
._ReferenceModules
:
863 for Pcd
in Module
.FixedAtBuildPcds
+ LibAuto
.FixedAtBuildPcds
:
864 key
= ".".join((Pcd
.TokenSpaceGuidCName
,Pcd
.TokenCName
))
865 if key
not in FixedAtBuildPcds
:
866 ShareFixedAtBuildPcdsSameValue
[key
] = True
867 FixedAtBuildPcds
[key
] = Pcd
.DefaultValue
869 if FixedAtBuildPcds
[key
] != Pcd
.DefaultValue
:
870 ShareFixedAtBuildPcdsSameValue
[key
] = False
871 for Pcd
in LibAuto
.FixedAtBuildPcds
:
872 key
= ".".join((Pcd
.TokenSpaceGuidCName
,Pcd
.TokenCName
))
873 if (Pcd
.TokenCName
,Pcd
.TokenSpaceGuidCName
) not in self
.NonDynamicPcdDict
:
876 DscPcd
= self
.NonDynamicPcdDict
[(Pcd
.TokenCName
,Pcd
.TokenSpaceGuidCName
)]
877 if DscPcd
.Type
!= "FixedAtBuild":
879 if key
in ShareFixedAtBuildPcdsSameValue
and ShareFixedAtBuildPcdsSameValue
[key
]:
880 LibAuto
.ConstPcd
[key
] = Pcd
.DefaultValue
882 ## Collect dynamic PCDs
884 # Gather dynamic PCDs list from each module and their settings from platform
885 # This interface should be invoked explicitly when platform action is created.
887 def CollectPlatformDynamicPcds(self
):
888 # for gathering error information
889 NoDatumTypePcdList
= set()
892 for F
in self
.Platform
.Modules
.keys():
893 M
= ModuleAutoGen(self
.Workspace
, F
, self
.BuildTarget
, self
.ToolChain
, self
.Arch
, self
.MetaFile
)
894 #GuidValue.update(M.Guids)
896 self
.Platform
.Modules
[F
].M
= M
898 for PcdFromModule
in M
.ModulePcdList
+M
.LibraryPcdList
:
899 # make sure that the "VOID*" kind of datum has MaxDatumSize set
900 if PcdFromModule
.DatumType
== "VOID*" and PcdFromModule
.MaxDatumSize
in [None, '']:
901 NoDatumTypePcdList
.add("%s.%s [%s]" % (PcdFromModule
.TokenSpaceGuidCName
, PcdFromModule
.TokenCName
, F
))
903 if PcdFromModule
.Type
in GenC
.gDynamicPcd
or PcdFromModule
.Type
in GenC
.gDynamicExPcd
:
905 # If a dynamic PCD used by a PEM module/PEI module & DXE module,
906 # it should be stored in Pcd PEI database, If a dynamic only
907 # used by DXE module, it should be stored in DXE PCD database.
908 # The default Phase is DXE
910 if M
.ModuleType
in ["PEIM", "PEI_CORE"]:
911 PcdFromModule
.Phase
= "PEI"
912 if PcdFromModule
not in self
._DynaPcdList
_:
913 self
._DynaPcdList
_.append(PcdFromModule
)
914 elif PcdFromModule
.Phase
== 'PEI':
915 # overwrite any the same PCD existing, if Phase is PEI
916 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
917 self
._DynaPcdList
_[Index
] = PcdFromModule
918 elif PcdFromModule
not in self
._NonDynaPcdList
_:
919 self
._NonDynaPcdList
_.append(PcdFromModule
)
921 # print out error information and break the build, if error found
922 if len(NoDatumTypePcdList
) > 0:
923 NoDatumTypePcdListString
= "\n\t\t".join(NoDatumTypePcdList
)
924 EdkLogger
.error("build", AUTOGEN_ERROR
, "PCD setting error",
926 ExtraData
="\n\tPCD(s) without MaxDatumSize:\n\t\t%s\n"
927 % NoDatumTypePcdListString
)
928 self
._NonDynamicPcdList
= self
._NonDynaPcdList
_
929 self
._DynamicPcdList
= self
._DynaPcdList
_
930 self
.AllPcdList
= self
._NonDynamicPcdList
+ self
._DynamicPcdList
933 # Sort dynamic PCD list to:
934 # 1) If PCD's datum type is VOID* and value is unicode string which starts with L, the PCD item should
935 # try to be put header of dynamicd List
936 # 2) If PCD is HII type, the PCD item should be put after unicode type PCD
938 # The reason of sorting is make sure the unicode string is in double-byte alignment in string table.
944 VpdFile
= VpdInfoFile
.VpdInfoFile()
945 NeedProcessVpdMapFile
= False
947 if (self
.Workspace
.ArchList
[-1] == self
.Arch
):
948 for Pcd
in self
._DynamicPcdList
:
949 # just pick the a value to determine whether is unicode string type
950 Sku
= Pcd
.SkuInfoList
[Pcd
.SkuInfoList
.keys()[0]]
951 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
953 PcdValue
= Sku
.DefaultValue
954 if Pcd
.DatumType
== 'VOID*' and PcdValue
.startswith("L"):
955 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
956 UnicodePcdArray
.append(Pcd
)
957 elif len(Sku
.VariableName
) > 0:
958 # if found HII type PCD then insert to right of UnicodeIndex
959 HiiPcdArray
.append(Pcd
)
961 OtherPcdArray
.append(Pcd
)
962 if Pcd
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
]:
963 VpdPcdDict
[(Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
)] = Pcd
965 PlatformPcds
= self
.Platform
.Pcds
.keys()
968 # Add VPD type PCD into VpdFile and determine whether the VPD PCD need to be fixed up.
970 for PcdKey
in PlatformPcds
:
971 Pcd
= self
.Platform
.Pcds
[PcdKey
]
972 if Pcd
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
] and \
973 PcdKey
in VpdPcdDict
:
974 Pcd
= VpdPcdDict
[PcdKey
]
975 for (SkuName
,Sku
) in Pcd
.SkuInfoList
.items():
976 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
977 VpdFile
.Add(Pcd
, Sku
.VpdOffset
)
978 # if the offset of a VPD is *, then it need to be fixed up by third party tool.
979 if not NeedProcessVpdMapFile
and Sku
.VpdOffset
== "*":
980 NeedProcessVpdMapFile
= True
981 if self
.Platform
.VpdToolGuid
== None or self
.Platform
.VpdToolGuid
== '':
982 EdkLogger
.error("Build", FILE_NOT_FOUND
, \
983 "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.")
987 # Fix the PCDs define in VPD PCD section that never referenced by module.
988 # An example is PCD for signature usage.
990 for DscPcd
in PlatformPcds
:
991 DscPcdEntry
= self
.Platform
.Pcds
[DscPcd
]
992 if DscPcdEntry
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
]:
993 if not (self
.Platform
.VpdToolGuid
== None or self
.Platform
.VpdToolGuid
== ''):
995 for VpdPcd
in VpdFile
._VpdArray
.keys():
996 # This PCD has been referenced by module
997 if (VpdPcd
.TokenSpaceGuidCName
== DscPcdEntry
.TokenSpaceGuidCName
) and \
998 (VpdPcd
.TokenCName
== DscPcdEntry
.TokenCName
):
1001 # Not found, it should be signature
1003 # just pick the a value to determine whether is unicode string type
1004 for (SkuName
,Sku
) in DscPcdEntry
.SkuInfoList
.items():
1005 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1007 # Need to iterate DEC pcd information to get the value & datumtype
1008 for eachDec
in self
.PackageList
:
1009 for DecPcd
in eachDec
.Pcds
:
1010 DecPcdEntry
= eachDec
.Pcds
[DecPcd
]
1011 if (DecPcdEntry
.TokenSpaceGuidCName
== DscPcdEntry
.TokenSpaceGuidCName
) and \
1012 (DecPcdEntry
.TokenCName
== DscPcdEntry
.TokenCName
):
1013 # Print warning message to let the developer make a determine.
1014 EdkLogger
.warn("build", "Unreferenced vpd pcd used!",
1015 File
=self
.MetaFile
, \
1016 ExtraData
= "PCD: %s.%s used in the DSC file %s is unreferenced." \
1017 %(DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
, self
.Platform
.MetaFile
.Path
))
1019 DscPcdEntry
.DatumType
= DecPcdEntry
.DatumType
1020 DscPcdEntry
.DefaultValue
= DecPcdEntry
.DefaultValue
1021 DscPcdEntry
.TokenValue
= DecPcdEntry
.TokenValue
1022 DscPcdEntry
.TokenSpaceGuidValue
= eachDec
.Guids
[DecPcdEntry
.TokenSpaceGuidCName
]
1023 # Only fix the value while no value provided in DSC file.
1024 if (Sku
.DefaultValue
== "" or Sku
.DefaultValue
==None):
1025 DscPcdEntry
.SkuInfoList
[DscPcdEntry
.SkuInfoList
.keys()[0]].DefaultValue
= DecPcdEntry
.DefaultValue
1027 if DscPcdEntry
not in self
._DynamicPcdList
:
1028 self
._DynamicPcdList
.append(DscPcdEntry
)
1029 # Sku = DscPcdEntry.SkuInfoList[DscPcdEntry.SkuInfoList.keys()[0]]
1030 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1031 PcdValue
= Sku
.DefaultValue
1032 VpdFile
.Add(DscPcdEntry
, Sku
.VpdOffset
)
1033 if not NeedProcessVpdMapFile
and Sku
.VpdOffset
== "*":
1034 NeedProcessVpdMapFile
= True
1035 if DscPcdEntry
.DatumType
== 'VOID*' and PcdValue
.startswith("L"):
1036 UnicodePcdArray
.append(DscPcdEntry
)
1037 elif len(Sku
.VariableName
) > 0:
1038 HiiPcdArray
.append(DscPcdEntry
)
1040 OtherPcdArray
.append(DscPcdEntry
)
1042 # if the offset of a VPD is *, then it need to be fixed up by third party tool.
1046 if (self
.Platform
.FlashDefinition
== None or self
.Platform
.FlashDefinition
== '') and \
1047 VpdFile
.GetCount() != 0:
1048 EdkLogger
.error("build", ATTRIBUTE_NOT_AVAILABLE
,
1049 "Fail to get FLASH_DEFINITION definition in DSC file %s which is required when DSC contains VPD PCD." % str(self
.Platform
.MetaFile
))
1051 if VpdFile
.GetCount() != 0:
1052 DscTimeStamp
= self
.Platform
.MetaFile
.TimeStamp
1053 FvPath
= os
.path
.join(self
.BuildDir
, "FV")
1054 if not os
.path
.exists(FvPath
):
1058 EdkLogger
.error("build", FILE_WRITE_FAILURE
, "Fail to create FV folder under %s" % self
.BuildDir
)
1061 VpdFilePath
= os
.path
.join(FvPath
, "%s.txt" % self
.Platform
.VpdToolGuid
)
1064 if not os
.path
.exists(VpdFilePath
) or os
.path
.getmtime(VpdFilePath
) < DscTimeStamp
:
1065 VpdFile
.Write(VpdFilePath
)
1067 # retrieve BPDG tool's path from tool_def.txt according to VPD_TOOL_GUID defined in DSC file.
1069 for ToolDef
in self
.ToolDefinition
.values():
1070 if ToolDef
.has_key("GUID") and ToolDef
["GUID"] == self
.Platform
.VpdToolGuid
:
1071 if not ToolDef
.has_key("PATH"):
1072 EdkLogger
.error("build", ATTRIBUTE_NOT_AVAILABLE
, "PATH attribute was not provided for BPDG guid tool %s in tools_def.txt" % self
.Platform
.VpdToolGuid
)
1073 BPDGToolName
= ToolDef
["PATH"]
1075 # Call third party GUID BPDG tool.
1076 if BPDGToolName
!= None:
1077 VpdInfoFile
.CallExtenalBPDGTool(BPDGToolName
, VpdFilePath
)
1079 EdkLogger
.error("Build", FILE_NOT_FOUND
, "Fail to find third-party BPDG tool to process VPD PCDs. BPDG Guid tool need to be defined in tools_def.txt and VPD_TOOL_GUID need to be provided in DSC file.")
1081 # Process VPD map file generated by third party BPDG tool
1082 if NeedProcessVpdMapFile
:
1083 VpdMapFilePath
= os
.path
.join(self
.BuildDir
, "FV", "%s.map" % self
.Platform
.VpdToolGuid
)
1084 if os
.path
.exists(VpdMapFilePath
):
1085 VpdFile
.Read(VpdMapFilePath
)
1088 for Pcd
in self
._DynamicPcdList
:
1089 # just pick the a value to determine whether is unicode string type
1091 for (SkuName
,Sku
) in Pcd
.SkuInfoList
.items():
1092 if Sku
.VpdOffset
== "*":
1093 Sku
.VpdOffset
= VpdFile
.GetOffset(Pcd
)[i
].strip()
1096 EdkLogger
.error("build", FILE_READ_FAILURE
, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath
)
1098 # Delete the DynamicPcdList At the last time enter into this function
1099 del self
._DynamicPcdList
[:]
1100 self
._DynamicPcdList
.extend(UnicodePcdArray
)
1101 self
._DynamicPcdList
.extend(HiiPcdArray
)
1102 self
._DynamicPcdList
.extend(OtherPcdArray
)
1105 ## Return the platform build data object
1106 def _GetPlatform(self
):
1107 if self
._Platform
== None:
1108 self
._Platform
= self
.BuildDatabase
[self
.MetaFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1109 return self
._Platform
1111 ## Return platform name
1113 return self
.Platform
.PlatformName
1115 ## Return the meta file GUID
1117 return self
.Platform
.Guid
1119 ## Return the platform version
1120 def _GetVersion(self
):
1121 return self
.Platform
.Version
1123 ## Return the FDF file name
1124 def _GetFdfFile(self
):
1125 if self
._FdfFile
== None:
1126 if self
.Workspace
.FdfFile
!= "":
1127 self
._FdfFile
= path
.join(self
.WorkspaceDir
, self
.Workspace
.FdfFile
)
1130 return self
._FdfFile
1132 ## Return the build output directory platform specifies
1133 def _GetOutputDir(self
):
1134 return self
.Platform
.OutputDirectory
1136 ## Return the directory to store all intermediate and final files built
1137 def _GetBuildDir(self
):
1138 if self
._BuildDir
== None:
1139 if os
.path
.isabs(self
.OutputDir
):
1140 self
._BuildDir
= path
.join(
1141 path
.abspath(self
.OutputDir
),
1142 self
.BuildTarget
+ "_" + self
.ToolChain
,
1145 self
._BuildDir
= path
.join(
1148 self
.BuildTarget
+ "_" + self
.ToolChain
,
1150 return self
._BuildDir
1152 ## Return directory of platform makefile
1154 # @retval string Makefile directory
1156 def _GetMakeFileDir(self
):
1157 if self
._MakeFileDir
== None:
1158 self
._MakeFileDir
= path
.join(self
.BuildDir
, self
.Arch
)
1159 return self
._MakeFileDir
1161 ## Return build command string
1163 # @retval string Build command string
1165 def _GetBuildCommand(self
):
1166 if self
._BuildCommand
== None:
1167 self
._BuildCommand
= []
1168 if "MAKE" in self
.ToolDefinition
and "PATH" in self
.ToolDefinition
["MAKE"]:
1169 self
._BuildCommand
+= SplitOption(self
.ToolDefinition
["MAKE"]["PATH"])
1170 if "FLAGS" in self
.ToolDefinition
["MAKE"]:
1171 NewOption
= self
.ToolDefinition
["MAKE"]["FLAGS"].strip()
1173 self
._BuildCommand
+= SplitOption(NewOption
)
1174 return self
._BuildCommand
1176 ## Get tool chain definition
1178 # Get each tool defition for given tool chain from tools_def.txt and platform
1180 def _GetToolDefinition(self
):
1181 if self
._ToolDefinitions
== None:
1182 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDictionary
1183 if TAB_TOD_DEFINES_COMMAND_TYPE
not in self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
:
1184 EdkLogger
.error('build', RESOURCE_NOT_AVAILABLE
, "No tools found in configuration",
1185 ExtraData
="[%s]" % self
.MetaFile
)
1186 self
._ToolDefinitions
= {}
1188 for Def
in ToolDefinition
:
1189 Target
, Tag
, Arch
, Tool
, Attr
= Def
.split("_")
1190 if Target
!= self
.BuildTarget
or Tag
!= self
.ToolChain
or Arch
!= self
.Arch
:
1193 Value
= ToolDefinition
[Def
]
1194 # don't record the DLL
1196 DllPathList
.add(Value
)
1199 if Tool
not in self
._ToolDefinitions
:
1200 self
._ToolDefinitions
[Tool
] = {}
1201 self
._ToolDefinitions
[Tool
][Attr
] = Value
1205 if GlobalData
.gOptions
.SilentMode
and "MAKE" in self
._ToolDefinitions
:
1206 if "FLAGS" not in self
._ToolDefinitions
["MAKE"]:
1207 self
._ToolDefinitions
["MAKE"]["FLAGS"] = ""
1208 self
._ToolDefinitions
["MAKE"]["FLAGS"] += " -s"
1210 for Tool
in self
._ToolDefinitions
:
1211 for Attr
in self
._ToolDefinitions
[Tool
]:
1212 Value
= self
._ToolDefinitions
[Tool
][Attr
]
1213 if Tool
in self
.BuildOption
and Attr
in self
.BuildOption
[Tool
]:
1214 # check if override is indicated
1215 if self
.BuildOption
[Tool
][Attr
].startswith('='):
1216 Value
= self
.BuildOption
[Tool
][Attr
][1:]
1218 Value
+= " " + self
.BuildOption
[Tool
][Attr
]
1221 # Don't put MAKE definition in the file
1225 ToolsDef
+= "%s = %s\n" % (Tool
, Value
)
1227 # Don't put MAKE definition in the file
1232 ToolsDef
+= "%s_%s = %s\n" % (Tool
, Attr
, Value
)
1235 SaveFileOnChange(self
.ToolDefinitionFile
, ToolsDef
)
1236 for DllPath
in DllPathList
:
1237 os
.environ
["PATH"] = DllPath
+ os
.pathsep
+ os
.environ
["PATH"]
1238 os
.environ
["MAKE_FLAGS"] = MakeFlags
1240 return self
._ToolDefinitions
1242 ## Return the paths of tools
1243 def _GetToolDefFile(self
):
1244 if self
._ToolDefFile
== None:
1245 self
._ToolDefFile
= os
.path
.join(self
.MakeFileDir
, "TOOLS_DEF." + self
.Arch
)
1246 return self
._ToolDefFile
1248 ## Retrieve the toolchain family of given toolchain tag. Default to 'MSFT'.
1249 def _GetToolChainFamily(self
):
1250 if self
._ToolChainFamily
== None:
1251 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
1252 if TAB_TOD_DEFINES_FAMILY
not in ToolDefinition \
1253 or self
.ToolChain
not in ToolDefinition
[TAB_TOD_DEFINES_FAMILY
] \
1254 or not ToolDefinition
[TAB_TOD_DEFINES_FAMILY
][self
.ToolChain
]:
1255 EdkLogger
.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
1257 self
._ToolChainFamily
= "MSFT"
1259 self
._ToolChainFamily
= ToolDefinition
[TAB_TOD_DEFINES_FAMILY
][self
.ToolChain
]
1260 return self
._ToolChainFamily
1262 def _GetBuildRuleFamily(self
):
1263 if self
._BuildRuleFamily
== None:
1264 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
1265 if TAB_TOD_DEFINES_BUILDRULEFAMILY
not in ToolDefinition \
1266 or self
.ToolChain
not in ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
] \
1267 or not ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
][self
.ToolChain
]:
1268 EdkLogger
.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
1270 self
._BuildRuleFamily
= "MSFT"
1272 self
._BuildRuleFamily
= ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
][self
.ToolChain
]
1273 return self
._BuildRuleFamily
1275 ## Return the build options specific for all modules in this platform
1276 def _GetBuildOptions(self
):
1277 if self
._BuildOption
== None:
1278 self
._BuildOption
= self
._ExpandBuildOption
(self
.Platform
.BuildOptions
)
1279 return self
._BuildOption
1281 ## Return the build options specific for EDK modules in this platform
1282 def _GetEdkBuildOptions(self
):
1283 if self
._EdkBuildOption
== None:
1284 self
._EdkBuildOption
= self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, EDK_NAME
)
1285 return self
._EdkBuildOption
1287 ## Return the build options specific for EDKII modules in this platform
1288 def _GetEdkIIBuildOptions(self
):
1289 if self
._EdkIIBuildOption
== None:
1290 self
._EdkIIBuildOption
= self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, EDKII_NAME
)
1291 return self
._EdkIIBuildOption
1293 ## Parse build_rule.txt in $(WORKSPACE)/Conf/build_rule.txt
1295 # @retval BuildRule object
1297 def _GetBuildRule(self
):
1298 if self
._BuildRule
== None:
1299 BuildRuleFile
= None
1300 if TAB_TAT_DEFINES_BUILD_RULE_CONF
in self
.Workspace
.TargetTxt
.TargetTxtDictionary
:
1301 BuildRuleFile
= self
.Workspace
.TargetTxt
.TargetTxtDictionary
[TAB_TAT_DEFINES_BUILD_RULE_CONF
]
1302 if BuildRuleFile
in [None, '']:
1303 BuildRuleFile
= gBuildRuleFile
1304 self
._BuildRule
= BuildRule(BuildRuleFile
)
1305 if self
._BuildRule
._FileVersion
== "":
1306 self
._BuildRule
._FileVersion
= AutoGenReqBuildRuleVerNum
1308 if self
._BuildRule
._FileVersion
< AutoGenReqBuildRuleVerNum
:
1309 # If Build Rule's version is less than the version number required by the tools, halting the build.
1310 EdkLogger
.error("build", AUTOGEN_ERROR
,
1311 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])"\
1312 % (self
._BuildRule
._FileVersion
, AutoGenReqBuildRuleVerNum
))
1314 return self
._BuildRule
1316 ## Summarize the packages used by modules in this platform
1317 def _GetPackageList(self
):
1318 if self
._PackageList
== None:
1319 self
._PackageList
= set()
1320 for La
in self
.LibraryAutoGenList
:
1321 self
._PackageList
.update(La
.DependentPackageList
)
1322 for Ma
in self
.ModuleAutoGenList
:
1323 self
._PackageList
.update(Ma
.DependentPackageList
)
1324 self
._PackageList
= list(self
._PackageList
)
1325 return self
._PackageList
1327 def _GetNonDynamicPcdDict(self
):
1328 if self
._NonDynamicPcdDict
:
1329 return self
._NonDynamicPcdDict
1330 for Pcd
in self
.NonDynamicPcdList
:
1331 self
._NonDynamicPcdDict
[(Pcd
.TokenCName
,Pcd
.TokenSpaceGuidCName
)] = Pcd
1332 return self
._NonDynamicPcdDict
1334 ## Get list of non-dynamic PCDs
1335 def _GetNonDynamicPcdList(self
):
1336 if self
._NonDynamicPcdList
== None:
1337 self
.CollectPlatformDynamicPcds()
1338 return self
._NonDynamicPcdList
1340 ## Get list of dynamic PCDs
1341 def _GetDynamicPcdList(self
):
1342 if self
._DynamicPcdList
== None:
1343 self
.CollectPlatformDynamicPcds()
1344 return self
._DynamicPcdList
1346 ## Generate Token Number for all PCD
1347 def _GetPcdTokenNumbers(self
):
1348 if self
._PcdTokenNumber
== None:
1349 self
._PcdTokenNumber
= sdict()
1352 # Make the Dynamic and DynamicEx PCD use within different TokenNumber area.
1356 # TokenNumber 0 ~ 10
1358 # TokeNumber 11 ~ 20
1360 for Pcd
in self
.DynamicPcdList
:
1361 if Pcd
.Phase
== "PEI":
1362 if Pcd
.Type
in ["Dynamic", "DynamicDefault", "DynamicVpd", "DynamicHii"]:
1363 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
1364 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
1367 for Pcd
in self
.DynamicPcdList
:
1368 if Pcd
.Phase
== "PEI":
1369 if Pcd
.Type
in ["DynamicEx", "DynamicExDefault", "DynamicExVpd", "DynamicExHii"]:
1370 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
1371 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
1374 for Pcd
in self
.DynamicPcdList
:
1375 if Pcd
.Phase
== "DXE":
1376 if Pcd
.Type
in ["Dynamic", "DynamicDefault", "DynamicVpd", "DynamicHii"]:
1377 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
1378 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
1381 for Pcd
in self
.DynamicPcdList
:
1382 if Pcd
.Phase
== "DXE":
1383 if Pcd
.Type
in ["DynamicEx", "DynamicExDefault", "DynamicExVpd", "DynamicExHii"]:
1384 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
1385 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
1388 for Pcd
in self
.NonDynamicPcdList
:
1389 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
1391 return self
._PcdTokenNumber
1393 ## Summarize ModuleAutoGen objects of all modules/libraries to be built for this platform
1394 def _GetAutoGenObjectList(self
):
1395 self
._ModuleAutoGenList
= []
1396 self
._LibraryAutoGenList
= []
1397 for ModuleFile
in self
.Platform
.Modules
:
1406 if Ma
not in self
._ModuleAutoGenList
:
1407 self
._ModuleAutoGenList
.append(Ma
)
1408 for La
in Ma
.LibraryAutoGenList
:
1409 if La
not in self
._LibraryAutoGenList
:
1410 self
._LibraryAutoGenList
.append(La
)
1411 if Ma
not in La
._ReferenceModules
:
1412 La
._ReferenceModules
.append(Ma
)
1414 ## Summarize ModuleAutoGen objects of all modules to be built for this platform
1415 def _GetModuleAutoGenList(self
):
1416 if self
._ModuleAutoGenList
== None:
1417 self
._GetAutoGenObjectList
()
1418 return self
._ModuleAutoGenList
1420 ## Summarize ModuleAutoGen objects of all libraries to be built for this platform
1421 def _GetLibraryAutoGenList(self
):
1422 if self
._LibraryAutoGenList
== None:
1423 self
._GetAutoGenObjectList
()
1424 return self
._LibraryAutoGenList
1426 ## Test if a module is supported by the platform
1428 # An error will be raised directly if the module or its arch is not supported
1429 # by the platform or current configuration
1431 def ValidModule(self
, Module
):
1432 return Module
in self
.Platform
.Modules
or Module
in self
.Platform
.LibraryInstances
1434 ## Resolve the library classes in a module to library instances
1436 # This method will not only resolve library classes but also sort the library
1437 # instances according to the dependency-ship.
1439 # @param Module The module from which the library classes will be resolved
1441 # @retval library_list List of library instances sorted
1443 def ApplyLibraryInstance(self
, Module
):
1444 ModuleType
= Module
.ModuleType
1446 # for overridding library instances with module specific setting
1447 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
1449 # add forced library instances (specified under LibraryClasses sections)
1451 # If a module has a MODULE_TYPE of USER_DEFINED,
1452 # do not link in NULL library class instances from the global [LibraryClasses.*] sections.
1454 if Module
.ModuleType
!= SUP_MODULE_USER_DEFINED
:
1455 for LibraryClass
in self
.Platform
.LibraryClasses
.GetKeys():
1456 if LibraryClass
.startswith("NULL") and self
.Platform
.LibraryClasses
[LibraryClass
, Module
.ModuleType
]:
1457 Module
.LibraryClasses
[LibraryClass
] = self
.Platform
.LibraryClasses
[LibraryClass
, Module
.ModuleType
]
1459 # add forced library instances (specified in module overrides)
1460 for LibraryClass
in PlatformModule
.LibraryClasses
:
1461 if LibraryClass
.startswith("NULL"):
1462 Module
.LibraryClasses
[LibraryClass
] = PlatformModule
.LibraryClasses
[LibraryClass
]
1465 LibraryConsumerList
= [Module
]
1467 ConsumedByList
= sdict()
1468 LibraryInstance
= sdict()
1470 EdkLogger
.verbose("")
1471 EdkLogger
.verbose("Library instances of module [%s] [%s]:" % (str(Module
), self
.Arch
))
1472 while len(LibraryConsumerList
) > 0:
1473 M
= LibraryConsumerList
.pop()
1474 for LibraryClassName
in M
.LibraryClasses
:
1475 if LibraryClassName
not in LibraryInstance
:
1476 # override library instance for this module
1477 if LibraryClassName
in PlatformModule
.LibraryClasses
:
1478 LibraryPath
= PlatformModule
.LibraryClasses
[LibraryClassName
]
1480 LibraryPath
= self
.Platform
.LibraryClasses
[LibraryClassName
, ModuleType
]
1481 if LibraryPath
== None or LibraryPath
== "":
1482 LibraryPath
= M
.LibraryClasses
[LibraryClassName
]
1483 if LibraryPath
== None or LibraryPath
== "":
1484 EdkLogger
.error("build", RESOURCE_NOT_AVAILABLE
,
1485 "Instance of library class [%s] is not found" % LibraryClassName
,
1487 ExtraData
="in [%s] [%s]\n\tconsumed by module [%s]" % (str(M
), self
.Arch
, str(Module
)))
1489 LibraryModule
= self
.BuildDatabase
[LibraryPath
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1490 # for those forced library instance (NULL library), add a fake library class
1491 if LibraryClassName
.startswith("NULL"):
1492 LibraryModule
.LibraryClass
.append(LibraryClassObject(LibraryClassName
, [ModuleType
]))
1493 elif LibraryModule
.LibraryClass
== None \
1494 or len(LibraryModule
.LibraryClass
) == 0 \
1495 or (ModuleType
!= 'USER_DEFINED'
1496 and ModuleType
not in LibraryModule
.LibraryClass
[0].SupModList
):
1497 # only USER_DEFINED can link against any library instance despite of its SupModList
1498 EdkLogger
.error("build", OPTION_MISSING
,
1499 "Module type [%s] is not supported by library instance [%s]" \
1500 % (ModuleType
, LibraryPath
), File
=self
.MetaFile
,
1501 ExtraData
="consumed by [%s]" % str(Module
))
1503 LibraryInstance
[LibraryClassName
] = LibraryModule
1504 LibraryConsumerList
.append(LibraryModule
)
1505 EdkLogger
.verbose("\t" + str(LibraryClassName
) + " : " + str(LibraryModule
))
1507 LibraryModule
= LibraryInstance
[LibraryClassName
]
1509 if LibraryModule
== None:
1512 if LibraryModule
.ConstructorList
!= [] and LibraryModule
not in Constructor
:
1513 Constructor
.append(LibraryModule
)
1515 if LibraryModule
not in ConsumedByList
:
1516 ConsumedByList
[LibraryModule
] = []
1517 # don't add current module itself to consumer list
1519 if M
in ConsumedByList
[LibraryModule
]:
1521 ConsumedByList
[LibraryModule
].append(M
)
1523 # Initialize the sorted output list to the empty set
1525 SortedLibraryList
= []
1527 # Q <- Set of all nodes with no incoming edges
1529 LibraryList
= [] #LibraryInstance.values()
1531 for LibraryClassName
in LibraryInstance
:
1532 M
= LibraryInstance
[LibraryClassName
]
1533 LibraryList
.append(M
)
1534 if ConsumedByList
[M
] == []:
1538 # start the DAG algorithm
1542 while Q
== [] and EdgeRemoved
:
1544 # for each node Item with a Constructor
1545 for Item
in LibraryList
:
1546 if Item
not in Constructor
:
1548 # for each Node without a constructor with an edge e from Item to Node
1549 for Node
in ConsumedByList
[Item
]:
1550 if Node
in Constructor
:
1552 # remove edge e from the graph if Node has no constructor
1553 ConsumedByList
[Item
].remove(Node
)
1555 if ConsumedByList
[Item
] == []:
1556 # insert Item into Q
1561 # DAG is done if there's no more incoming edge for all nodes
1565 # remove node from Q
1568 SortedLibraryList
.append(Node
)
1570 # for each node Item with an edge e from Node to Item do
1571 for Item
in LibraryList
:
1572 if Node
not in ConsumedByList
[Item
]:
1574 # remove edge e from the graph
1575 ConsumedByList
[Item
].remove(Node
)
1577 if ConsumedByList
[Item
] != []:
1579 # insert Item into Q, if Item has no other incoming edges
1583 # if any remaining node Item in the graph has a constructor and an incoming edge, then the graph has a cycle
1585 for Item
in LibraryList
:
1586 if ConsumedByList
[Item
] != [] and Item
in Constructor
and len(Constructor
) > 1:
1587 ErrorMessage
= "\tconsumed by " + "\n\tconsumed by ".join([str(L
) for L
in ConsumedByList
[Item
]])
1588 EdkLogger
.error("build", BUILD_ERROR
, 'Library [%s] with constructors has a cycle' % str(Item
),
1589 ExtraData
=ErrorMessage
, File
=self
.MetaFile
)
1590 if Item
not in SortedLibraryList
:
1591 SortedLibraryList
.append(Item
)
1594 # Build the list of constructor and destructir names
1595 # The DAG Topo sort produces the destructor order, so the list of constructors must generated in the reverse order
1597 SortedLibraryList
.reverse()
1598 return SortedLibraryList
1601 ## Override PCD setting (type, value, ...)
1603 # @param ToPcd The PCD to be overrided
1604 # @param FromPcd The PCD overrideing from
1606 def _OverridePcd(self
, ToPcd
, FromPcd
, Module
=""):
1608 # in case there's PCDs coming from FDF file, which have no type given.
1609 # at this point, ToPcd.Type has the type found from dependent
1613 if ToPcd
.Pending
and FromPcd
.Type
not in [None, '']:
1614 ToPcd
.Type
= FromPcd
.Type
1615 elif (ToPcd
.Type
not in [None, '']) and (FromPcd
.Type
not in [None, ''])\
1616 and (ToPcd
.Type
!= FromPcd
.Type
) and (ToPcd
.Type
in FromPcd
.Type
):
1617 if ToPcd
.Type
.strip() == "DynamicEx":
1618 ToPcd
.Type
= FromPcd
.Type
1619 elif ToPcd
.Type
not in [None, ''] and FromPcd
.Type
not in [None, ''] \
1620 and ToPcd
.Type
!= FromPcd
.Type
:
1621 EdkLogger
.error("build", OPTION_CONFLICT
, "Mismatched PCD type",
1622 ExtraData
="%s.%s is defined as [%s] in module %s, but as [%s] in platform."\
1623 % (ToPcd
.TokenSpaceGuidCName
, ToPcd
.TokenCName
,
1624 ToPcd
.Type
, Module
, FromPcd
.Type
),
1627 if FromPcd
.MaxDatumSize
not in [None, '']:
1628 ToPcd
.MaxDatumSize
= FromPcd
.MaxDatumSize
1629 if FromPcd
.DefaultValue
not in [None, '']:
1630 ToPcd
.DefaultValue
= FromPcd
.DefaultValue
1631 if FromPcd
.TokenValue
not in [None, '']:
1632 ToPcd
.TokenValue
= FromPcd
.TokenValue
1633 if FromPcd
.MaxDatumSize
not in [None, '']:
1634 ToPcd
.MaxDatumSize
= FromPcd
.MaxDatumSize
1635 if FromPcd
.DatumType
not in [None, '']:
1636 ToPcd
.DatumType
= FromPcd
.DatumType
1637 if FromPcd
.SkuInfoList
not in [None, '', []]:
1638 ToPcd
.SkuInfoList
= FromPcd
.SkuInfoList
1640 # check the validation of datum
1641 IsValid
, Cause
= CheckPcdDatum(ToPcd
.DatumType
, ToPcd
.DefaultValue
)
1643 EdkLogger
.error('build', FORMAT_INVALID
, Cause
, File
=self
.MetaFile
,
1644 ExtraData
="%s.%s" % (ToPcd
.TokenSpaceGuidCName
, ToPcd
.TokenCName
))
1646 if ToPcd
.DatumType
== "VOID*" and ToPcd
.MaxDatumSize
in ['', None]:
1647 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "No MaxDatumSize specified for PCD %s.%s" \
1648 % (ToPcd
.TokenSpaceGuidCName
, ToPcd
.TokenCName
))
1649 Value
= ToPcd
.DefaultValue
1650 if Value
in [None, '']:
1651 ToPcd
.MaxDatumSize
= '1'
1652 elif Value
[0] == 'L':
1653 ToPcd
.MaxDatumSize
= str((len(Value
) - 2) * 2)
1654 elif Value
[0] == '{':
1655 ToPcd
.MaxDatumSize
= str(len(Value
.split(',')))
1657 ToPcd
.MaxDatumSize
= str(len(Value
) - 1)
1659 # apply default SKU for dynamic PCDS if specified one is not available
1660 if (ToPcd
.Type
in PCD_DYNAMIC_TYPE_LIST
or ToPcd
.Type
in PCD_DYNAMIC_EX_TYPE_LIST
) \
1661 and ToPcd
.SkuInfoList
in [None, {}, '']:
1662 if self
.Platform
.SkuName
in self
.Platform
.SkuIds
:
1663 SkuName
= self
.Platform
.SkuName
1666 ToPcd
.SkuInfoList
= {
1667 SkuName
: SkuInfoClass(SkuName
, self
.Platform
.SkuIds
[SkuName
], '', '', '', '', '', ToPcd
.DefaultValue
)
1670 ## Apply PCD setting defined platform to a module
1672 # @param Module The module from which the PCD setting will be overrided
1674 # @retval PCD_list The list PCDs with settings from platform
1676 def ApplyPcdSetting(self
, Module
, Pcds
):
1677 # for each PCD in module
1678 for Name
,Guid
in Pcds
:
1679 PcdInModule
= Pcds
[Name
,Guid
]
1680 # find out the PCD setting in platform
1681 if (Name
,Guid
) in self
.Platform
.Pcds
:
1682 PcdInPlatform
= self
.Platform
.Pcds
[Name
,Guid
]
1684 PcdInPlatform
= None
1685 # then override the settings if any
1686 self
._OverridePcd
(PcdInModule
, PcdInPlatform
, Module
)
1687 # resolve the VariableGuid value
1688 for SkuId
in PcdInModule
.SkuInfoList
:
1689 Sku
= PcdInModule
.SkuInfoList
[SkuId
]
1690 if Sku
.VariableGuid
== '': continue
1691 Sku
.VariableGuidValue
= GuidValue(Sku
.VariableGuid
, self
.PackageList
)
1692 if Sku
.VariableGuidValue
== None:
1693 PackageList
= "\n\t".join([str(P
) for P
in self
.PackageList
])
1696 RESOURCE_NOT_AVAILABLE
,
1697 "Value of GUID [%s] is not found in" % Sku
.VariableGuid
,
1698 ExtraData
=PackageList
+ "\n\t(used with %s.%s from module %s)" \
1699 % (Guid
, Name
, str(Module
)),
1703 # override PCD settings with module specific setting
1704 if Module
in self
.Platform
.Modules
:
1705 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
1706 for Key
in PlatformModule
.Pcds
:
1708 self
._OverridePcd
(Pcds
[Key
], PlatformModule
.Pcds
[Key
], Module
)
1709 return Pcds
.values()
1711 ## Resolve library names to library modules
1713 # (for Edk.x modules)
1715 # @param Module The module from which the library names will be resolved
1717 # @retval library_list The list of library modules
1719 def ResolveLibraryReference(self
, Module
):
1720 EdkLogger
.verbose("")
1721 EdkLogger
.verbose("Library instances of module [%s] [%s]:" % (str(Module
), self
.Arch
))
1722 LibraryConsumerList
= [Module
]
1724 # "CompilerStub" is a must for Edk modules
1725 if Module
.Libraries
:
1726 Module
.Libraries
.append("CompilerStub")
1728 while len(LibraryConsumerList
) > 0:
1729 M
= LibraryConsumerList
.pop()
1730 for LibraryName
in M
.Libraries
:
1731 Library
= self
.Platform
.LibraryClasses
[LibraryName
, ':dummy:']
1733 for Key
in self
.Platform
.LibraryClasses
.data
.keys():
1734 if LibraryName
.upper() == Key
.upper():
1735 Library
= self
.Platform
.LibraryClasses
[Key
, ':dummy:']
1738 EdkLogger
.warn("build", "Library [%s] is not found" % LibraryName
, File
=str(M
),
1739 ExtraData
="\t%s [%s]" % (str(Module
), self
.Arch
))
1742 if Library
not in LibraryList
:
1743 LibraryList
.append(Library
)
1744 LibraryConsumerList
.append(Library
)
1745 EdkLogger
.verbose("\t" + LibraryName
+ " : " + str(Library
) + ' ' + str(type(Library
)))
1748 ## Calculate the priority value of the build option
1750 # @param Key Build option definition contain: TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
1752 # @retval Value Priority value based on the priority list.
1754 def CalculatePriorityValue(self
, Key
):
1755 Target
, ToolChain
, Arch
, CommandType
, Attr
= Key
.split('_')
1756 PriorityValue
= 0x11111
1758 PriorityValue
&= 0x01111
1759 if ToolChain
== "*":
1760 PriorityValue
&= 0x10111
1762 PriorityValue
&= 0x11011
1763 if CommandType
== "*":
1764 PriorityValue
&= 0x11101
1766 PriorityValue
&= 0x11110
1768 return self
.PrioList
["0x%0.5x"%PriorityValue
]
1771 ## Expand * in build option key
1773 # @param Options Options to be expanded
1775 # @retval options Options expanded
1777 def _ExpandBuildOption(self
, Options
, ModuleStyle
=None):
1784 # Construct a list contain the build options which need override.
1788 # Key[0] -- tool family
1789 # Key[1] -- TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
1791 if Key
[0] == self
.BuildRuleFamily
:
1792 Target
, ToolChain
, Arch
, CommandType
, Attr
= Key
[1].split('_')
1793 if Target
== self
.BuildTarget
or Target
== "*":
1794 if ToolChain
== self
.ToolChain
or ToolChain
== "*":
1795 if Arch
== self
.Arch
or Arch
== "*":
1796 if Options
[Key
].startswith("="):
1797 if OverrideList
.get(Key
[1]) != None:
1798 OverrideList
.pop(Key
[1])
1799 OverrideList
[Key
[1]] = Options
[Key
]
1802 # Use the highest priority value.
1804 if (len(OverrideList
) >= 2):
1805 KeyList
= OverrideList
.keys()
1806 for Index
in range(len(KeyList
)):
1807 NowKey
= KeyList
[Index
]
1808 Target1
, ToolChain1
, Arch1
, CommandType1
, Attr1
= NowKey
.split("_")
1809 for Index1
in range(len(KeyList
) - Index
- 1):
1810 NextKey
= KeyList
[Index1
+ Index
+ 1]
1812 # Compare two Key, if one is included by another, choose the higher priority one
1814 Target2
, ToolChain2
, Arch2
, CommandType2
, Attr2
= NextKey
.split("_")
1815 if Target1
== Target2
or Target1
== "*" or Target2
== "*":
1816 if ToolChain1
== ToolChain2
or ToolChain1
== "*" or ToolChain2
== "*":
1817 if Arch1
== Arch2
or Arch1
== "*" or Arch2
== "*":
1818 if CommandType1
== CommandType2
or CommandType1
== "*" or CommandType2
== "*":
1819 if Attr1
== Attr2
or Attr1
== "*" or Attr2
== "*":
1820 if self
.CalculatePriorityValue(NowKey
) > self
.CalculatePriorityValue(NextKey
):
1821 if Options
.get((self
.BuildRuleFamily
, NextKey
)) != None:
1822 Options
.pop((self
.BuildRuleFamily
, NextKey
))
1824 if Options
.get((self
.BuildRuleFamily
, NowKey
)) != None:
1825 Options
.pop((self
.BuildRuleFamily
, NowKey
))
1829 if ModuleStyle
!= None and len (Key
) > 2:
1830 # Check Module style is EDK or EDKII.
1831 # Only append build option for the matched style module.
1832 if ModuleStyle
== EDK_NAME
and Key
[2] != EDK_NAME
:
1834 elif ModuleStyle
== EDKII_NAME
and Key
[2] != EDKII_NAME
:
1837 Target
, Tag
, Arch
, Tool
, Attr
= Key
[1].split("_")
1838 # if tool chain family doesn't match, skip it
1839 if Tool
in self
.ToolDefinition
and Family
!= "":
1840 FamilyIsNull
= False
1841 if self
.ToolDefinition
[Tool
].get(TAB_TOD_DEFINES_BUILDRULEFAMILY
, "") != "":
1842 if Family
!= self
.ToolDefinition
[Tool
][TAB_TOD_DEFINES_BUILDRULEFAMILY
]:
1844 elif Family
!= self
.ToolDefinition
[Tool
][TAB_TOD_DEFINES_FAMILY
]:
1847 # expand any wildcard
1848 if Target
== "*" or Target
== self
.BuildTarget
:
1849 if Tag
== "*" or Tag
== self
.ToolChain
:
1850 if Arch
== "*" or Arch
== self
.Arch
:
1851 if Tool
not in BuildOptions
:
1852 BuildOptions
[Tool
] = {}
1853 if Attr
!= "FLAGS" or Attr
not in BuildOptions
[Tool
]:
1854 BuildOptions
[Tool
][Attr
] = Options
[Key
]
1856 # append options for the same tool
1857 BuildOptions
[Tool
][Attr
] += " " + Options
[Key
]
1858 # Build Option Family has been checked, which need't to be checked again for family.
1859 if FamilyMatch
or FamilyIsNull
:
1863 if ModuleStyle
!= None and len (Key
) > 2:
1864 # Check Module style is EDK or EDKII.
1865 # Only append build option for the matched style module.
1866 if ModuleStyle
== EDK_NAME
and Key
[2] != EDK_NAME
:
1868 elif ModuleStyle
== EDKII_NAME
and Key
[2] != EDKII_NAME
:
1871 Target
, Tag
, Arch
, Tool
, Attr
= Key
[1].split("_")
1872 # if tool chain family doesn't match, skip it
1873 if Tool
not in self
.ToolDefinition
or Family
=="":
1875 # option has been added before
1876 if Family
!= self
.ToolDefinition
[Tool
][TAB_TOD_DEFINES_FAMILY
]:
1879 # expand any wildcard
1880 if Target
== "*" or Target
== self
.BuildTarget
:
1881 if Tag
== "*" or Tag
== self
.ToolChain
:
1882 if Arch
== "*" or Arch
== self
.Arch
:
1883 if Tool
not in BuildOptions
:
1884 BuildOptions
[Tool
] = {}
1885 if Attr
!= "FLAGS" or Attr
not in BuildOptions
[Tool
]:
1886 BuildOptions
[Tool
][Attr
] = Options
[Key
]
1888 # append options for the same tool
1889 BuildOptions
[Tool
][Attr
] += " " + Options
[Key
]
1892 ## Append build options in platform to a module
1894 # @param Module The module to which the build options will be appened
1896 # @retval options The options appended with build options in platform
1898 def ApplyBuildOption(self
, Module
):
1899 # Get the different options for the different style module
1900 if Module
.AutoGenVersion
< 0x00010005:
1901 PlatformOptions
= self
.EdkBuildOption
1903 PlatformOptions
= self
.EdkIIBuildOption
1904 ModuleOptions
= self
._ExpandBuildOption
(Module
.BuildOptions
)
1905 if Module
in self
.Platform
.Modules
:
1906 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
1907 PlatformModuleOptions
= self
._ExpandBuildOption
(PlatformModule
.BuildOptions
)
1909 PlatformModuleOptions
= {}
1911 AllTools
= set(ModuleOptions
.keys() + PlatformOptions
.keys() + PlatformModuleOptions
.keys() + self
.ToolDefinition
.keys())
1913 for Tool
in AllTools
:
1914 if Tool
not in BuildOptions
:
1915 BuildOptions
[Tool
] = {}
1917 for Options
in [self
.ToolDefinition
, ModuleOptions
, PlatformOptions
, PlatformModuleOptions
]:
1918 if Tool
not in Options
:
1920 for Attr
in Options
[Tool
]:
1921 Value
= Options
[Tool
][Attr
]
1922 if Attr
not in BuildOptions
[Tool
]:
1923 BuildOptions
[Tool
][Attr
] = ""
1924 # check if override is indicated
1925 if Value
.startswith('='):
1926 BuildOptions
[Tool
][Attr
] = Value
[1:]
1928 BuildOptions
[Tool
][Attr
] += " " + Value
1929 if Module
.AutoGenVersion
< 0x00010005 and self
.Workspace
.UniFlag
!= None:
1931 # Override UNI flag only for EDK module.
1933 if 'BUILD' not in BuildOptions
:
1934 BuildOptions
['BUILD'] = {}
1935 BuildOptions
['BUILD']['FLAGS'] = self
.Workspace
.UniFlag
1938 Platform
= property(_GetPlatform
)
1939 Name
= property(_GetName
)
1940 Guid
= property(_GetGuid
)
1941 Version
= property(_GetVersion
)
1943 OutputDir
= property(_GetOutputDir
)
1944 BuildDir
= property(_GetBuildDir
)
1945 MakeFileDir
= property(_GetMakeFileDir
)
1946 FdfFile
= property(_GetFdfFile
)
1948 PcdTokenNumber
= property(_GetPcdTokenNumbers
) # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber
1949 DynamicPcdList
= property(_GetDynamicPcdList
) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
1950 NonDynamicPcdList
= property(_GetNonDynamicPcdList
) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
1951 NonDynamicPcdDict
= property(_GetNonDynamicPcdDict
)
1952 PackageList
= property(_GetPackageList
)
1954 ToolDefinition
= property(_GetToolDefinition
) # toolcode : tool path
1955 ToolDefinitionFile
= property(_GetToolDefFile
) # toolcode : lib path
1956 ToolChainFamily
= property(_GetToolChainFamily
)
1957 BuildRuleFamily
= property(_GetBuildRuleFamily
)
1958 BuildOption
= property(_GetBuildOptions
) # toolcode : option
1959 EdkBuildOption
= property(_GetEdkBuildOptions
) # edktoolcode : option
1960 EdkIIBuildOption
= property(_GetEdkIIBuildOptions
) # edkiitoolcode : option
1962 BuildCommand
= property(_GetBuildCommand
)
1963 BuildRule
= property(_GetBuildRule
)
1964 ModuleAutoGenList
= property(_GetModuleAutoGenList
)
1965 LibraryAutoGenList
= property(_GetLibraryAutoGenList
)
1967 ## ModuleAutoGen class
1969 # This class encapsules the AutoGen behaviors for the build tools. In addition to
1970 # the generation of AutoGen.h and AutoGen.c, it will generate *.depex file according
1971 # to the [depex] section in module's inf file.
1973 class ModuleAutoGen(AutoGen
):
1974 ## The real constructor of ModuleAutoGen
1976 # This method is not supposed to be called by users of ModuleAutoGen. It's
1977 # only used by factory method __new__() to do real initialization work for an
1978 # object of ModuleAutoGen
1980 # @param Workspace EdkIIWorkspaceBuild object
1981 # @param ModuleFile The path of module file
1982 # @param Target Build target (DEBUG, RELEASE)
1983 # @param Toolchain Name of tool chain
1984 # @param Arch The arch the module supports
1985 # @param PlatformFile Platform meta-file
1987 def _Init(self
, Workspace
, ModuleFile
, Target
, Toolchain
, Arch
, PlatformFile
):
1988 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "AutoGen module [%s] [%s]" % (ModuleFile
, Arch
))
1989 GlobalData
.gProcessingFile
= "%s [%s, %s, %s]" % (ModuleFile
, Arch
, Toolchain
, Target
)
1991 self
.Workspace
= Workspace
1992 self
.WorkspaceDir
= Workspace
.WorkspaceDir
1994 self
.MetaFile
= ModuleFile
1995 self
.PlatformInfo
= PlatformAutoGen(Workspace
, PlatformFile
, Target
, Toolchain
, Arch
)
1996 # check if this module is employed by active platform
1997 if not self
.PlatformInfo
.ValidModule(self
.MetaFile
):
1998 EdkLogger
.verbose("Module [%s] for [%s] is not employed by active platform\n" \
1999 % (self
.MetaFile
, Arch
))
2002 self
.SourceDir
= self
.MetaFile
.SubDir
2003 self
.SourceOverrideDir
= None
2004 # use overrided path defined in DSC file
2005 if self
.MetaFile
.Key
in GlobalData
.gOverrideDir
:
2006 self
.SourceOverrideDir
= GlobalData
.gOverrideDir
[self
.MetaFile
.Key
]
2008 self
.ToolChain
= Toolchain
2009 self
.BuildTarget
= Target
2011 self
.ToolChainFamily
= self
.PlatformInfo
.ToolChainFamily
2012 self
.BuildRuleFamily
= self
.PlatformInfo
.BuildRuleFamily
2014 self
.IsMakeFileCreated
= False
2015 self
.IsCodeFileCreated
= False
2016 self
.IsAsBuiltInfCreated
= False
2017 self
.DepexGenerated
= False
2019 self
.BuildDatabase
= self
.Workspace
.BuildDatabase
2024 self
._Version
= None
2025 self
._ModuleType
= None
2026 self
._ComponentType
= None
2027 self
._PcdIsDriver
= None
2028 self
._AutoGenVersion
= None
2029 self
._LibraryFlag
= None
2030 self
._CustomMakefile
= None
2033 self
._BuildDir
= None
2034 self
._OutputDir
= None
2035 self
._DebugDir
= None
2036 self
._MakeFileDir
= None
2038 self
._IncludePathList
= None
2039 self
._AutoGenFileList
= None
2040 self
._UnicodeFileList
= None
2041 self
._SourceFileList
= None
2042 self
._ObjectFileList
= None
2043 self
._BinaryFileList
= None
2045 self
._DependentPackageList
= None
2046 self
._DependentLibraryList
= None
2047 self
._LibraryAutoGenList
= None
2048 self
._DerivedPackageList
= None
2049 self
._ModulePcdList
= None
2050 self
._LibraryPcdList
= None
2051 self
._PcdComments
= sdict()
2052 self
._GuidList
= None
2053 self
._GuidsUsedByPcd
= None
2054 self
._GuidComments
= sdict()
2055 self
._ProtocolList
= None
2056 self
._ProtocolComments
= sdict()
2057 self
._PpiList
= None
2058 self
._PpiComments
= sdict()
2059 self
._DepexList
= None
2060 self
._DepexExpressionList
= None
2061 self
._BuildOption
= None
2062 self
._BuildOptionIncPathList
= None
2063 self
._BuildTargets
= None
2064 self
._IntroBuildTargetList
= None
2065 self
._FinalBuildTargetList
= None
2066 self
._FileTypes
= None
2067 self
._BuildRules
= None
2069 ## The Modules referenced to this Library
2070 # Only Library has this attribute
2071 self
._ReferenceModules
= []
2073 ## Store the FixedAtBuild Pcds
2075 self
._FixedAtBuildPcds
= []
2080 return "%s [%s]" % (self
.MetaFile
, self
.Arch
)
2082 # Get FixedAtBuild Pcds of this Module
2083 def _GetFixedAtBuildPcds(self
):
2084 if self
._FixedAtBuildPcds
:
2085 return self
._FixedAtBuildPcds
2086 for Pcd
in self
.ModulePcdList
:
2088 if not (Pcd
.Pending
== False and Pcd
.Type
== "FixedAtBuild"):
2090 elif Pcd
.Type
!= "FixedAtBuild":
2092 if Pcd
not in self
._FixedAtBuildPcds
:
2093 self
._FixedAtBuildPcds
.append(Pcd
)
2095 return self
._FixedAtBuildPcds
2097 # Macros could be used in build_rule.txt (also Makefile)
2098 def _GetMacros(self
):
2099 if self
._Macro
== None:
2100 self
._Macro
= sdict()
2101 self
._Macro
["WORKSPACE" ] = self
.WorkspaceDir
2102 self
._Macro
["MODULE_NAME" ] = self
.Name
2103 self
._Macro
["MODULE_GUID" ] = self
.Guid
2104 self
._Macro
["MODULE_VERSION" ] = self
.Version
2105 self
._Macro
["MODULE_TYPE" ] = self
.ModuleType
2106 self
._Macro
["MODULE_FILE" ] = str(self
.MetaFile
)
2107 self
._Macro
["MODULE_FILE_BASE_NAME" ] = self
.MetaFile
.BaseName
2108 self
._Macro
["MODULE_RELATIVE_DIR" ] = self
.SourceDir
2109 self
._Macro
["MODULE_DIR" ] = self
.SourceDir
2111 self
._Macro
["BASE_NAME" ] = self
.Name
2113 self
._Macro
["ARCH" ] = self
.Arch
2114 self
._Macro
["TOOLCHAIN" ] = self
.ToolChain
2115 self
._Macro
["TOOLCHAIN_TAG" ] = self
.ToolChain
2116 self
._Macro
["TOOL_CHAIN_TAG" ] = self
.ToolChain
2117 self
._Macro
["TARGET" ] = self
.BuildTarget
2119 self
._Macro
["BUILD_DIR" ] = self
.PlatformInfo
.BuildDir
2120 self
._Macro
["BIN_DIR" ] = os
.path
.join(self
.PlatformInfo
.BuildDir
, self
.Arch
)
2121 self
._Macro
["LIB_DIR" ] = os
.path
.join(self
.PlatformInfo
.BuildDir
, self
.Arch
)
2122 self
._Macro
["MODULE_BUILD_DIR" ] = self
.BuildDir
2123 self
._Macro
["OUTPUT_DIR" ] = self
.OutputDir
2124 self
._Macro
["DEBUG_DIR" ] = self
.DebugDir
2127 ## Return the module build data object
2128 def _GetModule(self
):
2129 if self
._Module
== None:
2130 self
._Module
= self
.Workspace
.BuildDatabase
[self
.MetaFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
2133 ## Return the module name
2134 def _GetBaseName(self
):
2135 return self
.Module
.BaseName
2137 ## Return the module DxsFile if exist
2138 def _GetDxsFile(self
):
2139 return self
.Module
.DxsFile
2141 ## Return the module SourceOverridePath
2142 def _GetSourceOverridePath(self
):
2143 return self
.Module
.SourceOverridePath
2145 ## Return the module meta-file GUID
2147 return self
.Module
.Guid
2149 ## Return the module version
2150 def _GetVersion(self
):
2151 return self
.Module
.Version
2153 ## Return the module type
2154 def _GetModuleType(self
):
2155 return self
.Module
.ModuleType
2157 ## Return the component type (for Edk.x style of module)
2158 def _GetComponentType(self
):
2159 return self
.Module
.ComponentType
2161 ## Return the build type
2162 def _GetBuildType(self
):
2163 return self
.Module
.BuildType
2165 ## Return the PCD_IS_DRIVER setting
2166 def _GetPcdIsDriver(self
):
2167 return self
.Module
.PcdIsDriver
2169 ## Return the autogen version, i.e. module meta-file version
2170 def _GetAutoGenVersion(self
):
2171 return self
.Module
.AutoGenVersion
2173 ## Check if the module is library or not
2174 def _IsLibrary(self
):
2175 if self
._LibraryFlag
== None:
2176 if self
.Module
.LibraryClass
!= None and self
.Module
.LibraryClass
!= []:
2177 self
._LibraryFlag
= True
2179 self
._LibraryFlag
= False
2180 return self
._LibraryFlag
2182 ## Check if the module is binary module or not
2183 def _IsBinaryModule(self
):
2184 return self
.Module
.IsBinaryModule
2186 ## Return the directory to store intermediate files of the module
2187 def _GetBuildDir(self
):
2188 if self
._BuildDir
== None:
2189 self
._BuildDir
= path
.join(
2190 self
.PlatformInfo
.BuildDir
,
2193 self
.MetaFile
.BaseName
2195 CreateDirectory(self
._BuildDir
)
2196 return self
._BuildDir
2198 ## Return the directory to store the intermediate object files of the mdoule
2199 def _GetOutputDir(self
):
2200 if self
._OutputDir
== None:
2201 self
._OutputDir
= path
.join(self
.BuildDir
, "OUTPUT")
2202 CreateDirectory(self
._OutputDir
)
2203 return self
._OutputDir
2205 ## Return the directory to store auto-gened source files of the mdoule
2206 def _GetDebugDir(self
):
2207 if self
._DebugDir
== None:
2208 self
._DebugDir
= path
.join(self
.BuildDir
, "DEBUG")
2209 CreateDirectory(self
._DebugDir
)
2210 return self
._DebugDir
2212 ## Return the path of custom file
2213 def _GetCustomMakefile(self
):
2214 if self
._CustomMakefile
== None:
2215 self
._CustomMakefile
= {}
2216 for Type
in self
.Module
.CustomMakefile
:
2217 if Type
in gMakeTypeMap
:
2218 MakeType
= gMakeTypeMap
[Type
]
2221 if self
.SourceOverrideDir
!= None:
2222 File
= os
.path
.join(self
.SourceOverrideDir
, self
.Module
.CustomMakefile
[Type
])
2223 if not os
.path
.exists(File
):
2224 File
= os
.path
.join(self
.SourceDir
, self
.Module
.CustomMakefile
[Type
])
2226 File
= os
.path
.join(self
.SourceDir
, self
.Module
.CustomMakefile
[Type
])
2227 self
._CustomMakefile
[MakeType
] = File
2228 return self
._CustomMakefile
2230 ## Return the directory of the makefile
2232 # @retval string The directory string of module's makefile
2234 def _GetMakeFileDir(self
):
2235 return self
.BuildDir
2237 ## Return build command string
2239 # @retval string Build command string
2241 def _GetBuildCommand(self
):
2242 return self
.PlatformInfo
.BuildCommand
2244 ## Get object list of all packages the module and its dependent libraries belong to
2246 # @retval list The list of package object
2248 def _GetDerivedPackageList(self
):
2250 for M
in [self
.Module
] + self
.DependentLibraryList
:
2251 for Package
in M
.Packages
:
2252 if Package
in PackageList
:
2254 PackageList
.append(Package
)
2257 ## Merge dependency expression
2259 # @retval list The token list of the dependency expression after parsed
2261 def _GetDepexTokenList(self
):
2262 if self
._DepexList
== None:
2263 self
._DepexList
= {}
2264 if self
.DxsFile
or self
.IsLibrary
or TAB_DEPENDENCY_EXPRESSION_FILE
in self
.FileTypes
:
2265 return self
._DepexList
2267 self
._DepexList
[self
.ModuleType
] = []
2269 for ModuleType
in self
._DepexList
:
2270 DepexList
= self
._DepexList
[ModuleType
]
2272 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
2274 for M
in [self
.Module
] + self
.DependentLibraryList
:
2276 for D
in M
.Depex
[self
.Arch
, ModuleType
]:
2278 DepexList
.append('AND')
2279 DepexList
.append('(')
2281 if DepexList
[-1] == 'END': # no need of a END at this time
2283 DepexList
.append(')')
2286 EdkLogger
.verbose("DEPEX[%s] (+%s) = %s" % (self
.Name
, M
.BaseName
, DepexList
))
2287 if 'BEFORE' in DepexList
or 'AFTER' in DepexList
:
2289 if len(DepexList
) > 0:
2290 EdkLogger
.verbose('')
2291 return self
._DepexList
2293 ## Merge dependency expression
2295 # @retval list The token list of the dependency expression after parsed
2297 def _GetDepexExpressionTokenList(self
):
2298 if self
._DepexExpressionList
== None:
2299 self
._DepexExpressionList
= {}
2300 if self
.DxsFile
or self
.IsLibrary
or TAB_DEPENDENCY_EXPRESSION_FILE
in self
.FileTypes
:
2301 return self
._DepexExpressionList
2303 self
._DepexExpressionList
[self
.ModuleType
] = ''
2305 for ModuleType
in self
._DepexExpressionList
:
2306 DepexExpressionList
= self
._DepexExpressionList
[ModuleType
]
2308 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
2310 for M
in [self
.Module
] + self
.DependentLibraryList
:
2312 for D
in M
.DepexExpression
[self
.Arch
, ModuleType
]:
2313 if DepexExpressionList
!= '':
2314 DepexExpressionList
+= ' AND '
2315 DepexExpressionList
+= '('
2316 DepexExpressionList
+= D
2317 DepexExpressionList
= DepexExpressionList
.rstrip('END').strip()
2318 DepexExpressionList
+= ')'
2321 EdkLogger
.verbose("DEPEX[%s] (+%s) = %s" % (self
.Name
, M
.BaseName
, DepexExpressionList
))
2322 if 'BEFORE' in DepexExpressionList
or 'AFTER' in DepexExpressionList
:
2324 if len(DepexExpressionList
) > 0:
2325 EdkLogger
.verbose('')
2326 self
._DepexExpressionList
[ModuleType
] = DepexExpressionList
2327 return self
._DepexExpressionList
2329 ## Return the list of specification version required for the module
2331 # @retval list The list of specification defined in module file
2333 def _GetSpecification(self
):
2334 return self
.Module
.Specification
2336 ## Tool option for the module build
2338 # @param PlatformInfo The object of PlatformBuildInfo
2339 # @retval dict The dict containing valid options
2341 def _GetModuleBuildOption(self
):
2342 if self
._BuildOption
== None:
2343 self
._BuildOption
= self
.PlatformInfo
.ApplyBuildOption(self
.Module
)
2344 return self
._BuildOption
2346 ## Get include path list from tool option for the module build
2348 # @retval list The include path list
2350 def _GetBuildOptionIncPathList(self
):
2351 if self
._BuildOptionIncPathList
== None:
2353 # Regular expression for finding Include Directories, the difference between MSFT and INTEL/GCC/RVCT
2354 # is the former use /I , the Latter used -I to specify include directories
2356 if self
.PlatformInfo
.ToolChainFamily
in ('MSFT'):
2357 gBuildOptIncludePattern
= re
.compile(r
"(?:.*?)/I[ \t]*([^ ]*)", re
.MULTILINE|re
.DOTALL
)
2358 elif self
.PlatformInfo
.ToolChainFamily
in ('INTEL', 'GCC', 'RVCT'):
2359 gBuildOptIncludePattern
= re
.compile(r
"(?:.*?)-I[ \t]*([^ ]*)", re
.MULTILINE|re
.DOTALL
)
2362 # New ToolChainFamily, don't known whether there is option to specify include directories
2364 self
._BuildOptionIncPathList
= []
2365 return self
._BuildOptionIncPathList
2367 BuildOptionIncPathList
= []
2368 for Tool
in ('CC', 'PP', 'VFRPP', 'ASLPP', 'ASLCC', 'APP', 'ASM'):
2371 FlagOption
= self
.BuildOption
[Tool
][Attr
]
2375 if self
.PlatformInfo
.ToolChainFamily
!= 'RVCT':
2376 IncPathList
= [NormPath(Path
, self
.Macros
) for Path
in gBuildOptIncludePattern
.findall(FlagOption
)]
2379 # RVCT may specify a list of directory seperated by commas
2382 for Path
in gBuildOptIncludePattern
.findall(FlagOption
):
2383 PathList
= GetSplitList(Path
, TAB_COMMA_SPLIT
)
2384 IncPathList
+= [NormPath(PathEntry
, self
.Macros
) for PathEntry
in PathList
]
2387 # EDK II modules must not reference header files outside of the packages they depend on or
2388 # within the module's directory tree. Report error if violation.
2390 if self
.AutoGenVersion
>= 0x00010005 and len(IncPathList
) > 0:
2391 for Path
in IncPathList
:
2392 if (Path
not in self
.IncludePathList
) and (CommonPath([Path
, self
.MetaFile
.Dir
]) != self
.MetaFile
.Dir
):
2393 ErrMsg
= "The include directory for the EDK II module in this line is invalid %s specified in %s FLAGS '%s'" % (Path
, Tool
, FlagOption
)
2394 EdkLogger
.error("build",
2397 File
= str(self
.MetaFile
))
2400 BuildOptionIncPathList
+= IncPathList
2402 self
._BuildOptionIncPathList
= BuildOptionIncPathList
2404 return self
._BuildOptionIncPathList
2406 ## Return a list of files which can be built from source
2408 # What kind of files can be built is determined by build rules in
2409 # $(WORKSPACE)/Conf/build_rule.txt and toolchain family.
2411 def _GetSourceFileList(self
):
2412 if self
._SourceFileList
== None:
2413 self
._SourceFileList
= []
2414 for F
in self
.Module
.Sources
:
2416 if F
.TagName
not in ("", "*", self
.ToolChain
):
2417 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "The toolchain [%s] for processing file [%s] is found, "
2418 "but [%s] is needed" % (F
.TagName
, str(F
), self
.ToolChain
))
2420 # match tool chain family
2421 if F
.ToolChainFamily
not in ("", "*", self
.ToolChainFamily
):
2424 "The file [%s] must be built by tools of [%s], " \
2425 "but current toolchain family is [%s]" \
2426 % (str(F
), F
.ToolChainFamily
, self
.ToolChainFamily
))
2429 # add the file path into search path list for file including
2430 if F
.Dir
not in self
.IncludePathList
and self
.AutoGenVersion
>= 0x00010005:
2431 self
.IncludePathList
.insert(0, F
.Dir
)
2432 self
._SourceFileList
.append(F
)
2433 self
._ApplyBuildRule
(F
, TAB_UNKNOWN_FILE
)
2434 return self
._SourceFileList
2436 ## Return the list of unicode files
2437 def _GetUnicodeFileList(self
):
2438 if self
._UnicodeFileList
== None:
2439 if TAB_UNICODE_FILE
in self
.FileTypes
:
2440 self
._UnicodeFileList
= self
.FileTypes
[TAB_UNICODE_FILE
]
2442 self
._UnicodeFileList
= []
2443 return self
._UnicodeFileList
2445 ## Return a list of files which can be built from binary
2447 # "Build" binary files are just to copy them to build directory.
2449 # @retval list The list of files which can be built later
2451 def _GetBinaryFiles(self
):
2452 if self
._BinaryFileList
== None:
2453 self
._BinaryFileList
= []
2454 for F
in self
.Module
.Binaries
:
2455 if F
.Target
not in ['COMMON', '*'] and F
.Target
!= self
.BuildTarget
:
2457 self
._BinaryFileList
.append(F
)
2458 self
._ApplyBuildRule
(F
, F
.Type
)
2459 return self
._BinaryFileList
2461 def _GetBuildRules(self
):
2462 if self
._BuildRules
== None:
2464 BuildRuleDatabase
= self
.PlatformInfo
.BuildRule
2465 for Type
in BuildRuleDatabase
.FileTypeList
:
2466 #first try getting build rule by BuildRuleFamily
2467 RuleObject
= BuildRuleDatabase
[Type
, self
.BuildType
, self
.Arch
, self
.BuildRuleFamily
]
2469 # build type is always module type, but ...
2470 if self
.ModuleType
!= self
.BuildType
:
2471 RuleObject
= BuildRuleDatabase
[Type
, self
.ModuleType
, self
.Arch
, self
.BuildRuleFamily
]
2472 #second try getting build rule by ToolChainFamily
2474 RuleObject
= BuildRuleDatabase
[Type
, self
.BuildType
, self
.Arch
, self
.ToolChainFamily
]
2476 # build type is always module type, but ...
2477 if self
.ModuleType
!= self
.BuildType
:
2478 RuleObject
= BuildRuleDatabase
[Type
, self
.ModuleType
, self
.Arch
, self
.ToolChainFamily
]
2481 RuleObject
= RuleObject
.Instantiate(self
.Macros
)
2482 BuildRules
[Type
] = RuleObject
2483 for Ext
in RuleObject
.SourceFileExtList
:
2484 BuildRules
[Ext
] = RuleObject
2485 self
._BuildRules
= BuildRules
2486 return self
._BuildRules
2488 def _ApplyBuildRule(self
, File
, FileType
):
2489 if self
._BuildTargets
== None:
2490 self
._IntroBuildTargetList
= set()
2491 self
._FinalBuildTargetList
= set()
2492 self
._BuildTargets
= {}
2493 self
._FileTypes
= {}
2499 while Index
< len(SourceList
):
2500 Source
= SourceList
[Index
]
2504 CreateDirectory(Source
.Dir
)
2506 if File
.IsBinary
and File
== Source
and self
._BinaryFileList
!= None and File
in self
._BinaryFileList
:
2507 # Skip all files that are not binary libraries
2508 if not self
.IsLibrary
:
2510 RuleObject
= self
.BuildRules
[TAB_DEFAULT_BINARY_FILE
]
2511 elif FileType
in self
.BuildRules
:
2512 RuleObject
= self
.BuildRules
[FileType
]
2513 elif Source
.Ext
in self
.BuildRules
:
2514 RuleObject
= self
.BuildRules
[Source
.Ext
]
2516 # stop at no more rules
2518 self
._FinalBuildTargetList
.add(LastTarget
)
2521 FileType
= RuleObject
.SourceFileType
2522 if FileType
not in self
._FileTypes
:
2523 self
._FileTypes
[FileType
] = set()
2524 self
._FileTypes
[FileType
].add(Source
)
2526 # stop at STATIC_LIBRARY for library
2527 if self
.IsLibrary
and FileType
== TAB_STATIC_LIBRARY
:
2529 self
._FinalBuildTargetList
.add(LastTarget
)
2532 Target
= RuleObject
.Apply(Source
)
2535 self
._FinalBuildTargetList
.add(LastTarget
)
2537 elif not Target
.Outputs
:
2538 # Only do build for target with outputs
2539 self
._FinalBuildTargetList
.add(Target
)
2541 if FileType
not in self
._BuildTargets
:
2542 self
._BuildTargets
[FileType
] = set()
2543 self
._BuildTargets
[FileType
].add(Target
)
2545 if not Source
.IsBinary
and Source
== File
:
2546 self
._IntroBuildTargetList
.add(Target
)
2548 # to avoid cyclic rule
2549 if FileType
in RuleChain
:
2552 RuleChain
.append(FileType
)
2553 SourceList
.extend(Target
.Outputs
)
2555 FileType
= TAB_UNKNOWN_FILE
2557 def _GetTargets(self
):
2558 if self
._BuildTargets
== None:
2559 self
._IntroBuildTargetList
= set()
2560 self
._FinalBuildTargetList
= set()
2561 self
._BuildTargets
= {}
2562 self
._FileTypes
= {}
2564 #TRICK: call _GetSourceFileList to apply build rule for source files
2565 if self
.SourceFileList
:
2568 #TRICK: call _GetBinaryFileList to apply build rule for binary files
2569 if self
.BinaryFileList
:
2572 return self
._BuildTargets
2574 def _GetIntroTargetList(self
):
2576 return self
._IntroBuildTargetList
2578 def _GetFinalTargetList(self
):
2580 return self
._FinalBuildTargetList
2582 def _GetFileTypes(self
):
2584 return self
._FileTypes
2586 ## Get the list of package object the module depends on
2588 # @retval list The package object list
2590 def _GetDependentPackageList(self
):
2591 return self
.Module
.Packages
2593 ## Return the list of auto-generated code file
2595 # @retval list The list of auto-generated file
2597 def _GetAutoGenFileList(self
):
2598 UniStringAutoGenC
= True
2599 UniStringBinBuffer
= StringIO()
2600 if self
.BuildType
== 'UEFI_HII':
2601 UniStringAutoGenC
= False
2602 if self
._AutoGenFileList
== None:
2603 self
._AutoGenFileList
= {}
2604 AutoGenC
= TemplateString()
2605 AutoGenH
= TemplateString()
2606 StringH
= TemplateString()
2607 GenC
.CreateCode(self
, AutoGenC
, AutoGenH
, StringH
, UniStringAutoGenC
, UniStringBinBuffer
)
2608 if str(AutoGenC
) != "" and TAB_C_CODE_FILE
in self
.FileTypes
:
2609 AutoFile
= PathClass(gAutoGenCodeFileName
, self
.DebugDir
)
2610 self
._AutoGenFileList
[AutoFile
] = str(AutoGenC
)
2611 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
2612 if str(AutoGenH
) != "":
2613 AutoFile
= PathClass(gAutoGenHeaderFileName
, self
.DebugDir
)
2614 self
._AutoGenFileList
[AutoFile
] = str(AutoGenH
)
2615 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
2616 if str(StringH
) != "":
2617 AutoFile
= PathClass(gAutoGenStringFileName
% {"module_name":self
.Name
}, self
.DebugDir
)
2618 self
._AutoGenFileList
[AutoFile
] = str(StringH
)
2619 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
2620 if UniStringBinBuffer
!= None and UniStringBinBuffer
.getvalue() != "":
2621 AutoFile
= PathClass(gAutoGenStringFormFileName
% {"module_name":self
.Name
}, self
.OutputDir
)
2622 self
._AutoGenFileList
[AutoFile
] = UniStringBinBuffer
.getvalue()
2623 AutoFile
.IsBinary
= True
2624 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
2625 if UniStringBinBuffer
!= None:
2626 UniStringBinBuffer
.close()
2627 return self
._AutoGenFileList
2629 ## Return the list of library modules explicitly or implicityly used by this module
2630 def _GetLibraryList(self
):
2631 if self
._DependentLibraryList
== None:
2632 # only merge library classes and PCD for non-library module
2634 self
._DependentLibraryList
= []
2636 if self
.AutoGenVersion
< 0x00010005:
2637 self
._DependentLibraryList
= self
.PlatformInfo
.ResolveLibraryReference(self
.Module
)
2639 self
._DependentLibraryList
= self
.PlatformInfo
.ApplyLibraryInstance(self
.Module
)
2640 return self
._DependentLibraryList
2643 def UpdateComments(Recver
, Src
):
2645 if Key
not in Recver
:
2647 Recver
[Key
].extend(Src
[Key
])
2648 ## Get the list of PCDs from current module
2650 # @retval list The list of PCD
2652 def _GetModulePcdList(self
):
2653 if self
._ModulePcdList
== None:
2654 # apply PCD settings from platform
2655 self
._ModulePcdList
= self
.PlatformInfo
.ApplyPcdSetting(self
.Module
, self
.Module
.Pcds
)
2656 self
.UpdateComments(self
._PcdComments
, self
.Module
.PcdComments
)
2657 return self
._ModulePcdList
2659 ## Get the list of PCDs from dependent libraries
2661 # @retval list The list of PCD
2663 def _GetLibraryPcdList(self
):
2664 if self
._LibraryPcdList
== None:
2666 if not self
.IsLibrary
:
2667 # get PCDs from dependent libraries
2668 for Library
in self
.DependentLibraryList
:
2669 self
.UpdateComments(self
._PcdComments
, Library
.PcdComments
)
2670 for Key
in Library
.Pcds
:
2671 # skip duplicated PCDs
2672 if Key
in self
.Module
.Pcds
or Key
in Pcds
:
2674 Pcds
[Key
] = copy
.copy(Library
.Pcds
[Key
])
2675 # apply PCD settings from platform
2676 self
._LibraryPcdList
= self
.PlatformInfo
.ApplyPcdSetting(self
.Module
, Pcds
)
2678 self
._LibraryPcdList
= []
2679 return self
._LibraryPcdList
2681 ## Get the GUID value mapping
2683 # @retval dict The mapping between GUID cname and its value
2685 def _GetGuidList(self
):
2686 if self
._GuidList
== None:
2687 self
._GuidList
= self
.Module
.Guids
2688 for Library
in self
.DependentLibraryList
:
2689 self
._GuidList
.update(Library
.Guids
)
2690 self
.UpdateComments(self
._GuidComments
, Library
.GuidComments
)
2691 self
.UpdateComments(self
._GuidComments
, self
.Module
.GuidComments
)
2692 return self
._GuidList
2694 def GetGuidsUsedByPcd(self
):
2695 if self
._GuidsUsedByPcd
== None:
2696 self
._GuidsUsedByPcd
= sdict()
2697 self
._GuidsUsedByPcd
.update(self
.Module
.GetGuidsUsedByPcd())
2698 for Library
in self
.DependentLibraryList
:
2699 self
._GuidsUsedByPcd
.update(Library
.GetGuidsUsedByPcd())
2700 return self
._GuidsUsedByPcd
2701 ## Get the protocol value mapping
2703 # @retval dict The mapping between protocol cname and its value
2705 def _GetProtocolList(self
):
2706 if self
._ProtocolList
== None:
2707 self
._ProtocolList
= self
.Module
.Protocols
2708 for Library
in self
.DependentLibraryList
:
2709 self
._ProtocolList
.update(Library
.Protocols
)
2710 self
.UpdateComments(self
._ProtocolComments
, Library
.ProtocolComments
)
2711 self
.UpdateComments(self
._ProtocolComments
, self
.Module
.ProtocolComments
)
2712 return self
._ProtocolList
2714 ## Get the PPI value mapping
2716 # @retval dict The mapping between PPI cname and its value
2718 def _GetPpiList(self
):
2719 if self
._PpiList
== None:
2720 self
._PpiList
= self
.Module
.Ppis
2721 for Library
in self
.DependentLibraryList
:
2722 self
._PpiList
.update(Library
.Ppis
)
2723 self
.UpdateComments(self
._PpiComments
, Library
.PpiComments
)
2724 self
.UpdateComments(self
._PpiComments
, self
.Module
.PpiComments
)
2725 return self
._PpiList
2727 ## Get the list of include search path
2729 # @retval list The list path
2731 def _GetIncludePathList(self
):
2732 if self
._IncludePathList
== None:
2733 self
._IncludePathList
= []
2734 if self
.AutoGenVersion
< 0x00010005:
2735 for Inc
in self
.Module
.Includes
:
2736 if Inc
not in self
._IncludePathList
:
2737 self
._IncludePathList
.append(Inc
)
2739 Inc
= path
.join(Inc
, self
.Arch
.capitalize())
2740 if os
.path
.exists(Inc
) and Inc
not in self
._IncludePathList
:
2741 self
._IncludePathList
.append(Inc
)
2742 # Edk module needs to put DEBUG_DIR at the end of search path and not to use SOURCE_DIR all the time
2743 self
._IncludePathList
.append(self
.DebugDir
)
2745 self
._IncludePathList
.append(self
.MetaFile
.Dir
)
2746 self
._IncludePathList
.append(self
.DebugDir
)
2748 for Package
in self
.Module
.Packages
:
2749 PackageDir
= path
.join(self
.WorkspaceDir
, Package
.MetaFile
.Dir
)
2750 if PackageDir
not in self
._IncludePathList
:
2751 self
._IncludePathList
.append(PackageDir
)
2752 for Inc
in Package
.Includes
:
2753 if Inc
not in self
._IncludePathList
:
2754 self
._IncludePathList
.append(str(Inc
))
2755 return self
._IncludePathList
2757 ## Create AsBuilt INF file the module
2759 def CreateAsBuiltInf(self
):
2760 if self
.IsAsBuiltInfCreated
:
2763 # Skip the following code for EDK I inf
2764 if self
.AutoGenVersion
< 0x00010005:
2767 # Skip the following code for libraries
2771 # Skip the following code for modules with no source files
2772 if self
.SourceFileList
== None or self
.SourceFileList
== []:
2775 # Skip the following code for modules without any binary files
2776 if self
.BinaryFileList
<> None and self
.BinaryFileList
<> []:
2779 ### TODO: How to handles mixed source and binary modules
2781 # Find all DynamicEx and PatchableInModule PCDs used by this module and dependent libraries
2782 # Also find all packages that the DynamicEx PCDs depend on
2787 PcdTokenSpaceList
= []
2788 for Pcd
in self
.ModulePcdList
+ self
.LibraryPcdList
:
2789 if Pcd
.Type
== TAB_PCDS_PATCHABLE_IN_MODULE
:
2790 PatchablePcds
[Pcd
.TokenCName
] = Pcd
2791 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, 'PatchableInModule'))
2792 elif Pcd
.Type
in GenC
.gDynamicExPcd
:
2795 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, 'DynamicEx'))
2796 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, 'Dynamic'))
2797 PcdTokenSpaceList
.append(Pcd
.TokenSpaceGuidCName
)
2799 GuidList
.update(self
.GuidList
)
2800 for TokenSpace
in self
.GetGuidsUsedByPcd():
2801 # If token space is not referred by patch PCD or Ex PCD, remove the GUID from GUID list
2802 # The GUIDs in GUIDs section should really be the GUIDs in source INF or referred by Ex an patch PCDs
2803 if TokenSpace
not in PcdTokenSpaceList
and TokenSpace
in GuidList
:
2804 GuidList
.pop(TokenSpace
)
2805 CheckList
= (GuidList
, self
.PpiList
, self
.ProtocolList
, PcdCheckList
)
2806 for Package
in self
.DerivedPackageList
:
2807 if Package
in Packages
:
2809 BeChecked
= (Package
.Guids
, Package
.Ppis
, Package
.Protocols
, Package
.Pcds
)
2811 for Index
in range(len(BeChecked
)):
2812 for Item
in CheckList
[Index
]:
2813 if Item
in BeChecked
[Index
]:
2814 Packages
+= [Package
]
2819 ModuleType
= self
.ModuleType
2820 if ModuleType
== 'UEFI_DRIVER' and self
.DepexGenerated
:
2821 ModuleType
= 'DXE_DRIVER'
2824 if self
.PcdIsDriver
!= '':
2825 DriverType
= self
.PcdIsDriver
2828 'module_name' : self
.Name
,
2829 'module_guid' : self
.Guid
,
2830 'module_module_type' : ModuleType
,
2831 'module_version_string' : self
.Version
,
2832 'pcd_is_driver_string' : [],
2833 'module_uefi_specification_version' : [],
2834 'module_pi_specification_version' : [],
2835 'module_arch' : self
.Arch
,
2836 'package_item' : ['%s' % (Package
.MetaFile
.File
.replace('\\','/')) for Package
in Packages
],
2838 'patchablepcd_item' : [],
2840 'protocol_item' : [],
2844 'libraryclasses_item' : []
2846 AsBuiltInfDict
['module_inf_version'] = '0x%08x' % self
.AutoGenVersion
2848 AsBuiltInfDict
['pcd_is_driver_string'] += [DriverType
]
2850 if 'UEFI_SPECIFICATION_VERSION' in self
.Specification
:
2851 AsBuiltInfDict
['module_uefi_specification_version'] += [self
.Specification
['UEFI_SPECIFICATION_VERSION']]
2852 if 'PI_SPECIFICATION_VERSION' in self
.Specification
:
2853 AsBuiltInfDict
['module_pi_specification_version'] += [self
.Specification
['PI_SPECIFICATION_VERSION']]
2855 OutputDir
= self
.OutputDir
.replace('\\','/').strip('/')
2856 if self
.ModuleType
in ['BASE', 'USER_DEFINED']:
2857 for Item
in self
.CodaTargetList
:
2858 File
= Item
.Target
.Path
.replace('\\','/').strip('/').replace(OutputDir
,'').strip('/')
2859 if Item
.Target
.Ext
.lower() == '.aml':
2860 AsBuiltInfDict
['binary_item'] += ['ASL|' + File
]
2861 elif Item
.Target
.Ext
.lower() == '.acpi':
2862 AsBuiltInfDict
['binary_item'] += ['ACPI|' + File
]
2864 AsBuiltInfDict
['binary_item'] += ['BIN|' + File
]
2866 for Item
in self
.CodaTargetList
:
2867 File
= Item
.Target
.Path
.replace('\\','/').strip('/').replace(OutputDir
,'').strip('/')
2868 if Item
.Target
.Ext
.lower() == '.efi':
2869 AsBuiltInfDict
['binary_item'] += ['PE32|' + self
.Name
+ '.efi']
2871 AsBuiltInfDict
['binary_item'] += ['BIN|' + File
]
2872 if self
.DepexGenerated
:
2873 if self
.ModuleType
in ['PEIM']:
2874 AsBuiltInfDict
['binary_item'] += ['PEI_DEPEX|' + self
.Name
+ '.depex']
2875 if self
.ModuleType
in ['DXE_DRIVER','DXE_RUNTIME_DRIVER','DXE_SAL_DRIVER','UEFI_DRIVER']:
2876 AsBuiltInfDict
['binary_item'] += ['DXE_DEPEX|' + self
.Name
+ '.depex']
2877 if self
.ModuleType
in ['DXE_SMM_DRIVER']:
2878 AsBuiltInfDict
['binary_item'] += ['SMM_DEPEX|' + self
.Name
+ '.depex']
2880 for Root
, Dirs
, Files
in os
.walk(OutputDir
):
2882 if File
.lower().endswith('.pdb'):
2883 AsBuiltInfDict
['binary_item'] += ['DISPOSABLE|' + File
]
2884 HeaderComments
= self
.Module
.HeaderComments
2886 for Index
in range(len(HeaderComments
)):
2887 if HeaderComments
[Index
].find('@BinaryHeader') != -1:
2888 HeaderComments
[Index
] = HeaderComments
[Index
].replace('@BinaryHeader', '@file')
2891 AsBuiltInfDict
['header_comments'] = '\n'.join(HeaderComments
[StartPos
:]).replace(':#', '://')
2893 (self
.ProtocolList
, self
._ProtocolComments
, 'protocol_item'),
2894 (self
.PpiList
, self
._PpiComments
, 'ppi_item'),
2895 (GuidList
, self
._GuidComments
, 'guid_item')
2897 for Item
in GenList
:
2898 for CName
in Item
[0]:
2900 if CName
in Item
[1]:
2901 Comments
= '\n '.join(Item
[1][CName
])
2904 Entry
= Comments
+ '\n ' + CName
2905 AsBuiltInfDict
[Item
[2]].append(Entry
)
2906 PatchList
= parsePcdInfoFromMapFile(
2907 os
.path
.join(self
.OutputDir
, self
.Name
+ '.map'),
2908 os
.path
.join(self
.OutputDir
, self
.Name
+ '.efi')
2911 for PatchPcd
in PatchList
:
2912 if PatchPcd
[0] not in PatchablePcds
:
2914 Pcd
= PatchablePcds
[PatchPcd
[0]]
2916 if Pcd
.DatumType
!= 'VOID*':
2917 HexFormat
= '0x%02x'
2918 if Pcd
.DatumType
== 'UINT16':
2919 HexFormat
= '0x%04x'
2920 elif Pcd
.DatumType
== 'UINT32':
2921 HexFormat
= '0x%08x'
2922 elif Pcd
.DatumType
== 'UINT64':
2923 HexFormat
= '0x%016x'
2924 PcdValue
= HexFormat
% int(Pcd
.DefaultValue
, 0)
2926 if Pcd
.MaxDatumSize
== None or Pcd
.MaxDatumSize
== '':
2927 EdkLogger
.error("build", AUTOGEN_ERROR
,
2928 "Unknown [MaxDatumSize] of PCD [%s.%s]" % (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
)
2930 ArraySize
= int(Pcd
.MaxDatumSize
, 0)
2931 PcdValue
= Pcd
.DefaultValue
2932 if PcdValue
[0] != '{':
2934 if PcdValue
[0] == 'L':
2936 PcdValue
= PcdValue
.lstrip('L')
2937 PcdValue
= eval(PcdValue
)
2939 for Index
in range(0, len(PcdValue
)):
2941 CharVal
= ord(PcdValue
[Index
])
2942 NewValue
= NewValue
+ '0x%02x' % (CharVal
& 0x00FF) + ', ' \
2943 + '0x%02x' % (CharVal
>> 8) + ', '
2945 NewValue
= NewValue
+ '0x%02x' % (ord(PcdValue
[Index
]) % 0x100) + ', '
2948 Padding
= Padding
* 2
2949 ArraySize
= ArraySize
/ 2
2950 if ArraySize
< (len(PcdValue
) + 1):
2951 EdkLogger
.error("build", AUTOGEN_ERROR
,
2952 "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
)
2954 if ArraySize
> len(PcdValue
) + 1:
2955 NewValue
= NewValue
+ Padding
* (ArraySize
- len(PcdValue
) - 1)
2956 PcdValue
= NewValue
+ Padding
.strip().rstrip(',') + '}'
2957 elif len(PcdValue
.split(',')) <= ArraySize
:
2958 PcdValue
= PcdValue
.rstrip('}') + ', 0x00' * (ArraySize
- len(PcdValue
.split(',')))
2961 EdkLogger
.error("build", AUTOGEN_ERROR
,
2962 "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
)
2964 PcdItem
= '%s.%s|%s|0x%X' % \
2965 (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
, PcdValue
, PatchPcd
[1])
2967 if (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) in self
._PcdComments
:
2968 PcdComments
= '\n '.join(self
._PcdComments
[Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
])
2970 PcdItem
= PcdComments
+ '\n ' + PcdItem
2971 AsBuiltInfDict
['patchablepcd_item'].append(PcdItem
)
2976 if Pcd
.Type
== TAB_PCDS_DYNAMIC_EX_HII
:
2977 for SkuName
in Pcd
.SkuInfoList
:
2978 SkuInfo
= Pcd
.SkuInfoList
[SkuName
]
2979 HiiInfo
= '## %s|%s|%s' % (SkuInfo
.VariableName
, SkuInfo
.VariableGuid
, SkuInfo
.VariableOffset
)
2981 if (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) in self
._PcdComments
:
2982 PcdCommentList
= self
._PcdComments
[Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
][:]
2985 for Index
, Comment
in enumerate(PcdCommentList
):
2986 for Usage
in UsageList
:
2987 if Comment
.find(Usage
) != -1:
2990 if UsageIndex
!= -1:
2991 PcdCommentList
[UsageIndex
] = PcdCommentList
[UsageIndex
] + ' ' + HiiInfo
2993 PcdCommentList
.append('## ' + HiiInfo
)
2994 PcdComments
= '\n '.join(PcdCommentList
)
2995 PcdEntry
= Pcd
.TokenSpaceGuidCName
+ '.' + Pcd
.TokenCName
2997 PcdEntry
= PcdComments
+ '\n ' + PcdEntry
2998 AsBuiltInfDict
['pcd_item'] += [PcdEntry
]
2999 for Item
in self
.BuildOption
:
3000 if 'FLAGS' in self
.BuildOption
[Item
]:
3001 AsBuiltInfDict
['flags_item'] += ['%s:%s_%s_%s_%s_FLAGS = %s' % (self
.ToolChainFamily
, self
.BuildTarget
, self
.ToolChain
, self
.Arch
, Item
, self
.BuildOption
[Item
]['FLAGS'].strip())]
3003 AsBuiltInf
= TemplateString()
3004 AsBuiltInf
.Append(gAsBuiltInfHeaderString
.Replace(AsBuiltInfDict
))
3006 SaveFileOnChange(os
.path
.join(self
.OutputDir
, self
.Name
+ '.inf'), str(AsBuiltInf
), False)
3008 self
.IsAsBuiltInfCreated
= True
3010 ## Create makefile for the module and its dependent libraries
3012 # @param CreateLibraryMakeFile Flag indicating if or not the makefiles of
3013 # dependent libraries will be created
3015 def CreateMakeFile(self
, CreateLibraryMakeFile
=True):
3016 if self
.IsMakeFileCreated
:
3019 if not self
.IsLibrary
and CreateLibraryMakeFile
:
3020 for LibraryAutoGen
in self
.LibraryAutoGenList
:
3021 LibraryAutoGen
.CreateMakeFile()
3023 if len(self
.CustomMakefile
) == 0:
3024 Makefile
= GenMake
.ModuleMakefile(self
)
3026 Makefile
= GenMake
.CustomMakefile(self
)
3027 if Makefile
.Generate():
3028 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated makefile for module %s [%s]" %
3029 (self
.Name
, self
.Arch
))
3031 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Skipped the generation of makefile for module %s [%s]" %
3032 (self
.Name
, self
.Arch
))
3034 self
.IsMakeFileCreated
= True
3036 ## Create autogen code for the module and its dependent libraries
3038 # @param CreateLibraryCodeFile Flag indicating if or not the code of
3039 # dependent libraries will be created
3041 def CreateCodeFile(self
, CreateLibraryCodeFile
=True):
3042 if self
.IsCodeFileCreated
:
3045 # Need to generate PcdDatabase even PcdDriver is binarymodule
3046 if self
.IsBinaryModule
and self
.PcdIsDriver
!= '':
3047 CreatePcdDatabaseCode(self
, TemplateString(), TemplateString())
3050 if not self
.IsLibrary
and CreateLibraryCodeFile
:
3051 for LibraryAutoGen
in self
.LibraryAutoGenList
:
3052 LibraryAutoGen
.CreateCodeFile()
3055 IgoredAutoGenList
= []
3057 for File
in self
.AutoGenFileList
:
3058 if GenC
.Generate(File
.Path
, self
.AutoGenFileList
[File
], File
.IsBinary
):
3059 #Ignore Edk AutoGen.c
3060 if self
.AutoGenVersion
< 0x00010005 and File
.Name
== 'AutoGen.c':
3063 AutoGenList
.append(str(File
))
3065 IgoredAutoGenList
.append(str(File
))
3067 # Skip the following code for EDK I inf
3068 if self
.AutoGenVersion
< 0x00010005:
3071 for ModuleType
in self
.DepexList
:
3072 # Ignore empty [depex] section or [depex] section for "USER_DEFINED" module
3073 if len(self
.DepexList
[ModuleType
]) == 0 or ModuleType
== "USER_DEFINED":
3076 Dpx
= GenDepex
.DependencyExpression(self
.DepexList
[ModuleType
], ModuleType
, True)
3077 DpxFile
= gAutoGenDepexFileName
% {"module_name" : self
.Name
}
3079 if len(Dpx
.PostfixNotation
) <> 0:
3080 self
.DepexGenerated
= True
3082 if Dpx
.Generate(path
.join(self
.OutputDir
, DpxFile
)):
3083 AutoGenList
.append(str(DpxFile
))
3085 IgoredAutoGenList
.append(str(DpxFile
))
3087 if IgoredAutoGenList
== []:
3088 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated [%s] files for module %s [%s]" %
3089 (" ".join(AutoGenList
), self
.Name
, self
.Arch
))
3090 elif AutoGenList
== []:
3091 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Skipped the generation of [%s] files for module %s [%s]" %
3092 (" ".join(IgoredAutoGenList
), self
.Name
, self
.Arch
))
3094 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated [%s] (skipped %s) files for module %s [%s]" %
3095 (" ".join(AutoGenList
), " ".join(IgoredAutoGenList
), self
.Name
, self
.Arch
))
3097 self
.IsCodeFileCreated
= True
3100 ## Summarize the ModuleAutoGen objects of all libraries used by this module
3101 def _GetLibraryAutoGenList(self
):
3102 if self
._LibraryAutoGenList
== None:
3103 self
._LibraryAutoGenList
= []
3104 for Library
in self
.DependentLibraryList
:
3111 self
.PlatformInfo
.MetaFile
3113 if La
not in self
._LibraryAutoGenList
:
3114 self
._LibraryAutoGenList
.append(La
)
3115 for Lib
in La
.CodaTargetList
:
3116 self
._ApplyBuildRule
(Lib
.Target
, TAB_UNKNOWN_FILE
)
3117 return self
._LibraryAutoGenList
3119 Module
= property(_GetModule
)
3120 Name
= property(_GetBaseName
)
3121 Guid
= property(_GetGuid
)
3122 Version
= property(_GetVersion
)
3123 ModuleType
= property(_GetModuleType
)
3124 ComponentType
= property(_GetComponentType
)
3125 BuildType
= property(_GetBuildType
)
3126 PcdIsDriver
= property(_GetPcdIsDriver
)
3127 AutoGenVersion
= property(_GetAutoGenVersion
)
3128 Macros
= property(_GetMacros
)
3129 Specification
= property(_GetSpecification
)
3131 IsLibrary
= property(_IsLibrary
)
3132 IsBinaryModule
= property(_IsBinaryModule
)
3133 BuildDir
= property(_GetBuildDir
)
3134 OutputDir
= property(_GetOutputDir
)
3135 DebugDir
= property(_GetDebugDir
)
3136 MakeFileDir
= property(_GetMakeFileDir
)
3137 CustomMakefile
= property(_GetCustomMakefile
)
3139 IncludePathList
= property(_GetIncludePathList
)
3140 AutoGenFileList
= property(_GetAutoGenFileList
)
3141 UnicodeFileList
= property(_GetUnicodeFileList
)
3142 SourceFileList
= property(_GetSourceFileList
)
3143 BinaryFileList
= property(_GetBinaryFiles
) # FileType : [File List]
3144 Targets
= property(_GetTargets
)
3145 IntroTargetList
= property(_GetIntroTargetList
)
3146 CodaTargetList
= property(_GetFinalTargetList
)
3147 FileTypes
= property(_GetFileTypes
)
3148 BuildRules
= property(_GetBuildRules
)
3150 DependentPackageList
= property(_GetDependentPackageList
)
3151 DependentLibraryList
= property(_GetLibraryList
)
3152 LibraryAutoGenList
= property(_GetLibraryAutoGenList
)
3153 DerivedPackageList
= property(_GetDerivedPackageList
)
3155 ModulePcdList
= property(_GetModulePcdList
)
3156 LibraryPcdList
= property(_GetLibraryPcdList
)
3157 GuidList
= property(_GetGuidList
)
3158 ProtocolList
= property(_GetProtocolList
)
3159 PpiList
= property(_GetPpiList
)
3160 DepexList
= property(_GetDepexTokenList
)
3161 DxsFile
= property(_GetDxsFile
)
3162 DepexExpressionList
= property(_GetDepexExpressionTokenList
)
3163 BuildOption
= property(_GetModuleBuildOption
)
3164 BuildOptionIncPathList
= property(_GetBuildOptionIncPathList
)
3165 BuildCommand
= property(_GetBuildCommand
)
3167 FixedAtBuildPcds
= property(_GetFixedAtBuildPcds
)
3169 # This acts like the main() function for the script, unless it is 'import'ed into another script.
3170 if __name__
== '__main__':