2 # Generate AutoGen.h, AutoGen.c and *.depex files
4 # Copyright (c) 2007 - 2017, Intel Corporation. All rights reserved.<BR>
5 # This program and the accompanying materials
6 # are licensed and made available under the terms and conditions of the BSD License
7 # which accompanies this distribution. The full text of the license may be found at
8 # http://opensource.org/licenses/bsd-license.php
10 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 import Common
.LongFilePathOs
as os
18 import os
.path
as path
25 from StringIO
import StringIO
27 from StrGather
import *
28 from BuildEngine
import BuildRule
30 from Common
.LongFilePathSupport
import CopyLongFilePath
31 from Common
.BuildToolError
import *
32 from Common
.DataType
import *
33 from Common
.Misc
import *
34 from Common
.String
import *
35 import Common
.GlobalData
as GlobalData
36 from GenFds
.FdfParser
import *
37 from CommonDataClass
.CommonClass
import SkuInfoClass
38 from Workspace
.BuildClassObject
import *
39 from GenPatchPcdTable
.GenPatchPcdTable
import parsePcdInfoFromMapFile
40 import Common
.VpdInfoFile
as VpdInfoFile
41 from GenPcdDb
import CreatePcdDatabaseCode
42 from Workspace
.MetaFileCommentParser
import UsageList
43 from Common
.MultipleWorkspace
import MultipleWorkspace
as mws
44 import InfSectionParser
47 from GenVar
import VariableMgr
,var_info
49 ## Regular expression for splitting Dependency Expression string into tokens
50 gDepexTokenPattern
= re
.compile("(\(|\)|\w+| \S+\.inf)")
53 # Match name = variable
55 gEfiVarStoreNamePattern
= re
.compile("\s*name\s*=\s*(\w+)")
57 # The format of guid in efivarstore statement likes following and must be correct:
58 # guid = {0xA04A27f4, 0xDF00, 0x4D42, {0xB5, 0x52, 0x39, 0x51, 0x13, 0x02, 0x11, 0x3D}}
60 gEfiVarStoreGuidPattern
= re
.compile("\s*guid\s*=\s*({.*?{.*?}\s*})")
62 ## Mapping Makefile type
63 gMakeTypeMap
= {"MSFT":"nmake", "GCC":"gmake"}
66 ## Build rule configuration file
67 gDefaultBuildRuleFile
= 'build_rule.txt'
69 ## Tools definition configuration file
70 gDefaultToolsDefFile
= 'tools_def.txt'
72 ## Build rule default version
73 AutoGenReqBuildRuleVerNum
= "0.1"
75 ## default file name for AutoGen
76 gAutoGenCodeFileName
= "AutoGen.c"
77 gAutoGenHeaderFileName
= "AutoGen.h"
78 gAutoGenStringFileName
= "%(module_name)sStrDefs.h"
79 gAutoGenStringFormFileName
= "%(module_name)sStrDefs.hpk"
80 gAutoGenDepexFileName
= "%(module_name)s.depex"
81 gAutoGenImageDefFileName
= "%(module_name)sImgDefs.h"
82 gAutoGenIdfFileName
= "%(module_name)sIdf.hpk"
83 gInfSpecVersion
= "0x00010017"
86 # Template string to generic AsBuilt INF
88 gAsBuiltInfHeaderString
= TemplateString("""${header_comments}
94 INF_VERSION = ${module_inf_version}
95 BASE_NAME = ${module_name}
96 FILE_GUID = ${module_guid}
97 MODULE_TYPE = ${module_module_type}${BEGIN}
98 VERSION_STRING = ${module_version_string}${END}${BEGIN}
99 PCD_IS_DRIVER = ${pcd_is_driver_string}${END}${BEGIN}
100 UEFI_SPECIFICATION_VERSION = ${module_uefi_specification_version}${END}${BEGIN}
101 PI_SPECIFICATION_VERSION = ${module_pi_specification_version}${END}${BEGIN}
102 ENTRY_POINT = ${module_entry_point}${END}${BEGIN}
103 UNLOAD_IMAGE = ${module_unload_image}${END}${BEGIN}
104 CONSTRUCTOR = ${module_constructor}${END}${BEGIN}
105 DESTRUCTOR = ${module_destructor}${END}${BEGIN}
106 SHADOW = ${module_shadow}${END}${BEGIN}
107 PCI_VENDOR_ID = ${module_pci_vendor_id}${END}${BEGIN}
108 PCI_DEVICE_ID = ${module_pci_device_id}${END}${BEGIN}
109 PCI_CLASS_CODE = ${module_pci_class_code}${END}${BEGIN}
110 PCI_REVISION = ${module_pci_revision}${END}${BEGIN}
111 BUILD_NUMBER = ${module_build_number}${END}${BEGIN}
112 SPEC = ${module_spec}${END}${BEGIN}
113 UEFI_HII_RESOURCE_SECTION = ${module_uefi_hii_resource_section}${END}${BEGIN}
114 MODULE_UNI_FILE = ${module_uni_file}${END}
116 [Packages.${module_arch}]${BEGIN}
117 ${package_item}${END}
119 [Binaries.${module_arch}]${BEGIN}
122 [PatchPcd.${module_arch}]${BEGIN}
126 [Protocols.${module_arch}]${BEGIN}
130 [Ppis.${module_arch}]${BEGIN}
134 [Guids.${module_arch}]${BEGIN}
138 [PcdEx.${module_arch}]${BEGIN}
142 [LibraryClasses.${module_arch}]
143 ## @LIB_INSTANCES${BEGIN}
144 # ${libraryclasses_item}${END}
148 ${userextension_tianocore_item}
152 [BuildOptions.${module_arch}]
154 ## ${flags_item}${END}
157 ## Base class for AutoGen
159 # This class just implements the cache mechanism of AutoGen objects.
161 class AutoGen(object):
162 # database to maintain the objects of xxxAutoGen
163 _CACHE_
= {} # (BuildTarget, ToolChain) : {ARCH : {platform file: AutoGen object}}}
167 # @param Class class object of real AutoGen class
168 # (WorkspaceAutoGen, ModuleAutoGen or PlatformAutoGen)
169 # @param Workspace Workspace directory or WorkspaceAutoGen object
170 # @param MetaFile The path of meta file
171 # @param Target Build target
172 # @param Toolchain Tool chain name
173 # @param Arch Target arch
174 # @param *args The specific class related parameters
175 # @param **kwargs The specific class related dict parameters
177 def __new__(Class
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
178 # check if the object has been created
179 Key
= (Target
, Toolchain
)
180 if Key
not in Class
._CACHE
_ or Arch
not in Class
._CACHE
_[Key
] \
181 or MetaFile
not in Class
._CACHE
_[Key
][Arch
]:
182 AutoGenObject
= super(AutoGen
, Class
).__new
__(Class
)
183 # call real constructor
184 if not AutoGenObject
._Init
(Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
186 if Key
not in Class
._CACHE
_:
187 Class
._CACHE
_[Key
] = {}
188 if Arch
not in Class
._CACHE
_[Key
]:
189 Class
._CACHE
_[Key
][Arch
] = {}
190 Class
._CACHE
_[Key
][Arch
][MetaFile
] = AutoGenObject
192 AutoGenObject
= Class
._CACHE
_[Key
][Arch
][MetaFile
]
198 # The file path of platform file will be used to represent hash value of this object
200 # @retval int Hash value of the file path of platform file
203 return hash(self
.MetaFile
)
207 # The file path of platform file will be used to represent this object
209 # @retval string String of platform file path
212 return str(self
.MetaFile
)
215 def __eq__(self
, Other
):
216 return Other
and self
.MetaFile
== Other
218 ## Workspace AutoGen class
220 # This class is used mainly to control the whole platform build for different
221 # architecture. This class will generate top level makefile.
223 class WorkspaceAutoGen(AutoGen
):
224 ## Real constructor of WorkspaceAutoGen
226 # This method behaves the same as __init__ except that it needs explicit invoke
227 # (in super class's __new__ method)
229 # @param WorkspaceDir Root directory of workspace
230 # @param ActivePlatform Meta-file of active platform
231 # @param Target Build target
232 # @param Toolchain Tool chain name
233 # @param ArchList List of architecture of current build
234 # @param MetaFileDb Database containing meta-files
235 # @param BuildConfig Configuration of build
236 # @param ToolDefinition Tool chain definitions
237 # @param FlashDefinitionFile File of flash definition
238 # @param Fds FD list to be generated
239 # @param Fvs FV list to be generated
240 # @param Caps Capsule list to be generated
241 # @param SkuId SKU id from command line
243 def _Init(self
, WorkspaceDir
, ActivePlatform
, Target
, Toolchain
, ArchList
, MetaFileDb
,
244 BuildConfig
, ToolDefinition
, FlashDefinitionFile
='', Fds
=None, Fvs
=None, Caps
=None, SkuId
='', UniFlag
=None,
245 Progress
=None, BuildModule
=None):
252 self
.BuildDatabase
= MetaFileDb
253 self
.MetaFile
= ActivePlatform
254 self
.WorkspaceDir
= WorkspaceDir
255 self
.Platform
= self
.BuildDatabase
[self
.MetaFile
, 'COMMON', Target
, Toolchain
]
256 GlobalData
.gActivePlatform
= self
.Platform
257 self
.BuildTarget
= Target
258 self
.ToolChain
= Toolchain
259 self
.ArchList
= ArchList
261 self
.UniFlag
= UniFlag
263 self
.TargetTxt
= BuildConfig
264 self
.ToolDef
= ToolDefinition
265 self
.FdfFile
= FlashDefinitionFile
266 self
.FdTargetList
= Fds
267 self
.FvTargetList
= Fvs
268 self
.CapTargetList
= Caps
269 self
.AutoGenObjectList
= []
270 self
._BuildDir
= None
272 self
._MakeFileDir
= None
273 self
._BuildCommand
= None
275 # there's many relative directory operations, so ...
276 os
.chdir(self
.WorkspaceDir
)
281 if not self
.ArchList
:
282 ArchList
= set(self
.Platform
.SupArchList
)
284 ArchList
= set(self
.ArchList
) & set(self
.Platform
.SupArchList
)
286 EdkLogger
.error("build", PARAMETER_INVALID
,
287 ExtraData
= "Invalid ARCH specified. [Valid ARCH: %s]" % (" ".join(self
.Platform
.SupArchList
)))
288 elif self
.ArchList
and len(ArchList
) != len(self
.ArchList
):
289 SkippedArchList
= set(self
.ArchList
).symmetric_difference(set(self
.Platform
.SupArchList
))
290 EdkLogger
.verbose("\nArch [%s] is ignored because the platform supports [%s] only!"
291 % (" ".join(SkippedArchList
), " ".join(self
.Platform
.SupArchList
)))
292 self
.ArchList
= tuple(ArchList
)
294 # Validate build target
295 if self
.BuildTarget
not in self
.Platform
.BuildTargets
:
296 EdkLogger
.error("build", PARAMETER_INVALID
,
297 ExtraData
="Build target [%s] is not supported by the platform. [Valid target: %s]"
298 % (self
.BuildTarget
, " ".join(self
.Platform
.BuildTargets
)))
301 # parse FDF file to get PCDs in it, if any
303 self
.FdfFile
= self
.Platform
.FlashDefinition
307 EdkLogger
.info('%-16s = %s' % ("Architecture(s)", ' '.join(self
.ArchList
)))
308 EdkLogger
.info('%-16s = %s' % ("Build target", self
.BuildTarget
))
309 EdkLogger
.info('%-16s = %s' % ("Toolchain", self
.ToolChain
))
311 EdkLogger
.info('\n%-24s = %s' % ("Active Platform", self
.Platform
))
313 EdkLogger
.info('%-24s = %s' % ("Active Module", BuildModule
))
316 EdkLogger
.info('%-24s = %s' % ("Flash Image Definition", self
.FdfFile
))
318 EdkLogger
.verbose("\nFLASH_DEFINITION = %s" % self
.FdfFile
)
321 # Progress.Start("\nProcessing meta-data")
325 # Mark now build in AutoGen Phase
327 GlobalData
.gAutoGenPhase
= True
328 Fdf
= FdfParser(self
.FdfFile
.Path
)
330 GlobalData
.gFdfParser
= Fdf
331 GlobalData
.gAutoGenPhase
= False
332 PcdSet
= Fdf
.Profile
.PcdDict
333 if Fdf
.CurrentFdName
and Fdf
.CurrentFdName
in Fdf
.Profile
.FdDict
:
334 FdDict
= Fdf
.Profile
.FdDict
[Fdf
.CurrentFdName
]
335 for FdRegion
in FdDict
.RegionList
:
336 if str(FdRegion
.RegionType
) is 'FILE' and self
.Platform
.VpdToolGuid
in str(FdRegion
.RegionDataList
):
337 if int(FdRegion
.Offset
) % 8 != 0:
338 EdkLogger
.error("build", FORMAT_INVALID
, 'The VPD Base Address %s must be 8-byte aligned.' % (FdRegion
.Offset
))
339 ModuleList
= Fdf
.Profile
.InfList
340 self
.FdfProfile
= Fdf
.Profile
341 for fvname
in self
.FvTargetList
:
342 if fvname
.upper() not in self
.FdfProfile
.FvDict
:
343 EdkLogger
.error("build", OPTION_VALUE_INVALID
,
344 "No such an FV in FDF file: %s" % fvname
)
346 # In DSC file may use FILE_GUID to override the module, then in the Platform.Modules use FILE_GUIDmodule.inf as key,
347 # but the path (self.MetaFile.Path) is the real path
348 for key
in self
.FdfProfile
.InfDict
:
352 for Arch
in self
.ArchList
:
353 Platform_cache
[Arch
] = self
.BuildDatabase
[self
.MetaFile
, Arch
, Target
, Toolchain
]
354 MetaFile_cache
[Arch
] = []
355 for Pkey
in Platform_cache
[Arch
].Modules
.keys():
356 MetaFile_cache
[Arch
].append(Platform_cache
[Arch
].Modules
[Pkey
].MetaFile
)
357 for Inf
in self
.FdfProfile
.InfDict
[key
]:
358 ModuleFile
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, Arch
)
359 for Arch
in self
.ArchList
:
360 if ModuleFile
in MetaFile_cache
[Arch
]:
363 ModuleData
= self
.BuildDatabase
[ModuleFile
, Arch
, Target
, Toolchain
]
364 if not ModuleData
.IsBinaryModule
:
365 EdkLogger
.error('build', PARSER_ERROR
, "Module %s NOT found in DSC file; Is it really a binary module?" % ModuleFile
)
368 for Arch
in self
.ArchList
:
370 Platform
= self
.BuildDatabase
[self
.MetaFile
, Arch
, Target
, Toolchain
]
372 for Pkey
in Platform
.Modules
.keys():
373 MetaFileList
.append(Platform
.Modules
[Pkey
].MetaFile
)
374 for Inf
in self
.FdfProfile
.InfDict
[key
]:
375 ModuleFile
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, Arch
)
376 if ModuleFile
in MetaFileList
:
378 ModuleData
= self
.BuildDatabase
[ModuleFile
, Arch
, Target
, Toolchain
]
379 if not ModuleData
.IsBinaryModule
:
380 EdkLogger
.error('build', PARSER_ERROR
, "Module %s NOT found in DSC file; Is it really a binary module?" % ModuleFile
)
385 self
.FdfProfile
= None
386 if self
.FdTargetList
:
387 EdkLogger
.info("No flash definition file found. FD [%s] will be ignored." % " ".join(self
.FdTargetList
))
388 self
.FdTargetList
= []
389 if self
.FvTargetList
:
390 EdkLogger
.info("No flash definition file found. FV [%s] will be ignored." % " ".join(self
.FvTargetList
))
391 self
.FvTargetList
= []
392 if self
.CapTargetList
:
393 EdkLogger
.info("No flash definition file found. Capsule [%s] will be ignored." % " ".join(self
.CapTargetList
))
394 self
.CapTargetList
= []
396 # apply SKU and inject PCDs from Flash Definition file
397 for Arch
in self
.ArchList
:
398 Platform
= self
.BuildDatabase
[self
.MetaFile
, Arch
, Target
, Toolchain
]
402 PGen
= PlatformAutoGen(self
, self
.MetaFile
, Target
, Toolchain
, Arch
)
403 if GlobalData
.BuildOptionPcd
:
404 for i
, pcd
in enumerate(GlobalData
.BuildOptionPcd
):
405 if type(pcd
) is tuple:
407 (pcdname
, pcdvalue
) = pcd
.split('=')
409 EdkLogger
.error('build', AUTOGEN_ERROR
, "No Value specified for the PCD %s." % (pcdname
))
411 (TokenSpaceGuidCName
, TokenCName
) = pcdname
.split('.')
415 TokenSpaceGuidCName
= ''
416 HasTokenSpace
= False
417 TokenSpaceGuidCNameList
= []
421 for package
in PGen
.PackageList
:
422 for key
in package
.Pcds
:
423 PcdItem
= package
.Pcds
[key
]
425 if (PcdItem
.TokenCName
, PcdItem
.TokenSpaceGuidCName
) == (TokenCName
, TokenSpaceGuidCName
):
426 PcdDatumType
= PcdItem
.DatumType
427 NewValue
= BuildOptionPcdValueFormat(TokenSpaceGuidCName
, TokenCName
, PcdDatumType
, pcdvalue
)
430 if PcdItem
.TokenCName
== TokenCName
:
431 if not PcdItem
.TokenSpaceGuidCName
in TokenSpaceGuidCNameList
:
432 if len (TokenSpaceGuidCNameList
) < 1:
433 TokenSpaceGuidCNameList
.append(PcdItem
.TokenSpaceGuidCName
)
434 PcdDatumType
= PcdItem
.DatumType
435 TokenSpaceGuidCName
= PcdItem
.TokenSpaceGuidCName
436 NewValue
= BuildOptionPcdValueFormat(TokenSpaceGuidCName
, TokenCName
, PcdDatumType
, pcdvalue
)
442 "The Pcd %s is found under multiple different TokenSpaceGuid: %s and %s." % (TokenCName
, PcdItem
.TokenSpaceGuidCName
, TokenSpaceGuidCNameList
[0])
445 GlobalData
.BuildOptionPcd
[i
] = (TokenSpaceGuidCName
, TokenCName
, NewValue
)
449 EdkLogger
.error('build', AUTOGEN_ERROR
, "The Pcd %s.%s is not found in the DEC file." % (TokenSpaceGuidCName
, TokenCName
))
451 EdkLogger
.error('build', AUTOGEN_ERROR
, "The Pcd %s is not found in the DEC file." % (TokenCName
))
453 for BuildData
in PGen
.BuildDatabase
._CACHE
_.values():
454 if BuildData
.Arch
!= Arch
:
456 if BuildData
.MetaFile
.Ext
== '.dec':
458 for key
in BuildData
.Pcds
:
459 PcdItem
= BuildData
.Pcds
[key
]
460 if (TokenSpaceGuidCName
, TokenCName
) == (PcdItem
.TokenSpaceGuidCName
, PcdItem
.TokenCName
):
461 PcdItem
.DefaultValue
= NewValue
463 if (TokenCName
, TokenSpaceGuidCName
) in PcdSet
:
464 PcdSet
[(TokenCName
, TokenSpaceGuidCName
)] = NewValue
466 SourcePcdDict
= {'DynamicEx':[], 'PatchableInModule':[],'Dynamic':[],'FixedAtBuild':[]}
467 BinaryPcdDict
= {'DynamicEx':[], 'PatchableInModule':[]}
468 SourcePcdDict_Keys
= SourcePcdDict
.keys()
469 BinaryPcdDict_Keys
= BinaryPcdDict
.keys()
471 # generate the SourcePcdDict and BinaryPcdDict
472 for BuildData
in PGen
.BuildDatabase
._CACHE
_.values():
473 if BuildData
.Arch
!= Arch
:
475 if BuildData
.MetaFile
.Ext
== '.inf':
476 for key
in BuildData
.Pcds
:
477 if BuildData
.Pcds
[key
].Pending
:
478 if key
in Platform
.Pcds
:
479 PcdInPlatform
= Platform
.Pcds
[key
]
480 if PcdInPlatform
.Type
not in [None, '']:
481 BuildData
.Pcds
[key
].Type
= PcdInPlatform
.Type
483 if BuildData
.MetaFile
in Platform
.Modules
:
484 PlatformModule
= Platform
.Modules
[str(BuildData
.MetaFile
)]
485 if key
in PlatformModule
.Pcds
:
486 PcdInPlatform
= PlatformModule
.Pcds
[key
]
487 if PcdInPlatform
.Type
not in [None, '']:
488 BuildData
.Pcds
[key
].Type
= PcdInPlatform
.Type
490 if 'DynamicEx' in BuildData
.Pcds
[key
].Type
:
491 if BuildData
.IsBinaryModule
:
492 if (BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
) not in BinaryPcdDict
['DynamicEx']:
493 BinaryPcdDict
['DynamicEx'].append((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
495 if (BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
) not in SourcePcdDict
['DynamicEx']:
496 SourcePcdDict
['DynamicEx'].append((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
498 elif 'PatchableInModule' in BuildData
.Pcds
[key
].Type
:
499 if BuildData
.MetaFile
.Ext
== '.inf':
500 if BuildData
.IsBinaryModule
:
501 if (BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
) not in BinaryPcdDict
['PatchableInModule']:
502 BinaryPcdDict
['PatchableInModule'].append((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
504 if (BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
) not in SourcePcdDict
['PatchableInModule']:
505 SourcePcdDict
['PatchableInModule'].append((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
507 elif 'Dynamic' in BuildData
.Pcds
[key
].Type
:
508 if (BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
) not in SourcePcdDict
['Dynamic']:
509 SourcePcdDict
['Dynamic'].append((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
510 elif 'FixedAtBuild' in BuildData
.Pcds
[key
].Type
:
511 if (BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
) not in SourcePcdDict
['FixedAtBuild']:
512 SourcePcdDict
['FixedAtBuild'].append((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
516 # A PCD can only use one type for all source modules
518 for i
in SourcePcdDict_Keys
:
519 for j
in SourcePcdDict_Keys
:
521 IntersectionList
= list(set(SourcePcdDict
[i
]).intersection(set(SourcePcdDict
[j
])))
522 if len(IntersectionList
) > 0:
526 "Building modules from source INFs, following PCD use %s and %s access method. It must be corrected to use only one access method." % (i
, j
),
527 ExtraData
="%s" % '\n\t'.join([str(P
[1]+'.'+P
[0]) for P
in IntersectionList
])
533 # intersection the BinaryPCD for Mixed PCD
535 for i
in BinaryPcdDict_Keys
:
536 for j
in BinaryPcdDict_Keys
:
538 IntersectionList
= list(set(BinaryPcdDict
[i
]).intersection(set(BinaryPcdDict
[j
])))
539 for item
in IntersectionList
:
540 NewPcd1
= (item
[0] + '_' + i
, item
[1])
541 NewPcd2
= (item
[0] + '_' + j
, item
[1])
542 if item
not in GlobalData
.MixedPcd
:
543 GlobalData
.MixedPcd
[item
] = [NewPcd1
, NewPcd2
]
545 if NewPcd1
not in GlobalData
.MixedPcd
[item
]:
546 GlobalData
.MixedPcd
[item
].append(NewPcd1
)
547 if NewPcd2
not in GlobalData
.MixedPcd
[item
]:
548 GlobalData
.MixedPcd
[item
].append(NewPcd2
)
553 # intersection the SourcePCD and BinaryPCD for Mixed PCD
555 for i
in SourcePcdDict_Keys
:
556 for j
in BinaryPcdDict_Keys
:
558 IntersectionList
= list(set(SourcePcdDict
[i
]).intersection(set(BinaryPcdDict
[j
])))
559 for item
in IntersectionList
:
560 NewPcd1
= (item
[0] + '_' + i
, item
[1])
561 NewPcd2
= (item
[0] + '_' + j
, item
[1])
562 if item
not in GlobalData
.MixedPcd
:
563 GlobalData
.MixedPcd
[item
] = [NewPcd1
, NewPcd2
]
565 if NewPcd1
not in GlobalData
.MixedPcd
[item
]:
566 GlobalData
.MixedPcd
[item
].append(NewPcd1
)
567 if NewPcd2
not in GlobalData
.MixedPcd
[item
]:
568 GlobalData
.MixedPcd
[item
].append(NewPcd2
)
572 for BuildData
in PGen
.BuildDatabase
._CACHE
_.values():
573 if BuildData
.Arch
!= Arch
:
575 for key
in BuildData
.Pcds
:
576 for SinglePcd
in GlobalData
.MixedPcd
:
577 if (BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
) == SinglePcd
:
578 for item
in GlobalData
.MixedPcd
[SinglePcd
]:
579 Pcd_Type
= item
[0].split('_')[-1]
580 if (Pcd_Type
== BuildData
.Pcds
[key
].Type
) or (Pcd_Type
== TAB_PCDS_DYNAMIC_EX
and BuildData
.Pcds
[key
].Type
in GenC
.gDynamicExPcd
) or \
581 (Pcd_Type
== TAB_PCDS_DYNAMIC
and BuildData
.Pcds
[key
].Type
in GenC
.gDynamicPcd
):
582 Value
= BuildData
.Pcds
[key
]
583 Value
.TokenCName
= BuildData
.Pcds
[key
].TokenCName
+ '_' + Pcd_Type
585 newkey
= (Value
.TokenCName
, key
[1])
587 newkey
= (Value
.TokenCName
, key
[1], key
[2])
588 del BuildData
.Pcds
[key
]
589 BuildData
.Pcds
[newkey
] = Value
597 # handle the mixed pcd in FDF file
599 if key
in GlobalData
.MixedPcd
:
602 for item
in GlobalData
.MixedPcd
[key
]:
605 #Collect package set information from INF of FDF
607 for Inf
in ModuleList
:
608 ModuleFile
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, Arch
)
609 if ModuleFile
in Platform
.Modules
:
611 ModuleData
= self
.BuildDatabase
[ModuleFile
, Arch
, Target
, Toolchain
]
612 PkgSet
.update(ModuleData
.Packages
)
613 Pkgs
= list(PkgSet
) + list(PGen
.PackageList
)
616 DecPcds
[Pcd
[0], Pcd
[1]] = Pkg
.Pcds
[Pcd
]
617 DecPcdsKey
.add((Pcd
[0], Pcd
[1], Pcd
[2]))
619 Platform
.SkuName
= self
.SkuId
620 for Name
, Guid
in PcdSet
:
621 if (Name
, Guid
) not in DecPcds
:
625 "PCD (%s.%s) used in FDF is not declared in DEC files." % (Guid
, Name
),
626 File
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
][0],
627 Line
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
][1]
630 # Check whether Dynamic or DynamicEx PCD used in FDF file. If used, build break and give a error message.
631 if (Name
, Guid
, TAB_PCDS_FIXED_AT_BUILD
) in DecPcdsKey \
632 or (Name
, Guid
, TAB_PCDS_PATCHABLE_IN_MODULE
) in DecPcdsKey \
633 or (Name
, Guid
, TAB_PCDS_FEATURE_FLAG
) in DecPcdsKey
:
634 Platform
.AddPcd(Name
, Guid
, PcdSet
[Name
, Guid
])
636 elif (Name
, Guid
, TAB_PCDS_DYNAMIC
) in DecPcdsKey
or (Name
, Guid
, TAB_PCDS_DYNAMIC_EX
) in DecPcdsKey
:
640 "Using Dynamic or DynamicEx type of PCD [%s.%s] in FDF file is not allowed." % (Guid
, Name
),
641 File
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
][0],
642 Line
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
][1]
645 Pa
= PlatformAutoGen(self
, self
.MetaFile
, Target
, Toolchain
, Arch
)
647 # Explicitly collect platform's dynamic PCDs
649 Pa
.CollectPlatformDynamicPcds()
650 Pa
.CollectFixedAtBuildPcds()
651 self
.AutoGenObjectList
.append(Pa
)
654 # Generate Package level hash value
656 GlobalData
.gPackageHash
[Arch
] = {}
657 if GlobalData
.gUseHashCache
:
659 self
._GenPkgLevelHash
(Pkg
)
662 # Check PCDs token value conflict in each DEC file.
664 self
._CheckAllPcdsTokenValueConflict
()
667 # Check PCD type and definition between DSC and DEC
669 self
._CheckPcdDefineAndType
()
672 # self._CheckDuplicateInFV(Fdf)
675 # Create BuildOptions Macro & PCD metafile, also add the Active Platform and FDF file.
677 content
= 'gCommandLineDefines: '
678 content
+= str(GlobalData
.gCommandLineDefines
)
679 content
+= os
.linesep
680 content
+= 'BuildOptionPcd: '
681 content
+= str(GlobalData
.BuildOptionPcd
)
682 content
+= os
.linesep
683 content
+= 'Active Platform: '
684 content
+= str(self
.Platform
)
685 content
+= os
.linesep
687 content
+= 'Flash Image Definition: '
688 content
+= str(self
.FdfFile
)
689 content
+= os
.linesep
690 SaveFileOnChange(os
.path
.join(self
.BuildDir
, 'BuildOptions'), content
, False)
693 # Create PcdToken Number file for Dynamic/DynamicEx Pcd.
695 PcdTokenNumber
= 'PcdTokenNumber: '
696 if Pa
.PcdTokenNumber
:
697 if Pa
.DynamicPcdList
:
698 for Pcd
in Pa
.DynamicPcdList
:
699 PcdTokenNumber
+= os
.linesep
700 PcdTokenNumber
+= str((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
))
701 PcdTokenNumber
+= ' : '
702 PcdTokenNumber
+= str(Pa
.PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
])
703 SaveFileOnChange(os
.path
.join(self
.BuildDir
, 'PcdTokenNumber'), PcdTokenNumber
, False)
706 # Get set of workspace metafiles
708 AllWorkSpaceMetaFiles
= self
._GetMetaFiles
(Target
, Toolchain
, Arch
)
711 # Retrieve latest modified time of all metafiles
714 for f
in AllWorkSpaceMetaFiles
:
715 if os
.stat(f
)[8] > SrcTimeStamp
:
716 SrcTimeStamp
= os
.stat(f
)[8]
717 self
._SrcTimeStamp
= SrcTimeStamp
719 if GlobalData
.gUseHashCache
:
721 for files
in AllWorkSpaceMetaFiles
:
722 if files
.endswith('.dec'):
728 SaveFileOnChange(os
.path
.join(self
.BuildDir
, 'AutoGen.hash'), m
.hexdigest(), True)
729 GlobalData
.gPlatformHash
= m
.hexdigest()
732 # Write metafile list to build directory
734 AutoGenFilePath
= os
.path
.join(self
.BuildDir
, 'AutoGen')
735 if os
.path
.exists (AutoGenFilePath
):
736 os
.remove(AutoGenFilePath
)
737 if not os
.path
.exists(self
.BuildDir
):
738 os
.makedirs(self
.BuildDir
)
739 with
open(os
.path
.join(self
.BuildDir
, 'AutoGen'), 'w+') as file:
740 for f
in AllWorkSpaceMetaFiles
:
744 def _GenPkgLevelHash(self
, Pkg
):
745 PkgDir
= os
.path
.join(self
.BuildDir
, Pkg
.Arch
, Pkg
.PackageName
)
746 CreateDirectory(PkgDir
)
747 HashFile
= os
.path
.join(PkgDir
, Pkg
.PackageName
+ '.hash')
749 # Get .dec file's hash value
750 f
= open(Pkg
.MetaFile
.Path
, 'r')
754 # Get include files hash value
756 for inc
in Pkg
.Includes
:
757 for Root
, Dirs
, Files
in os
.walk(str(inc
)):
759 File_Path
= os
.path
.join(Root
, File
)
760 f
= open(File_Path
, 'r')
764 SaveFileOnChange(HashFile
, m
.hexdigest(), True)
765 if Pkg
.PackageName
not in GlobalData
.gPackageHash
[Pkg
.Arch
]:
766 GlobalData
.gPackageHash
[Pkg
.Arch
][Pkg
.PackageName
] = m
.hexdigest()
768 def _GetMetaFiles(self
, Target
, Toolchain
, Arch
):
769 AllWorkSpaceMetaFiles
= set()
774 AllWorkSpaceMetaFiles
.add (self
.FdfFile
.Path
)
776 FdfFiles
= GlobalData
.gFdfParser
.GetAllIncludedFile()
778 AllWorkSpaceMetaFiles
.add (f
.FileName
)
782 AllWorkSpaceMetaFiles
.add(self
.MetaFile
.Path
)
785 # add build_rule.txt & tools_def.txt
787 AllWorkSpaceMetaFiles
.add(os
.path
.join(GlobalData
.gConfDirectory
, gDefaultBuildRuleFile
))
788 AllWorkSpaceMetaFiles
.add(os
.path
.join(GlobalData
.gConfDirectory
, gDefaultToolsDefFile
))
790 # add BuildOption metafile
792 AllWorkSpaceMetaFiles
.add(os
.path
.join(self
.BuildDir
, 'BuildOptions'))
794 # add PcdToken Number file for Dynamic/DynamicEx Pcd
796 AllWorkSpaceMetaFiles
.add(os
.path
.join(self
.BuildDir
, 'PcdTokenNumber'))
798 for Arch
in self
.ArchList
:
799 Platform
= self
.BuildDatabase
[self
.MetaFile
, Arch
, Target
, Toolchain
]
800 PGen
= PlatformAutoGen(self
, self
.MetaFile
, Target
, Toolchain
, Arch
)
805 for Package
in PGen
.PackageList
:
806 AllWorkSpaceMetaFiles
.add(Package
.MetaFile
.Path
)
811 for filePath
in Platform
._RawData
.IncludedFiles
:
812 AllWorkSpaceMetaFiles
.add(filePath
.Path
)
814 return AllWorkSpaceMetaFiles
816 ## _CheckDuplicateInFV() method
818 # Check whether there is duplicate modules/files exist in FV section.
819 # The check base on the file GUID;
821 def _CheckDuplicateInFV(self
, Fdf
):
822 for Fv
in Fdf
.Profile
.FvDict
:
824 for FfsFile
in Fdf
.Profile
.FvDict
[Fv
].FfsList
:
825 if FfsFile
.InfFileName
and FfsFile
.NameGuid
== None:
830 for Pa
in self
.AutoGenObjectList
:
833 for Module
in Pa
.ModuleAutoGenList
:
834 if path
.normpath(Module
.MetaFile
.File
) == path
.normpath(FfsFile
.InfFileName
):
836 if not Module
.Guid
.upper() in _GuidDict
.keys():
837 _GuidDict
[Module
.Guid
.upper()] = FfsFile
840 EdkLogger
.error("build",
842 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile
.CurrentLineNum
,
843 FfsFile
.CurrentLineContent
,
844 _GuidDict
[Module
.Guid
.upper()].CurrentLineNum
,
845 _GuidDict
[Module
.Guid
.upper()].CurrentLineContent
,
846 Module
.Guid
.upper()),
847 ExtraData
=self
.FdfFile
)
849 # Some INF files not have entity in DSC file.
852 if FfsFile
.InfFileName
.find('$') == -1:
853 InfPath
= NormPath(FfsFile
.InfFileName
)
854 if not os
.path
.exists(InfPath
):
855 EdkLogger
.error('build', GENFDS_ERROR
, "Non-existant Module %s !" % (FfsFile
.InfFileName
))
857 PathClassObj
= PathClass(FfsFile
.InfFileName
, self
.WorkspaceDir
)
859 # Here we just need to get FILE_GUID from INF file, use 'COMMON' as ARCH attribute. and use
860 # BuildObject from one of AutoGenObjectList is enough.
862 InfObj
= self
.AutoGenObjectList
[0].BuildDatabase
.WorkspaceDb
.BuildObject
[PathClassObj
, 'COMMON', self
.BuildTarget
, self
.ToolChain
]
863 if not InfObj
.Guid
.upper() in _GuidDict
.keys():
864 _GuidDict
[InfObj
.Guid
.upper()] = FfsFile
866 EdkLogger
.error("build",
868 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile
.CurrentLineNum
,
869 FfsFile
.CurrentLineContent
,
870 _GuidDict
[InfObj
.Guid
.upper()].CurrentLineNum
,
871 _GuidDict
[InfObj
.Guid
.upper()].CurrentLineContent
,
872 InfObj
.Guid
.upper()),
873 ExtraData
=self
.FdfFile
)
876 if FfsFile
.NameGuid
!= None:
877 _CheckPCDAsGuidPattern
= re
.compile("^PCD\(.+\..+\)$")
880 # If the NameGuid reference a PCD name.
881 # The style must match: PCD(xxxx.yyy)
883 if _CheckPCDAsGuidPattern
.match(FfsFile
.NameGuid
):
885 # Replace the PCD value.
887 _PcdName
= FfsFile
.NameGuid
.lstrip("PCD(").rstrip(")")
889 for Pa
in self
.AutoGenObjectList
:
891 for PcdItem
in Pa
.AllPcdList
:
892 if (PcdItem
.TokenSpaceGuidCName
+ "." + PcdItem
.TokenCName
) == _PcdName
:
894 # First convert from CFormatGuid to GUID string
896 _PcdGuidString
= GuidStructureStringToGuidString(PcdItem
.DefaultValue
)
898 if not _PcdGuidString
:
900 # Then try Byte array.
902 _PcdGuidString
= GuidStructureByteArrayToGuidString(PcdItem
.DefaultValue
)
904 if not _PcdGuidString
:
906 # Not Byte array or CFormat GUID, raise error.
908 EdkLogger
.error("build",
910 "The format of PCD value is incorrect. PCD: %s , Value: %s\n" % (_PcdName
, PcdItem
.DefaultValue
),
911 ExtraData
=self
.FdfFile
)
913 if not _PcdGuidString
.upper() in _GuidDict
.keys():
914 _GuidDict
[_PcdGuidString
.upper()] = FfsFile
918 EdkLogger
.error("build",
920 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile
.CurrentLineNum
,
921 FfsFile
.CurrentLineContent
,
922 _GuidDict
[_PcdGuidString
.upper()].CurrentLineNum
,
923 _GuidDict
[_PcdGuidString
.upper()].CurrentLineContent
,
924 FfsFile
.NameGuid
.upper()),
925 ExtraData
=self
.FdfFile
)
927 if not FfsFile
.NameGuid
.upper() in _GuidDict
.keys():
928 _GuidDict
[FfsFile
.NameGuid
.upper()] = FfsFile
931 # Two raw file GUID conflict.
933 EdkLogger
.error("build",
935 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile
.CurrentLineNum
,
936 FfsFile
.CurrentLineContent
,
937 _GuidDict
[FfsFile
.NameGuid
.upper()].CurrentLineNum
,
938 _GuidDict
[FfsFile
.NameGuid
.upper()].CurrentLineContent
,
939 FfsFile
.NameGuid
.upper()),
940 ExtraData
=self
.FdfFile
)
943 def _CheckPcdDefineAndType(self
):
945 "FixedAtBuild", "PatchableInModule", "FeatureFlag",
946 "Dynamic", #"DynamicHii", "DynamicVpd",
947 "DynamicEx", # "DynamicExHii", "DynamicExVpd"
950 # This dict store PCDs which are not used by any modules with specified arches
952 for Pa
in self
.AutoGenObjectList
:
953 # Key of DSC's Pcds dictionary is PcdCName, TokenSpaceGuid
954 for Pcd
in Pa
.Platform
.Pcds
:
955 PcdType
= Pa
.Platform
.Pcds
[Pcd
].Type
957 # If no PCD type, this PCD comes from FDF
961 # Try to remove Hii and Vpd suffix
962 if PcdType
.startswith("DynamicEx"):
963 PcdType
= "DynamicEx"
964 elif PcdType
.startswith("Dynamic"):
967 for Package
in Pa
.PackageList
:
968 # Key of DEC's Pcds dictionary is PcdCName, TokenSpaceGuid, PcdType
969 if (Pcd
[0], Pcd
[1], PcdType
) in Package
.Pcds
:
971 for Type
in PcdTypeList
:
972 if (Pcd
[0], Pcd
[1], Type
) in Package
.Pcds
:
976 "Type [%s] of PCD [%s.%s] in DSC file doesn't match the type [%s] defined in DEC file." \
977 % (Pa
.Platform
.Pcds
[Pcd
].Type
, Pcd
[1], Pcd
[0], Type
),
982 UnusedPcd
.setdefault(Pcd
, []).append(Pa
.Arch
)
984 for Pcd
in UnusedPcd
:
987 "The PCD was not specified by any INF module in the platform for the given architecture.\n"
988 "\tPCD: [%s.%s]\n\tPlatform: [%s]\n\tArch: %s"
989 % (Pcd
[1], Pcd
[0], os
.path
.basename(str(self
.MetaFile
)), str(UnusedPcd
[Pcd
])),
994 return "%s [%s]" % (self
.MetaFile
, ", ".join(self
.ArchList
))
996 ## Return the directory to store FV files
998 if self
._FvDir
== None:
999 self
._FvDir
= path
.join(self
.BuildDir
, 'FV')
1002 ## Return the directory to store all intermediate and final files built
1003 def _GetBuildDir(self
):
1004 if self
._BuildDir
== None:
1005 return self
.AutoGenObjectList
[0].BuildDir
1007 ## Return the build output directory platform specifies
1008 def _GetOutputDir(self
):
1009 return self
.Platform
.OutputDirectory
1011 ## Return platform name
1013 return self
.Platform
.PlatformName
1015 ## Return meta-file GUID
1017 return self
.Platform
.Guid
1019 ## Return platform version
1020 def _GetVersion(self
):
1021 return self
.Platform
.Version
1023 ## Return paths of tools
1024 def _GetToolDefinition(self
):
1025 return self
.AutoGenObjectList
[0].ToolDefinition
1027 ## Return directory of platform makefile
1029 # @retval string Makefile directory
1031 def _GetMakeFileDir(self
):
1032 if self
._MakeFileDir
== None:
1033 self
._MakeFileDir
= self
.BuildDir
1034 return self
._MakeFileDir
1036 ## Return build command string
1038 # @retval string Build command string
1040 def _GetBuildCommand(self
):
1041 if self
._BuildCommand
== None:
1042 # BuildCommand should be all the same. So just get one from platform AutoGen
1043 self
._BuildCommand
= self
.AutoGenObjectList
[0].BuildCommand
1044 return self
._BuildCommand
1046 ## Check the PCDs token value conflict in each DEC file.
1048 # Will cause build break and raise error message while two PCDs conflict.
1052 def _CheckAllPcdsTokenValueConflict(self
):
1053 for Pa
in self
.AutoGenObjectList
:
1054 for Package
in Pa
.PackageList
:
1055 PcdList
= Package
.Pcds
.values()
1056 PcdList
.sort(lambda x
, y
: cmp(int(x
.TokenValue
, 0), int(y
.TokenValue
, 0)))
1058 while (Count
< len(PcdList
) - 1) :
1059 Item
= PcdList
[Count
]
1060 ItemNext
= PcdList
[Count
+ 1]
1062 # Make sure in the same token space the TokenValue should be unique
1064 if (int(Item
.TokenValue
, 0) == int(ItemNext
.TokenValue
, 0)):
1065 SameTokenValuePcdList
= []
1066 SameTokenValuePcdList
.append(Item
)
1067 SameTokenValuePcdList
.append(ItemNext
)
1068 RemainPcdListLength
= len(PcdList
) - Count
- 2
1069 for ValueSameCount
in range(RemainPcdListLength
):
1070 if int(PcdList
[len(PcdList
) - RemainPcdListLength
+ ValueSameCount
].TokenValue
, 0) == int(Item
.TokenValue
, 0):
1071 SameTokenValuePcdList
.append(PcdList
[len(PcdList
) - RemainPcdListLength
+ ValueSameCount
])
1075 # Sort same token value PCD list with TokenGuid and TokenCName
1077 SameTokenValuePcdList
.sort(lambda x
, y
: cmp("%s.%s" % (x
.TokenSpaceGuidCName
, x
.TokenCName
), "%s.%s" % (y
.TokenSpaceGuidCName
, y
.TokenCName
)))
1078 SameTokenValuePcdListCount
= 0
1079 while (SameTokenValuePcdListCount
< len(SameTokenValuePcdList
) - 1):
1081 TemListItem
= SameTokenValuePcdList
[SameTokenValuePcdListCount
]
1082 TemListItemNext
= SameTokenValuePcdList
[SameTokenValuePcdListCount
+ 1]
1084 if (TemListItem
.TokenSpaceGuidCName
== TemListItemNext
.TokenSpaceGuidCName
) and (TemListItem
.TokenCName
!= TemListItemNext
.TokenCName
):
1085 for PcdItem
in GlobalData
.MixedPcd
:
1086 if (TemListItem
.TokenCName
, TemListItem
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
] or \
1087 (TemListItemNext
.TokenCName
, TemListItemNext
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
1093 "The TokenValue [%s] of PCD [%s.%s] is conflict with: [%s.%s] in %s"\
1094 % (TemListItem
.TokenValue
, TemListItem
.TokenSpaceGuidCName
, TemListItem
.TokenCName
, TemListItemNext
.TokenSpaceGuidCName
, TemListItemNext
.TokenCName
, Package
),
1097 SameTokenValuePcdListCount
+= 1
1098 Count
+= SameTokenValuePcdListCount
1101 PcdList
= Package
.Pcds
.values()
1102 PcdList
.sort(lambda x
, y
: cmp("%s.%s" % (x
.TokenSpaceGuidCName
, x
.TokenCName
), "%s.%s" % (y
.TokenSpaceGuidCName
, y
.TokenCName
)))
1104 while (Count
< len(PcdList
) - 1) :
1105 Item
= PcdList
[Count
]
1106 ItemNext
= PcdList
[Count
+ 1]
1108 # Check PCDs with same TokenSpaceGuidCName.TokenCName have same token value as well.
1110 if (Item
.TokenSpaceGuidCName
== ItemNext
.TokenSpaceGuidCName
) and (Item
.TokenCName
== ItemNext
.TokenCName
) and (int(Item
.TokenValue
, 0) != int(ItemNext
.TokenValue
, 0)):
1114 "The TokenValue [%s] of PCD [%s.%s] in %s defined in two places should be same as well."\
1115 % (Item
.TokenValue
, Item
.TokenSpaceGuidCName
, Item
.TokenCName
, Package
),
1119 ## Generate fds command
1120 def _GenFdsCommand(self
):
1121 return (GenMake
.TopLevelMakefile(self
)._TEMPLATE
_.Replace(GenMake
.TopLevelMakefile(self
)._TemplateDict
)).strip()
1123 ## Create makefile for the platform and modules in it
1125 # @param CreateDepsMakeFile Flag indicating if the makefile for
1126 # modules will be created as well
1128 def CreateMakeFile(self
, CreateDepsMakeFile
=False):
1129 if CreateDepsMakeFile
:
1130 for Pa
in self
.AutoGenObjectList
:
1131 Pa
.CreateMakeFile(CreateDepsMakeFile
)
1133 ## Create autogen code for platform and modules
1135 # Since there's no autogen code for platform, this method will do nothing
1136 # if CreateModuleCodeFile is set to False.
1138 # @param CreateDepsCodeFile Flag indicating if creating module's
1139 # autogen code file or not
1141 def CreateCodeFile(self
, CreateDepsCodeFile
=False):
1142 if not CreateDepsCodeFile
:
1144 for Pa
in self
.AutoGenObjectList
:
1145 Pa
.CreateCodeFile(CreateDepsCodeFile
)
1147 ## Create AsBuilt INF file the platform
1149 def CreateAsBuiltInf(self
):
1152 Name
= property(_GetName
)
1153 Guid
= property(_GetGuid
)
1154 Version
= property(_GetVersion
)
1155 OutputDir
= property(_GetOutputDir
)
1157 ToolDefinition
= property(_GetToolDefinition
) # toolcode : tool path
1159 BuildDir
= property(_GetBuildDir
)
1160 FvDir
= property(_GetFvDir
)
1161 MakeFileDir
= property(_GetMakeFileDir
)
1162 BuildCommand
= property(_GetBuildCommand
)
1163 GenFdsCommand
= property(_GenFdsCommand
)
1165 ## AutoGen class for platform
1167 # PlatformAutoGen class will process the original information in platform
1168 # file in order to generate makefile for platform.
1170 class PlatformAutoGen(AutoGen
):
1172 # Used to store all PCDs for both PEI and DXE phase, in order to generate
1173 # correct PCD database
1176 _NonDynaPcdList_
= []
1180 # The priority list while override build option
1182 PrioList
= {"0x11111" : 16, # TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE (Highest)
1183 "0x01111" : 15, # ******_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
1184 "0x10111" : 14, # TARGET_*********_ARCH_COMMANDTYPE_ATTRIBUTE
1185 "0x00111" : 13, # ******_*********_ARCH_COMMANDTYPE_ATTRIBUTE
1186 "0x11011" : 12, # TARGET_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
1187 "0x01011" : 11, # ******_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
1188 "0x10011" : 10, # TARGET_*********_****_COMMANDTYPE_ATTRIBUTE
1189 "0x00011" : 9, # ******_*********_****_COMMANDTYPE_ATTRIBUTE
1190 "0x11101" : 8, # TARGET_TOOLCHAIN_ARCH_***********_ATTRIBUTE
1191 "0x01101" : 7, # ******_TOOLCHAIN_ARCH_***********_ATTRIBUTE
1192 "0x10101" : 6, # TARGET_*********_ARCH_***********_ATTRIBUTE
1193 "0x00101" : 5, # ******_*********_ARCH_***********_ATTRIBUTE
1194 "0x11001" : 4, # TARGET_TOOLCHAIN_****_***********_ATTRIBUTE
1195 "0x01001" : 3, # ******_TOOLCHAIN_****_***********_ATTRIBUTE
1196 "0x10001" : 2, # TARGET_*********_****_***********_ATTRIBUTE
1197 "0x00001" : 1} # ******_*********_****_***********_ATTRIBUTE (Lowest)
1199 ## The real constructor of PlatformAutoGen
1201 # This method is not supposed to be called by users of PlatformAutoGen. It's
1202 # only used by factory method __new__() to do real initialization work for an
1203 # object of PlatformAutoGen
1205 # @param Workspace WorkspaceAutoGen object
1206 # @param PlatformFile Platform file (DSC file)
1207 # @param Target Build target (DEBUG, RELEASE)
1208 # @param Toolchain Name of tool chain
1209 # @param Arch arch of the platform supports
1211 def _Init(self
, Workspace
, PlatformFile
, Target
, Toolchain
, Arch
):
1212 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "AutoGen platform [%s] [%s]" % (PlatformFile
, Arch
))
1213 GlobalData
.gProcessingFile
= "%s [%s, %s, %s]" % (PlatformFile
, Arch
, Toolchain
, Target
)
1215 self
.MetaFile
= PlatformFile
1216 self
.Workspace
= Workspace
1217 self
.WorkspaceDir
= Workspace
.WorkspaceDir
1218 self
.ToolChain
= Toolchain
1219 self
.BuildTarget
= Target
1221 self
.SourceDir
= PlatformFile
.SubDir
1222 self
.SourceOverrideDir
= None
1223 self
.FdTargetList
= self
.Workspace
.FdTargetList
1224 self
.FvTargetList
= self
.Workspace
.FvTargetList
1225 self
.AllPcdList
= []
1226 # get the original module/package/platform objects
1227 self
.BuildDatabase
= Workspace
.BuildDatabase
1228 self
.DscBuildDataObj
= Workspace
.Platform
1230 # flag indicating if the makefile/C-code file has been created or not
1231 self
.IsMakeFileCreated
= False
1232 self
.IsCodeFileCreated
= False
1234 self
._Platform
= None
1237 self
._Version
= None
1239 self
._BuildRule
= None
1240 self
._SourceDir
= None
1241 self
._BuildDir
= None
1242 self
._OutputDir
= None
1244 self
._MakeFileDir
= None
1245 self
._FdfFile
= None
1247 self
._PcdTokenNumber
= None # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber
1248 self
._DynamicPcdList
= None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
1249 self
._NonDynamicPcdList
= None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
1250 self
._NonDynamicPcdDict
= {}
1252 self
._ToolDefinitions
= None
1253 self
._ToolDefFile
= None # toolcode : tool path
1254 self
._ToolChainFamily
= None
1255 self
._BuildRuleFamily
= None
1256 self
._BuildOption
= None # toolcode : option
1257 self
._EdkBuildOption
= None # edktoolcode : option
1258 self
._EdkIIBuildOption
= None # edkiitoolcode : option
1259 self
._PackageList
= None
1260 self
._ModuleAutoGenList
= None
1261 self
._LibraryAutoGenList
= None
1262 self
._BuildCommand
= None
1263 self
._AsBuildInfList
= []
1264 self
._AsBuildModuleList
= []
1266 self
.VariableInfo
= None
1268 if GlobalData
.gFdfParser
!= None:
1269 self
._AsBuildInfList
= GlobalData
.gFdfParser
.Profile
.InfList
1270 for Inf
in self
._AsBuildInfList
:
1271 InfClass
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, self
.Arch
)
1272 M
= self
.BuildDatabase
[InfClass
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1273 if not M
.IsSupportedArch
:
1275 self
._AsBuildModuleList
.append(InfClass
)
1276 # get library/modules for build
1277 self
.LibraryBuildDirectoryList
= []
1278 self
.ModuleBuildDirectoryList
= []
1283 return "%s [%s]" % (self
.MetaFile
, self
.Arch
)
1285 ## Create autogen code for platform and modules
1287 # Since there's no autogen code for platform, this method will do nothing
1288 # if CreateModuleCodeFile is set to False.
1290 # @param CreateModuleCodeFile Flag indicating if creating module's
1291 # autogen code file or not
1293 def CreateCodeFile(self
, CreateModuleCodeFile
=False):
1294 # only module has code to be greated, so do nothing if CreateModuleCodeFile is False
1295 if self
.IsCodeFileCreated
or not CreateModuleCodeFile
:
1298 for Ma
in self
.ModuleAutoGenList
:
1299 Ma
.CreateCodeFile(True)
1301 # don't do this twice
1302 self
.IsCodeFileCreated
= True
1304 ## Generate Fds Command
1305 def _GenFdsCommand(self
):
1306 return self
.Workspace
.GenFdsCommand
1308 ## Create makefile for the platform and mdoules in it
1310 # @param CreateModuleMakeFile Flag indicating if the makefile for
1311 # modules will be created as well
1313 def CreateMakeFile(self
, CreateModuleMakeFile
=False, FfsCommand
= {}):
1314 if CreateModuleMakeFile
:
1315 for ModuleFile
in self
.Platform
.Modules
:
1316 Ma
= ModuleAutoGen(self
.Workspace
, ModuleFile
, self
.BuildTarget
,
1317 self
.ToolChain
, self
.Arch
, self
.MetaFile
)
1318 if (ModuleFile
.File
, self
.Arch
) in FfsCommand
:
1319 Ma
.CreateMakeFile(True, FfsCommand
[ModuleFile
.File
, self
.Arch
])
1321 Ma
.CreateMakeFile(True)
1322 #Ma.CreateAsBuiltInf()
1324 # no need to create makefile for the platform more than once
1325 if self
.IsMakeFileCreated
:
1328 # create library/module build dirs for platform
1329 Makefile
= GenMake
.PlatformMakefile(self
)
1330 self
.LibraryBuildDirectoryList
= Makefile
.GetLibraryBuildDirectoryList()
1331 self
.ModuleBuildDirectoryList
= Makefile
.GetModuleBuildDirectoryList()
1333 self
.IsMakeFileCreated
= True
1335 ## Deal with Shared FixedAtBuild Pcds
1337 def CollectFixedAtBuildPcds(self
):
1338 for LibAuto
in self
.LibraryAutoGenList
:
1339 FixedAtBuildPcds
= {}
1340 ShareFixedAtBuildPcdsSameValue
= {}
1341 for Module
in LibAuto
._ReferenceModules
:
1342 for Pcd
in Module
.FixedAtBuildPcds
+ LibAuto
.FixedAtBuildPcds
:
1343 key
= ".".join((Pcd
.TokenSpaceGuidCName
,Pcd
.TokenCName
))
1344 if key
not in FixedAtBuildPcds
:
1345 ShareFixedAtBuildPcdsSameValue
[key
] = True
1346 FixedAtBuildPcds
[key
] = Pcd
.DefaultValue
1348 if FixedAtBuildPcds
[key
] != Pcd
.DefaultValue
:
1349 ShareFixedAtBuildPcdsSameValue
[key
] = False
1350 for Pcd
in LibAuto
.FixedAtBuildPcds
:
1351 key
= ".".join((Pcd
.TokenSpaceGuidCName
,Pcd
.TokenCName
))
1352 if (Pcd
.TokenCName
,Pcd
.TokenSpaceGuidCName
) not in self
.NonDynamicPcdDict
:
1355 DscPcd
= self
.NonDynamicPcdDict
[(Pcd
.TokenCName
,Pcd
.TokenSpaceGuidCName
)]
1356 if DscPcd
.Type
!= "FixedAtBuild":
1358 if key
in ShareFixedAtBuildPcdsSameValue
and ShareFixedAtBuildPcdsSameValue
[key
]:
1359 LibAuto
.ConstPcd
[key
] = Pcd
.DefaultValue
1361 def CollectVariables(self
, DynamicPcdSet
):
1365 if self
.Workspace
.FdfFile
:
1366 FdDict
= self
.Workspace
.FdfProfile
.FdDict
[GlobalData
.gFdfParser
.CurrentFdName
]
1367 for FdRegion
in FdDict
.RegionList
:
1368 for item
in FdRegion
.RegionDataList
:
1369 if self
.Platform
.VpdToolGuid
.strip() and self
.Platform
.VpdToolGuid
in item
:
1370 VpdRegionSize
= FdRegion
.Size
1371 VpdRegionBase
= FdRegion
.Offset
1375 VariableInfo
= VariableMgr(self
.DscBuildDataObj
._GetDefaultStores
(),self
.DscBuildDataObj
._GetSkuIds
())
1376 VariableInfo
.SetVpdRegionMaxSize(VpdRegionSize
)
1377 VariableInfo
.SetVpdRegionOffset(VpdRegionBase
)
1379 for Pcd
in DynamicPcdSet
:
1380 pcdname
= ".".join((Pcd
.TokenSpaceGuidCName
,Pcd
.TokenCName
))
1381 for SkuName
in Pcd
.SkuInfoList
:
1382 Sku
= Pcd
.SkuInfoList
[SkuName
]
1384 if SkuId
== None or SkuId
== '':
1386 if len(Sku
.VariableName
) > 0:
1387 VariableGuidStructure
= Sku
.VariableGuidValue
1388 VariableGuid
= GuidStructureStringToGuidString(VariableGuidStructure
)
1389 if Pcd
.Phase
== "DXE":
1390 for StorageName
in Sku
.DefaultStoreDict
:
1391 VariableInfo
.append_variable(var_info(Index
,pcdname
,StorageName
,SkuName
, StringToArray(Sku
.VariableName
),VariableGuid
, Sku
.VariableAttribute
, Sku
.HiiDefaultValue
,Sku
.DefaultStoreDict
[StorageName
],Pcd
.DatumType
))
1395 def UpdateNVStoreMaxSize(self
,OrgVpdFile
):
1396 VpdMapFilePath
= os
.path
.join(self
.BuildDir
, "FV", "%s.map" % self
.Platform
.VpdToolGuid
)
1397 # VpdFile = VpdInfoFile.VpdInfoFile()
1398 PcdNvStoreDfBuffer
= [item
for item
in self
._DynamicPcdList
if item
.TokenCName
== "PcdNvStoreDefaultValueBuffer" and item
.TokenSpaceGuidCName
== "gEfiMdeModulePkgTokenSpaceGuid"]
1400 if PcdNvStoreDfBuffer
:
1401 if os
.path
.exists(VpdMapFilePath
):
1402 OrgVpdFile
.Read(VpdMapFilePath
)
1403 PcdItems
= OrgVpdFile
.GetOffset(PcdNvStoreDfBuffer
[0])
1404 NvStoreOffset
= PcdItems
[0].strip() if PcdItems
else 0
1406 EdkLogger
.error("build", FILE_READ_FAILURE
, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath
)
1408 NvStoreOffset
= int(NvStoreOffset
,16) if NvStoreOffset
.upper().startswith("0X") else int(NvStoreOffset
)
1409 maxsize
= self
.VariableInfo
.VpdRegionSize
- NvStoreOffset
1410 var_data
= self
.VariableInfo
.PatchNVStoreDefaultMaxSize(maxsize
)
1411 default_skuobj
= PcdNvStoreDfBuffer
[0].SkuInfoList
.get("DEFAULT")
1413 if var_data
and default_skuobj
:
1414 default_skuobj
.DefaultValue
= var_data
1415 PcdNvStoreDfBuffer
[0].DefaultValue
= var_data
1416 PcdNvStoreDfBuffer
[0].SkuInfoList
.clear()
1417 PcdNvStoreDfBuffer
[0].SkuInfoList
['DEFAULT'] = default_skuobj
1418 PcdNvStoreDfBuffer
[0].MaxDatumSize
= str(len(default_skuobj
.DefaultValue
.split(",")))
1422 ## Collect dynamic PCDs
1424 # Gather dynamic PCDs list from each module and their settings from platform
1425 # This interface should be invoked explicitly when platform action is created.
1427 def CollectPlatformDynamicPcds(self
):
1428 # Override the platform Pcd's value by build option
1429 if GlobalData
.BuildOptionPcd
:
1430 for key
in self
.Platform
.Pcds
:
1431 PlatformPcd
= self
.Platform
.Pcds
[key
]
1432 for PcdItem
in GlobalData
.BuildOptionPcd
:
1433 if (PlatformPcd
.TokenSpaceGuidCName
, PlatformPcd
.TokenCName
) == (PcdItem
[0], PcdItem
[1]):
1434 PlatformPcd
.DefaultValue
= PcdItem
[2]
1435 if PlatformPcd
.SkuInfoList
:
1436 Sku
= PlatformPcd
.SkuInfoList
[PlatformPcd
.SkuInfoList
.keys()[0]]
1437 Sku
.DefaultValue
= PcdItem
[2]
1440 for key
in self
.Platform
.Pcds
:
1441 for SinglePcd
in GlobalData
.MixedPcd
:
1442 if (self
.Platform
.Pcds
[key
].TokenCName
, self
.Platform
.Pcds
[key
].TokenSpaceGuidCName
) == SinglePcd
:
1443 for item
in GlobalData
.MixedPcd
[SinglePcd
]:
1444 Pcd_Type
= item
[0].split('_')[-1]
1445 if (Pcd_Type
== self
.Platform
.Pcds
[key
].Type
) or (Pcd_Type
== TAB_PCDS_DYNAMIC_EX
and self
.Platform
.Pcds
[key
].Type
in GenC
.gDynamicExPcd
) or \
1446 (Pcd_Type
== TAB_PCDS_DYNAMIC
and self
.Platform
.Pcds
[key
].Type
in GenC
.gDynamicPcd
):
1447 Value
= self
.Platform
.Pcds
[key
]
1448 Value
.TokenCName
= self
.Platform
.Pcds
[key
].TokenCName
+ '_' + Pcd_Type
1450 newkey
= (Value
.TokenCName
, key
[1])
1452 newkey
= (Value
.TokenCName
, key
[1], key
[2])
1453 del self
.Platform
.Pcds
[key
]
1454 self
.Platform
.Pcds
[newkey
] = Value
1462 # for gathering error information
1463 NoDatumTypePcdList
= set()
1465 self
._GuidValue
= {}
1467 for InfName
in self
._AsBuildInfList
:
1468 InfName
= mws
.join(self
.WorkspaceDir
, InfName
)
1469 FdfModuleList
.append(os
.path
.normpath(InfName
))
1470 for F
in self
.Platform
.Modules
.keys():
1471 M
= ModuleAutoGen(self
.Workspace
, F
, self
.BuildTarget
, self
.ToolChain
, self
.Arch
, self
.MetaFile
)
1472 #GuidValue.update(M.Guids)
1474 self
.Platform
.Modules
[F
].M
= M
1476 for PcdFromModule
in M
.ModulePcdList
+ M
.LibraryPcdList
:
1477 # make sure that the "VOID*" kind of datum has MaxDatumSize set
1478 if PcdFromModule
.DatumType
== "VOID*" and PcdFromModule
.MaxDatumSize
in [None, '']:
1479 NoDatumTypePcdList
.add("%s.%s [%s]" % (PcdFromModule
.TokenSpaceGuidCName
, PcdFromModule
.TokenCName
, F
))
1481 # Check the PCD from Binary INF or Source INF
1482 if M
.IsBinaryModule
== True:
1483 PcdFromModule
.IsFromBinaryInf
= True
1485 # Check the PCD from DSC or not
1486 if (PcdFromModule
.TokenCName
, PcdFromModule
.TokenSpaceGuidCName
) in self
.Platform
.Pcds
.keys():
1487 PcdFromModule
.IsFromDsc
= True
1489 PcdFromModule
.IsFromDsc
= False
1490 if PcdFromModule
.Type
in GenC
.gDynamicPcd
or PcdFromModule
.Type
in GenC
.gDynamicExPcd
:
1491 if F
.Path
not in FdfModuleList
:
1492 # If one of the Source built modules listed in the DSC is not listed
1493 # in FDF modules, and the INF lists a PCD can only use the PcdsDynamic
1494 # access method (it is only listed in the DEC file that declares the
1495 # PCD as PcdsDynamic), then build tool will report warning message
1496 # notify the PI that they are attempting to build a module that must
1497 # be included in a flash image in order to be functional. These Dynamic
1498 # PCD will not be added into the Database unless it is used by other
1499 # modules that are included in the FDF file.
1500 if PcdFromModule
.Type
in GenC
.gDynamicPcd
and \
1501 PcdFromModule
.IsFromBinaryInf
== False:
1502 # Print warning message to let the developer make a determine.
1503 if PcdFromModule
not in PcdNotInDb
:
1504 PcdNotInDb
.append(PcdFromModule
)
1506 # If one of the Source built modules listed in the DSC is not listed in
1507 # FDF modules, and the INF lists a PCD can only use the PcdsDynamicEx
1508 # access method (it is only listed in the DEC file that declares the
1509 # PCD as PcdsDynamicEx), then DO NOT break the build; DO NOT add the
1510 # PCD to the Platform's PCD Database.
1511 if PcdFromModule
.Type
in GenC
.gDynamicExPcd
:
1512 if PcdFromModule
not in PcdNotInDb
:
1513 PcdNotInDb
.append(PcdFromModule
)
1516 # If a dynamic PCD used by a PEM module/PEI module & DXE module,
1517 # it should be stored in Pcd PEI database, If a dynamic only
1518 # used by DXE module, it should be stored in DXE PCD database.
1519 # The default Phase is DXE
1521 if M
.ModuleType
in ["PEIM", "PEI_CORE"]:
1522 PcdFromModule
.Phase
= "PEI"
1523 if PcdFromModule
not in self
._DynaPcdList
_:
1524 self
._DynaPcdList
_.append(PcdFromModule
)
1525 elif PcdFromModule
.Phase
== 'PEI':
1526 # overwrite any the same PCD existing, if Phase is PEI
1527 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1528 self
._DynaPcdList
_[Index
] = PcdFromModule
1529 elif PcdFromModule
not in self
._NonDynaPcdList
_:
1530 self
._NonDynaPcdList
_.append(PcdFromModule
)
1531 elif PcdFromModule
in self
._NonDynaPcdList
_ and PcdFromModule
.IsFromBinaryInf
== True:
1532 Index
= self
._NonDynaPcdList
_.index(PcdFromModule
)
1533 if self
._NonDynaPcdList
_[Index
].IsFromBinaryInf
== False:
1534 #The PCD from Binary INF will override the same one from source INF
1535 self
._NonDynaPcdList
_.remove (self
._NonDynaPcdList
_[Index
])
1536 PcdFromModule
.Pending
= False
1537 self
._NonDynaPcdList
_.append (PcdFromModule
)
1538 # Parse the DynamicEx PCD from the AsBuild INF module list of FDF.
1540 for ModuleInf
in self
.Platform
.Modules
.keys():
1541 DscModuleList
.append (os
.path
.normpath(ModuleInf
.Path
))
1542 # add the PCD from modules that listed in FDF but not in DSC to Database
1543 for InfName
in FdfModuleList
:
1544 if InfName
not in DscModuleList
:
1545 InfClass
= PathClass(InfName
)
1546 M
= self
.BuildDatabase
[InfClass
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1547 # If a module INF in FDF but not in current arch's DSC module list, it must be module (either binary or source)
1548 # for different Arch. PCDs in source module for different Arch is already added before, so skip the source module here.
1549 # For binary module, if in current arch, we need to list the PCDs into database.
1550 if not M
.IsSupportedArch
:
1552 # Override the module PCD setting by platform setting
1553 ModulePcdList
= self
.ApplyPcdSetting(M
, M
.Pcds
)
1554 for PcdFromModule
in ModulePcdList
:
1555 PcdFromModule
.IsFromBinaryInf
= True
1556 PcdFromModule
.IsFromDsc
= False
1557 # Only allow the DynamicEx and Patchable PCD in AsBuild INF
1558 if PcdFromModule
.Type
not in GenC
.gDynamicExPcd
and PcdFromModule
.Type
not in TAB_PCDS_PATCHABLE_IN_MODULE
:
1559 EdkLogger
.error("build", AUTOGEN_ERROR
, "PCD setting error",
1561 ExtraData
="\n\tExisted %s PCD %s in:\n\t\t%s\n"
1562 % (PcdFromModule
.Type
, PcdFromModule
.TokenCName
, InfName
))
1563 # make sure that the "VOID*" kind of datum has MaxDatumSize set
1564 if PcdFromModule
.DatumType
== "VOID*" and PcdFromModule
.MaxDatumSize
in [None, '']:
1565 NoDatumTypePcdList
.add("%s.%s [%s]" % (PcdFromModule
.TokenSpaceGuidCName
, PcdFromModule
.TokenCName
, InfName
))
1566 if M
.ModuleType
in ["PEIM", "PEI_CORE"]:
1567 PcdFromModule
.Phase
= "PEI"
1568 if PcdFromModule
not in self
._DynaPcdList
_ and PcdFromModule
.Type
in GenC
.gDynamicExPcd
:
1569 self
._DynaPcdList
_.append(PcdFromModule
)
1570 elif PcdFromModule
not in self
._NonDynaPcdList
_ and PcdFromModule
.Type
in TAB_PCDS_PATCHABLE_IN_MODULE
:
1571 self
._NonDynaPcdList
_.append(PcdFromModule
)
1572 if PcdFromModule
in self
._DynaPcdList
_ and PcdFromModule
.Phase
== 'PEI' and PcdFromModule
.Type
in GenC
.gDynamicExPcd
:
1573 # Overwrite the phase of any the same PCD existing, if Phase is PEI.
1574 # It is to solve the case that a dynamic PCD used by a PEM module/PEI
1575 # module & DXE module at a same time.
1576 # Overwrite the type of the PCDs in source INF by the type of AsBuild
1577 # INF file as DynamicEx.
1578 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1579 self
._DynaPcdList
_[Index
].Phase
= PcdFromModule
.Phase
1580 self
._DynaPcdList
_[Index
].Type
= PcdFromModule
.Type
1581 for PcdFromModule
in self
._NonDynaPcdList
_:
1582 # If a PCD is not listed in the DSC file, but binary INF files used by
1583 # this platform all (that use this PCD) list the PCD in a [PatchPcds]
1584 # section, AND all source INF files used by this platform the build
1585 # that use the PCD list the PCD in either a [Pcds] or [PatchPcds]
1586 # section, then the tools must NOT add the PCD to the Platform's PCD
1587 # Database; the build must assign the access method for this PCD as
1588 # PcdsPatchableInModule.
1589 if PcdFromModule
not in self
._DynaPcdList
_:
1591 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1592 if PcdFromModule
.IsFromDsc
== False and \
1593 PcdFromModule
.Type
in TAB_PCDS_PATCHABLE_IN_MODULE
and \
1594 PcdFromModule
.IsFromBinaryInf
== True and \
1595 self
._DynaPcdList
_[Index
].IsFromBinaryInf
== False:
1596 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1597 self
._DynaPcdList
_.remove (self
._DynaPcdList
_[Index
])
1599 # print out error information and break the build, if error found
1600 if len(NoDatumTypePcdList
) > 0:
1601 NoDatumTypePcdListString
= "\n\t\t".join(NoDatumTypePcdList
)
1602 EdkLogger
.error("build", AUTOGEN_ERROR
, "PCD setting error",
1604 ExtraData
="\n\tPCD(s) without MaxDatumSize:\n\t\t%s\n"
1605 % NoDatumTypePcdListString
)
1606 self
._NonDynamicPcdList
= self
._NonDynaPcdList
_
1607 self
._DynamicPcdList
= self
._DynaPcdList
_
1609 # Sort dynamic PCD list to:
1610 # 1) If PCD's datum type is VOID* and value is unicode string which starts with L, the PCD item should
1611 # try to be put header of dynamicd List
1612 # 2) If PCD is HII type, the PCD item should be put after unicode type PCD
1614 # The reason of sorting is make sure the unicode string is in double-byte alignment in string table.
1616 UnicodePcdArray
= []
1620 VpdFile
= VpdInfoFile
.VpdInfoFile()
1621 NeedProcessVpdMapFile
= False
1623 for pcd
in self
.Platform
.Pcds
.keys():
1624 if pcd
not in self
._PlatformPcds
.keys():
1625 self
._PlatformPcds
[pcd
] = self
.Platform
.Pcds
[pcd
]
1627 for item
in self
._PlatformPcds
:
1628 if self
._PlatformPcds
[item
].DatumType
and self
._PlatformPcds
[item
].DatumType
not in [TAB_UINT8
, TAB_UINT16
, TAB_UINT32
, TAB_UINT64
, TAB_VOID
, "BOOLEAN"]:
1629 self
._PlatformPcds
[item
].DatumType
= "VOID*"
1631 if (self
.Workspace
.ArchList
[-1] == self
.Arch
):
1632 for Pcd
in self
._DynamicPcdList
:
1633 # just pick the a value to determine whether is unicode string type
1634 Sku
= Pcd
.SkuInfoList
[Pcd
.SkuInfoList
.keys()[0]]
1635 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1637 if Pcd
.DatumType
not in [TAB_UINT8
, TAB_UINT16
, TAB_UINT32
, TAB_UINT64
, TAB_VOID
, "BOOLEAN"]:
1638 Pcd
.DatumType
= "VOID*"
1640 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
1641 # if found HII type PCD then insert to right of UnicodeIndex
1642 if Pcd
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
]:
1643 VpdPcdDict
[(Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
)] = Pcd
1645 #Collect DynamicHii PCD values and assign it to DynamicExVpd PCD gEfiMdeModulePkgTokenSpaceGuid.PcdNvStoreDefaultValueBuffer
1646 PcdNvStoreDfBuffer
= VpdPcdDict
.get(("PcdNvStoreDefaultValueBuffer","gEfiMdeModulePkgTokenSpaceGuid"))
1647 if PcdNvStoreDfBuffer
:
1648 self
.VariableInfo
= self
.CollectVariables(self
._DynamicPcdList
)
1649 vardump
= self
.VariableInfo
.dump()
1651 PcdNvStoreDfBuffer
.DefaultValue
= vardump
1652 for skuname
in PcdNvStoreDfBuffer
.SkuInfoList
:
1653 PcdNvStoreDfBuffer
.SkuInfoList
[skuname
].DefaultValue
= vardump
1654 PcdNvStoreDfBuffer
.MaxDatumSize
= str(len(vardump
.split(",")))
1656 PlatformPcds
= self
._PlatformPcds
.keys()
1659 # Add VPD type PCD into VpdFile and determine whether the VPD PCD need to be fixed up.
1662 for PcdKey
in PlatformPcds
:
1663 Pcd
= self
._PlatformPcds
[PcdKey
]
1664 if Pcd
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
] and \
1665 PcdKey
in VpdPcdDict
:
1666 Pcd
= VpdPcdDict
[PcdKey
]
1668 for (SkuName
,Sku
) in Pcd
.SkuInfoList
.items():
1669 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1670 PcdValue
= Sku
.DefaultValue
1672 PcdValue
= Pcd
.DefaultValue
1673 if Sku
.VpdOffset
!= '*':
1674 if PcdValue
.startswith("{"):
1676 elif PcdValue
.startswith("L"):
1681 VpdOffset
= int(Sku
.VpdOffset
)
1684 VpdOffset
= int(Sku
.VpdOffset
, 16)
1686 EdkLogger
.error("build", FORMAT_INVALID
, "Invalid offset value %s for PCD %s.%s." % (Sku
.VpdOffset
, Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
1687 if VpdOffset
% Alignment
!= 0:
1688 if PcdValue
.startswith("{"):
1689 EdkLogger
.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
), File
=self
.MetaFile
)
1691 EdkLogger
.error("build", FORMAT_INVALID
, 'The offset value of PCD %s.%s should be %s-byte aligned.' % (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
, Alignment
))
1692 if PcdValue
not in SkuValueMap
:
1693 SkuValueMap
[PcdValue
] = []
1694 VpdFile
.Add(Pcd
, Sku
.VpdOffset
)
1695 SkuValueMap
[PcdValue
].append(Sku
)
1696 # if the offset of a VPD is *, then it need to be fixed up by third party tool.
1697 if not NeedProcessVpdMapFile
and Sku
.VpdOffset
== "*":
1698 NeedProcessVpdMapFile
= True
1699 if self
.Platform
.VpdToolGuid
== None or self
.Platform
.VpdToolGuid
== '':
1700 EdkLogger
.error("Build", FILE_NOT_FOUND
, \
1701 "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.")
1703 VpdSkuMap
[PcdKey
] = SkuValueMap
1705 # Fix the PCDs define in VPD PCD section that never referenced by module.
1706 # An example is PCD for signature usage.
1708 for DscPcd
in PlatformPcds
:
1709 DscPcdEntry
= self
._PlatformPcds
[DscPcd
]
1710 if DscPcdEntry
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
]:
1711 if not (self
.Platform
.VpdToolGuid
== None or self
.Platform
.VpdToolGuid
== ''):
1713 for VpdPcd
in VpdFile
._VpdArray
.keys():
1714 # This PCD has been referenced by module
1715 if (VpdPcd
.TokenSpaceGuidCName
== DscPcdEntry
.TokenSpaceGuidCName
) and \
1716 (VpdPcd
.TokenCName
== DscPcdEntry
.TokenCName
):
1719 # Not found, it should be signature
1721 # just pick the a value to determine whether is unicode string type
1723 for (SkuName
,Sku
) in DscPcdEntry
.SkuInfoList
.items():
1724 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1726 # Need to iterate DEC pcd information to get the value & datumtype
1727 for eachDec
in self
.PackageList
:
1728 for DecPcd
in eachDec
.Pcds
:
1729 DecPcdEntry
= eachDec
.Pcds
[DecPcd
]
1730 if (DecPcdEntry
.TokenSpaceGuidCName
== DscPcdEntry
.TokenSpaceGuidCName
) and \
1731 (DecPcdEntry
.TokenCName
== DscPcdEntry
.TokenCName
):
1732 # Print warning message to let the developer make a determine.
1733 EdkLogger
.warn("build", "Unreferenced vpd pcd used!",
1734 File
=self
.MetaFile
, \
1735 ExtraData
= "PCD: %s.%s used in the DSC file %s is unreferenced." \
1736 %(DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
, self
.Platform
.MetaFile
.Path
))
1738 DscPcdEntry
.DatumType
= DecPcdEntry
.DatumType
1739 DscPcdEntry
.DefaultValue
= DecPcdEntry
.DefaultValue
1740 DscPcdEntry
.TokenValue
= DecPcdEntry
.TokenValue
1741 DscPcdEntry
.TokenSpaceGuidValue
= eachDec
.Guids
[DecPcdEntry
.TokenSpaceGuidCName
]
1742 # Only fix the value while no value provided in DSC file.
1743 if (Sku
.DefaultValue
== "" or Sku
.DefaultValue
==None):
1744 DscPcdEntry
.SkuInfoList
[DscPcdEntry
.SkuInfoList
.keys()[0]].DefaultValue
= DecPcdEntry
.DefaultValue
1746 if DscPcdEntry
not in self
._DynamicPcdList
:
1747 self
._DynamicPcdList
.append(DscPcdEntry
)
1748 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1749 PcdValue
= Sku
.DefaultValue
1751 PcdValue
= DscPcdEntry
.DefaultValue
1752 if Sku
.VpdOffset
!= '*':
1753 if PcdValue
.startswith("{"):
1755 elif PcdValue
.startswith("L"):
1760 VpdOffset
= int(Sku
.VpdOffset
)
1763 VpdOffset
= int(Sku
.VpdOffset
, 16)
1765 EdkLogger
.error("build", FORMAT_INVALID
, "Invalid offset value %s for PCD %s.%s." % (Sku
.VpdOffset
, DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
))
1766 if VpdOffset
% Alignment
!= 0:
1767 if PcdValue
.startswith("{"):
1768 EdkLogger
.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
), File
=self
.MetaFile
)
1770 EdkLogger
.error("build", FORMAT_INVALID
, 'The offset value of PCD %s.%s should be %s-byte aligned.' % (DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
, Alignment
))
1771 if PcdValue
not in SkuValueMap
:
1772 SkuValueMap
[PcdValue
] = []
1773 VpdFile
.Add(DscPcdEntry
, Sku
.VpdOffset
)
1774 SkuValueMap
[PcdValue
].append(Sku
)
1775 if not NeedProcessVpdMapFile
and Sku
.VpdOffset
== "*":
1776 NeedProcessVpdMapFile
= True
1777 if DscPcdEntry
.DatumType
== 'VOID*' and PcdValue
.startswith("L"):
1778 UnicodePcdArray
.append(DscPcdEntry
)
1779 elif len(Sku
.VariableName
) > 0:
1780 HiiPcdArray
.append(DscPcdEntry
)
1782 OtherPcdArray
.append(DscPcdEntry
)
1784 # if the offset of a VPD is *, then it need to be fixed up by third party tool.
1785 VpdSkuMap
[DscPcd
] = SkuValueMap
1786 if (self
.Platform
.FlashDefinition
== None or self
.Platform
.FlashDefinition
== '') and \
1787 VpdFile
.GetCount() != 0:
1788 EdkLogger
.error("build", ATTRIBUTE_NOT_AVAILABLE
,
1789 "Fail to get FLASH_DEFINITION definition in DSC file %s which is required when DSC contains VPD PCD." % str(self
.Platform
.MetaFile
))
1791 if VpdFile
.GetCount() != 0:
1793 self
.FixVpdOffset(VpdFile
)
1795 self
.FixVpdOffset(self
.UpdateNVStoreMaxSize(VpdFile
))
1797 # Process VPD map file generated by third party BPDG tool
1798 if NeedProcessVpdMapFile
:
1799 VpdMapFilePath
= os
.path
.join(self
.BuildDir
, "FV", "%s.map" % self
.Platform
.VpdToolGuid
)
1800 if os
.path
.exists(VpdMapFilePath
):
1801 VpdFile
.Read(VpdMapFilePath
)
1804 for pcd
in VpdSkuMap
:
1805 vpdinfo
= VpdFile
.GetVpdInfo(pcd
)
1807 # just pick the a value to determine whether is unicode string type
1809 for pcdvalue
in VpdSkuMap
[pcd
]:
1810 for sku
in VpdSkuMap
[pcd
][pcdvalue
]:
1811 for item
in vpdinfo
:
1812 if item
[2] == pcdvalue
:
1813 sku
.VpdOffset
= item
[1]
1815 EdkLogger
.error("build", FILE_READ_FAILURE
, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath
)
1817 # Delete the DynamicPcdList At the last time enter into this function
1818 for Pcd
in self
._DynamicPcdList
:
1819 # just pick the a value to determine whether is unicode string type
1820 Sku
= Pcd
.SkuInfoList
[Pcd
.SkuInfoList
.keys()[0]]
1821 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1823 if Pcd
.DatumType
not in [TAB_UINT8
, TAB_UINT16
, TAB_UINT32
, TAB_UINT64
, TAB_VOID
, "BOOLEAN"]:
1824 Pcd
.DatumType
= "VOID*"
1826 PcdValue
= Sku
.DefaultValue
1827 if Pcd
.DatumType
== 'VOID*' and PcdValue
.startswith("L"):
1828 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
1829 UnicodePcdArray
.append(Pcd
)
1830 elif len(Sku
.VariableName
) > 0:
1831 # if found HII type PCD then insert to right of UnicodeIndex
1832 HiiPcdArray
.append(Pcd
)
1834 OtherPcdArray
.append(Pcd
)
1835 del self
._DynamicPcdList
[:]
1836 self
._DynamicPcdList
.extend(UnicodePcdArray
)
1837 self
._DynamicPcdList
.extend(HiiPcdArray
)
1838 self
._DynamicPcdList
.extend(OtherPcdArray
)
1839 allskuset
= [(SkuName
,Sku
.SkuId
) for pcd
in self
._DynamicPcdList
for (SkuName
,Sku
) in pcd
.SkuInfoList
.items()]
1840 for pcd
in self
._DynamicPcdList
:
1841 if len(pcd
.SkuInfoList
) == 1:
1842 for (SkuName
,SkuId
) in allskuset
:
1843 if type(SkuId
) in (str,unicode) and eval(SkuId
) == 0 or SkuId
== 0:
1845 pcd
.SkuInfoList
[SkuName
] = copy
.deepcopy(pcd
.SkuInfoList
['DEFAULT'])
1846 pcd
.SkuInfoList
[SkuName
].SkuId
= SkuId
1847 self
.AllPcdList
= self
._NonDynamicPcdList
+ self
._DynamicPcdList
1849 def FixVpdOffset(self
,VpdFile
):
1850 FvPath
= os
.path
.join(self
.BuildDir
, "FV")
1851 if not os
.path
.exists(FvPath
):
1855 EdkLogger
.error("build", FILE_WRITE_FAILURE
, "Fail to create FV folder under %s" % self
.BuildDir
)
1857 VpdFilePath
= os
.path
.join(FvPath
, "%s.txt" % self
.Platform
.VpdToolGuid
)
1859 if VpdFile
.Write(VpdFilePath
):
1860 # retrieve BPDG tool's path from tool_def.txt according to VPD_TOOL_GUID defined in DSC file.
1862 for ToolDef
in self
.ToolDefinition
.values():
1863 if ToolDef
.has_key("GUID") and ToolDef
["GUID"] == self
.Platform
.VpdToolGuid
:
1864 if not ToolDef
.has_key("PATH"):
1865 EdkLogger
.error("build", ATTRIBUTE_NOT_AVAILABLE
, "PATH attribute was not provided for BPDG guid tool %s in tools_def.txt" % self
.Platform
.VpdToolGuid
)
1866 BPDGToolName
= ToolDef
["PATH"]
1868 # Call third party GUID BPDG tool.
1869 if BPDGToolName
!= None:
1870 VpdInfoFile
.CallExtenalBPDGTool(BPDGToolName
, VpdFilePath
)
1872 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.")
1874 ## Return the platform build data object
1875 def _GetPlatform(self
):
1876 if self
._Platform
== None:
1877 self
._Platform
= self
.BuildDatabase
[self
.MetaFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1878 return self
._Platform
1880 ## Return platform name
1882 return self
.Platform
.PlatformName
1884 ## Return the meta file GUID
1886 return self
.Platform
.Guid
1888 ## Return the platform version
1889 def _GetVersion(self
):
1890 return self
.Platform
.Version
1892 ## Return the FDF file name
1893 def _GetFdfFile(self
):
1894 if self
._FdfFile
== None:
1895 if self
.Workspace
.FdfFile
!= "":
1896 self
._FdfFile
= mws
.join(self
.WorkspaceDir
, self
.Workspace
.FdfFile
)
1899 return self
._FdfFile
1901 ## Return the build output directory platform specifies
1902 def _GetOutputDir(self
):
1903 return self
.Platform
.OutputDirectory
1905 ## Return the directory to store all intermediate and final files built
1906 def _GetBuildDir(self
):
1907 if self
._BuildDir
== None:
1908 if os
.path
.isabs(self
.OutputDir
):
1909 self
._BuildDir
= path
.join(
1910 path
.abspath(self
.OutputDir
),
1911 self
.BuildTarget
+ "_" + self
.ToolChain
,
1914 self
._BuildDir
= path
.join(
1917 self
.BuildTarget
+ "_" + self
.ToolChain
,
1919 GlobalData
.gBuildDirectory
= self
._BuildDir
1920 return self
._BuildDir
1922 ## Return directory of platform makefile
1924 # @retval string Makefile directory
1926 def _GetMakeFileDir(self
):
1927 if self
._MakeFileDir
== None:
1928 self
._MakeFileDir
= path
.join(self
.BuildDir
, self
.Arch
)
1929 return self
._MakeFileDir
1931 ## Return build command string
1933 # @retval string Build command string
1935 def _GetBuildCommand(self
):
1936 if self
._BuildCommand
== None:
1937 self
._BuildCommand
= []
1938 if "MAKE" in self
.ToolDefinition
and "PATH" in self
.ToolDefinition
["MAKE"]:
1939 self
._BuildCommand
+= SplitOption(self
.ToolDefinition
["MAKE"]["PATH"])
1940 if "FLAGS" in self
.ToolDefinition
["MAKE"]:
1941 NewOption
= self
.ToolDefinition
["MAKE"]["FLAGS"].strip()
1943 self
._BuildCommand
+= SplitOption(NewOption
)
1944 return self
._BuildCommand
1946 ## Get tool chain definition
1948 # Get each tool defition for given tool chain from tools_def.txt and platform
1950 def _GetToolDefinition(self
):
1951 if self
._ToolDefinitions
== None:
1952 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDictionary
1953 if TAB_TOD_DEFINES_COMMAND_TYPE
not in self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
:
1954 EdkLogger
.error('build', RESOURCE_NOT_AVAILABLE
, "No tools found in configuration",
1955 ExtraData
="[%s]" % self
.MetaFile
)
1956 self
._ToolDefinitions
= {}
1958 for Def
in ToolDefinition
:
1959 Target
, Tag
, Arch
, Tool
, Attr
= Def
.split("_")
1960 if Target
!= self
.BuildTarget
or Tag
!= self
.ToolChain
or Arch
!= self
.Arch
:
1963 Value
= ToolDefinition
[Def
]
1964 # don't record the DLL
1966 DllPathList
.add(Value
)
1969 if Tool
not in self
._ToolDefinitions
:
1970 self
._ToolDefinitions
[Tool
] = {}
1971 self
._ToolDefinitions
[Tool
][Attr
] = Value
1975 if GlobalData
.gOptions
.SilentMode
and "MAKE" in self
._ToolDefinitions
:
1976 if "FLAGS" not in self
._ToolDefinitions
["MAKE"]:
1977 self
._ToolDefinitions
["MAKE"]["FLAGS"] = ""
1978 self
._ToolDefinitions
["MAKE"]["FLAGS"] += " -s"
1980 for Tool
in self
._ToolDefinitions
:
1981 for Attr
in self
._ToolDefinitions
[Tool
]:
1982 Value
= self
._ToolDefinitions
[Tool
][Attr
]
1983 if Tool
in self
.BuildOption
and Attr
in self
.BuildOption
[Tool
]:
1984 # check if override is indicated
1985 if self
.BuildOption
[Tool
][Attr
].startswith('='):
1986 Value
= self
.BuildOption
[Tool
][Attr
][1:]
1989 Value
+= " " + self
.BuildOption
[Tool
][Attr
]
1991 Value
= self
.BuildOption
[Tool
][Attr
]
1994 # Don't put MAKE definition in the file
1998 ToolsDef
+= "%s = %s\n" % (Tool
, Value
)
2000 # Don't put MAKE definition in the file
2005 ToolsDef
+= "%s_%s = %s\n" % (Tool
, Attr
, Value
)
2008 SaveFileOnChange(self
.ToolDefinitionFile
, ToolsDef
)
2009 for DllPath
in DllPathList
:
2010 os
.environ
["PATH"] = DllPath
+ os
.pathsep
+ os
.environ
["PATH"]
2011 os
.environ
["MAKE_FLAGS"] = MakeFlags
2013 return self
._ToolDefinitions
2015 ## Return the paths of tools
2016 def _GetToolDefFile(self
):
2017 if self
._ToolDefFile
== None:
2018 self
._ToolDefFile
= os
.path
.join(self
.MakeFileDir
, "TOOLS_DEF." + self
.Arch
)
2019 return self
._ToolDefFile
2021 ## Retrieve the toolchain family of given toolchain tag. Default to 'MSFT'.
2022 def _GetToolChainFamily(self
):
2023 if self
._ToolChainFamily
== None:
2024 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
2025 if TAB_TOD_DEFINES_FAMILY
not in ToolDefinition \
2026 or self
.ToolChain
not in ToolDefinition
[TAB_TOD_DEFINES_FAMILY
] \
2027 or not ToolDefinition
[TAB_TOD_DEFINES_FAMILY
][self
.ToolChain
]:
2028 EdkLogger
.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
2030 self
._ToolChainFamily
= "MSFT"
2032 self
._ToolChainFamily
= ToolDefinition
[TAB_TOD_DEFINES_FAMILY
][self
.ToolChain
]
2033 return self
._ToolChainFamily
2035 def _GetBuildRuleFamily(self
):
2036 if self
._BuildRuleFamily
== None:
2037 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
2038 if TAB_TOD_DEFINES_BUILDRULEFAMILY
not in ToolDefinition \
2039 or self
.ToolChain
not in ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
] \
2040 or not ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
][self
.ToolChain
]:
2041 EdkLogger
.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
2043 self
._BuildRuleFamily
= "MSFT"
2045 self
._BuildRuleFamily
= ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
][self
.ToolChain
]
2046 return self
._BuildRuleFamily
2048 ## Return the build options specific for all modules in this platform
2049 def _GetBuildOptions(self
):
2050 if self
._BuildOption
== None:
2051 self
._BuildOption
= self
._ExpandBuildOption
(self
.Platform
.BuildOptions
)
2052 return self
._BuildOption
2054 ## Return the build options specific for EDK modules in this platform
2055 def _GetEdkBuildOptions(self
):
2056 if self
._EdkBuildOption
== None:
2057 self
._EdkBuildOption
= self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, EDK_NAME
)
2058 return self
._EdkBuildOption
2060 ## Return the build options specific for EDKII modules in this platform
2061 def _GetEdkIIBuildOptions(self
):
2062 if self
._EdkIIBuildOption
== None:
2063 self
._EdkIIBuildOption
= self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, EDKII_NAME
)
2064 return self
._EdkIIBuildOption
2066 ## Parse build_rule.txt in Conf Directory.
2068 # @retval BuildRule object
2070 def _GetBuildRule(self
):
2071 if self
._BuildRule
== None:
2072 BuildRuleFile
= None
2073 if TAB_TAT_DEFINES_BUILD_RULE_CONF
in self
.Workspace
.TargetTxt
.TargetTxtDictionary
:
2074 BuildRuleFile
= self
.Workspace
.TargetTxt
.TargetTxtDictionary
[TAB_TAT_DEFINES_BUILD_RULE_CONF
]
2075 if BuildRuleFile
in [None, '']:
2076 BuildRuleFile
= gDefaultBuildRuleFile
2077 self
._BuildRule
= BuildRule(BuildRuleFile
)
2078 if self
._BuildRule
._FileVersion
== "":
2079 self
._BuildRule
._FileVersion
= AutoGenReqBuildRuleVerNum
2081 if self
._BuildRule
._FileVersion
< AutoGenReqBuildRuleVerNum
:
2082 # If Build Rule's version is less than the version number required by the tools, halting the build.
2083 EdkLogger
.error("build", AUTOGEN_ERROR
,
2084 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])"\
2085 % (self
._BuildRule
._FileVersion
, AutoGenReqBuildRuleVerNum
))
2087 return self
._BuildRule
2089 ## Summarize the packages used by modules in this platform
2090 def _GetPackageList(self
):
2091 if self
._PackageList
== None:
2092 self
._PackageList
= set()
2093 for La
in self
.LibraryAutoGenList
:
2094 self
._PackageList
.update(La
.DependentPackageList
)
2095 for Ma
in self
.ModuleAutoGenList
:
2096 self
._PackageList
.update(Ma
.DependentPackageList
)
2097 #Collect package set information from INF of FDF
2099 for ModuleFile
in self
._AsBuildModuleList
:
2100 if ModuleFile
in self
.Platform
.Modules
:
2102 ModuleData
= self
.BuildDatabase
[ModuleFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
2103 PkgSet
.update(ModuleData
.Packages
)
2104 self
._PackageList
= list(self
._PackageList
) + list (PkgSet
)
2105 return self
._PackageList
2107 def _GetNonDynamicPcdDict(self
):
2108 if self
._NonDynamicPcdDict
:
2109 return self
._NonDynamicPcdDict
2110 for Pcd
in self
.NonDynamicPcdList
:
2111 self
._NonDynamicPcdDict
[(Pcd
.TokenCName
,Pcd
.TokenSpaceGuidCName
)] = Pcd
2112 return self
._NonDynamicPcdDict
2114 ## Get list of non-dynamic PCDs
2115 def _GetNonDynamicPcdList(self
):
2116 if self
._NonDynamicPcdList
== None:
2117 self
.CollectPlatformDynamicPcds()
2118 return self
._NonDynamicPcdList
2120 ## Get list of dynamic PCDs
2121 def _GetDynamicPcdList(self
):
2122 if self
._DynamicPcdList
== None:
2123 self
.CollectPlatformDynamicPcds()
2124 return self
._DynamicPcdList
2126 ## Generate Token Number for all PCD
2127 def _GetPcdTokenNumbers(self
):
2128 if self
._PcdTokenNumber
== None:
2129 self
._PcdTokenNumber
= sdict()
2132 # Make the Dynamic and DynamicEx PCD use within different TokenNumber area.
2136 # TokenNumber 0 ~ 10
2138 # TokeNumber 11 ~ 20
2140 for Pcd
in self
.DynamicPcdList
:
2141 if Pcd
.Phase
== "PEI":
2142 if Pcd
.Type
in ["Dynamic", "DynamicDefault", "DynamicVpd", "DynamicHii"]:
2143 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
2144 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2147 for Pcd
in self
.DynamicPcdList
:
2148 if Pcd
.Phase
== "PEI":
2149 if Pcd
.Type
in ["DynamicEx", "DynamicExDefault", "DynamicExVpd", "DynamicExHii"]:
2150 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
2151 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2154 for Pcd
in self
.DynamicPcdList
:
2155 if Pcd
.Phase
== "DXE":
2156 if Pcd
.Type
in ["Dynamic", "DynamicDefault", "DynamicVpd", "DynamicHii"]:
2157 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
2158 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2161 for Pcd
in self
.DynamicPcdList
:
2162 if Pcd
.Phase
== "DXE":
2163 if Pcd
.Type
in ["DynamicEx", "DynamicExDefault", "DynamicExVpd", "DynamicExHii"]:
2164 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
2165 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2168 for Pcd
in self
.NonDynamicPcdList
:
2169 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2171 return self
._PcdTokenNumber
2173 ## Summarize ModuleAutoGen objects of all modules/libraries to be built for this platform
2174 def _GetAutoGenObjectList(self
):
2175 self
._ModuleAutoGenList
= []
2176 self
._LibraryAutoGenList
= []
2177 for ModuleFile
in self
.Platform
.Modules
:
2186 if Ma
not in self
._ModuleAutoGenList
:
2187 self
._ModuleAutoGenList
.append(Ma
)
2188 for La
in Ma
.LibraryAutoGenList
:
2189 if La
not in self
._LibraryAutoGenList
:
2190 self
._LibraryAutoGenList
.append(La
)
2191 if Ma
not in La
._ReferenceModules
:
2192 La
._ReferenceModules
.append(Ma
)
2194 ## Summarize ModuleAutoGen objects of all modules to be built for this platform
2195 def _GetModuleAutoGenList(self
):
2196 if self
._ModuleAutoGenList
== None:
2197 self
._GetAutoGenObjectList
()
2198 return self
._ModuleAutoGenList
2200 ## Summarize ModuleAutoGen objects of all libraries to be built for this platform
2201 def _GetLibraryAutoGenList(self
):
2202 if self
._LibraryAutoGenList
== None:
2203 self
._GetAutoGenObjectList
()
2204 return self
._LibraryAutoGenList
2206 ## Test if a module is supported by the platform
2208 # An error will be raised directly if the module or its arch is not supported
2209 # by the platform or current configuration
2211 def ValidModule(self
, Module
):
2212 return Module
in self
.Platform
.Modules
or Module
in self
.Platform
.LibraryInstances \
2213 or Module
in self
._AsBuildModuleList
2215 ## Resolve the library classes in a module to library instances
2217 # This method will not only resolve library classes but also sort the library
2218 # instances according to the dependency-ship.
2220 # @param Module The module from which the library classes will be resolved
2222 # @retval library_list List of library instances sorted
2224 def ApplyLibraryInstance(self
, Module
):
2225 # Cover the case that the binary INF file is list in the FDF file but not DSC file, return empty list directly
2226 if str(Module
) not in self
.Platform
.Modules
:
2229 ModuleType
= Module
.ModuleType
2231 # for overridding library instances with module specific setting
2232 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
2234 # add forced library instances (specified under LibraryClasses sections)
2236 # If a module has a MODULE_TYPE of USER_DEFINED,
2237 # do not link in NULL library class instances from the global [LibraryClasses.*] sections.
2239 if Module
.ModuleType
!= SUP_MODULE_USER_DEFINED
:
2240 for LibraryClass
in self
.Platform
.LibraryClasses
.GetKeys():
2241 if LibraryClass
.startswith("NULL") and self
.Platform
.LibraryClasses
[LibraryClass
, Module
.ModuleType
]:
2242 Module
.LibraryClasses
[LibraryClass
] = self
.Platform
.LibraryClasses
[LibraryClass
, Module
.ModuleType
]
2244 # add forced library instances (specified in module overrides)
2245 for LibraryClass
in PlatformModule
.LibraryClasses
:
2246 if LibraryClass
.startswith("NULL"):
2247 Module
.LibraryClasses
[LibraryClass
] = PlatformModule
.LibraryClasses
[LibraryClass
]
2250 LibraryConsumerList
= [Module
]
2252 ConsumedByList
= sdict()
2253 LibraryInstance
= sdict()
2255 EdkLogger
.verbose("")
2256 EdkLogger
.verbose("Library instances of module [%s] [%s]:" % (str(Module
), self
.Arch
))
2257 while len(LibraryConsumerList
) > 0:
2258 M
= LibraryConsumerList
.pop()
2259 for LibraryClassName
in M
.LibraryClasses
:
2260 if LibraryClassName
not in LibraryInstance
:
2261 # override library instance for this module
2262 if LibraryClassName
in PlatformModule
.LibraryClasses
:
2263 LibraryPath
= PlatformModule
.LibraryClasses
[LibraryClassName
]
2265 LibraryPath
= self
.Platform
.LibraryClasses
[LibraryClassName
, ModuleType
]
2266 if LibraryPath
== None or LibraryPath
== "":
2267 LibraryPath
= M
.LibraryClasses
[LibraryClassName
]
2268 if LibraryPath
== None or LibraryPath
== "":
2269 EdkLogger
.error("build", RESOURCE_NOT_AVAILABLE
,
2270 "Instance of library class [%s] is not found" % LibraryClassName
,
2272 ExtraData
="in [%s] [%s]\n\tconsumed by module [%s]" % (str(M
), self
.Arch
, str(Module
)))
2274 LibraryModule
= self
.BuildDatabase
[LibraryPath
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
2275 # for those forced library instance (NULL library), add a fake library class
2276 if LibraryClassName
.startswith("NULL"):
2277 LibraryModule
.LibraryClass
.append(LibraryClassObject(LibraryClassName
, [ModuleType
]))
2278 elif LibraryModule
.LibraryClass
== None \
2279 or len(LibraryModule
.LibraryClass
) == 0 \
2280 or (ModuleType
!= 'USER_DEFINED'
2281 and ModuleType
not in LibraryModule
.LibraryClass
[0].SupModList
):
2282 # only USER_DEFINED can link against any library instance despite of its SupModList
2283 EdkLogger
.error("build", OPTION_MISSING
,
2284 "Module type [%s] is not supported by library instance [%s]" \
2285 % (ModuleType
, LibraryPath
), File
=self
.MetaFile
,
2286 ExtraData
="consumed by [%s]" % str(Module
))
2288 LibraryInstance
[LibraryClassName
] = LibraryModule
2289 LibraryConsumerList
.append(LibraryModule
)
2290 EdkLogger
.verbose("\t" + str(LibraryClassName
) + " : " + str(LibraryModule
))
2292 LibraryModule
= LibraryInstance
[LibraryClassName
]
2294 if LibraryModule
== None:
2297 if LibraryModule
.ConstructorList
!= [] and LibraryModule
not in Constructor
:
2298 Constructor
.append(LibraryModule
)
2300 if LibraryModule
not in ConsumedByList
:
2301 ConsumedByList
[LibraryModule
] = []
2302 # don't add current module itself to consumer list
2304 if M
in ConsumedByList
[LibraryModule
]:
2306 ConsumedByList
[LibraryModule
].append(M
)
2308 # Initialize the sorted output list to the empty set
2310 SortedLibraryList
= []
2312 # Q <- Set of all nodes with no incoming edges
2314 LibraryList
= [] #LibraryInstance.values()
2316 for LibraryClassName
in LibraryInstance
:
2317 M
= LibraryInstance
[LibraryClassName
]
2318 LibraryList
.append(M
)
2319 if ConsumedByList
[M
] == []:
2323 # start the DAG algorithm
2327 while Q
== [] and EdgeRemoved
:
2329 # for each node Item with a Constructor
2330 for Item
in LibraryList
:
2331 if Item
not in Constructor
:
2333 # for each Node without a constructor with an edge e from Item to Node
2334 for Node
in ConsumedByList
[Item
]:
2335 if Node
in Constructor
:
2337 # remove edge e from the graph if Node has no constructor
2338 ConsumedByList
[Item
].remove(Node
)
2340 if ConsumedByList
[Item
] == []:
2341 # insert Item into Q
2346 # DAG is done if there's no more incoming edge for all nodes
2350 # remove node from Q
2353 SortedLibraryList
.append(Node
)
2355 # for each node Item with an edge e from Node to Item do
2356 for Item
in LibraryList
:
2357 if Node
not in ConsumedByList
[Item
]:
2359 # remove edge e from the graph
2360 ConsumedByList
[Item
].remove(Node
)
2362 if ConsumedByList
[Item
] != []:
2364 # insert Item into Q, if Item has no other incoming edges
2368 # if any remaining node Item in the graph has a constructor and an incoming edge, then the graph has a cycle
2370 for Item
in LibraryList
:
2371 if ConsumedByList
[Item
] != [] and Item
in Constructor
and len(Constructor
) > 1:
2372 ErrorMessage
= "\tconsumed by " + "\n\tconsumed by ".join([str(L
) for L
in ConsumedByList
[Item
]])
2373 EdkLogger
.error("build", BUILD_ERROR
, 'Library [%s] with constructors has a cycle' % str(Item
),
2374 ExtraData
=ErrorMessage
, File
=self
.MetaFile
)
2375 if Item
not in SortedLibraryList
:
2376 SortedLibraryList
.append(Item
)
2379 # Build the list of constructor and destructir names
2380 # The DAG Topo sort produces the destructor order, so the list of constructors must generated in the reverse order
2382 SortedLibraryList
.reverse()
2383 return SortedLibraryList
2386 ## Override PCD setting (type, value, ...)
2388 # @param ToPcd The PCD to be overrided
2389 # @param FromPcd The PCD overrideing from
2391 def _OverridePcd(self
, ToPcd
, FromPcd
, Module
=""):
2393 # in case there's PCDs coming from FDF file, which have no type given.
2394 # at this point, ToPcd.Type has the type found from dependent
2397 TokenCName
= ToPcd
.TokenCName
2398 for PcdItem
in GlobalData
.MixedPcd
:
2399 if (ToPcd
.TokenCName
, ToPcd
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
2400 TokenCName
= PcdItem
[0]
2403 if GlobalData
.BuildOptionPcd
:
2404 for pcd
in GlobalData
.BuildOptionPcd
:
2405 if (FromPcd
.TokenSpaceGuidCName
, FromPcd
.TokenCName
) == (pcd
[0], pcd
[1]):
2406 FromPcd
.DefaultValue
= pcd
[2]
2408 if ToPcd
.Pending
and FromPcd
.Type
not in [None, '']:
2409 ToPcd
.Type
= FromPcd
.Type
2410 elif (ToPcd
.Type
not in [None, '']) and (FromPcd
.Type
not in [None, ''])\
2411 and (ToPcd
.Type
!= FromPcd
.Type
) and (ToPcd
.Type
in FromPcd
.Type
):
2412 if ToPcd
.Type
.strip() == "DynamicEx":
2413 ToPcd
.Type
= FromPcd
.Type
2414 elif ToPcd
.Type
not in [None, ''] and FromPcd
.Type
not in [None, ''] \
2415 and ToPcd
.Type
!= FromPcd
.Type
:
2416 EdkLogger
.error("build", OPTION_CONFLICT
, "Mismatched PCD type",
2417 ExtraData
="%s.%s is defined as [%s] in module %s, but as [%s] in platform."\
2418 % (ToPcd
.TokenSpaceGuidCName
, TokenCName
,
2419 ToPcd
.Type
, Module
, FromPcd
.Type
),
2422 if FromPcd
.MaxDatumSize
not in [None, '']:
2423 ToPcd
.MaxDatumSize
= FromPcd
.MaxDatumSize
2424 if FromPcd
.DefaultValue
not in [None, '']:
2425 ToPcd
.DefaultValue
= FromPcd
.DefaultValue
2426 if FromPcd
.TokenValue
not in [None, '']:
2427 ToPcd
.TokenValue
= FromPcd
.TokenValue
2428 if FromPcd
.MaxDatumSize
not in [None, '']:
2429 ToPcd
.MaxDatumSize
= FromPcd
.MaxDatumSize
2430 if FromPcd
.DatumType
not in [None, '']:
2431 ToPcd
.DatumType
= FromPcd
.DatumType
2432 if FromPcd
.SkuInfoList
not in [None, '', []]:
2433 ToPcd
.SkuInfoList
= FromPcd
.SkuInfoList
2435 # check the validation of datum
2436 IsValid
, Cause
= CheckPcdDatum(ToPcd
.DatumType
, ToPcd
.DefaultValue
)
2438 EdkLogger
.error('build', FORMAT_INVALID
, Cause
, File
=self
.MetaFile
,
2439 ExtraData
="%s.%s" % (ToPcd
.TokenSpaceGuidCName
, TokenCName
))
2440 ToPcd
.validateranges
= FromPcd
.validateranges
2441 ToPcd
.validlists
= FromPcd
.validlists
2442 ToPcd
.expressions
= FromPcd
.expressions
2444 if ToPcd
.DatumType
== "VOID*" and ToPcd
.MaxDatumSize
in ['', None]:
2445 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "No MaxDatumSize specified for PCD %s.%s" \
2446 % (ToPcd
.TokenSpaceGuidCName
, TokenCName
))
2447 Value
= ToPcd
.DefaultValue
2448 if Value
in [None, '']:
2449 ToPcd
.MaxDatumSize
= '1'
2450 elif Value
[0] == 'L':
2451 ToPcd
.MaxDatumSize
= str((len(Value
) - 2) * 2)
2452 elif Value
[0] == '{':
2453 ToPcd
.MaxDatumSize
= str(len(Value
.split(',')))
2455 ToPcd
.MaxDatumSize
= str(len(Value
) - 1)
2457 # apply default SKU for dynamic PCDS if specified one is not available
2458 if (ToPcd
.Type
in PCD_DYNAMIC_TYPE_LIST
or ToPcd
.Type
in PCD_DYNAMIC_EX_TYPE_LIST
) \
2459 and ToPcd
.SkuInfoList
in [None, {}, '']:
2460 if self
.Platform
.SkuName
in self
.Platform
.SkuIds
:
2461 SkuName
= self
.Platform
.SkuName
2464 ToPcd
.SkuInfoList
= {
2465 SkuName
: SkuInfoClass(SkuName
, self
.Platform
.SkuIds
[SkuName
][0], '', '', '', '', '', ToPcd
.DefaultValue
)
2468 ## Apply PCD setting defined platform to a module
2470 # @param Module The module from which the PCD setting will be overrided
2472 # @retval PCD_list The list PCDs with settings from platform
2474 def ApplyPcdSetting(self
, Module
, Pcds
):
2475 # for each PCD in module
2476 for Name
, Guid
in Pcds
:
2477 PcdInModule
= Pcds
[Name
, Guid
]
2478 # find out the PCD setting in platform
2479 if (Name
, Guid
) in self
.Platform
.Pcds
:
2480 PcdInPlatform
= self
.Platform
.Pcds
[Name
, Guid
]
2482 PcdInPlatform
= None
2483 # then override the settings if any
2484 self
._OverridePcd
(PcdInModule
, PcdInPlatform
, Module
)
2485 # resolve the VariableGuid value
2486 for SkuId
in PcdInModule
.SkuInfoList
:
2487 Sku
= PcdInModule
.SkuInfoList
[SkuId
]
2488 if Sku
.VariableGuid
== '': continue
2489 Sku
.VariableGuidValue
= GuidValue(Sku
.VariableGuid
, self
.PackageList
, self
.MetaFile
.Path
)
2490 if Sku
.VariableGuidValue
== None:
2491 PackageList
= "\n\t".join([str(P
) for P
in self
.PackageList
])
2494 RESOURCE_NOT_AVAILABLE
,
2495 "Value of GUID [%s] is not found in" % Sku
.VariableGuid
,
2496 ExtraData
=PackageList
+ "\n\t(used with %s.%s from module %s)" \
2497 % (Guid
, Name
, str(Module
)),
2501 # override PCD settings with module specific setting
2502 if Module
in self
.Platform
.Modules
:
2503 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
2504 for Key
in PlatformModule
.Pcds
:
2509 elif Key
in GlobalData
.MixedPcd
:
2510 for PcdItem
in GlobalData
.MixedPcd
[Key
]:
2512 ToPcd
= Pcds
[PcdItem
]
2516 self
._OverridePcd
(ToPcd
, PlatformModule
.Pcds
[Key
], Module
)
2517 return Pcds
.values()
2519 ## Resolve library names to library modules
2521 # (for Edk.x modules)
2523 # @param Module The module from which the library names will be resolved
2525 # @retval library_list The list of library modules
2527 def ResolveLibraryReference(self
, Module
):
2528 EdkLogger
.verbose("")
2529 EdkLogger
.verbose("Library instances of module [%s] [%s]:" % (str(Module
), self
.Arch
))
2530 LibraryConsumerList
= [Module
]
2532 # "CompilerStub" is a must for Edk modules
2533 if Module
.Libraries
:
2534 Module
.Libraries
.append("CompilerStub")
2536 while len(LibraryConsumerList
) > 0:
2537 M
= LibraryConsumerList
.pop()
2538 for LibraryName
in M
.Libraries
:
2539 Library
= self
.Platform
.LibraryClasses
[LibraryName
, ':dummy:']
2541 for Key
in self
.Platform
.LibraryClasses
.data
.keys():
2542 if LibraryName
.upper() == Key
.upper():
2543 Library
= self
.Platform
.LibraryClasses
[Key
, ':dummy:']
2546 EdkLogger
.warn("build", "Library [%s] is not found" % LibraryName
, File
=str(M
),
2547 ExtraData
="\t%s [%s]" % (str(Module
), self
.Arch
))
2550 if Library
not in LibraryList
:
2551 LibraryList
.append(Library
)
2552 LibraryConsumerList
.append(Library
)
2553 EdkLogger
.verbose("\t" + LibraryName
+ " : " + str(Library
) + ' ' + str(type(Library
)))
2556 ## Calculate the priority value of the build option
2558 # @param Key Build option definition contain: TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
2560 # @retval Value Priority value based on the priority list.
2562 def CalculatePriorityValue(self
, Key
):
2563 Target
, ToolChain
, Arch
, CommandType
, Attr
= Key
.split('_')
2564 PriorityValue
= 0x11111
2566 PriorityValue
&= 0x01111
2567 if ToolChain
== "*":
2568 PriorityValue
&= 0x10111
2570 PriorityValue
&= 0x11011
2571 if CommandType
== "*":
2572 PriorityValue
&= 0x11101
2574 PriorityValue
&= 0x11110
2576 return self
.PrioList
["0x%0.5x" % PriorityValue
]
2579 ## Expand * in build option key
2581 # @param Options Options to be expanded
2583 # @retval options Options expanded
2585 def _ExpandBuildOption(self
, Options
, ModuleStyle
=None):
2592 # Construct a list contain the build options which need override.
2596 # Key[0] -- tool family
2597 # Key[1] -- TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
2599 if (Key
[0] == self
.BuildRuleFamily
and
2600 (ModuleStyle
== None or len(Key
) < 3 or (len(Key
) > 2 and Key
[2] == ModuleStyle
))):
2601 Target
, ToolChain
, Arch
, CommandType
, Attr
= Key
[1].split('_')
2602 if Target
== self
.BuildTarget
or Target
== "*":
2603 if ToolChain
== self
.ToolChain
or ToolChain
== "*":
2604 if Arch
== self
.Arch
or Arch
== "*":
2605 if Options
[Key
].startswith("="):
2606 if OverrideList
.get(Key
[1]) != None:
2607 OverrideList
.pop(Key
[1])
2608 OverrideList
[Key
[1]] = Options
[Key
]
2611 # Use the highest priority value.
2613 if (len(OverrideList
) >= 2):
2614 KeyList
= OverrideList
.keys()
2615 for Index
in range(len(KeyList
)):
2616 NowKey
= KeyList
[Index
]
2617 Target1
, ToolChain1
, Arch1
, CommandType1
, Attr1
= NowKey
.split("_")
2618 for Index1
in range(len(KeyList
) - Index
- 1):
2619 NextKey
= KeyList
[Index1
+ Index
+ 1]
2621 # Compare two Key, if one is included by another, choose the higher priority one
2623 Target2
, ToolChain2
, Arch2
, CommandType2
, Attr2
= NextKey
.split("_")
2624 if Target1
== Target2
or Target1
== "*" or Target2
== "*":
2625 if ToolChain1
== ToolChain2
or ToolChain1
== "*" or ToolChain2
== "*":
2626 if Arch1
== Arch2
or Arch1
== "*" or Arch2
== "*":
2627 if CommandType1
== CommandType2
or CommandType1
== "*" or CommandType2
== "*":
2628 if Attr1
== Attr2
or Attr1
== "*" or Attr2
== "*":
2629 if self
.CalculatePriorityValue(NowKey
) > self
.CalculatePriorityValue(NextKey
):
2630 if Options
.get((self
.BuildRuleFamily
, NextKey
)) != None:
2631 Options
.pop((self
.BuildRuleFamily
, NextKey
))
2633 if Options
.get((self
.BuildRuleFamily
, NowKey
)) != None:
2634 Options
.pop((self
.BuildRuleFamily
, NowKey
))
2637 if ModuleStyle
!= None and len (Key
) > 2:
2638 # Check Module style is EDK or EDKII.
2639 # Only append build option for the matched style module.
2640 if ModuleStyle
== EDK_NAME
and Key
[2] != EDK_NAME
:
2642 elif ModuleStyle
== EDKII_NAME
and Key
[2] != EDKII_NAME
:
2645 Target
, Tag
, Arch
, Tool
, Attr
= Key
[1].split("_")
2646 # if tool chain family doesn't match, skip it
2647 if Tool
in self
.ToolDefinition
and Family
!= "":
2648 FamilyIsNull
= False
2649 if self
.ToolDefinition
[Tool
].get(TAB_TOD_DEFINES_BUILDRULEFAMILY
, "") != "":
2650 if Family
!= self
.ToolDefinition
[Tool
][TAB_TOD_DEFINES_BUILDRULEFAMILY
]:
2652 elif Family
!= self
.ToolDefinition
[Tool
][TAB_TOD_DEFINES_FAMILY
]:
2655 # expand any wildcard
2656 if Target
== "*" or Target
== self
.BuildTarget
:
2657 if Tag
== "*" or Tag
== self
.ToolChain
:
2658 if Arch
== "*" or Arch
== self
.Arch
:
2659 if Tool
not in BuildOptions
:
2660 BuildOptions
[Tool
] = {}
2661 if Attr
!= "FLAGS" or Attr
not in BuildOptions
[Tool
] or Options
[Key
].startswith('='):
2662 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2664 # append options for the same tool except PATH
2666 BuildOptions
[Tool
][Attr
] += " " + Options
[Key
]
2668 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2669 # Build Option Family has been checked, which need't to be checked again for family.
2670 if FamilyMatch
or FamilyIsNull
:
2674 if ModuleStyle
!= None and len (Key
) > 2:
2675 # Check Module style is EDK or EDKII.
2676 # Only append build option for the matched style module.
2677 if ModuleStyle
== EDK_NAME
and Key
[2] != EDK_NAME
:
2679 elif ModuleStyle
== EDKII_NAME
and Key
[2] != EDKII_NAME
:
2682 Target
, Tag
, Arch
, Tool
, Attr
= Key
[1].split("_")
2683 # if tool chain family doesn't match, skip it
2684 if Tool
not in self
.ToolDefinition
or Family
== "":
2686 # option has been added before
2687 if Family
!= self
.ToolDefinition
[Tool
][TAB_TOD_DEFINES_FAMILY
]:
2690 # expand any wildcard
2691 if Target
== "*" or Target
== self
.BuildTarget
:
2692 if Tag
== "*" or Tag
== self
.ToolChain
:
2693 if Arch
== "*" or Arch
== self
.Arch
:
2694 if Tool
not in BuildOptions
:
2695 BuildOptions
[Tool
] = {}
2696 if Attr
!= "FLAGS" or Attr
not in BuildOptions
[Tool
] or Options
[Key
].startswith('='):
2697 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2699 # append options for the same tool except PATH
2701 BuildOptions
[Tool
][Attr
] += " " + Options
[Key
]
2703 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2706 ## Append build options in platform to a module
2708 # @param Module The module to which the build options will be appened
2710 # @retval options The options appended with build options in platform
2712 def ApplyBuildOption(self
, Module
):
2713 # Get the different options for the different style module
2714 if Module
.AutoGenVersion
< 0x00010005:
2715 PlatformOptions
= self
.EdkBuildOption
2716 ModuleTypeOptions
= self
.Platform
.GetBuildOptionsByModuleType(EDK_NAME
, Module
.ModuleType
)
2718 PlatformOptions
= self
.EdkIIBuildOption
2719 ModuleTypeOptions
= self
.Platform
.GetBuildOptionsByModuleType(EDKII_NAME
, Module
.ModuleType
)
2720 ModuleTypeOptions
= self
._ExpandBuildOption
(ModuleTypeOptions
)
2721 ModuleOptions
= self
._ExpandBuildOption
(Module
.BuildOptions
)
2722 if Module
in self
.Platform
.Modules
:
2723 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
2724 PlatformModuleOptions
= self
._ExpandBuildOption
(PlatformModule
.BuildOptions
)
2726 PlatformModuleOptions
= {}
2728 BuildRuleOrder
= None
2729 for Options
in [self
.ToolDefinition
, ModuleOptions
, PlatformOptions
, ModuleTypeOptions
, PlatformModuleOptions
]:
2730 for Tool
in Options
:
2731 for Attr
in Options
[Tool
]:
2732 if Attr
== TAB_TOD_DEFINES_BUILDRULEORDER
:
2733 BuildRuleOrder
= Options
[Tool
][Attr
]
2735 AllTools
= set(ModuleOptions
.keys() + PlatformOptions
.keys() +
2736 PlatformModuleOptions
.keys() + ModuleTypeOptions
.keys() +
2737 self
.ToolDefinition
.keys())
2739 for Tool
in AllTools
:
2740 if Tool
not in BuildOptions
:
2741 BuildOptions
[Tool
] = {}
2743 for Options
in [self
.ToolDefinition
, ModuleOptions
, PlatformOptions
, ModuleTypeOptions
, PlatformModuleOptions
]:
2744 if Tool
not in Options
:
2746 for Attr
in Options
[Tool
]:
2747 Value
= Options
[Tool
][Attr
]
2749 # Do not generate it in Makefile
2751 if Attr
== TAB_TOD_DEFINES_BUILDRULEORDER
:
2753 if Attr
not in BuildOptions
[Tool
]:
2754 BuildOptions
[Tool
][Attr
] = ""
2755 # check if override is indicated
2756 if Value
.startswith('='):
2757 ToolPath
= Value
[1:]
2758 ToolPath
= mws
.handleWsMacro(ToolPath
)
2759 BuildOptions
[Tool
][Attr
] = ToolPath
2761 Value
= mws
.handleWsMacro(Value
)
2763 BuildOptions
[Tool
][Attr
] += " " + Value
2765 BuildOptions
[Tool
][Attr
] = Value
2766 if Module
.AutoGenVersion
< 0x00010005 and self
.Workspace
.UniFlag
!= None:
2768 # Override UNI flag only for EDK module.
2770 if 'BUILD' not in BuildOptions
:
2771 BuildOptions
['BUILD'] = {}
2772 BuildOptions
['BUILD']['FLAGS'] = self
.Workspace
.UniFlag
2773 return BuildOptions
, BuildRuleOrder
2775 Platform
= property(_GetPlatform
)
2776 Name
= property(_GetName
)
2777 Guid
= property(_GetGuid
)
2778 Version
= property(_GetVersion
)
2780 OutputDir
= property(_GetOutputDir
)
2781 BuildDir
= property(_GetBuildDir
)
2782 MakeFileDir
= property(_GetMakeFileDir
)
2783 FdfFile
= property(_GetFdfFile
)
2785 PcdTokenNumber
= property(_GetPcdTokenNumbers
) # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber
2786 DynamicPcdList
= property(_GetDynamicPcdList
) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
2787 NonDynamicPcdList
= property(_GetNonDynamicPcdList
) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
2788 NonDynamicPcdDict
= property(_GetNonDynamicPcdDict
)
2789 PackageList
= property(_GetPackageList
)
2791 ToolDefinition
= property(_GetToolDefinition
) # toolcode : tool path
2792 ToolDefinitionFile
= property(_GetToolDefFile
) # toolcode : lib path
2793 ToolChainFamily
= property(_GetToolChainFamily
)
2794 BuildRuleFamily
= property(_GetBuildRuleFamily
)
2795 BuildOption
= property(_GetBuildOptions
) # toolcode : option
2796 EdkBuildOption
= property(_GetEdkBuildOptions
) # edktoolcode : option
2797 EdkIIBuildOption
= property(_GetEdkIIBuildOptions
) # edkiitoolcode : option
2799 BuildCommand
= property(_GetBuildCommand
)
2800 BuildRule
= property(_GetBuildRule
)
2801 ModuleAutoGenList
= property(_GetModuleAutoGenList
)
2802 LibraryAutoGenList
= property(_GetLibraryAutoGenList
)
2803 GenFdsCommand
= property(_GenFdsCommand
)
2805 ## ModuleAutoGen class
2807 # This class encapsules the AutoGen behaviors for the build tools. In addition to
2808 # the generation of AutoGen.h and AutoGen.c, it will generate *.depex file according
2809 # to the [depex] section in module's inf file.
2811 class ModuleAutoGen(AutoGen
):
2812 ## Cache the timestamps of metafiles of every module in a class variable
2816 ## The real constructor of ModuleAutoGen
2818 # This method is not supposed to be called by users of ModuleAutoGen. It's
2819 # only used by factory method __new__() to do real initialization work for an
2820 # object of ModuleAutoGen
2822 # @param Workspace EdkIIWorkspaceBuild object
2823 # @param ModuleFile The path of module file
2824 # @param Target Build target (DEBUG, RELEASE)
2825 # @param Toolchain Name of tool chain
2826 # @param Arch The arch the module supports
2827 # @param PlatformFile Platform meta-file
2829 def _Init(self
, Workspace
, ModuleFile
, Target
, Toolchain
, Arch
, PlatformFile
):
2830 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "AutoGen module [%s] [%s]" % (ModuleFile
, Arch
))
2831 GlobalData
.gProcessingFile
= "%s [%s, %s, %s]" % (ModuleFile
, Arch
, Toolchain
, Target
)
2833 self
.Workspace
= Workspace
2834 self
.WorkspaceDir
= Workspace
.WorkspaceDir
2836 self
.MetaFile
= ModuleFile
2837 self
.PlatformInfo
= PlatformAutoGen(Workspace
, PlatformFile
, Target
, Toolchain
, Arch
)
2838 # check if this module is employed by active platform
2839 if not self
.PlatformInfo
.ValidModule(self
.MetaFile
):
2840 EdkLogger
.verbose("Module [%s] for [%s] is not employed by active platform\n" \
2841 % (self
.MetaFile
, Arch
))
2844 self
.SourceDir
= self
.MetaFile
.SubDir
2845 self
.SourceDir
= mws
.relpath(self
.SourceDir
, self
.WorkspaceDir
)
2847 self
.SourceOverrideDir
= None
2848 # use overrided path defined in DSC file
2849 if self
.MetaFile
.Key
in GlobalData
.gOverrideDir
:
2850 self
.SourceOverrideDir
= GlobalData
.gOverrideDir
[self
.MetaFile
.Key
]
2852 self
.ToolChain
= Toolchain
2853 self
.BuildTarget
= Target
2855 self
.ToolChainFamily
= self
.PlatformInfo
.ToolChainFamily
2856 self
.BuildRuleFamily
= self
.PlatformInfo
.BuildRuleFamily
2858 self
.IsMakeFileCreated
= False
2859 self
.IsCodeFileCreated
= False
2860 self
.IsAsBuiltInfCreated
= False
2861 self
.DepexGenerated
= False
2863 self
.BuildDatabase
= self
.Workspace
.BuildDatabase
2864 self
.BuildRuleOrder
= None
2870 self
._Version
= None
2871 self
._ModuleType
= None
2872 self
._ComponentType
= None
2873 self
._PcdIsDriver
= None
2874 self
._AutoGenVersion
= None
2875 self
._LibraryFlag
= None
2876 self
._CustomMakefile
= None
2879 self
._BuildDir
= None
2880 self
._OutputDir
= None
2881 self
._FfsOutputDir
= None
2882 self
._DebugDir
= None
2883 self
._MakeFileDir
= None
2885 self
._IncludePathList
= None
2886 self
._IncludePathLength
= 0
2887 self
._AutoGenFileList
= None
2888 self
._UnicodeFileList
= None
2889 self
._VfrFileList
= None
2890 self
._IdfFileList
= None
2891 self
._SourceFileList
= None
2892 self
._ObjectFileList
= None
2893 self
._BinaryFileList
= None
2895 self
._DependentPackageList
= None
2896 self
._DependentLibraryList
= None
2897 self
._LibraryAutoGenList
= None
2898 self
._DerivedPackageList
= None
2899 self
._ModulePcdList
= None
2900 self
._LibraryPcdList
= None
2901 self
._PcdComments
= sdict()
2902 self
._GuidList
= None
2903 self
._GuidsUsedByPcd
= None
2904 self
._GuidComments
= sdict()
2905 self
._ProtocolList
= None
2906 self
._ProtocolComments
= sdict()
2907 self
._PpiList
= None
2908 self
._PpiComments
= sdict()
2909 self
._DepexList
= None
2910 self
._DepexExpressionList
= None
2911 self
._BuildOption
= None
2912 self
._BuildOptionIncPathList
= None
2913 self
._BuildTargets
= None
2914 self
._IntroBuildTargetList
= None
2915 self
._FinalBuildTargetList
= None
2916 self
._FileTypes
= None
2917 self
._BuildRules
= None
2919 self
._TimeStampPath
= None
2921 self
.AutoGenDepSet
= set()
2924 ## The Modules referenced to this Library
2925 # Only Library has this attribute
2926 self
._ReferenceModules
= []
2928 ## Store the FixedAtBuild Pcds
2930 self
._FixedAtBuildPcds
= []
2935 return "%s [%s]" % (self
.MetaFile
, self
.Arch
)
2937 # Get FixedAtBuild Pcds of this Module
2938 def _GetFixedAtBuildPcds(self
):
2939 if self
._FixedAtBuildPcds
:
2940 return self
._FixedAtBuildPcds
2941 for Pcd
in self
.ModulePcdList
:
2942 if Pcd
.Type
!= "FixedAtBuild":
2944 if Pcd
not in self
._FixedAtBuildPcds
:
2945 self
._FixedAtBuildPcds
.append(Pcd
)
2947 return self
._FixedAtBuildPcds
2949 def _GetUniqueBaseName(self
):
2950 BaseName
= self
.Name
2951 for Module
in self
.PlatformInfo
.ModuleAutoGenList
:
2952 if Module
.MetaFile
== self
.MetaFile
:
2954 if Module
.Name
== self
.Name
:
2955 if uuid
.UUID(Module
.Guid
) == uuid
.UUID(self
.Guid
):
2956 EdkLogger
.error("build", FILE_DUPLICATED
, 'Modules have same BaseName and FILE_GUID:\n'
2957 ' %s\n %s' % (Module
.MetaFile
, self
.MetaFile
))
2958 BaseName
= '%s_%s' % (self
.Name
, self
.Guid
)
2961 # Macros could be used in build_rule.txt (also Makefile)
2962 def _GetMacros(self
):
2963 if self
._Macro
== None:
2964 self
._Macro
= sdict()
2965 self
._Macro
["WORKSPACE" ] = self
.WorkspaceDir
2966 self
._Macro
["MODULE_NAME" ] = self
.Name
2967 self
._Macro
["MODULE_NAME_GUID" ] = self
._GetUniqueBaseName
()
2968 self
._Macro
["MODULE_GUID" ] = self
.Guid
2969 self
._Macro
["MODULE_VERSION" ] = self
.Version
2970 self
._Macro
["MODULE_TYPE" ] = self
.ModuleType
2971 self
._Macro
["MODULE_FILE" ] = str(self
.MetaFile
)
2972 self
._Macro
["MODULE_FILE_BASE_NAME" ] = self
.MetaFile
.BaseName
2973 self
._Macro
["MODULE_RELATIVE_DIR" ] = self
.SourceDir
2974 self
._Macro
["MODULE_DIR" ] = self
.SourceDir
2976 self
._Macro
["BASE_NAME" ] = self
.Name
2978 self
._Macro
["ARCH" ] = self
.Arch
2979 self
._Macro
["TOOLCHAIN" ] = self
.ToolChain
2980 self
._Macro
["TOOLCHAIN_TAG" ] = self
.ToolChain
2981 self
._Macro
["TOOL_CHAIN_TAG" ] = self
.ToolChain
2982 self
._Macro
["TARGET" ] = self
.BuildTarget
2984 self
._Macro
["BUILD_DIR" ] = self
.PlatformInfo
.BuildDir
2985 self
._Macro
["BIN_DIR" ] = os
.path
.join(self
.PlatformInfo
.BuildDir
, self
.Arch
)
2986 self
._Macro
["LIB_DIR" ] = os
.path
.join(self
.PlatformInfo
.BuildDir
, self
.Arch
)
2987 self
._Macro
["MODULE_BUILD_DIR" ] = self
.BuildDir
2988 self
._Macro
["OUTPUT_DIR" ] = self
.OutputDir
2989 self
._Macro
["DEBUG_DIR" ] = self
.DebugDir
2990 self
._Macro
["DEST_DIR_OUTPUT" ] = self
.OutputDir
2991 self
._Macro
["DEST_DIR_DEBUG" ] = self
.DebugDir
2992 self
._Macro
["PLATFORM_NAME" ] = self
.PlatformInfo
.Name
2993 self
._Macro
["PLATFORM_GUID" ] = self
.PlatformInfo
.Guid
2994 self
._Macro
["PLATFORM_VERSION" ] = self
.PlatformInfo
.Version
2995 self
._Macro
["PLATFORM_RELATIVE_DIR" ] = self
.PlatformInfo
.SourceDir
2996 self
._Macro
["PLATFORM_DIR" ] = mws
.join(self
.WorkspaceDir
, self
.PlatformInfo
.SourceDir
)
2997 self
._Macro
["PLATFORM_OUTPUT_DIR" ] = self
.PlatformInfo
.OutputDir
2998 self
._Macro
["FFS_OUTPUT_DIR" ] = self
.FfsOutputDir
3001 ## Return the module build data object
3002 def _GetModule(self
):
3003 if self
._Module
== None:
3004 self
._Module
= self
.Workspace
.BuildDatabase
[self
.MetaFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
3007 ## Return the module name
3008 def _GetBaseName(self
):
3009 return self
.Module
.BaseName
3011 ## Return the module DxsFile if exist
3012 def _GetDxsFile(self
):
3013 return self
.Module
.DxsFile
3015 ## Return the module SourceOverridePath
3016 def _GetSourceOverridePath(self
):
3017 return self
.Module
.SourceOverridePath
3019 ## Return the module meta-file GUID
3022 # To build same module more than once, the module path with FILE_GUID overridden has
3023 # the file name FILE_GUIDmodule.inf, but the relative path (self.MetaFile.File) is the realy path
3024 # in DSC. The overridden GUID can be retrieved from file name
3026 if os
.path
.basename(self
.MetaFile
.File
) != os
.path
.basename(self
.MetaFile
.Path
):
3028 # Length of GUID is 36
3030 return os
.path
.basename(self
.MetaFile
.Path
)[:36]
3031 return self
.Module
.Guid
3033 ## Return the module version
3034 def _GetVersion(self
):
3035 return self
.Module
.Version
3037 ## Return the module type
3038 def _GetModuleType(self
):
3039 return self
.Module
.ModuleType
3041 ## Return the component type (for Edk.x style of module)
3042 def _GetComponentType(self
):
3043 return self
.Module
.ComponentType
3045 ## Return the build type
3046 def _GetBuildType(self
):
3047 return self
.Module
.BuildType
3049 ## Return the PCD_IS_DRIVER setting
3050 def _GetPcdIsDriver(self
):
3051 return self
.Module
.PcdIsDriver
3053 ## Return the autogen version, i.e. module meta-file version
3054 def _GetAutoGenVersion(self
):
3055 return self
.Module
.AutoGenVersion
3057 ## Check if the module is library or not
3058 def _IsLibrary(self
):
3059 if self
._LibraryFlag
== None:
3060 if self
.Module
.LibraryClass
!= None and self
.Module
.LibraryClass
!= []:
3061 self
._LibraryFlag
= True
3063 self
._LibraryFlag
= False
3064 return self
._LibraryFlag
3066 ## Check if the module is binary module or not
3067 def _IsBinaryModule(self
):
3068 return self
.Module
.IsBinaryModule
3070 ## Return the directory to store intermediate files of the module
3071 def _GetBuildDir(self
):
3072 if self
._BuildDir
== None:
3073 self
._BuildDir
= path
.join(
3074 self
.PlatformInfo
.BuildDir
,
3077 self
.MetaFile
.BaseName
3079 CreateDirectory(self
._BuildDir
)
3080 return self
._BuildDir
3082 ## Return the directory to store the intermediate object files of the mdoule
3083 def _GetOutputDir(self
):
3084 if self
._OutputDir
== None:
3085 self
._OutputDir
= path
.join(self
.BuildDir
, "OUTPUT")
3086 CreateDirectory(self
._OutputDir
)
3087 return self
._OutputDir
3089 ## Return the directory to store ffs file
3090 def _GetFfsOutputDir(self
):
3091 if self
._FfsOutputDir
== None:
3092 if GlobalData
.gFdfParser
!= None:
3093 self
._FfsOutputDir
= path
.join(self
.PlatformInfo
.BuildDir
, "FV", "Ffs", self
.Guid
+ self
.Name
)
3095 self
._FfsOutputDir
= ''
3096 return self
._FfsOutputDir
3098 ## Return the directory to store auto-gened source files of the mdoule
3099 def _GetDebugDir(self
):
3100 if self
._DebugDir
== None:
3101 self
._DebugDir
= path
.join(self
.BuildDir
, "DEBUG")
3102 CreateDirectory(self
._DebugDir
)
3103 return self
._DebugDir
3105 ## Return the path of custom file
3106 def _GetCustomMakefile(self
):
3107 if self
._CustomMakefile
== None:
3108 self
._CustomMakefile
= {}
3109 for Type
in self
.Module
.CustomMakefile
:
3110 if Type
in gMakeTypeMap
:
3111 MakeType
= gMakeTypeMap
[Type
]
3114 if self
.SourceOverrideDir
!= None:
3115 File
= os
.path
.join(self
.SourceOverrideDir
, self
.Module
.CustomMakefile
[Type
])
3116 if not os
.path
.exists(File
):
3117 File
= os
.path
.join(self
.SourceDir
, self
.Module
.CustomMakefile
[Type
])
3119 File
= os
.path
.join(self
.SourceDir
, self
.Module
.CustomMakefile
[Type
])
3120 self
._CustomMakefile
[MakeType
] = File
3121 return self
._CustomMakefile
3123 ## Return the directory of the makefile
3125 # @retval string The directory string of module's makefile
3127 def _GetMakeFileDir(self
):
3128 return self
.BuildDir
3130 ## Return build command string
3132 # @retval string Build command string
3134 def _GetBuildCommand(self
):
3135 return self
.PlatformInfo
.BuildCommand
3137 ## Get object list of all packages the module and its dependent libraries belong to
3139 # @retval list The list of package object
3141 def _GetDerivedPackageList(self
):
3143 for M
in [self
.Module
] + self
.DependentLibraryList
:
3144 for Package
in M
.Packages
:
3145 if Package
in PackageList
:
3147 PackageList
.append(Package
)
3150 ## Get the depex string
3152 # @return : a string contain all depex expresion.
3153 def _GetDepexExpresionString(self
):
3156 ## DPX_SOURCE IN Define section.
3157 if self
.Module
.DxsFile
:
3159 for M
in [self
.Module
] + self
.DependentLibraryList
:
3160 Filename
= M
.MetaFile
.Path
3161 InfObj
= InfSectionParser
.InfSectionParser(Filename
)
3162 DepexExpresionList
= InfObj
.GetDepexExpresionList()
3163 for DepexExpresion
in DepexExpresionList
:
3164 for key
in DepexExpresion
.keys():
3165 Arch
, ModuleType
= key
3166 DepexExpr
= [x
for x
in DepexExpresion
[key
] if not str(x
).startswith('#')]
3167 # the type of build module is USER_DEFINED.
3168 # All different DEPEX section tags would be copied into the As Built INF file
3169 # and there would be separate DEPEX section tags
3170 if self
.ModuleType
.upper() == SUP_MODULE_USER_DEFINED
:
3171 if (Arch
.upper() == self
.Arch
.upper()) and (ModuleType
.upper() != TAB_ARCH_COMMON
):
3172 DepexList
.append({(Arch
, ModuleType
): DepexExpr
})
3174 if Arch
.upper() == TAB_ARCH_COMMON
or \
3175 (Arch
.upper() == self
.Arch
.upper() and \
3176 ModuleType
.upper() in [TAB_ARCH_COMMON
, self
.ModuleType
.upper()]):
3177 DepexList
.append({(Arch
, ModuleType
): DepexExpr
})
3179 #the type of build module is USER_DEFINED.
3180 if self
.ModuleType
.upper() == SUP_MODULE_USER_DEFINED
:
3181 for Depex
in DepexList
:
3182 for key
in Depex
.keys():
3183 DepexStr
+= '[Depex.%s.%s]\n' % key
3184 DepexStr
+= '\n'.join(['# '+ val
for val
in Depex
[key
]])
3187 return '[Depex.%s]\n' % self
.Arch
3190 #the type of build module not is USER_DEFINED.
3192 for Depex
in DepexList
:
3197 for D
in Depex
.values():
3198 DepexStr
+= ' '.join([val
for val
in D
])
3199 Index
= DepexStr
.find('END')
3200 if Index
> -1 and Index
== len(DepexStr
) - 3:
3201 DepexStr
= DepexStr
[:-3]
3202 DepexStr
= DepexStr
.strip()
3205 DepexStr
= DepexStr
.lstrip('(').rstrip(')').strip()
3207 return '[Depex.%s]\n' % self
.Arch
3208 return '[Depex.%s]\n# ' % self
.Arch
+ DepexStr
3210 ## Merge dependency expression
3212 # @retval list The token list of the dependency expression after parsed
3214 def _GetDepexTokenList(self
):
3215 if self
._DepexList
== None:
3216 self
._DepexList
= {}
3217 if self
.DxsFile
or self
.IsLibrary
or TAB_DEPENDENCY_EXPRESSION_FILE
in self
.FileTypes
:
3218 return self
._DepexList
3220 self
._DepexList
[self
.ModuleType
] = []
3222 for ModuleType
in self
._DepexList
:
3223 DepexList
= self
._DepexList
[ModuleType
]
3225 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
3227 for M
in [self
.Module
] + self
.DependentLibraryList
:
3229 for D
in M
.Depex
[self
.Arch
, ModuleType
]:
3231 DepexList
.append('AND')
3232 DepexList
.append('(')
3234 if DepexList
[-1] == 'END': # no need of a END at this time
3236 DepexList
.append(')')
3239 EdkLogger
.verbose("DEPEX[%s] (+%s) = %s" % (self
.Name
, M
.BaseName
, DepexList
))
3240 if 'BEFORE' in DepexList
or 'AFTER' in DepexList
:
3242 if len(DepexList
) > 0:
3243 EdkLogger
.verbose('')
3244 return self
._DepexList
3246 ## Merge dependency expression
3248 # @retval list The token list of the dependency expression after parsed
3250 def _GetDepexExpressionTokenList(self
):
3251 if self
._DepexExpressionList
== None:
3252 self
._DepexExpressionList
= {}
3253 if self
.DxsFile
or self
.IsLibrary
or TAB_DEPENDENCY_EXPRESSION_FILE
in self
.FileTypes
:
3254 return self
._DepexExpressionList
3256 self
._DepexExpressionList
[self
.ModuleType
] = ''
3258 for ModuleType
in self
._DepexExpressionList
:
3259 DepexExpressionList
= self
._DepexExpressionList
[ModuleType
]
3261 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
3263 for M
in [self
.Module
] + self
.DependentLibraryList
:
3265 for D
in M
.DepexExpression
[self
.Arch
, ModuleType
]:
3266 if DepexExpressionList
!= '':
3267 DepexExpressionList
+= ' AND '
3268 DepexExpressionList
+= '('
3269 DepexExpressionList
+= D
3270 DepexExpressionList
= DepexExpressionList
.rstrip('END').strip()
3271 DepexExpressionList
+= ')'
3274 EdkLogger
.verbose("DEPEX[%s] (+%s) = %s" % (self
.Name
, M
.BaseName
, DepexExpressionList
))
3275 if 'BEFORE' in DepexExpressionList
or 'AFTER' in DepexExpressionList
:
3277 if len(DepexExpressionList
) > 0:
3278 EdkLogger
.verbose('')
3279 self
._DepexExpressionList
[ModuleType
] = DepexExpressionList
3280 return self
._DepexExpressionList
3282 # Get the tiano core user extension, it is contain dependent library.
3283 # @retval: a list contain tiano core userextension.
3285 def _GetTianoCoreUserExtensionList(self
):
3286 TianoCoreUserExtentionList
= []
3287 for M
in [self
.Module
] + self
.DependentLibraryList
:
3288 Filename
= M
.MetaFile
.Path
3289 InfObj
= InfSectionParser
.InfSectionParser(Filename
)
3290 TianoCoreUserExtenList
= InfObj
.GetUserExtensionTianoCore()
3291 for TianoCoreUserExtent
in TianoCoreUserExtenList
:
3292 for Section
in TianoCoreUserExtent
.keys():
3293 ItemList
= Section
.split(TAB_SPLIT
)
3295 if len(ItemList
) == 4:
3297 if Arch
.upper() == TAB_ARCH_COMMON
or Arch
.upper() == self
.Arch
.upper():
3299 TianoCoreList
.extend([TAB_SECTION_START
+ Section
+ TAB_SECTION_END
])
3300 TianoCoreList
.extend(TianoCoreUserExtent
[Section
][:])
3301 TianoCoreList
.append('\n')
3302 TianoCoreUserExtentionList
.append(TianoCoreList
)
3304 return TianoCoreUserExtentionList
3306 ## Return the list of specification version required for the module
3308 # @retval list The list of specification defined in module file
3310 def _GetSpecification(self
):
3311 return self
.Module
.Specification
3313 ## Tool option for the module build
3315 # @param PlatformInfo The object of PlatformBuildInfo
3316 # @retval dict The dict containing valid options
3318 def _GetModuleBuildOption(self
):
3319 if self
._BuildOption
== None:
3320 self
._BuildOption
, self
.BuildRuleOrder
= self
.PlatformInfo
.ApplyBuildOption(self
.Module
)
3321 if self
.BuildRuleOrder
:
3322 self
.BuildRuleOrder
= ['.%s' % Ext
for Ext
in self
.BuildRuleOrder
.split()]
3323 return self
._BuildOption
3325 ## Get include path list from tool option for the module build
3327 # @retval list The include path list
3329 def _GetBuildOptionIncPathList(self
):
3330 if self
._BuildOptionIncPathList
== None:
3332 # Regular expression for finding Include Directories, the difference between MSFT and INTEL/GCC/RVCT
3333 # is the former use /I , the Latter used -I to specify include directories
3335 if self
.PlatformInfo
.ToolChainFamily
in ('MSFT'):
3336 gBuildOptIncludePattern
= re
.compile(r
"(?:.*?)/I[ \t]*([^ ]*)", re
.MULTILINE | re
.DOTALL
)
3337 elif self
.PlatformInfo
.ToolChainFamily
in ('INTEL', 'GCC', 'RVCT'):
3338 gBuildOptIncludePattern
= re
.compile(r
"(?:.*?)-I[ \t]*([^ ]*)", re
.MULTILINE | re
.DOTALL
)
3341 # New ToolChainFamily, don't known whether there is option to specify include directories
3343 self
._BuildOptionIncPathList
= []
3344 return self
._BuildOptionIncPathList
3346 BuildOptionIncPathList
= []
3347 for Tool
in ('CC', 'PP', 'VFRPP', 'ASLPP', 'ASLCC', 'APP', 'ASM'):
3350 FlagOption
= self
.BuildOption
[Tool
][Attr
]
3354 if self
.PlatformInfo
.ToolChainFamily
!= 'RVCT':
3355 IncPathList
= [NormPath(Path
, self
.Macros
) for Path
in gBuildOptIncludePattern
.findall(FlagOption
)]
3358 # RVCT may specify a list of directory seperated by commas
3361 for Path
in gBuildOptIncludePattern
.findall(FlagOption
):
3362 PathList
= GetSplitList(Path
, TAB_COMMA_SPLIT
)
3363 IncPathList
+= [NormPath(PathEntry
, self
.Macros
) for PathEntry
in PathList
]
3366 # EDK II modules must not reference header files outside of the packages they depend on or
3367 # within the module's directory tree. Report error if violation.
3369 if self
.AutoGenVersion
>= 0x00010005 and len(IncPathList
) > 0:
3370 for Path
in IncPathList
:
3371 if (Path
not in self
.IncludePathList
) and (CommonPath([Path
, self
.MetaFile
.Dir
]) != self
.MetaFile
.Dir
):
3372 ErrMsg
= "The include directory for the EDK II module in this line is invalid %s specified in %s FLAGS '%s'" % (Path
, Tool
, FlagOption
)
3373 EdkLogger
.error("build",
3376 File
=str(self
.MetaFile
))
3379 BuildOptionIncPathList
+= IncPathList
3381 self
._BuildOptionIncPathList
= BuildOptionIncPathList
3383 return self
._BuildOptionIncPathList
3385 ## Return a list of files which can be built from source
3387 # What kind of files can be built is determined by build rules in
3388 # $(CONF_DIRECTORY)/build_rule.txt and toolchain family.
3390 def _GetSourceFileList(self
):
3391 if self
._SourceFileList
== None:
3392 self
._SourceFileList
= []
3393 for F
in self
.Module
.Sources
:
3395 if F
.TagName
not in ("", "*", self
.ToolChain
):
3396 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "The toolchain [%s] for processing file [%s] is found, "
3397 "but [%s] is needed" % (F
.TagName
, str(F
), self
.ToolChain
))
3399 # match tool chain family or build rule family
3400 if F
.ToolChainFamily
not in ("", "*", self
.ToolChainFamily
, self
.BuildRuleFamily
):
3403 "The file [%s] must be built by tools of [%s], " \
3404 "but current toolchain family is [%s], buildrule family is [%s]" \
3405 % (str(F
), F
.ToolChainFamily
, self
.ToolChainFamily
, self
.BuildRuleFamily
))
3408 # add the file path into search path list for file including
3409 if F
.Dir
not in self
.IncludePathList
and self
.AutoGenVersion
>= 0x00010005:
3410 self
.IncludePathList
.insert(0, F
.Dir
)
3411 self
._SourceFileList
.append(F
)
3413 self
._MatchBuildRuleOrder
(self
._SourceFileList
)
3415 for F
in self
._SourceFileList
:
3416 self
._ApplyBuildRule
(F
, TAB_UNKNOWN_FILE
)
3417 return self
._SourceFileList
3419 def _MatchBuildRuleOrder(self
, FileList
):
3421 self
._GetModuleBuildOption
()
3422 for SingleFile
in FileList
:
3423 if self
.BuildRuleOrder
and SingleFile
.Ext
in self
.BuildRuleOrder
and SingleFile
.Ext
in self
.BuildRules
:
3424 key
= SingleFile
.Path
.split(SingleFile
.Ext
)[0]
3425 if key
in Order_Dict
:
3426 Order_Dict
[key
].append(SingleFile
.Ext
)
3428 Order_Dict
[key
] = [SingleFile
.Ext
]
3431 for F
in Order_Dict
:
3432 if len(Order_Dict
[F
]) > 1:
3433 Order_Dict
[F
].sort(key
=lambda i
: self
.BuildRuleOrder
.index(i
))
3434 for Ext
in Order_Dict
[F
][1:]:
3435 RemoveList
.append(F
+ Ext
)
3437 for item
in RemoveList
:
3438 FileList
.remove(item
)
3442 ## Return the list of unicode files
3443 def _GetUnicodeFileList(self
):
3444 if self
._UnicodeFileList
== None:
3445 if TAB_UNICODE_FILE
in self
.FileTypes
:
3446 self
._UnicodeFileList
= self
.FileTypes
[TAB_UNICODE_FILE
]
3448 self
._UnicodeFileList
= []
3449 return self
._UnicodeFileList
3451 ## Return the list of vfr files
3452 def _GetVfrFileList(self
):
3453 if self
._VfrFileList
== None:
3454 if TAB_VFR_FILE
in self
.FileTypes
:
3455 self
._VfrFileList
= self
.FileTypes
[TAB_VFR_FILE
]
3457 self
._VfrFileList
= []
3458 return self
._VfrFileList
3460 ## Return the list of Image Definition files
3461 def _GetIdfFileList(self
):
3462 if self
._IdfFileList
== None:
3463 if TAB_IMAGE_FILE
in self
.FileTypes
:
3464 self
._IdfFileList
= self
.FileTypes
[TAB_IMAGE_FILE
]
3466 self
._IdfFileList
= []
3467 return self
._IdfFileList
3469 ## Return a list of files which can be built from binary
3471 # "Build" binary files are just to copy them to build directory.
3473 # @retval list The list of files which can be built later
3475 def _GetBinaryFiles(self
):
3476 if self
._BinaryFileList
== None:
3477 self
._BinaryFileList
= []
3478 for F
in self
.Module
.Binaries
:
3479 if F
.Target
not in ['COMMON', '*'] and F
.Target
!= self
.BuildTarget
:
3481 self
._BinaryFileList
.append(F
)
3482 self
._ApplyBuildRule
(F
, F
.Type
)
3483 return self
._BinaryFileList
3485 def _GetBuildRules(self
):
3486 if self
._BuildRules
== None:
3488 BuildRuleDatabase
= self
.PlatformInfo
.BuildRule
3489 for Type
in BuildRuleDatabase
.FileTypeList
:
3490 #first try getting build rule by BuildRuleFamily
3491 RuleObject
= BuildRuleDatabase
[Type
, self
.BuildType
, self
.Arch
, self
.BuildRuleFamily
]
3493 # build type is always module type, but ...
3494 if self
.ModuleType
!= self
.BuildType
:
3495 RuleObject
= BuildRuleDatabase
[Type
, self
.ModuleType
, self
.Arch
, self
.BuildRuleFamily
]
3496 #second try getting build rule by ToolChainFamily
3498 RuleObject
= BuildRuleDatabase
[Type
, self
.BuildType
, self
.Arch
, self
.ToolChainFamily
]
3500 # build type is always module type, but ...
3501 if self
.ModuleType
!= self
.BuildType
:
3502 RuleObject
= BuildRuleDatabase
[Type
, self
.ModuleType
, self
.Arch
, self
.ToolChainFamily
]
3505 RuleObject
= RuleObject
.Instantiate(self
.Macros
)
3506 BuildRules
[Type
] = RuleObject
3507 for Ext
in RuleObject
.SourceFileExtList
:
3508 BuildRules
[Ext
] = RuleObject
3509 self
._BuildRules
= BuildRules
3510 return self
._BuildRules
3512 def _ApplyBuildRule(self
, File
, FileType
):
3513 if self
._BuildTargets
== None:
3514 self
._IntroBuildTargetList
= set()
3515 self
._FinalBuildTargetList
= set()
3516 self
._BuildTargets
= {}
3517 self
._FileTypes
= {}
3519 SubDirectory
= os
.path
.join(self
.OutputDir
, File
.SubDir
)
3520 if not os
.path
.exists(SubDirectory
):
3521 CreateDirectory(SubDirectory
)
3527 # Make sure to get build rule order value
3529 self
._GetModuleBuildOption
()
3531 while Index
< len(SourceList
):
3532 Source
= SourceList
[Index
]
3536 CreateDirectory(Source
.Dir
)
3538 if File
.IsBinary
and File
== Source
and self
._BinaryFileList
!= None and File
in self
._BinaryFileList
:
3539 # Skip all files that are not binary libraries
3540 if not self
.IsLibrary
:
3542 RuleObject
= self
.BuildRules
[TAB_DEFAULT_BINARY_FILE
]
3543 elif FileType
in self
.BuildRules
:
3544 RuleObject
= self
.BuildRules
[FileType
]
3545 elif Source
.Ext
in self
.BuildRules
:
3546 RuleObject
= self
.BuildRules
[Source
.Ext
]
3548 # stop at no more rules
3550 self
._FinalBuildTargetList
.add(LastTarget
)
3553 FileType
= RuleObject
.SourceFileType
3554 if FileType
not in self
._FileTypes
:
3555 self
._FileTypes
[FileType
] = set()
3556 self
._FileTypes
[FileType
].add(Source
)
3558 # stop at STATIC_LIBRARY for library
3559 if self
.IsLibrary
and FileType
== TAB_STATIC_LIBRARY
:
3561 self
._FinalBuildTargetList
.add(LastTarget
)
3564 Target
= RuleObject
.Apply(Source
, self
.BuildRuleOrder
)
3567 self
._FinalBuildTargetList
.add(LastTarget
)
3569 elif not Target
.Outputs
:
3570 # Only do build for target with outputs
3571 self
._FinalBuildTargetList
.add(Target
)
3573 if FileType
not in self
._BuildTargets
:
3574 self
._BuildTargets
[FileType
] = set()
3575 self
._BuildTargets
[FileType
].add(Target
)
3577 if not Source
.IsBinary
and Source
== File
:
3578 self
._IntroBuildTargetList
.add(Target
)
3580 # to avoid cyclic rule
3581 if FileType
in RuleChain
:
3584 RuleChain
.append(FileType
)
3585 SourceList
.extend(Target
.Outputs
)
3587 FileType
= TAB_UNKNOWN_FILE
3589 def _GetTargets(self
):
3590 if self
._BuildTargets
== None:
3591 self
._IntroBuildTargetList
= set()
3592 self
._FinalBuildTargetList
= set()
3593 self
._BuildTargets
= {}
3594 self
._FileTypes
= {}
3596 #TRICK: call _GetSourceFileList to apply build rule for source files
3597 if self
.SourceFileList
:
3600 #TRICK: call _GetBinaryFileList to apply build rule for binary files
3601 if self
.BinaryFileList
:
3604 return self
._BuildTargets
3606 def _GetIntroTargetList(self
):
3608 return self
._IntroBuildTargetList
3610 def _GetFinalTargetList(self
):
3612 return self
._FinalBuildTargetList
3614 def _GetFileTypes(self
):
3616 return self
._FileTypes
3618 ## Get the list of package object the module depends on
3620 # @retval list The package object list
3622 def _GetDependentPackageList(self
):
3623 return self
.Module
.Packages
3625 ## Return the list of auto-generated code file
3627 # @retval list The list of auto-generated file
3629 def _GetAutoGenFileList(self
):
3630 UniStringAutoGenC
= True
3631 IdfStringAutoGenC
= True
3632 UniStringBinBuffer
= StringIO()
3633 IdfGenBinBuffer
= StringIO()
3634 if self
.BuildType
== 'UEFI_HII':
3635 UniStringAutoGenC
= False
3636 IdfStringAutoGenC
= False
3637 if self
._AutoGenFileList
== None:
3638 self
._AutoGenFileList
= {}
3639 AutoGenC
= TemplateString()
3640 AutoGenH
= TemplateString()
3641 StringH
= TemplateString()
3642 StringIdf
= TemplateString()
3643 GenC
.CreateCode(self
, AutoGenC
, AutoGenH
, StringH
, UniStringAutoGenC
, UniStringBinBuffer
, StringIdf
, IdfStringAutoGenC
, IdfGenBinBuffer
)
3645 # AutoGen.c is generated if there are library classes in inf, or there are object files
3647 if str(AutoGenC
) != "" and (len(self
.Module
.LibraryClasses
) > 0
3648 or TAB_OBJECT_FILE
in self
.FileTypes
):
3649 AutoFile
= PathClass(gAutoGenCodeFileName
, self
.DebugDir
)
3650 self
._AutoGenFileList
[AutoFile
] = str(AutoGenC
)
3651 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3652 if str(AutoGenH
) != "":
3653 AutoFile
= PathClass(gAutoGenHeaderFileName
, self
.DebugDir
)
3654 self
._AutoGenFileList
[AutoFile
] = str(AutoGenH
)
3655 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3656 if str(StringH
) != "":
3657 AutoFile
= PathClass(gAutoGenStringFileName
% {"module_name":self
.Name
}, self
.DebugDir
)
3658 self
._AutoGenFileList
[AutoFile
] = str(StringH
)
3659 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3660 if UniStringBinBuffer
!= None and UniStringBinBuffer
.getvalue() != "":
3661 AutoFile
= PathClass(gAutoGenStringFormFileName
% {"module_name":self
.Name
}, self
.OutputDir
)
3662 self
._AutoGenFileList
[AutoFile
] = UniStringBinBuffer
.getvalue()
3663 AutoFile
.IsBinary
= True
3664 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3665 if UniStringBinBuffer
!= None:
3666 UniStringBinBuffer
.close()
3667 if str(StringIdf
) != "":
3668 AutoFile
= PathClass(gAutoGenImageDefFileName
% {"module_name":self
.Name
}, self
.DebugDir
)
3669 self
._AutoGenFileList
[AutoFile
] = str(StringIdf
)
3670 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3671 if IdfGenBinBuffer
!= None and IdfGenBinBuffer
.getvalue() != "":
3672 AutoFile
= PathClass(gAutoGenIdfFileName
% {"module_name":self
.Name
}, self
.OutputDir
)
3673 self
._AutoGenFileList
[AutoFile
] = IdfGenBinBuffer
.getvalue()
3674 AutoFile
.IsBinary
= True
3675 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3676 if IdfGenBinBuffer
!= None:
3677 IdfGenBinBuffer
.close()
3678 return self
._AutoGenFileList
3680 ## Return the list of library modules explicitly or implicityly used by this module
3681 def _GetLibraryList(self
):
3682 if self
._DependentLibraryList
== None:
3683 # only merge library classes and PCD for non-library module
3685 self
._DependentLibraryList
= []
3687 if self
.AutoGenVersion
< 0x00010005:
3688 self
._DependentLibraryList
= self
.PlatformInfo
.ResolveLibraryReference(self
.Module
)
3690 self
._DependentLibraryList
= self
.PlatformInfo
.ApplyLibraryInstance(self
.Module
)
3691 return self
._DependentLibraryList
3694 def UpdateComments(Recver
, Src
):
3696 if Key
not in Recver
:
3698 Recver
[Key
].extend(Src
[Key
])
3699 ## Get the list of PCDs from current module
3701 # @retval list The list of PCD
3703 def _GetModulePcdList(self
):
3704 if self
._ModulePcdList
== None:
3705 # apply PCD settings from platform
3706 self
._ModulePcdList
= self
.PlatformInfo
.ApplyPcdSetting(self
.Module
, self
.Module
.Pcds
)
3707 self
.UpdateComments(self
._PcdComments
, self
.Module
.PcdComments
)
3708 return self
._ModulePcdList
3710 ## Get the list of PCDs from dependent libraries
3712 # @retval list The list of PCD
3714 def _GetLibraryPcdList(self
):
3715 if self
._LibraryPcdList
== None:
3717 if not self
.IsLibrary
:
3718 # get PCDs from dependent libraries
3719 for Library
in self
.DependentLibraryList
:
3720 self
.UpdateComments(self
._PcdComments
, Library
.PcdComments
)
3721 for Key
in Library
.Pcds
:
3722 # skip duplicated PCDs
3723 if Key
in self
.Module
.Pcds
or Key
in Pcds
:
3725 Pcds
[Key
] = copy
.copy(Library
.Pcds
[Key
])
3726 # apply PCD settings from platform
3727 self
._LibraryPcdList
= self
.PlatformInfo
.ApplyPcdSetting(self
.Module
, Pcds
)
3729 self
._LibraryPcdList
= []
3730 return self
._LibraryPcdList
3732 ## Get the GUID value mapping
3734 # @retval dict The mapping between GUID cname and its value
3736 def _GetGuidList(self
):
3737 if self
._GuidList
== None:
3738 self
._GuidList
= sdict()
3739 self
._GuidList
.update(self
.Module
.Guids
)
3740 for Library
in self
.DependentLibraryList
:
3741 self
._GuidList
.update(Library
.Guids
)
3742 self
.UpdateComments(self
._GuidComments
, Library
.GuidComments
)
3743 self
.UpdateComments(self
._GuidComments
, self
.Module
.GuidComments
)
3744 return self
._GuidList
3746 def GetGuidsUsedByPcd(self
):
3747 if self
._GuidsUsedByPcd
== None:
3748 self
._GuidsUsedByPcd
= sdict()
3749 self
._GuidsUsedByPcd
.update(self
.Module
.GetGuidsUsedByPcd())
3750 for Library
in self
.DependentLibraryList
:
3751 self
._GuidsUsedByPcd
.update(Library
.GetGuidsUsedByPcd())
3752 return self
._GuidsUsedByPcd
3753 ## Get the protocol value mapping
3755 # @retval dict The mapping between protocol cname and its value
3757 def _GetProtocolList(self
):
3758 if self
._ProtocolList
== None:
3759 self
._ProtocolList
= sdict()
3760 self
._ProtocolList
.update(self
.Module
.Protocols
)
3761 for Library
in self
.DependentLibraryList
:
3762 self
._ProtocolList
.update(Library
.Protocols
)
3763 self
.UpdateComments(self
._ProtocolComments
, Library
.ProtocolComments
)
3764 self
.UpdateComments(self
._ProtocolComments
, self
.Module
.ProtocolComments
)
3765 return self
._ProtocolList
3767 ## Get the PPI value mapping
3769 # @retval dict The mapping between PPI cname and its value
3771 def _GetPpiList(self
):
3772 if self
._PpiList
== None:
3773 self
._PpiList
= sdict()
3774 self
._PpiList
.update(self
.Module
.Ppis
)
3775 for Library
in self
.DependentLibraryList
:
3776 self
._PpiList
.update(Library
.Ppis
)
3777 self
.UpdateComments(self
._PpiComments
, Library
.PpiComments
)
3778 self
.UpdateComments(self
._PpiComments
, self
.Module
.PpiComments
)
3779 return self
._PpiList
3781 ## Get the list of include search path
3783 # @retval list The list path
3785 def _GetIncludePathList(self
):
3786 if self
._IncludePathList
== None:
3787 self
._IncludePathList
= []
3788 if self
.AutoGenVersion
< 0x00010005:
3789 for Inc
in self
.Module
.Includes
:
3790 if Inc
not in self
._IncludePathList
:
3791 self
._IncludePathList
.append(Inc
)
3793 Inc
= path
.join(Inc
, self
.Arch
.capitalize())
3794 if os
.path
.exists(Inc
) and Inc
not in self
._IncludePathList
:
3795 self
._IncludePathList
.append(Inc
)
3796 # Edk module needs to put DEBUG_DIR at the end of search path and not to use SOURCE_DIR all the time
3797 self
._IncludePathList
.append(self
.DebugDir
)
3799 self
._IncludePathList
.append(self
.MetaFile
.Dir
)
3800 self
._IncludePathList
.append(self
.DebugDir
)
3802 for Package
in self
.Module
.Packages
:
3803 PackageDir
= mws
.join(self
.WorkspaceDir
, Package
.MetaFile
.Dir
)
3804 if PackageDir
not in self
._IncludePathList
:
3805 self
._IncludePathList
.append(PackageDir
)
3806 IncludesList
= Package
.Includes
3807 if Package
._PrivateIncludes
:
3808 if not self
.MetaFile
.Path
.startswith(PackageDir
):
3809 IncludesList
= list(set(Package
.Includes
).difference(set(Package
._PrivateIncludes
)))
3810 for Inc
in IncludesList
:
3811 if Inc
not in self
._IncludePathList
:
3812 self
._IncludePathList
.append(str(Inc
))
3813 return self
._IncludePathList
3815 def _GetIncludePathLength(self
):
3816 self
._IncludePathLength
= 0
3817 if self
._IncludePathList
:
3818 for inc
in self
._IncludePathList
:
3819 self
._IncludePathLength
+= len(' ' + inc
)
3820 return self
._IncludePathLength
3822 ## Get HII EX PCDs which maybe used by VFR
3824 # efivarstore used by VFR may relate with HII EX PCDs
3825 # Get the variable name and GUID from efivarstore and HII EX PCD
3826 # List the HII EX PCDs in As Built INF if both name and GUID match.
3828 # @retval list HII EX PCDs
3830 def _GetPcdsMaybeUsedByVfr(self
):
3831 if not self
.SourceFileList
:
3835 for SrcFile
in self
.SourceFileList
:
3836 if SrcFile
.Ext
.lower() != '.vfr':
3838 Vfri
= os
.path
.join(self
.OutputDir
, SrcFile
.BaseName
+ '.i')
3839 if not os
.path
.exists(Vfri
):
3841 VfriFile
= open(Vfri
, 'r')
3842 Content
= VfriFile
.read()
3844 Pos
= Content
.find('efivarstore')
3847 # Make sure 'efivarstore' is the start of efivarstore statement
3848 # In case of the value of 'name' (name = efivarstore) is equal to 'efivarstore'
3851 while Index
>= 0 and Content
[Index
] in ' \t\r\n':
3853 if Index
>= 0 and Content
[Index
] != ';':
3854 Pos
= Content
.find('efivarstore', Pos
+ len('efivarstore'))
3857 # 'efivarstore' must be followed by name and guid
3859 Name
= gEfiVarStoreNamePattern
.search(Content
, Pos
)
3862 Guid
= gEfiVarStoreGuidPattern
.search(Content
, Pos
)
3865 NameArray
= ConvertStringToByteArray('L"' + Name
.group(1) + '"')
3866 NameGuids
.append((NameArray
, GuidStructureStringToGuidString(Guid
.group(1))))
3867 Pos
= Content
.find('efivarstore', Name
.end())
3871 for Pcd
in self
.PlatformInfo
.Platform
.Pcds
.values():
3872 if Pcd
.Type
!= TAB_PCDS_DYNAMIC_EX_HII
:
3874 for SkuName
in Pcd
.SkuInfoList
:
3875 SkuInfo
= Pcd
.SkuInfoList
[SkuName
]
3876 Name
= ConvertStringToByteArray(SkuInfo
.VariableName
)
3877 Value
= GuidValue(SkuInfo
.VariableGuid
, self
.PlatformInfo
.PackageList
, self
.MetaFile
.Path
)
3880 Guid
= GuidStructureStringToGuidString(Value
)
3881 if (Name
, Guid
) in NameGuids
and Pcd
not in HiiExPcds
:
3882 HiiExPcds
.append(Pcd
)
3887 def _GenOffsetBin(self
):
3889 for SourceFile
in self
.Module
.Sources
:
3890 if SourceFile
.Type
.upper() == ".VFR" :
3892 # search the .map file to find the offset of vfr binary in the PE32+/TE file.
3894 VfrUniBaseName
[SourceFile
.BaseName
] = (SourceFile
.BaseName
+ "Bin")
3895 if SourceFile
.Type
.upper() == ".UNI" :
3897 # search the .map file to find the offset of Uni strings binary in the PE32+/TE file.
3899 VfrUniBaseName
["UniOffsetName"] = (self
.Name
+ "Strings")
3901 if len(VfrUniBaseName
) == 0:
3903 MapFileName
= os
.path
.join(self
.OutputDir
, self
.Name
+ ".map")
3904 EfiFileName
= os
.path
.join(self
.OutputDir
, self
.Name
+ ".efi")
3905 VfrUniOffsetList
= GetVariableOffset(MapFileName
, EfiFileName
, VfrUniBaseName
.values())
3906 if not VfrUniOffsetList
:
3909 OutputName
= '%sOffset.bin' % self
.Name
3910 UniVfrOffsetFileName
= os
.path
.join( self
.OutputDir
, OutputName
)
3913 fInputfile
= open(UniVfrOffsetFileName
, "wb+", 0)
3915 EdkLogger
.error("build", FILE_OPEN_FAILURE
, "File open failed for %s" % UniVfrOffsetFileName
,None)
3917 # Use a instance of StringIO to cache data
3918 fStringIO
= StringIO('')
3920 for Item
in VfrUniOffsetList
:
3921 if (Item
[0].find("Strings") != -1):
3923 # UNI offset in image.
3925 # { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } }
3927 UniGuid
= [0xe0, 0xc5, 0x13, 0x89, 0xf6, 0x33, 0x86, 0x4d, 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66]
3928 UniGuid
= [chr(ItemGuid
) for ItemGuid
in UniGuid
]
3929 fStringIO
.write(''.join(UniGuid
))
3930 UniValue
= pack ('Q', int (Item
[1], 16))
3931 fStringIO
.write (UniValue
)
3934 # VFR binary offset in image.
3936 # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } };
3938 VfrGuid
= [0xb4, 0x7c, 0xbc, 0xd0, 0x47, 0x6a, 0x5f, 0x49, 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2]
3939 VfrGuid
= [chr(ItemGuid
) for ItemGuid
in VfrGuid
]
3940 fStringIO
.write(''.join(VfrGuid
))
3942 VfrValue
= pack ('Q', int (Item
[1], 16))
3943 fStringIO
.write (VfrValue
)
3945 # write data into file.
3948 fInputfile
.write (fStringIO
.getvalue())
3950 EdkLogger
.error("build", FILE_WRITE_FAILURE
, "Write data to file %s failed, please check whether the "
3951 "file been locked or using by other applications." %UniVfrOffsetFileName
,None)
3957 ## Create AsBuilt INF file the module
3959 def CreateAsBuiltInf(self
, IsOnlyCopy
= False):
3960 self
.OutputFile
= []
3962 if GlobalData
.gBinCacheDest
:
3963 self
.CopyModuleToCache()
3966 if self
.IsAsBuiltInfCreated
:
3969 # Skip the following code for EDK I inf
3970 if self
.AutoGenVersion
< 0x00010005:
3973 # Skip the following code for libraries
3977 # Skip the following code for modules with no source files
3978 if self
.SourceFileList
== None or self
.SourceFileList
== []:
3981 # Skip the following code for modules without any binary files
3982 if self
.BinaryFileList
<> None and self
.BinaryFileList
<> []:
3985 ### TODO: How to handles mixed source and binary modules
3987 # Find all DynamicEx and PatchableInModule PCDs used by this module and dependent libraries
3988 # Also find all packages that the DynamicEx PCDs depend on
3993 PcdTokenSpaceList
= []
3994 for Pcd
in self
.ModulePcdList
+ self
.LibraryPcdList
:
3995 if Pcd
.Type
== TAB_PCDS_PATCHABLE_IN_MODULE
:
3996 PatchablePcds
+= [Pcd
]
3997 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, 'PatchableInModule'))
3998 elif Pcd
.Type
in GenC
.gDynamicExPcd
:
4001 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, 'DynamicEx'))
4002 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, 'Dynamic'))
4003 PcdTokenSpaceList
.append(Pcd
.TokenSpaceGuidCName
)
4005 GuidList
.update(self
.GuidList
)
4006 for TokenSpace
in self
.GetGuidsUsedByPcd():
4007 # If token space is not referred by patch PCD or Ex PCD, remove the GUID from GUID list
4008 # The GUIDs in GUIDs section should really be the GUIDs in source INF or referred by Ex an patch PCDs
4009 if TokenSpace
not in PcdTokenSpaceList
and TokenSpace
in GuidList
:
4010 GuidList
.pop(TokenSpace
)
4011 CheckList
= (GuidList
, self
.PpiList
, self
.ProtocolList
, PcdCheckList
)
4012 for Package
in self
.DerivedPackageList
:
4013 if Package
in Packages
:
4015 BeChecked
= (Package
.Guids
, Package
.Ppis
, Package
.Protocols
, Package
.Pcds
)
4017 for Index
in range(len(BeChecked
)):
4018 for Item
in CheckList
[Index
]:
4019 if Item
in BeChecked
[Index
]:
4020 Packages
+= [Package
]
4025 VfrPcds
= self
._GetPcdsMaybeUsedByVfr
()
4026 for Pkg
in self
.PlatformInfo
.PackageList
:
4029 for VfrPcd
in VfrPcds
:
4030 if ((VfrPcd
.TokenCName
, VfrPcd
.TokenSpaceGuidCName
, 'DynamicEx') in Pkg
.Pcds
or
4031 (VfrPcd
.TokenCName
, VfrPcd
.TokenSpaceGuidCName
, 'Dynamic') in Pkg
.Pcds
):
4035 ModuleType
= self
.ModuleType
4036 if ModuleType
== 'UEFI_DRIVER' and self
.DepexGenerated
:
4037 ModuleType
= 'DXE_DRIVER'
4040 if self
.PcdIsDriver
!= '':
4041 DriverType
= self
.PcdIsDriver
4044 MDefs
= self
.Module
.Defines
4047 'module_name' : self
.Name
,
4048 'module_guid' : Guid
,
4049 'module_module_type' : ModuleType
,
4050 'module_version_string' : [MDefs
['VERSION_STRING']] if 'VERSION_STRING' in MDefs
else [],
4051 'pcd_is_driver_string' : [],
4052 'module_uefi_specification_version' : [],
4053 'module_pi_specification_version' : [],
4054 'module_entry_point' : self
.Module
.ModuleEntryPointList
,
4055 'module_unload_image' : self
.Module
.ModuleUnloadImageList
,
4056 'module_constructor' : self
.Module
.ConstructorList
,
4057 'module_destructor' : self
.Module
.DestructorList
,
4058 'module_shadow' : [MDefs
['SHADOW']] if 'SHADOW' in MDefs
else [],
4059 'module_pci_vendor_id' : [MDefs
['PCI_VENDOR_ID']] if 'PCI_VENDOR_ID' in MDefs
else [],
4060 'module_pci_device_id' : [MDefs
['PCI_DEVICE_ID']] if 'PCI_DEVICE_ID' in MDefs
else [],
4061 'module_pci_class_code' : [MDefs
['PCI_CLASS_CODE']] if 'PCI_CLASS_CODE' in MDefs
else [],
4062 'module_pci_revision' : [MDefs
['PCI_REVISION']] if 'PCI_REVISION' in MDefs
else [],
4063 'module_build_number' : [MDefs
['BUILD_NUMBER']] if 'BUILD_NUMBER' in MDefs
else [],
4064 'module_spec' : [MDefs
['SPEC']] if 'SPEC' in MDefs
else [],
4065 'module_uefi_hii_resource_section' : [MDefs
['UEFI_HII_RESOURCE_SECTION']] if 'UEFI_HII_RESOURCE_SECTION' in MDefs
else [],
4066 'module_uni_file' : [MDefs
['MODULE_UNI_FILE']] if 'MODULE_UNI_FILE' in MDefs
else [],
4067 'module_arch' : self
.Arch
,
4068 'package_item' : ['%s' % (Package
.MetaFile
.File
.replace('\\', '/')) for Package
in Packages
],
4070 'patchablepcd_item' : [],
4072 'protocol_item' : [],
4076 'libraryclasses_item' : []
4079 if 'MODULE_UNI_FILE' in MDefs
:
4080 UNIFile
= os
.path
.join(self
.MetaFile
.Dir
, MDefs
['MODULE_UNI_FILE'])
4081 if os
.path
.isfile(UNIFile
):
4082 shutil
.copy2(UNIFile
, self
.OutputDir
)
4084 if self
.AutoGenVersion
> int(gInfSpecVersion
, 0):
4085 AsBuiltInfDict
['module_inf_version'] = '0x%08x' % self
.AutoGenVersion
4087 AsBuiltInfDict
['module_inf_version'] = gInfSpecVersion
4090 AsBuiltInfDict
['pcd_is_driver_string'] += [DriverType
]
4092 if 'UEFI_SPECIFICATION_VERSION' in self
.Specification
:
4093 AsBuiltInfDict
['module_uefi_specification_version'] += [self
.Specification
['UEFI_SPECIFICATION_VERSION']]
4094 if 'PI_SPECIFICATION_VERSION' in self
.Specification
:
4095 AsBuiltInfDict
['module_pi_specification_version'] += [self
.Specification
['PI_SPECIFICATION_VERSION']]
4097 OutputDir
= self
.OutputDir
.replace('\\', '/').strip('/')
4098 for Item
in self
.CodaTargetList
:
4099 File
= Item
.Target
.Path
.replace('\\', '/').strip('/').replace(OutputDir
, '').strip('/')
4100 if File
not in self
.OutputFile
:
4101 self
.OutputFile
.append(File
)
4102 if Item
.Target
.Ext
.lower() == '.aml':
4103 AsBuiltInfDict
['binary_item'] += ['ASL|' + File
]
4104 elif Item
.Target
.Ext
.lower() == '.acpi':
4105 AsBuiltInfDict
['binary_item'] += ['ACPI|' + File
]
4106 elif Item
.Target
.Ext
.lower() == '.efi':
4107 AsBuiltInfDict
['binary_item'] += ['PE32|' + self
.Name
+ '.efi']
4109 AsBuiltInfDict
['binary_item'] += ['BIN|' + File
]
4110 if self
.DepexGenerated
:
4111 if self
.Name
+ '.depex' not in self
.OutputFile
:
4112 self
.OutputFile
.append(self
.Name
+ '.depex')
4113 if self
.ModuleType
in ['PEIM']:
4114 AsBuiltInfDict
['binary_item'] += ['PEI_DEPEX|' + self
.Name
+ '.depex']
4115 if self
.ModuleType
in ['DXE_DRIVER', 'DXE_RUNTIME_DRIVER', 'DXE_SAL_DRIVER', 'UEFI_DRIVER']:
4116 AsBuiltInfDict
['binary_item'] += ['DXE_DEPEX|' + self
.Name
+ '.depex']
4117 if self
.ModuleType
in ['DXE_SMM_DRIVER']:
4118 AsBuiltInfDict
['binary_item'] += ['SMM_DEPEX|' + self
.Name
+ '.depex']
4120 Bin
= self
._GenOffsetBin
()
4122 AsBuiltInfDict
['binary_item'] += ['BIN|%s' % Bin
]
4123 if Bin
not in self
.OutputFile
:
4124 self
.OutputFile
.append(Bin
)
4126 for Root
, Dirs
, Files
in os
.walk(OutputDir
):
4128 if File
.lower().endswith('.pdb'):
4129 AsBuiltInfDict
['binary_item'] += ['DISPOSABLE|' + File
]
4130 if File
not in self
.OutputFile
:
4131 self
.OutputFile
.append(File
)
4132 HeaderComments
= self
.Module
.HeaderComments
4134 for Index
in range(len(HeaderComments
)):
4135 if HeaderComments
[Index
].find('@BinaryHeader') != -1:
4136 HeaderComments
[Index
] = HeaderComments
[Index
].replace('@BinaryHeader', '@file')
4139 AsBuiltInfDict
['header_comments'] = '\n'.join(HeaderComments
[StartPos
:]).replace(':#', '://')
4140 AsBuiltInfDict
['tail_comments'] = '\n'.join(self
.Module
.TailComments
)
4143 (self
.ProtocolList
, self
._ProtocolComments
, 'protocol_item'),
4144 (self
.PpiList
, self
._PpiComments
, 'ppi_item'),
4145 (GuidList
, self
._GuidComments
, 'guid_item')
4147 for Item
in GenList
:
4148 for CName
in Item
[0]:
4150 if CName
in Item
[1]:
4151 Comments
= '\n '.join(Item
[1][CName
])
4154 Entry
= Comments
+ '\n ' + CName
4155 AsBuiltInfDict
[Item
[2]].append(Entry
)
4156 PatchList
= parsePcdInfoFromMapFile(
4157 os
.path
.join(self
.OutputDir
, self
.Name
+ '.map'),
4158 os
.path
.join(self
.OutputDir
, self
.Name
+ '.efi')
4161 for Pcd
in PatchablePcds
:
4162 TokenCName
= Pcd
.TokenCName
4163 for PcdItem
in GlobalData
.MixedPcd
:
4164 if (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
4165 TokenCName
= PcdItem
[0]
4167 for PatchPcd
in PatchList
:
4168 if TokenCName
== PatchPcd
[0]:
4173 if Pcd
.DatumType
== 'BOOLEAN':
4174 BoolValue
= Pcd
.DefaultValue
.upper()
4175 if BoolValue
== 'TRUE':
4176 Pcd
.DefaultValue
= '1'
4177 elif BoolValue
== 'FALSE':
4178 Pcd
.DefaultValue
= '0'
4180 if Pcd
.DatumType
in ['UINT8', 'UINT16', 'UINT32', 'UINT64', 'BOOLEAN']:
4181 HexFormat
= '0x%02x'
4182 if Pcd
.DatumType
== 'UINT16':
4183 HexFormat
= '0x%04x'
4184 elif Pcd
.DatumType
== 'UINT32':
4185 HexFormat
= '0x%08x'
4186 elif Pcd
.DatumType
== 'UINT64':
4187 HexFormat
= '0x%016x'
4188 PcdValue
= HexFormat
% int(Pcd
.DefaultValue
, 0)
4190 if Pcd
.MaxDatumSize
== None or Pcd
.MaxDatumSize
== '':
4191 EdkLogger
.error("build", AUTOGEN_ERROR
,
4192 "Unknown [MaxDatumSize] of PCD [%s.%s]" % (Pcd
.TokenSpaceGuidCName
, TokenCName
)
4194 ArraySize
= int(Pcd
.MaxDatumSize
, 0)
4195 PcdValue
= Pcd
.DefaultValue
4196 if PcdValue
[0] != '{':
4198 if PcdValue
[0] == 'L':
4200 PcdValue
= PcdValue
.lstrip('L')
4201 PcdValue
= eval(PcdValue
)
4203 for Index
in range(0, len(PcdValue
)):
4205 CharVal
= ord(PcdValue
[Index
])
4206 NewValue
= NewValue
+ '0x%02x' % (CharVal
& 0x00FF) + ', ' \
4207 + '0x%02x' % (CharVal
>> 8) + ', '
4209 NewValue
= NewValue
+ '0x%02x' % (ord(PcdValue
[Index
]) % 0x100) + ', '
4212 Padding
= Padding
* 2
4213 ArraySize
= ArraySize
/ 2
4214 if ArraySize
< (len(PcdValue
) + 1):
4215 EdkLogger
.error("build", AUTOGEN_ERROR
,
4216 "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd
.TokenSpaceGuidCName
, TokenCName
)
4218 if ArraySize
> len(PcdValue
) + 1:
4219 NewValue
= NewValue
+ Padding
* (ArraySize
- len(PcdValue
) - 1)
4220 PcdValue
= NewValue
+ Padding
.strip().rstrip(',') + '}'
4221 elif len(PcdValue
.split(',')) <= ArraySize
:
4222 PcdValue
= PcdValue
.rstrip('}') + ', 0x00' * (ArraySize
- len(PcdValue
.split(',')))
4225 EdkLogger
.error("build", AUTOGEN_ERROR
,
4226 "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd
.TokenSpaceGuidCName
, TokenCName
)
4228 PcdItem
= '%s.%s|%s|0x%X' % \
4229 (Pcd
.TokenSpaceGuidCName
, TokenCName
, PcdValue
, PatchPcd
[1])
4231 if (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) in self
._PcdComments
:
4232 PcdComments
= '\n '.join(self
._PcdComments
[Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
])
4234 PcdItem
= PcdComments
+ '\n ' + PcdItem
4235 AsBuiltInfDict
['patchablepcd_item'].append(PcdItem
)
4238 for Pcd
in Pcds
+ VfrPcds
:
4243 TokenCName
= Pcd
.TokenCName
4244 for PcdItem
in GlobalData
.MixedPcd
:
4245 if (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
4246 TokenCName
= PcdItem
[0]
4248 if Pcd
.Type
== TAB_PCDS_DYNAMIC_EX_HII
:
4249 for SkuName
in Pcd
.SkuInfoList
:
4250 SkuInfo
= Pcd
.SkuInfoList
[SkuName
]
4251 SkuId
= SkuInfo
.SkuId
4252 HiiInfo
= '## %s|%s|%s' % (SkuInfo
.VariableName
, SkuInfo
.VariableGuid
, SkuInfo
.VariableOffset
)
4256 # Don't generate duplicated HII PCD
4258 if (SkuId
, Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) in HiiPcds
:
4261 HiiPcds
.append((SkuId
, Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
4262 if (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) in self
._PcdComments
:
4263 PcdCommentList
= self
._PcdComments
[Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
][:]
4267 for Index
, Comment
in enumerate(PcdCommentList
):
4268 for Usage
in UsageList
:
4269 if Comment
.find(Usage
) != -1:
4273 if UsageIndex
!= -1:
4274 PcdCommentList
[UsageIndex
] = '## %s %s %s' % (UsageStr
, HiiInfo
, PcdCommentList
[UsageIndex
].replace(UsageStr
, ''))
4276 PcdCommentList
.append('## UNDEFINED ' + HiiInfo
)
4277 PcdComments
= '\n '.join(PcdCommentList
)
4278 PcdEntry
= Pcd
.TokenSpaceGuidCName
+ '.' + TokenCName
4280 PcdEntry
= PcdComments
+ '\n ' + PcdEntry
4281 AsBuiltInfDict
['pcd_item'] += [PcdEntry
]
4282 for Item
in self
.BuildOption
:
4283 if 'FLAGS' in self
.BuildOption
[Item
]:
4284 AsBuiltInfDict
['flags_item'] += ['%s:%s_%s_%s_%s_FLAGS = %s' % (self
.ToolChainFamily
, self
.BuildTarget
, self
.ToolChain
, self
.Arch
, Item
, self
.BuildOption
[Item
]['FLAGS'].strip())]
4286 # Generated LibraryClasses section in comments.
4287 for Library
in self
.LibraryAutoGenList
:
4288 AsBuiltInfDict
['libraryclasses_item'] += [Library
.MetaFile
.File
.replace('\\', '/')]
4290 # Generated UserExtensions TianoCore section.
4291 # All tianocore user extensions are copied.
4293 for TianoCore
in self
._GetTianoCoreUserExtensionList
():
4294 UserExtStr
+= '\n'.join(TianoCore
)
4295 ExtensionFile
= os
.path
.join(self
.MetaFile
.Dir
, TianoCore
[1])
4296 if os
.path
.isfile(ExtensionFile
):
4297 shutil
.copy2(ExtensionFile
, self
.OutputDir
)
4298 AsBuiltInfDict
['userextension_tianocore_item'] = UserExtStr
4300 # Generated depex expression section in comments.
4301 AsBuiltInfDict
['depexsection_item'] = ''
4302 DepexExpresion
= self
._GetDepexExpresionString
()
4304 AsBuiltInfDict
['depexsection_item'] = DepexExpresion
4306 AsBuiltInf
= TemplateString()
4307 AsBuiltInf
.Append(gAsBuiltInfHeaderString
.Replace(AsBuiltInfDict
))
4309 SaveFileOnChange(os
.path
.join(self
.OutputDir
, self
.Name
+ '.inf'), str(AsBuiltInf
), False)
4311 self
.IsAsBuiltInfCreated
= True
4312 if GlobalData
.gBinCacheDest
:
4313 self
.CopyModuleToCache()
4315 def CopyModuleToCache(self
):
4316 FileDir
= path
.join(GlobalData
.gBinCacheDest
, self
.Arch
, self
.SourceDir
, self
.MetaFile
.BaseName
)
4317 CreateDirectory (FileDir
)
4318 HashFile
= path
.join(self
.BuildDir
, self
.Name
+ '.hash')
4319 ModuleFile
= path
.join(self
.OutputDir
, self
.Name
+ '.inf')
4320 if os
.path
.exists(HashFile
):
4321 shutil
.copy2(HashFile
, FileDir
)
4322 if os
.path
.exists(ModuleFile
):
4323 shutil
.copy2(ModuleFile
, FileDir
)
4324 if not self
.OutputFile
:
4325 Ma
= self
.Workspace
.BuildDatabase
[PathClass(ModuleFile
), self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
4326 self
.OutputFile
= Ma
.Binaries
4328 for File
in self
.OutputFile
:
4330 if not os
.path
.isabs(File
):
4331 File
= os
.path
.join(self
.OutputDir
, File
)
4332 if os
.path
.exists(File
):
4333 shutil
.copy2(File
, FileDir
)
4335 def AttemptModuleCacheCopy(self
):
4336 if self
.IsBinaryModule
:
4338 FileDir
= path
.join(GlobalData
.gBinCacheSource
, self
.Arch
, self
.SourceDir
, self
.MetaFile
.BaseName
)
4339 HashFile
= path
.join(FileDir
, self
.Name
+ '.hash')
4340 if os
.path
.exists(HashFile
):
4341 f
= open(HashFile
, 'r')
4342 CacheHash
= f
.read()
4344 if GlobalData
.gModuleHash
[self
.Arch
][self
.Name
]:
4345 if CacheHash
== GlobalData
.gModuleHash
[self
.Arch
][self
.Name
]:
4346 for root
, dir, files
in os
.walk(FileDir
):
4348 if self
.Name
+ '.hash' in f
:
4349 shutil
.copy2(HashFile
, self
.BuildDir
)
4351 File
= path
.join(root
, f
)
4352 shutil
.copy2(File
, self
.OutputDir
)
4353 if self
.Name
== "PcdPeim" or self
.Name
== "PcdDxe":
4354 CreatePcdDatabaseCode(self
, TemplateString(), TemplateString())
4358 ## Create makefile for the module and its dependent libraries
4360 # @param CreateLibraryMakeFile Flag indicating if or not the makefiles of
4361 # dependent libraries will be created
4363 def CreateMakeFile(self
, CreateLibraryMakeFile
=True, GenFfsList
= []):
4364 # Ignore generating makefile when it is a binary module
4365 if self
.IsBinaryModule
:
4368 if self
.IsMakeFileCreated
:
4370 self
.GenFfsList
= GenFfsList
4371 if not self
.IsLibrary
and CreateLibraryMakeFile
:
4372 for LibraryAutoGen
in self
.LibraryAutoGenList
:
4373 LibraryAutoGen
.CreateMakeFile()
4378 if len(self
.CustomMakefile
) == 0:
4379 Makefile
= GenMake
.ModuleMakefile(self
)
4381 Makefile
= GenMake
.CustomMakefile(self
)
4382 if Makefile
.Generate():
4383 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated makefile for module %s [%s]" %
4384 (self
.Name
, self
.Arch
))
4386 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Skipped the generation of makefile for module %s [%s]" %
4387 (self
.Name
, self
.Arch
))
4389 self
.CreateTimeStamp(Makefile
)
4390 self
.IsMakeFileCreated
= True
4392 def CopyBinaryFiles(self
):
4393 for File
in self
.Module
.Binaries
:
4395 DstPath
= os
.path
.join(self
.OutputDir
, os
.path
.basename(SrcPath
))
4396 CopyLongFilePath(SrcPath
, DstPath
)
4397 ## Create autogen code for the module and its dependent libraries
4399 # @param CreateLibraryCodeFile Flag indicating if or not the code of
4400 # dependent libraries will be created
4402 def CreateCodeFile(self
, CreateLibraryCodeFile
=True):
4403 if self
.IsCodeFileCreated
:
4406 # Need to generate PcdDatabase even PcdDriver is binarymodule
4407 if self
.IsBinaryModule
and self
.PcdIsDriver
!= '':
4408 CreatePcdDatabaseCode(self
, TemplateString(), TemplateString())
4410 if self
.IsBinaryModule
:
4412 self
.CopyBinaryFiles()
4415 if not self
.IsLibrary
and CreateLibraryCodeFile
:
4416 for LibraryAutoGen
in self
.LibraryAutoGenList
:
4417 LibraryAutoGen
.CreateCodeFile()
4423 IgoredAutoGenList
= []
4425 for File
in self
.AutoGenFileList
:
4426 if GenC
.Generate(File
.Path
, self
.AutoGenFileList
[File
], File
.IsBinary
):
4427 #Ignore Edk AutoGen.c
4428 if self
.AutoGenVersion
< 0x00010005 and File
.Name
== 'AutoGen.c':
4431 AutoGenList
.append(str(File
))
4433 IgoredAutoGenList
.append(str(File
))
4435 # Skip the following code for EDK I inf
4436 if self
.AutoGenVersion
< 0x00010005:
4439 for ModuleType
in self
.DepexList
:
4440 # Ignore empty [depex] section or [depex] section for "USER_DEFINED" module
4441 if len(self
.DepexList
[ModuleType
]) == 0 or ModuleType
== "USER_DEFINED":
4444 Dpx
= GenDepex
.DependencyExpression(self
.DepexList
[ModuleType
], ModuleType
, True)
4445 DpxFile
= gAutoGenDepexFileName
% {"module_name" : self
.Name
}
4447 if len(Dpx
.PostfixNotation
) <> 0:
4448 self
.DepexGenerated
= True
4450 if Dpx
.Generate(path
.join(self
.OutputDir
, DpxFile
)):
4451 AutoGenList
.append(str(DpxFile
))
4453 IgoredAutoGenList
.append(str(DpxFile
))
4455 if IgoredAutoGenList
== []:
4456 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated [%s] files for module %s [%s]" %
4457 (" ".join(AutoGenList
), self
.Name
, self
.Arch
))
4458 elif AutoGenList
== []:
4459 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Skipped the generation of [%s] files for module %s [%s]" %
4460 (" ".join(IgoredAutoGenList
), self
.Name
, self
.Arch
))
4462 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated [%s] (skipped %s) files for module %s [%s]" %
4463 (" ".join(AutoGenList
), " ".join(IgoredAutoGenList
), self
.Name
, self
.Arch
))
4465 self
.IsCodeFileCreated
= True
4468 ## Summarize the ModuleAutoGen objects of all libraries used by this module
4469 def _GetLibraryAutoGenList(self
):
4470 if self
._LibraryAutoGenList
== None:
4471 self
._LibraryAutoGenList
= []
4472 for Library
in self
.DependentLibraryList
:
4479 self
.PlatformInfo
.MetaFile
4481 if La
not in self
._LibraryAutoGenList
:
4482 self
._LibraryAutoGenList
.append(La
)
4483 for Lib
in La
.CodaTargetList
:
4484 self
._ApplyBuildRule
(Lib
.Target
, TAB_UNKNOWN_FILE
)
4485 return self
._LibraryAutoGenList
4487 def GenModuleHash(self
):
4488 if self
.Arch
not in GlobalData
.gModuleHash
:
4489 GlobalData
.gModuleHash
[self
.Arch
] = {}
4491 # Add Platform level hash
4492 m
.update(GlobalData
.gPlatformHash
)
4493 # Add Package level hash
4494 if self
.DependentPackageList
:
4495 for Pkg
in self
.DependentPackageList
:
4496 if Pkg
.PackageName
in GlobalData
.gPackageHash
[self
.Arch
]:
4497 m
.update(GlobalData
.gPackageHash
[self
.Arch
][Pkg
.PackageName
])
4500 if self
.LibraryAutoGenList
:
4501 for Lib
in self
.LibraryAutoGenList
:
4502 if Lib
.Name
not in GlobalData
.gModuleHash
[self
.Arch
]:
4504 m
.update(GlobalData
.gModuleHash
[self
.Arch
][Lib
.Name
])
4507 f
= open(str(self
.MetaFile
), 'r')
4511 # Add Module's source files
4512 if self
.SourceFileList
:
4513 for File
in self
.SourceFileList
:
4514 f
= open(str(File
), 'r')
4519 ModuleHashFile
= path
.join(self
.BuildDir
, self
.Name
+ ".hash")
4520 if self
.Name
not in GlobalData
.gModuleHash
[self
.Arch
]:
4521 GlobalData
.gModuleHash
[self
.Arch
][self
.Name
] = m
.hexdigest()
4522 if GlobalData
.gBinCacheSource
:
4523 CacheValid
= self
.AttemptModuleCacheCopy()
4526 return SaveFileOnChange(ModuleHashFile
, m
.hexdigest(), True)
4528 ## Decide whether we can skip the ModuleAutoGen process
4529 def CanSkipbyHash(self
):
4530 if GlobalData
.gUseHashCache
:
4531 return not self
.GenModuleHash()
4533 ## Decide whether we can skip the ModuleAutoGen process
4534 # If any source file is newer than the module than we cannot skip
4537 if not os
.path
.exists(self
.GetTimeStampPath()):
4539 #last creation time of the module
4540 DstTimeStamp
= os
.stat(self
.GetTimeStampPath())[8]
4542 SrcTimeStamp
= self
.Workspace
._SrcTimeStamp
4543 if SrcTimeStamp
> DstTimeStamp
:
4546 with
open(self
.GetTimeStampPath(),'r') as f
:
4548 source
= source
.rstrip('\n')
4549 if not os
.path
.exists(source
):
4551 if source
not in ModuleAutoGen
.TimeDict
:
4552 ModuleAutoGen
.TimeDict
[source
] = os
.stat(source
)[8]
4553 if ModuleAutoGen
.TimeDict
[source
] > DstTimeStamp
:
4557 def GetTimeStampPath(self
):
4558 if self
._TimeStampPath
== None:
4559 self
._TimeStampPath
= os
.path
.join(self
.MakeFileDir
, 'AutoGenTimeStamp')
4560 return self
._TimeStampPath
4561 def CreateTimeStamp(self
, Makefile
):
4565 FileSet
.add (self
.MetaFile
.Path
)
4567 for SourceFile
in self
.Module
.Sources
:
4568 FileSet
.add (SourceFile
.Path
)
4570 for Lib
in self
.DependentLibraryList
:
4571 FileSet
.add (Lib
.MetaFile
.Path
)
4573 for f
in self
.AutoGenDepSet
:
4574 FileSet
.add (f
.Path
)
4576 if os
.path
.exists (self
.GetTimeStampPath()):
4577 os
.remove (self
.GetTimeStampPath())
4578 with
open(self
.GetTimeStampPath(), 'w+') as file:
4582 Module
= property(_GetModule
)
4583 Name
= property(_GetBaseName
)
4584 Guid
= property(_GetGuid
)
4585 Version
= property(_GetVersion
)
4586 ModuleType
= property(_GetModuleType
)
4587 ComponentType
= property(_GetComponentType
)
4588 BuildType
= property(_GetBuildType
)
4589 PcdIsDriver
= property(_GetPcdIsDriver
)
4590 AutoGenVersion
= property(_GetAutoGenVersion
)
4591 Macros
= property(_GetMacros
)
4592 Specification
= property(_GetSpecification
)
4594 IsLibrary
= property(_IsLibrary
)
4595 IsBinaryModule
= property(_IsBinaryModule
)
4596 BuildDir
= property(_GetBuildDir
)
4597 OutputDir
= property(_GetOutputDir
)
4598 FfsOutputDir
= property(_GetFfsOutputDir
)
4599 DebugDir
= property(_GetDebugDir
)
4600 MakeFileDir
= property(_GetMakeFileDir
)
4601 CustomMakefile
= property(_GetCustomMakefile
)
4603 IncludePathList
= property(_GetIncludePathList
)
4604 IncludePathLength
= property(_GetIncludePathLength
)
4605 AutoGenFileList
= property(_GetAutoGenFileList
)
4606 UnicodeFileList
= property(_GetUnicodeFileList
)
4607 VfrFileList
= property(_GetVfrFileList
)
4608 SourceFileList
= property(_GetSourceFileList
)
4609 BinaryFileList
= property(_GetBinaryFiles
) # FileType : [File List]
4610 Targets
= property(_GetTargets
)
4611 IntroTargetList
= property(_GetIntroTargetList
)
4612 CodaTargetList
= property(_GetFinalTargetList
)
4613 FileTypes
= property(_GetFileTypes
)
4614 BuildRules
= property(_GetBuildRules
)
4615 IdfFileList
= property(_GetIdfFileList
)
4617 DependentPackageList
= property(_GetDependentPackageList
)
4618 DependentLibraryList
= property(_GetLibraryList
)
4619 LibraryAutoGenList
= property(_GetLibraryAutoGenList
)
4620 DerivedPackageList
= property(_GetDerivedPackageList
)
4622 ModulePcdList
= property(_GetModulePcdList
)
4623 LibraryPcdList
= property(_GetLibraryPcdList
)
4624 GuidList
= property(_GetGuidList
)
4625 ProtocolList
= property(_GetProtocolList
)
4626 PpiList
= property(_GetPpiList
)
4627 DepexList
= property(_GetDepexTokenList
)
4628 DxsFile
= property(_GetDxsFile
)
4629 DepexExpressionList
= property(_GetDepexExpressionTokenList
)
4630 BuildOption
= property(_GetModuleBuildOption
)
4631 BuildOptionIncPathList
= property(_GetBuildOptionIncPathList
)
4632 BuildCommand
= property(_GetBuildCommand
)
4634 FixedAtBuildPcds
= property(_GetFixedAtBuildPcds
)
4636 # This acts like the main() function for the script, unless it is 'import'ed into another script.
4637 if __name__
== '__main__':