2 # Generate AutoGen.h, AutoGen.c and *.depex files
4 # Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.<BR>
5 # Copyright (c) 2018, Hewlett Packard Enterprise Development, L.P.<BR>
6 # Copyright (c) 2019, American Megatrends, Inc. All rights reserved.<BR>
8 # This program and the accompanying materials
9 # are licensed and made available under the terms and conditions of the BSD License
10 # which accompanies this distribution. The full text of the license may be found at
11 # http://opensource.org/licenses/bsd-license.php
13 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 from __future__
import print_function
20 from __future__
import absolute_import
21 import Common
.LongFilePathOs
as os
23 import os
.path
as path
29 from . import GenDepex
30 from io
import BytesIO
32 from .StrGather
import *
33 from .BuildEngine
import BuildRule
35 from Common
.LongFilePathSupport
import CopyLongFilePath
36 from Common
.BuildToolError
import *
37 from Common
.DataType
import *
38 from Common
.Misc
import *
39 from Common
.StringUtils
import *
40 import Common
.GlobalData
as GlobalData
41 from GenFds
.FdfParser
import *
42 from CommonDataClass
.CommonClass
import SkuInfoClass
43 from GenPatchPcdTable
.GenPatchPcdTable
import parsePcdInfoFromMapFile
44 import Common
.VpdInfoFile
as VpdInfoFile
45 from .GenPcdDb
import CreatePcdDatabaseCode
46 from Workspace
.MetaFileCommentParser
import UsageList
47 from Workspace
.WorkspaceCommon
import GetModuleLibInstances
48 from Common
.MultipleWorkspace
import MultipleWorkspace
as mws
49 from . import InfSectionParser
52 from .GenVar
import VariableMgr
, var_info
53 from collections
import OrderedDict
54 from collections
import defaultdict
55 from Workspace
.WorkspaceCommon
import OrderedListDict
56 from Common
.ToolDefClassObject
import gDefaultToolsDefFile
58 from Common
.caching
import cached_property
, cached_class_function
60 ## Regular expression for splitting Dependency Expression string into tokens
61 gDepexTokenPattern
= re
.compile("(\(|\)|\w+| \S+\.inf)")
63 ## Regular expression for match: PCD(xxxx.yyy)
64 gPCDAsGuidPattern
= re
.compile(r
"^PCD\(.+\..+\)$")
67 # Regular expression for finding Include Directories, the difference between MSFT and INTEL/GCC/RVCT
68 # is the former use /I , the Latter used -I to specify include directories
70 gBuildOptIncludePatternMsft
= re
.compile(r
"(?:.*?)/I[ \t]*([^ ]*)", re
.MULTILINE | re
.DOTALL
)
71 gBuildOptIncludePatternOther
= re
.compile(r
"(?:.*?)-I[ \t]*([^ ]*)", re
.MULTILINE | re
.DOTALL
)
74 # Match name = variable
76 gEfiVarStoreNamePattern
= re
.compile("\s*name\s*=\s*(\w+)")
78 # The format of guid in efivarstore statement likes following and must be correct:
79 # guid = {0xA04A27f4, 0xDF00, 0x4D42, {0xB5, 0x52, 0x39, 0x51, 0x13, 0x02, 0x11, 0x3D}}
81 gEfiVarStoreGuidPattern
= re
.compile("\s*guid\s*=\s*({.*?{.*?}\s*})")
83 ## Mapping Makefile type
84 gMakeTypeMap
= {TAB_COMPILER_MSFT
:"nmake", "GCC":"gmake"}
87 ## Build rule configuration file
88 gDefaultBuildRuleFile
= 'build_rule.txt'
90 ## Build rule default version
91 AutoGenReqBuildRuleVerNum
= "0.1"
93 ## default file name for AutoGen
94 gAutoGenCodeFileName
= "AutoGen.c"
95 gAutoGenHeaderFileName
= "AutoGen.h"
96 gAutoGenStringFileName
= "%(module_name)sStrDefs.h"
97 gAutoGenStringFormFileName
= "%(module_name)sStrDefs.hpk"
98 gAutoGenDepexFileName
= "%(module_name)s.depex"
99 gAutoGenImageDefFileName
= "%(module_name)sImgDefs.h"
100 gAutoGenIdfFileName
= "%(module_name)sIdf.hpk"
101 gInfSpecVersion
= "0x00010017"
104 # Template string to generic AsBuilt INF
106 gAsBuiltInfHeaderString
= TemplateString("""${header_comments}
109 # FILE auto-generated
112 INF_VERSION = ${module_inf_version}
113 BASE_NAME = ${module_name}
114 FILE_GUID = ${module_guid}
115 MODULE_TYPE = ${module_module_type}${BEGIN}
116 VERSION_STRING = ${module_version_string}${END}${BEGIN}
117 PCD_IS_DRIVER = ${pcd_is_driver_string}${END}${BEGIN}
118 UEFI_SPECIFICATION_VERSION = ${module_uefi_specification_version}${END}${BEGIN}
119 PI_SPECIFICATION_VERSION = ${module_pi_specification_version}${END}${BEGIN}
120 ENTRY_POINT = ${module_entry_point}${END}${BEGIN}
121 UNLOAD_IMAGE = ${module_unload_image}${END}${BEGIN}
122 CONSTRUCTOR = ${module_constructor}${END}${BEGIN}
123 DESTRUCTOR = ${module_destructor}${END}${BEGIN}
124 SHADOW = ${module_shadow}${END}${BEGIN}
125 PCI_VENDOR_ID = ${module_pci_vendor_id}${END}${BEGIN}
126 PCI_DEVICE_ID = ${module_pci_device_id}${END}${BEGIN}
127 PCI_CLASS_CODE = ${module_pci_class_code}${END}${BEGIN}
128 PCI_REVISION = ${module_pci_revision}${END}${BEGIN}
129 BUILD_NUMBER = ${module_build_number}${END}${BEGIN}
130 SPEC = ${module_spec}${END}${BEGIN}
131 UEFI_HII_RESOURCE_SECTION = ${module_uefi_hii_resource_section}${END}${BEGIN}
132 MODULE_UNI_FILE = ${module_uni_file}${END}
134 [Packages.${module_arch}]${BEGIN}
135 ${package_item}${END}
137 [Binaries.${module_arch}]${BEGIN}
140 [PatchPcd.${module_arch}]${BEGIN}
144 [Protocols.${module_arch}]${BEGIN}
148 [Ppis.${module_arch}]${BEGIN}
152 [Guids.${module_arch}]${BEGIN}
156 [PcdEx.${module_arch}]${BEGIN}
160 [LibraryClasses.${module_arch}]
161 ## @LIB_INSTANCES${BEGIN}
162 # ${libraryclasses_item}${END}
166 ${userextension_tianocore_item}
170 [BuildOptions.${module_arch}]
172 ## ${flags_item}${END}
175 ## Base class for AutoGen
177 # This class just implements the cache mechanism of AutoGen objects.
179 class AutoGen(object):
180 # database to maintain the objects in each child class
181 __ObjectCache
= {} # (BuildTarget, ToolChain, ARCH, platform file): AutoGen object
185 # @param Class class object of real AutoGen class
186 # (WorkspaceAutoGen, ModuleAutoGen or PlatformAutoGen)
187 # @param Workspace Workspace directory or WorkspaceAutoGen object
188 # @param MetaFile The path of meta file
189 # @param Target Build target
190 # @param Toolchain Tool chain name
191 # @param Arch Target arch
192 # @param *args The specific class related parameters
193 # @param **kwargs The specific class related dict parameters
195 def __new__(cls
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
196 # check if the object has been created
197 Key
= (Target
, Toolchain
, Arch
, MetaFile
)
198 if Key
in cls
.__ObjectCache
:
199 # if it exists, just return it directly
200 return cls
.__ObjectCache
[Key
]
201 # it didnt exist. create it, cache it, then return it
202 RetVal
= cls
.__ObjectCache
[Key
] = super(AutoGen
, cls
).__new
__(cls
)
205 def __init__ (self
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
206 super(AutoGen
, self
).__init
__(self
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
)
210 # The file path of platform file will be used to represent hash value of this object
212 # @retval int Hash value of the file path of platform file
215 return hash(self
.MetaFile
)
219 # The file path of platform file will be used to represent this object
221 # @retval string String of platform file path
224 return str(self
.MetaFile
)
227 def __eq__(self
, Other
):
228 return Other
and self
.MetaFile
== Other
230 ## Workspace AutoGen class
232 # This class is used mainly to control the whole platform build for different
233 # architecture. This class will generate top level makefile.
235 class WorkspaceAutoGen(AutoGen
):
236 # call super().__init__ then call the worker function with different parameter count
237 def __init__(self
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
238 if not hasattr(self
, "_Init"):
239 super(WorkspaceAutoGen
, self
).__init
__(Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
)
240 self
._InitWorker
(Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
)
243 ## Initialize WorkspaceAutoGen
245 # @param WorkspaceDir Root directory of workspace
246 # @param ActivePlatform Meta-file of active platform
247 # @param Target Build target
248 # @param Toolchain Tool chain name
249 # @param ArchList List of architecture of current build
250 # @param MetaFileDb Database containing meta-files
251 # @param BuildConfig Configuration of build
252 # @param ToolDefinition Tool chain definitions
253 # @param FlashDefinitionFile File of flash definition
254 # @param Fds FD list to be generated
255 # @param Fvs FV list to be generated
256 # @param Caps Capsule list to be generated
257 # @param SkuId SKU id from command line
259 def _InitWorker(self
, WorkspaceDir
, ActivePlatform
, Target
, Toolchain
, ArchList
, MetaFileDb
,
260 BuildConfig
, ToolDefinition
, FlashDefinitionFile
='', Fds
=None, Fvs
=None, Caps
=None, SkuId
='', UniFlag
=None,
261 Progress
=None, BuildModule
=None):
262 self
.BuildDatabase
= MetaFileDb
263 self
.MetaFile
= ActivePlatform
264 self
.WorkspaceDir
= WorkspaceDir
265 self
.Platform
= self
.BuildDatabase
[self
.MetaFile
, TAB_ARCH_COMMON
, Target
, Toolchain
]
266 GlobalData
.gActivePlatform
= self
.Platform
267 self
.BuildTarget
= Target
268 self
.ToolChain
= Toolchain
269 self
.ArchList
= ArchList
271 self
.UniFlag
= UniFlag
273 self
.TargetTxt
= BuildConfig
274 self
.ToolDef
= ToolDefinition
275 self
.FdfFile
= FlashDefinitionFile
276 self
.FdTargetList
= Fds
if Fds
else []
277 self
.FvTargetList
= Fvs
if Fvs
else []
278 self
.CapTargetList
= Caps
if Caps
else []
279 self
.AutoGenObjectList
= []
282 # there's many relative directory operations, so ...
283 os
.chdir(self
.WorkspaceDir
)
288 if not self
.ArchList
:
289 ArchList
= set(self
.Platform
.SupArchList
)
291 ArchList
= set(self
.ArchList
) & set(self
.Platform
.SupArchList
)
293 EdkLogger
.error("build", PARAMETER_INVALID
,
294 ExtraData
= "Invalid ARCH specified. [Valid ARCH: %s]" % (" ".join(self
.Platform
.SupArchList
)))
295 elif self
.ArchList
and len(ArchList
) != len(self
.ArchList
):
296 SkippedArchList
= set(self
.ArchList
).symmetric_difference(set(self
.Platform
.SupArchList
))
297 EdkLogger
.verbose("\nArch [%s] is ignored because the platform supports [%s] only!"
298 % (" ".join(SkippedArchList
), " ".join(self
.Platform
.SupArchList
)))
299 self
.ArchList
= tuple(ArchList
)
301 # Validate build target
302 if self
.BuildTarget
not in self
.Platform
.BuildTargets
:
303 EdkLogger
.error("build", PARAMETER_INVALID
,
304 ExtraData
="Build target [%s] is not supported by the platform. [Valid target: %s]"
305 % (self
.BuildTarget
, " ".join(self
.Platform
.BuildTargets
)))
308 # parse FDF file to get PCDs in it, if any
310 self
.FdfFile
= self
.Platform
.FlashDefinition
314 EdkLogger
.info('%-16s = %s' % ("Architecture(s)", ' '.join(self
.ArchList
)))
315 EdkLogger
.info('%-16s = %s' % ("Build target", self
.BuildTarget
))
316 EdkLogger
.info('%-16s = %s' % ("Toolchain", self
.ToolChain
))
318 EdkLogger
.info('\n%-24s = %s' % ("Active Platform", self
.Platform
))
320 EdkLogger
.info('%-24s = %s' % ("Active Module", BuildModule
))
323 EdkLogger
.info('%-24s = %s' % ("Flash Image Definition", self
.FdfFile
))
325 EdkLogger
.verbose("\nFLASH_DEFINITION = %s" % self
.FdfFile
)
328 Progress
.Start("\nProcessing meta-data")
332 # Mark now build in AutoGen Phase
334 GlobalData
.gAutoGenPhase
= True
335 Fdf
= FdfParser(self
.FdfFile
.Path
)
337 GlobalData
.gFdfParser
= Fdf
338 GlobalData
.gAutoGenPhase
= False
339 PcdSet
= Fdf
.Profile
.PcdDict
340 if Fdf
.CurrentFdName
and Fdf
.CurrentFdName
in Fdf
.Profile
.FdDict
:
341 FdDict
= Fdf
.Profile
.FdDict
[Fdf
.CurrentFdName
]
342 for FdRegion
in FdDict
.RegionList
:
343 if str(FdRegion
.RegionType
) is 'FILE' and self
.Platform
.VpdToolGuid
in str(FdRegion
.RegionDataList
):
344 if int(FdRegion
.Offset
) % 8 != 0:
345 EdkLogger
.error("build", FORMAT_INVALID
, 'The VPD Base Address %s must be 8-byte aligned.' % (FdRegion
.Offset
))
346 ModuleList
= Fdf
.Profile
.InfList
347 self
.FdfProfile
= Fdf
.Profile
348 for fvname
in self
.FvTargetList
:
349 if fvname
.upper() not in self
.FdfProfile
.FvDict
:
350 EdkLogger
.error("build", OPTION_VALUE_INVALID
,
351 "No such an FV in FDF file: %s" % fvname
)
353 # In DSC file may use FILE_GUID to override the module, then in the Platform.Modules use FILE_GUIDmodule.inf as key,
354 # but the path (self.MetaFile.Path) is the real path
355 for key
in self
.FdfProfile
.InfDict
:
357 MetaFile_cache
= defaultdict(set)
358 for Arch
in self
.ArchList
:
359 Current_Platform_cache
= self
.BuildDatabase
[self
.MetaFile
, Arch
, Target
, Toolchain
]
360 for Pkey
in Current_Platform_cache
.Modules
:
361 MetaFile_cache
[Arch
].add(Current_Platform_cache
.Modules
[Pkey
].MetaFile
)
362 for Inf
in self
.FdfProfile
.InfDict
[key
]:
363 ModuleFile
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, Arch
)
364 for Arch
in self
.ArchList
:
365 if ModuleFile
in MetaFile_cache
[Arch
]:
368 ModuleData
= self
.BuildDatabase
[ModuleFile
, Arch
, Target
, Toolchain
]
369 if not ModuleData
.IsBinaryModule
:
370 EdkLogger
.error('build', PARSER_ERROR
, "Module %s NOT found in DSC file; Is it really a binary module?" % ModuleFile
)
373 for Arch
in self
.ArchList
:
375 Platform
= self
.BuildDatabase
[self
.MetaFile
, Arch
, Target
, Toolchain
]
377 for Pkey
in Platform
.Modules
:
378 MetaFileList
.add(Platform
.Modules
[Pkey
].MetaFile
)
379 for Inf
in self
.FdfProfile
.InfDict
[key
]:
380 ModuleFile
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, Arch
)
381 if ModuleFile
in MetaFileList
:
383 ModuleData
= self
.BuildDatabase
[ModuleFile
, Arch
, Target
, Toolchain
]
384 if not ModuleData
.IsBinaryModule
:
385 EdkLogger
.error('build', PARSER_ERROR
, "Module %s NOT found in DSC file; Is it really a binary module?" % ModuleFile
)
390 self
.FdfProfile
= None
391 if self
.FdTargetList
:
392 EdkLogger
.info("No flash definition file found. FD [%s] will be ignored." % " ".join(self
.FdTargetList
))
393 self
.FdTargetList
= []
394 if self
.FvTargetList
:
395 EdkLogger
.info("No flash definition file found. FV [%s] will be ignored." % " ".join(self
.FvTargetList
))
396 self
.FvTargetList
= []
397 if self
.CapTargetList
:
398 EdkLogger
.info("No flash definition file found. Capsule [%s] will be ignored." % " ".join(self
.CapTargetList
))
399 self
.CapTargetList
= []
401 # apply SKU and inject PCDs from Flash Definition file
402 for Arch
in self
.ArchList
:
403 Platform
= self
.BuildDatabase
[self
.MetaFile
, Arch
, Target
, Toolchain
]
404 PlatformPcds
= Platform
.Pcds
405 self
._GuidDict
= Platform
._GuidDict
406 SourcePcdDict
= {TAB_PCDS_DYNAMIC_EX
:set(), TAB_PCDS_PATCHABLE_IN_MODULE
:set(),TAB_PCDS_DYNAMIC
:set(),TAB_PCDS_FIXED_AT_BUILD
:set()}
407 BinaryPcdDict
= {TAB_PCDS_DYNAMIC_EX
:set(), TAB_PCDS_PATCHABLE_IN_MODULE
:set()}
408 SourcePcdDict_Keys
= SourcePcdDict
.keys()
409 BinaryPcdDict_Keys
= BinaryPcdDict
.keys()
411 # generate the SourcePcdDict and BinaryPcdDict
412 PGen
= PlatformAutoGen(self
, self
.MetaFile
, Target
, Toolchain
, Arch
)
413 for BuildData
in PGen
.BuildDatabase
._CACHE
_.values():
414 if BuildData
.Arch
!= Arch
:
416 if BuildData
.MetaFile
.Ext
== '.inf':
417 for key
in BuildData
.Pcds
:
418 if BuildData
.Pcds
[key
].Pending
:
419 if key
in Platform
.Pcds
:
420 PcdInPlatform
= Platform
.Pcds
[key
]
421 if PcdInPlatform
.Type
:
422 BuildData
.Pcds
[key
].Type
= PcdInPlatform
.Type
423 BuildData
.Pcds
[key
].Pending
= False
425 if BuildData
.MetaFile
in Platform
.Modules
:
426 PlatformModule
= Platform
.Modules
[str(BuildData
.MetaFile
)]
427 if key
in PlatformModule
.Pcds
:
428 PcdInPlatform
= PlatformModule
.Pcds
[key
]
429 if PcdInPlatform
.Type
:
430 BuildData
.Pcds
[key
].Type
= PcdInPlatform
.Type
431 BuildData
.Pcds
[key
].Pending
= False
433 #Pcd used in Library, Pcd Type from reference module if Pcd Type is Pending
434 if BuildData
.Pcds
[key
].Pending
:
435 MGen
= ModuleAutoGen(self
, BuildData
.MetaFile
, Target
, Toolchain
, Arch
, self
.MetaFile
)
436 if MGen
and MGen
.IsLibrary
:
437 if MGen
in PGen
.LibraryAutoGenList
:
438 ReferenceModules
= MGen
.ReferenceModules
439 for ReferenceModule
in ReferenceModules
:
440 if ReferenceModule
.MetaFile
in Platform
.Modules
:
441 RefPlatformModule
= Platform
.Modules
[str(ReferenceModule
.MetaFile
)]
442 if key
in RefPlatformModule
.Pcds
:
443 PcdInReferenceModule
= RefPlatformModule
.Pcds
[key
]
444 if PcdInReferenceModule
.Type
:
445 BuildData
.Pcds
[key
].Type
= PcdInReferenceModule
.Type
446 BuildData
.Pcds
[key
].Pending
= False
449 if TAB_PCDS_DYNAMIC_EX
in BuildData
.Pcds
[key
].Type
:
450 if BuildData
.IsBinaryModule
:
451 BinaryPcdDict
[TAB_PCDS_DYNAMIC_EX
].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
453 SourcePcdDict
[TAB_PCDS_DYNAMIC_EX
].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
455 elif TAB_PCDS_PATCHABLE_IN_MODULE
in BuildData
.Pcds
[key
].Type
:
456 if BuildData
.MetaFile
.Ext
== '.inf':
457 if BuildData
.IsBinaryModule
:
458 BinaryPcdDict
[TAB_PCDS_PATCHABLE_IN_MODULE
].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
460 SourcePcdDict
[TAB_PCDS_PATCHABLE_IN_MODULE
].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
462 elif TAB_PCDS_DYNAMIC
in BuildData
.Pcds
[key
].Type
:
463 SourcePcdDict
[TAB_PCDS_DYNAMIC
].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
464 elif TAB_PCDS_FIXED_AT_BUILD
in BuildData
.Pcds
[key
].Type
:
465 SourcePcdDict
[TAB_PCDS_FIXED_AT_BUILD
].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
469 # A PCD can only use one type for all source modules
471 for i
in SourcePcdDict_Keys
:
472 for j
in SourcePcdDict_Keys
:
474 Intersections
= SourcePcdDict
[i
].intersection(SourcePcdDict
[j
])
475 if len(Intersections
) > 0:
479 "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
),
480 ExtraData
='\n\t'.join(str(P
[1]+'.'+P
[0]) for P
in Intersections
)
484 # intersection the BinaryPCD for Mixed PCD
486 for i
in BinaryPcdDict_Keys
:
487 for j
in BinaryPcdDict_Keys
:
489 Intersections
= BinaryPcdDict
[i
].intersection(BinaryPcdDict
[j
])
490 for item
in Intersections
:
491 NewPcd1
= (item
[0] + '_' + i
, item
[1])
492 NewPcd2
= (item
[0] + '_' + j
, item
[1])
493 if item
not in GlobalData
.MixedPcd
:
494 GlobalData
.MixedPcd
[item
] = [NewPcd1
, NewPcd2
]
496 if NewPcd1
not in GlobalData
.MixedPcd
[item
]:
497 GlobalData
.MixedPcd
[item
].append(NewPcd1
)
498 if NewPcd2
not in GlobalData
.MixedPcd
[item
]:
499 GlobalData
.MixedPcd
[item
].append(NewPcd2
)
502 # intersection the SourcePCD and BinaryPCD for Mixed PCD
504 for i
in SourcePcdDict_Keys
:
505 for j
in BinaryPcdDict_Keys
:
507 Intersections
= SourcePcdDict
[i
].intersection(BinaryPcdDict
[j
])
508 for item
in Intersections
:
509 NewPcd1
= (item
[0] + '_' + i
, item
[1])
510 NewPcd2
= (item
[0] + '_' + j
, item
[1])
511 if item
not in GlobalData
.MixedPcd
:
512 GlobalData
.MixedPcd
[item
] = [NewPcd1
, NewPcd2
]
514 if NewPcd1
not in GlobalData
.MixedPcd
[item
]:
515 GlobalData
.MixedPcd
[item
].append(NewPcd1
)
516 if NewPcd2
not in GlobalData
.MixedPcd
[item
]:
517 GlobalData
.MixedPcd
[item
].append(NewPcd2
)
519 for BuildData
in PGen
.BuildDatabase
._CACHE
_.values():
520 if BuildData
.Arch
!= Arch
:
522 for key
in BuildData
.Pcds
:
523 for SinglePcd
in GlobalData
.MixedPcd
:
524 if (BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
) == SinglePcd
:
525 for item
in GlobalData
.MixedPcd
[SinglePcd
]:
526 Pcd_Type
= item
[0].split('_')[-1]
527 if (Pcd_Type
== BuildData
.Pcds
[key
].Type
) or (Pcd_Type
== TAB_PCDS_DYNAMIC_EX
and BuildData
.Pcds
[key
].Type
in PCD_DYNAMIC_EX_TYPE_SET
) or \
528 (Pcd_Type
== TAB_PCDS_DYNAMIC
and BuildData
.Pcds
[key
].Type
in PCD_DYNAMIC_TYPE_SET
):
529 Value
= BuildData
.Pcds
[key
]
530 Value
.TokenCName
= BuildData
.Pcds
[key
].TokenCName
+ '_' + Pcd_Type
532 newkey
= (Value
.TokenCName
, key
[1])
534 newkey
= (Value
.TokenCName
, key
[1], key
[2])
535 del BuildData
.Pcds
[key
]
536 BuildData
.Pcds
[newkey
] = Value
540 # handle the mixed pcd in FDF file
542 if key
in GlobalData
.MixedPcd
:
545 for item
in GlobalData
.MixedPcd
[key
]:
548 #Collect package set information from INF of FDF
550 for Inf
in ModuleList
:
551 ModuleFile
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, Arch
)
552 if ModuleFile
in Platform
.Modules
:
554 ModuleData
= self
.BuildDatabase
[ModuleFile
, Arch
, Target
, Toolchain
]
555 PkgSet
.update(ModuleData
.Packages
)
556 Pkgs
= list(PkgSet
) + list(PGen
.PackageList
)
561 DecPcds
.add((Pcd
[0], Pcd
[1]))
562 DecPcdsKey
.add((Pcd
[0], Pcd
[1], Pcd
[2]))
564 Platform
.SkuName
= self
.SkuId
565 for Name
, Guid
,Fileds
in PcdSet
:
566 if (Name
, Guid
) not in DecPcds
:
570 "PCD (%s.%s) used in FDF is not declared in DEC files." % (Guid
, Name
),
571 File
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
, Fileds
][0],
572 Line
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
, Fileds
][1]
575 # Check whether Dynamic or DynamicEx PCD used in FDF file. If used, build break and give a error message.
576 if (Name
, Guid
, TAB_PCDS_FIXED_AT_BUILD
) in DecPcdsKey \
577 or (Name
, Guid
, TAB_PCDS_PATCHABLE_IN_MODULE
) in DecPcdsKey \
578 or (Name
, Guid
, TAB_PCDS_FEATURE_FLAG
) in DecPcdsKey
:
580 elif (Name
, Guid
, TAB_PCDS_DYNAMIC
) in DecPcdsKey
or (Name
, Guid
, TAB_PCDS_DYNAMIC_EX
) in DecPcdsKey
:
584 "Using Dynamic or DynamicEx type of PCD [%s.%s] in FDF file is not allowed." % (Guid
, Name
),
585 File
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
, Fileds
][0],
586 Line
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
, Fileds
][1]
589 Pa
= PlatformAutoGen(self
, self
.MetaFile
, Target
, Toolchain
, Arch
)
591 # Explicitly collect platform's dynamic PCDs
593 Pa
.CollectPlatformDynamicPcds()
594 Pa
.CollectFixedAtBuildPcds()
595 self
.AutoGenObjectList
.append(Pa
)
598 # Generate Package level hash value
600 GlobalData
.gPackageHash
[Arch
] = {}
601 if GlobalData
.gUseHashCache
:
603 self
._GenPkgLevelHash
(Pkg
)
606 # Check PCDs token value conflict in each DEC file.
608 self
._CheckAllPcdsTokenValueConflict
()
611 # Check PCD type and definition between DSC and DEC
613 self
._CheckPcdDefineAndType
()
616 # Create BuildOptions Macro & PCD metafile, also add the Active Platform and FDF file.
618 content
= 'gCommandLineDefines: '
619 content
+= str(GlobalData
.gCommandLineDefines
)
620 content
+= os
.linesep
621 content
+= 'BuildOptionPcd: '
622 content
+= str(GlobalData
.BuildOptionPcd
)
623 content
+= os
.linesep
624 content
+= 'Active Platform: '
625 content
+= str(self
.Platform
)
626 content
+= os
.linesep
628 content
+= 'Flash Image Definition: '
629 content
+= str(self
.FdfFile
)
630 content
+= os
.linesep
631 SaveFileOnChange(os
.path
.join(self
.BuildDir
, 'BuildOptions'), content
, False)
634 # Create PcdToken Number file for Dynamic/DynamicEx Pcd.
636 PcdTokenNumber
= 'PcdTokenNumber: '
637 if Pa
.PcdTokenNumber
:
638 if Pa
.DynamicPcdList
:
639 for Pcd
in Pa
.DynamicPcdList
:
640 PcdTokenNumber
+= os
.linesep
641 PcdTokenNumber
+= str((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
))
642 PcdTokenNumber
+= ' : '
643 PcdTokenNumber
+= str(Pa
.PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
])
644 SaveFileOnChange(os
.path
.join(self
.BuildDir
, 'PcdTokenNumber'), PcdTokenNumber
, False)
647 # Get set of workspace metafiles
649 AllWorkSpaceMetaFiles
= self
._GetMetaFiles
(Target
, Toolchain
, Arch
)
652 # Retrieve latest modified time of all metafiles
655 for f
in AllWorkSpaceMetaFiles
:
656 if os
.stat(f
)[8] > SrcTimeStamp
:
657 SrcTimeStamp
= os
.stat(f
)[8]
658 self
._SrcTimeStamp
= SrcTimeStamp
660 if GlobalData
.gUseHashCache
:
662 for files
in AllWorkSpaceMetaFiles
:
663 if files
.endswith('.dec'):
669 SaveFileOnChange(os
.path
.join(self
.BuildDir
, 'AutoGen.hash'), m
.hexdigest(), True)
670 GlobalData
.gPlatformHash
= m
.hexdigest()
673 # Write metafile list to build directory
675 AutoGenFilePath
= os
.path
.join(self
.BuildDir
, 'AutoGen')
676 if os
.path
.exists (AutoGenFilePath
):
677 os
.remove(AutoGenFilePath
)
678 if not os
.path
.exists(self
.BuildDir
):
679 os
.makedirs(self
.BuildDir
)
680 with
open(os
.path
.join(self
.BuildDir
, 'AutoGen'), 'w+') as file:
681 for f
in AllWorkSpaceMetaFiles
:
685 def _GenPkgLevelHash(self
, Pkg
):
686 if Pkg
.PackageName
in GlobalData
.gPackageHash
[Pkg
.Arch
]:
689 PkgDir
= os
.path
.join(self
.BuildDir
, Pkg
.Arch
, Pkg
.PackageName
)
690 CreateDirectory(PkgDir
)
691 HashFile
= os
.path
.join(PkgDir
, Pkg
.PackageName
+ '.hash')
693 # Get .dec file's hash value
694 f
= open(Pkg
.MetaFile
.Path
, 'r')
698 # Get include files hash value
700 for inc
in sorted(Pkg
.Includes
, key
=lambda x
: str(x
)):
701 for Root
, Dirs
, Files
in os
.walk(str(inc
)):
702 for File
in sorted(Files
):
703 File_Path
= os
.path
.join(Root
, File
)
704 f
= open(File_Path
, 'r')
708 SaveFileOnChange(HashFile
, m
.hexdigest(), True)
709 GlobalData
.gPackageHash
[Pkg
.Arch
][Pkg
.PackageName
] = m
.hexdigest()
711 def _GetMetaFiles(self
, Target
, Toolchain
, Arch
):
712 AllWorkSpaceMetaFiles
= set()
717 AllWorkSpaceMetaFiles
.add (self
.FdfFile
.Path
)
718 for f
in GlobalData
.gFdfParser
.GetAllIncludedFile():
719 AllWorkSpaceMetaFiles
.add (f
.FileName
)
723 AllWorkSpaceMetaFiles
.add(self
.MetaFile
.Path
)
726 # add build_rule.txt & tools_def.txt
728 AllWorkSpaceMetaFiles
.add(os
.path
.join(GlobalData
.gConfDirectory
, gDefaultBuildRuleFile
))
729 AllWorkSpaceMetaFiles
.add(os
.path
.join(GlobalData
.gConfDirectory
, gDefaultToolsDefFile
))
731 # add BuildOption metafile
733 AllWorkSpaceMetaFiles
.add(os
.path
.join(self
.BuildDir
, 'BuildOptions'))
735 # add PcdToken Number file for Dynamic/DynamicEx Pcd
737 AllWorkSpaceMetaFiles
.add(os
.path
.join(self
.BuildDir
, 'PcdTokenNumber'))
739 for Arch
in self
.ArchList
:
743 for Package
in PlatformAutoGen(self
, self
.MetaFile
, Target
, Toolchain
, Arch
).PackageList
:
744 AllWorkSpaceMetaFiles
.add(Package
.MetaFile
.Path
)
749 for filePath
in self
.BuildDatabase
[self
.MetaFile
, Arch
, Target
, Toolchain
]._RawData
.IncludedFiles
:
750 AllWorkSpaceMetaFiles
.add(filePath
.Path
)
752 return AllWorkSpaceMetaFiles
754 def _CheckPcdDefineAndType(self
):
755 PcdTypeSet
= {TAB_PCDS_FIXED_AT_BUILD
,
756 TAB_PCDS_PATCHABLE_IN_MODULE
,
757 TAB_PCDS_FEATURE_FLAG
,
761 # This dict store PCDs which are not used by any modules with specified arches
762 UnusedPcd
= OrderedDict()
763 for Pa
in self
.AutoGenObjectList
:
764 # Key of DSC's Pcds dictionary is PcdCName, TokenSpaceGuid
765 for Pcd
in Pa
.Platform
.Pcds
:
766 PcdType
= Pa
.Platform
.Pcds
[Pcd
].Type
768 # If no PCD type, this PCD comes from FDF
772 # Try to remove Hii and Vpd suffix
773 if PcdType
.startswith(TAB_PCDS_DYNAMIC_EX
):
774 PcdType
= TAB_PCDS_DYNAMIC_EX
775 elif PcdType
.startswith(TAB_PCDS_DYNAMIC
):
776 PcdType
= TAB_PCDS_DYNAMIC
778 for Package
in Pa
.PackageList
:
779 # Key of DEC's Pcds dictionary is PcdCName, TokenSpaceGuid, PcdType
780 if (Pcd
[0], Pcd
[1], PcdType
) in Package
.Pcds
:
782 for Type
in PcdTypeSet
:
783 if (Pcd
[0], Pcd
[1], Type
) in Package
.Pcds
:
787 "Type [%s] of PCD [%s.%s] in DSC file doesn't match the type [%s] defined in DEC file." \
788 % (Pa
.Platform
.Pcds
[Pcd
].Type
, Pcd
[1], Pcd
[0], Type
),
793 UnusedPcd
.setdefault(Pcd
, []).append(Pa
.Arch
)
795 for Pcd
in UnusedPcd
:
798 "The PCD was not specified by any INF module in the platform for the given architecture.\n"
799 "\tPCD: [%s.%s]\n\tPlatform: [%s]\n\tArch: %s"
800 % (Pcd
[1], Pcd
[0], os
.path
.basename(str(self
.MetaFile
)), str(UnusedPcd
[Pcd
])),
805 return "%s [%s]" % (self
.MetaFile
, ", ".join(self
.ArchList
))
807 ## Return the directory to store FV files
810 return path
.join(self
.BuildDir
, TAB_FV_DIRECTORY
)
812 ## Return the directory to store all intermediate and final files built
815 return self
.AutoGenObjectList
[0].BuildDir
817 ## Return the build output directory platform specifies
820 return self
.Platform
.OutputDirectory
822 ## Return platform name
825 return self
.Platform
.PlatformName
827 ## Return meta-file GUID
830 return self
.Platform
.Guid
832 ## Return platform version
835 return self
.Platform
.Version
837 ## Return paths of tools
839 def ToolDefinition(self
):
840 return self
.AutoGenObjectList
[0].ToolDefinition
842 ## Return directory of platform makefile
844 # @retval string Makefile directory
847 def MakeFileDir(self
):
850 ## Return build command string
852 # @retval string Build command string
855 def BuildCommand(self
):
856 # BuildCommand should be all the same. So just get one from platform AutoGen
857 return self
.AutoGenObjectList
[0].BuildCommand
859 ## Check the PCDs token value conflict in each DEC file.
861 # Will cause build break and raise error message while two PCDs conflict.
865 def _CheckAllPcdsTokenValueConflict(self
):
866 for Pa
in self
.AutoGenObjectList
:
867 for Package
in Pa
.PackageList
:
868 PcdList
= Package
.Pcds
.values()
869 PcdList
.sort(key
=lambda x
: int(x
.TokenValue
, 0))
871 while (Count
< len(PcdList
) - 1) :
872 Item
= PcdList
[Count
]
873 ItemNext
= PcdList
[Count
+ 1]
875 # Make sure in the same token space the TokenValue should be unique
877 if (int(Item
.TokenValue
, 0) == int(ItemNext
.TokenValue
, 0)):
878 SameTokenValuePcdList
= []
879 SameTokenValuePcdList
.append(Item
)
880 SameTokenValuePcdList
.append(ItemNext
)
881 RemainPcdListLength
= len(PcdList
) - Count
- 2
882 for ValueSameCount
in range(RemainPcdListLength
):
883 if int(PcdList
[len(PcdList
) - RemainPcdListLength
+ ValueSameCount
].TokenValue
, 0) == int(Item
.TokenValue
, 0):
884 SameTokenValuePcdList
.append(PcdList
[len(PcdList
) - RemainPcdListLength
+ ValueSameCount
])
888 # Sort same token value PCD list with TokenGuid and TokenCName
890 SameTokenValuePcdList
.sort(key
=lambda x
: "%s.%s" % (x
.TokenSpaceGuidCName
, x
.TokenCName
))
891 SameTokenValuePcdListCount
= 0
892 while (SameTokenValuePcdListCount
< len(SameTokenValuePcdList
) - 1):
894 TemListItem
= SameTokenValuePcdList
[SameTokenValuePcdListCount
]
895 TemListItemNext
= SameTokenValuePcdList
[SameTokenValuePcdListCount
+ 1]
897 if (TemListItem
.TokenSpaceGuidCName
== TemListItemNext
.TokenSpaceGuidCName
) and (TemListItem
.TokenCName
!= TemListItemNext
.TokenCName
):
898 for PcdItem
in GlobalData
.MixedPcd
:
899 if (TemListItem
.TokenCName
, TemListItem
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
] or \
900 (TemListItemNext
.TokenCName
, TemListItemNext
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
906 "The TokenValue [%s] of PCD [%s.%s] is conflict with: [%s.%s] in %s"\
907 % (TemListItem
.TokenValue
, TemListItem
.TokenSpaceGuidCName
, TemListItem
.TokenCName
, TemListItemNext
.TokenSpaceGuidCName
, TemListItemNext
.TokenCName
, Package
),
910 SameTokenValuePcdListCount
+= 1
911 Count
+= SameTokenValuePcdListCount
914 PcdList
= Package
.Pcds
.values()
915 PcdList
.sort(key
=lambda x
: "%s.%s" % (x
.TokenSpaceGuidCName
, x
.TokenCName
))
917 while (Count
< len(PcdList
) - 1) :
918 Item
= PcdList
[Count
]
919 ItemNext
= PcdList
[Count
+ 1]
921 # Check PCDs with same TokenSpaceGuidCName.TokenCName have same token value as well.
923 if (Item
.TokenSpaceGuidCName
== ItemNext
.TokenSpaceGuidCName
) and (Item
.TokenCName
== ItemNext
.TokenCName
) and (int(Item
.TokenValue
, 0) != int(ItemNext
.TokenValue
, 0)):
927 "The TokenValue [%s] of PCD [%s.%s] in %s defined in two places should be same as well."\
928 % (Item
.TokenValue
, Item
.TokenSpaceGuidCName
, Item
.TokenCName
, Package
),
932 ## Generate fds command
934 def GenFdsCommand(self
):
935 return (GenMake
.TopLevelMakefile(self
)._TEMPLATE
_.Replace(GenMake
.TopLevelMakefile(self
)._TemplateDict
)).strip()
938 def GenFdsCommandDict(self
):
940 LogLevel
= EdkLogger
.GetLevel()
941 if LogLevel
== EdkLogger
.VERBOSE
:
942 FdsCommandDict
["verbose"] = True
943 elif LogLevel
<= EdkLogger
.DEBUG_9
:
944 FdsCommandDict
["debug"] = LogLevel
- 1
945 elif LogLevel
== EdkLogger
.QUIET
:
946 FdsCommandDict
["quiet"] = True
948 if GlobalData
.gEnableGenfdsMultiThread
:
949 FdsCommandDict
["GenfdsMultiThread"] = True
950 if GlobalData
.gIgnoreSource
:
951 FdsCommandDict
["IgnoreSources"] = True
953 FdsCommandDict
["OptionPcd"] = []
954 for pcd
in GlobalData
.BuildOptionPcd
:
956 pcdname
= '.'.join(pcd
[0:3])
958 pcdname
= '.'.join(pcd
[0:2])
959 if pcd
[3].startswith('{'):
960 FdsCommandDict
["OptionPcd"].append(pcdname
+ '=' + 'H' + '"' + pcd
[3] + '"')
962 FdsCommandDict
["OptionPcd"].append(pcdname
+ '=' + pcd
[3])
965 # macros passed to GenFds
967 MacroDict
.update(GlobalData
.gGlobalDefines
)
968 MacroDict
.update(GlobalData
.gCommandLineDefines
)
969 for MacroName
in MacroDict
:
970 if MacroDict
[MacroName
] != "":
971 MacroList
.append('"%s=%s"' % (MacroName
, MacroDict
[MacroName
].replace('\\', '\\\\')))
973 MacroList
.append('"%s"' % MacroName
)
974 FdsCommandDict
["macro"] = MacroList
976 FdsCommandDict
["fdf_file"] = [self
.FdfFile
]
977 FdsCommandDict
["build_target"] = self
.BuildTarget
978 FdsCommandDict
["toolchain_tag"] = self
.ToolChain
979 FdsCommandDict
["active_platform"] = str(self
)
981 FdsCommandDict
["conf_directory"] = GlobalData
.gConfDirectory
982 FdsCommandDict
["build_architecture_list"] = ','.join(self
.ArchList
)
983 FdsCommandDict
["platform_build_directory"] = self
.BuildDir
985 FdsCommandDict
["fd"] = self
.FdTargetList
986 FdsCommandDict
["fv"] = self
.FvTargetList
987 FdsCommandDict
["cap"] = self
.CapTargetList
988 return FdsCommandDict
990 ## Create makefile for the platform and modules in it
992 # @param CreateDepsMakeFile Flag indicating if the makefile for
993 # modules will be created as well
995 def CreateMakeFile(self
, CreateDepsMakeFile
=False):
996 if not CreateDepsMakeFile
:
998 for Pa
in self
.AutoGenObjectList
:
999 Pa
.CreateMakeFile(True)
1001 ## Create autogen code for platform and modules
1003 # Since there's no autogen code for platform, this method will do nothing
1004 # if CreateModuleCodeFile is set to False.
1006 # @param CreateDepsCodeFile Flag indicating if creating module's
1007 # autogen code file or not
1009 def CreateCodeFile(self
, CreateDepsCodeFile
=False):
1010 if not CreateDepsCodeFile
:
1012 for Pa
in self
.AutoGenObjectList
:
1013 Pa
.CreateCodeFile(True)
1015 ## Create AsBuilt INF file the platform
1017 def CreateAsBuiltInf(self
):
1021 ## AutoGen class for platform
1023 # PlatformAutoGen class will process the original information in platform
1024 # file in order to generate makefile for platform.
1026 class PlatformAutoGen(AutoGen
):
1027 # call super().__init__ then call the worker function with different parameter count
1028 def __init__(self
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
1029 if not hasattr(self
, "_Init"):
1030 super(PlatformAutoGen
, self
).__init
__(self
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
)
1031 self
._InitWorker
(Workspace
, MetaFile
, Target
, Toolchain
, Arch
)
1034 # Used to store all PCDs for both PEI and DXE phase, in order to generate
1035 # correct PCD database
1038 _NonDynaPcdList_
= []
1042 # The priority list while override build option
1044 PrioList
= {"0x11111" : 16, # TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE (Highest)
1045 "0x01111" : 15, # ******_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
1046 "0x10111" : 14, # TARGET_*********_ARCH_COMMANDTYPE_ATTRIBUTE
1047 "0x00111" : 13, # ******_*********_ARCH_COMMANDTYPE_ATTRIBUTE
1048 "0x11011" : 12, # TARGET_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
1049 "0x01011" : 11, # ******_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
1050 "0x10011" : 10, # TARGET_*********_****_COMMANDTYPE_ATTRIBUTE
1051 "0x00011" : 9, # ******_*********_****_COMMANDTYPE_ATTRIBUTE
1052 "0x11101" : 8, # TARGET_TOOLCHAIN_ARCH_***********_ATTRIBUTE
1053 "0x01101" : 7, # ******_TOOLCHAIN_ARCH_***********_ATTRIBUTE
1054 "0x10101" : 6, # TARGET_*********_ARCH_***********_ATTRIBUTE
1055 "0x00101" : 5, # ******_*********_ARCH_***********_ATTRIBUTE
1056 "0x11001" : 4, # TARGET_TOOLCHAIN_****_***********_ATTRIBUTE
1057 "0x01001" : 3, # ******_TOOLCHAIN_****_***********_ATTRIBUTE
1058 "0x10001" : 2, # TARGET_*********_****_***********_ATTRIBUTE
1059 "0x00001" : 1} # ******_*********_****_***********_ATTRIBUTE (Lowest)
1061 ## Initialize PlatformAutoGen
1064 # @param Workspace WorkspaceAutoGen object
1065 # @param PlatformFile Platform file (DSC file)
1066 # @param Target Build target (DEBUG, RELEASE)
1067 # @param Toolchain Name of tool chain
1068 # @param Arch arch of the platform supports
1070 def _InitWorker(self
, Workspace
, PlatformFile
, Target
, Toolchain
, Arch
):
1071 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "AutoGen platform [%s] [%s]" % (PlatformFile
, Arch
))
1072 GlobalData
.gProcessingFile
= "%s [%s, %s, %s]" % (PlatformFile
, Arch
, Toolchain
, Target
)
1074 self
.MetaFile
= PlatformFile
1075 self
.Workspace
= Workspace
1076 self
.WorkspaceDir
= Workspace
.WorkspaceDir
1077 self
.ToolChain
= Toolchain
1078 self
.BuildTarget
= Target
1080 self
.SourceDir
= PlatformFile
.SubDir
1081 self
.SourceOverrideDir
= None
1082 self
.FdTargetList
= self
.Workspace
.FdTargetList
1083 self
.FvTargetList
= self
.Workspace
.FvTargetList
1084 self
.AllPcdList
= []
1085 # get the original module/package/platform objects
1086 self
.BuildDatabase
= Workspace
.BuildDatabase
1087 self
.DscBuildDataObj
= Workspace
.Platform
1089 # flag indicating if the makefile/C-code file has been created or not
1090 self
.IsMakeFileCreated
= False
1092 self
._DynamicPcdList
= None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
1093 self
._NonDynamicPcdList
= None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
1095 self
._AsBuildInfList
= []
1096 self
._AsBuildModuleList
= []
1098 self
.VariableInfo
= None
1100 if GlobalData
.gFdfParser
is not None:
1101 self
._AsBuildInfList
= GlobalData
.gFdfParser
.Profile
.InfList
1102 for Inf
in self
._AsBuildInfList
:
1103 InfClass
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, self
.Arch
)
1104 M
= self
.BuildDatabase
[InfClass
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1105 if not M
.IsBinaryModule
:
1107 self
._AsBuildModuleList
.append(InfClass
)
1108 # get library/modules for build
1109 self
.LibraryBuildDirectoryList
= []
1110 self
.ModuleBuildDirectoryList
= []
1114 @cached_class_function
1116 return "%s [%s]" % (self
.MetaFile
, self
.Arch
)
1118 ## Create autogen code for platform and modules
1120 # Since there's no autogen code for platform, this method will do nothing
1121 # if CreateModuleCodeFile is set to False.
1123 # @param CreateModuleCodeFile Flag indicating if creating module's
1124 # autogen code file or not
1126 @cached_class_function
1127 def CreateCodeFile(self
, CreateModuleCodeFile
=False):
1128 # only module has code to be greated, so do nothing if CreateModuleCodeFile is False
1129 if not CreateModuleCodeFile
:
1132 for Ma
in self
.ModuleAutoGenList
:
1133 Ma
.CreateCodeFile(True)
1135 ## Generate Fds Command
1137 def GenFdsCommand(self
):
1138 return self
.Workspace
.GenFdsCommand
1140 ## Create makefile for the platform and modules in it
1142 # @param CreateModuleMakeFile Flag indicating if the makefile for
1143 # modules will be created as well
1145 def CreateMakeFile(self
, CreateModuleMakeFile
=False, FfsCommand
= {}):
1146 if CreateModuleMakeFile
:
1147 for Ma
in self
._MaList
:
1148 key
= (Ma
.MetaFile
.File
, self
.Arch
)
1149 if key
in FfsCommand
:
1150 Ma
.CreateMakeFile(True, FfsCommand
[key
])
1152 Ma
.CreateMakeFile(True)
1154 # no need to create makefile for the platform more than once
1155 if self
.IsMakeFileCreated
:
1158 # create library/module build dirs for platform
1159 Makefile
= GenMake
.PlatformMakefile(self
)
1160 self
.LibraryBuildDirectoryList
= Makefile
.GetLibraryBuildDirectoryList()
1161 self
.ModuleBuildDirectoryList
= Makefile
.GetModuleBuildDirectoryList()
1163 self
.IsMakeFileCreated
= True
1165 ## Deal with Shared FixedAtBuild Pcds
1167 def CollectFixedAtBuildPcds(self
):
1168 for LibAuto
in self
.LibraryAutoGenList
:
1169 FixedAtBuildPcds
= {}
1170 ShareFixedAtBuildPcdsSameValue
= {}
1171 for Module
in LibAuto
.ReferenceModules
:
1172 for Pcd
in set(Module
.FixedAtBuildPcds
+ LibAuto
.FixedAtBuildPcds
):
1173 DefaultValue
= Pcd
.DefaultValue
1174 # Cover the case: DSC component override the Pcd value and the Pcd only used in one Lib
1175 if Pcd
in Module
.LibraryPcdList
:
1176 Index
= Module
.LibraryPcdList
.index(Pcd
)
1177 DefaultValue
= Module
.LibraryPcdList
[Index
].DefaultValue
1178 key
= ".".join((Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
1179 if key
not in FixedAtBuildPcds
:
1180 ShareFixedAtBuildPcdsSameValue
[key
] = True
1181 FixedAtBuildPcds
[key
] = DefaultValue
1183 if FixedAtBuildPcds
[key
] != DefaultValue
:
1184 ShareFixedAtBuildPcdsSameValue
[key
] = False
1185 for Pcd
in LibAuto
.FixedAtBuildPcds
:
1186 key
= ".".join((Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
1187 if (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
) not in self
.NonDynamicPcdDict
:
1190 DscPcd
= self
.NonDynamicPcdDict
[(Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
)]
1191 if DscPcd
.Type
!= TAB_PCDS_FIXED_AT_BUILD
:
1193 if key
in ShareFixedAtBuildPcdsSameValue
and ShareFixedAtBuildPcdsSameValue
[key
]:
1194 LibAuto
.ConstPcd
[key
] = FixedAtBuildPcds
[key
]
1196 def CollectVariables(self
, DynamicPcdSet
):
1199 if self
.Workspace
.FdfFile
:
1200 FdDict
= self
.Workspace
.FdfProfile
.FdDict
[GlobalData
.gFdfParser
.CurrentFdName
]
1201 for FdRegion
in FdDict
.RegionList
:
1202 for item
in FdRegion
.RegionDataList
:
1203 if self
.Platform
.VpdToolGuid
.strip() and self
.Platform
.VpdToolGuid
in item
:
1204 VpdRegionSize
= FdRegion
.Size
1205 VpdRegionBase
= FdRegion
.Offset
1208 VariableInfo
= VariableMgr(self
.DscBuildDataObj
._GetDefaultStores
(), self
.DscBuildDataObj
.SkuIds
)
1209 VariableInfo
.SetVpdRegionMaxSize(VpdRegionSize
)
1210 VariableInfo
.SetVpdRegionOffset(VpdRegionBase
)
1212 for Pcd
in DynamicPcdSet
:
1213 pcdname
= ".".join((Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
1214 for SkuName
in Pcd
.SkuInfoList
:
1215 Sku
= Pcd
.SkuInfoList
[SkuName
]
1217 if SkuId
is None or SkuId
== '':
1219 if len(Sku
.VariableName
) > 0:
1220 if Sku
.VariableAttribute
and 'NV' not in Sku
.VariableAttribute
:
1222 VariableGuidStructure
= Sku
.VariableGuidValue
1223 VariableGuid
= GuidStructureStringToGuidString(VariableGuidStructure
)
1224 for StorageName
in Sku
.DefaultStoreDict
:
1225 VariableInfo
.append_variable(var_info(Index
, pcdname
, StorageName
, SkuName
, StringToArray(Sku
.VariableName
), VariableGuid
, Sku
.VariableOffset
, Sku
.VariableAttribute
, Sku
.HiiDefaultValue
, Sku
.DefaultStoreDict
[StorageName
] if Pcd
.DatumType
in TAB_PCD_NUMERIC_TYPES
else StringToArray(Sku
.DefaultStoreDict
[StorageName
]), Pcd
.DatumType
, Pcd
.CustomAttribute
['DscPosition'], Pcd
.CustomAttribute
.get('IsStru',False)))
1229 def UpdateNVStoreMaxSize(self
, OrgVpdFile
):
1230 if self
.VariableInfo
:
1231 VpdMapFilePath
= os
.path
.join(self
.BuildDir
, TAB_FV_DIRECTORY
, "%s.map" % self
.Platform
.VpdToolGuid
)
1232 PcdNvStoreDfBuffer
= [item
for item
in self
._DynamicPcdList
if item
.TokenCName
== "PcdNvStoreDefaultValueBuffer" and item
.TokenSpaceGuidCName
== "gEfiMdeModulePkgTokenSpaceGuid"]
1234 if PcdNvStoreDfBuffer
:
1235 if os
.path
.exists(VpdMapFilePath
):
1236 OrgVpdFile
.Read(VpdMapFilePath
)
1237 PcdItems
= OrgVpdFile
.GetOffset(PcdNvStoreDfBuffer
[0])
1238 NvStoreOffset
= PcdItems
.values()[0].strip() if PcdItems
else '0'
1240 EdkLogger
.error("build", FILE_READ_FAILURE
, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath
)
1242 NvStoreOffset
= int(NvStoreOffset
, 16) if NvStoreOffset
.upper().startswith("0X") else int(NvStoreOffset
)
1243 default_skuobj
= PcdNvStoreDfBuffer
[0].SkuInfoList
.get(TAB_DEFAULT
)
1244 maxsize
= self
.VariableInfo
.VpdRegionSize
- NvStoreOffset
if self
.VariableInfo
.VpdRegionSize
else len(default_skuobj
.DefaultValue
.split(","))
1245 var_data
= self
.VariableInfo
.PatchNVStoreDefaultMaxSize(maxsize
)
1247 if var_data
and default_skuobj
:
1248 default_skuobj
.DefaultValue
= var_data
1249 PcdNvStoreDfBuffer
[0].DefaultValue
= var_data
1250 PcdNvStoreDfBuffer
[0].SkuInfoList
.clear()
1251 PcdNvStoreDfBuffer
[0].SkuInfoList
[TAB_DEFAULT
] = default_skuobj
1252 PcdNvStoreDfBuffer
[0].MaxDatumSize
= str(len(default_skuobj
.DefaultValue
.split(",")))
1256 ## Collect dynamic PCDs
1258 # Gather dynamic PCDs list from each module and their settings from platform
1259 # This interface should be invoked explicitly when platform action is created.
1261 def CollectPlatformDynamicPcds(self
):
1262 for key
in self
.Platform
.Pcds
:
1263 for SinglePcd
in GlobalData
.MixedPcd
:
1264 if (self
.Platform
.Pcds
[key
].TokenCName
, self
.Platform
.Pcds
[key
].TokenSpaceGuidCName
) == SinglePcd
:
1265 for item
in GlobalData
.MixedPcd
[SinglePcd
]:
1266 Pcd_Type
= item
[0].split('_')[-1]
1267 if (Pcd_Type
== self
.Platform
.Pcds
[key
].Type
) or (Pcd_Type
== TAB_PCDS_DYNAMIC_EX
and self
.Platform
.Pcds
[key
].Type
in PCD_DYNAMIC_EX_TYPE_SET
) or \
1268 (Pcd_Type
== TAB_PCDS_DYNAMIC
and self
.Platform
.Pcds
[key
].Type
in PCD_DYNAMIC_TYPE_SET
):
1269 Value
= self
.Platform
.Pcds
[key
]
1270 Value
.TokenCName
= self
.Platform
.Pcds
[key
].TokenCName
+ '_' + Pcd_Type
1272 newkey
= (Value
.TokenCName
, key
[1])
1274 newkey
= (Value
.TokenCName
, key
[1], key
[2])
1275 del self
.Platform
.Pcds
[key
]
1276 self
.Platform
.Pcds
[newkey
] = Value
1280 # for gathering error information
1281 NoDatumTypePcdList
= set()
1283 for InfName
in self
._AsBuildInfList
:
1284 InfName
= mws
.join(self
.WorkspaceDir
, InfName
)
1285 FdfModuleList
.append(os
.path
.normpath(InfName
))
1286 for M
in self
._MaList
:
1287 # F is the Module for which M is the module autogen
1288 for PcdFromModule
in M
.ModulePcdList
+ M
.LibraryPcdList
:
1289 # make sure that the "VOID*" kind of datum has MaxDatumSize set
1290 if PcdFromModule
.DatumType
== TAB_VOID
and not PcdFromModule
.MaxDatumSize
:
1291 NoDatumTypePcdList
.add("%s.%s [%s]" % (PcdFromModule
.TokenSpaceGuidCName
, PcdFromModule
.TokenCName
, M
.MetaFile
))
1293 # Check the PCD from Binary INF or Source INF
1294 if M
.IsBinaryModule
== True:
1295 PcdFromModule
.IsFromBinaryInf
= True
1297 # Check the PCD from DSC or not
1298 PcdFromModule
.IsFromDsc
= (PcdFromModule
.TokenCName
, PcdFromModule
.TokenSpaceGuidCName
) in self
.Platform
.Pcds
1300 if PcdFromModule
.Type
in PCD_DYNAMIC_TYPE_SET
or PcdFromModule
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
1301 if M
.MetaFile
.Path
not in FdfModuleList
:
1302 # If one of the Source built modules listed in the DSC is not listed
1303 # in FDF modules, and the INF lists a PCD can only use the PcdsDynamic
1304 # access method (it is only listed in the DEC file that declares the
1305 # PCD as PcdsDynamic), then build tool will report warning message
1306 # notify the PI that they are attempting to build a module that must
1307 # be included in a flash image in order to be functional. These Dynamic
1308 # PCD will not be added into the Database unless it is used by other
1309 # modules that are included in the FDF file.
1310 if PcdFromModule
.Type
in PCD_DYNAMIC_TYPE_SET
and \
1311 PcdFromModule
.IsFromBinaryInf
== False:
1312 # Print warning message to let the developer make a determine.
1314 # If one of the Source built modules listed in the DSC is not listed in
1315 # FDF modules, and the INF lists a PCD can only use the PcdsDynamicEx
1316 # access method (it is only listed in the DEC file that declares the
1317 # PCD as PcdsDynamicEx), then DO NOT break the build; DO NOT add the
1318 # PCD to the Platform's PCD Database.
1319 if PcdFromModule
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
1322 # If a dynamic PCD used by a PEM module/PEI module & DXE module,
1323 # it should be stored in Pcd PEI database, If a dynamic only
1324 # used by DXE module, it should be stored in DXE PCD database.
1325 # The default Phase is DXE
1327 if M
.ModuleType
in SUP_MODULE_SET_PEI
:
1328 PcdFromModule
.Phase
= "PEI"
1329 if PcdFromModule
not in self
._DynaPcdList
_:
1330 self
._DynaPcdList
_.append(PcdFromModule
)
1331 elif PcdFromModule
.Phase
== 'PEI':
1332 # overwrite any the same PCD existing, if Phase is PEI
1333 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1334 self
._DynaPcdList
_[Index
] = PcdFromModule
1335 elif PcdFromModule
not in self
._NonDynaPcdList
_:
1336 self
._NonDynaPcdList
_.append(PcdFromModule
)
1337 elif PcdFromModule
in self
._NonDynaPcdList
_ and PcdFromModule
.IsFromBinaryInf
== True:
1338 Index
= self
._NonDynaPcdList
_.index(PcdFromModule
)
1339 if self
._NonDynaPcdList
_[Index
].IsFromBinaryInf
== False:
1340 #The PCD from Binary INF will override the same one from source INF
1341 self
._NonDynaPcdList
_.remove (self
._NonDynaPcdList
_[Index
])
1342 PcdFromModule
.Pending
= False
1343 self
._NonDynaPcdList
_.append (PcdFromModule
)
1344 DscModuleSet
= {os
.path
.normpath(ModuleInf
.Path
) for ModuleInf
in self
.Platform
.Modules
}
1345 # add the PCD from modules that listed in FDF but not in DSC to Database
1346 for InfName
in FdfModuleList
:
1347 if InfName
not in DscModuleSet
:
1348 InfClass
= PathClass(InfName
)
1349 M
= self
.BuildDatabase
[InfClass
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1350 # If a module INF in FDF but not in current arch's DSC module list, it must be module (either binary or source)
1351 # for different Arch. PCDs in source module for different Arch is already added before, so skip the source module here.
1352 # For binary module, if in current arch, we need to list the PCDs into database.
1353 if not M
.IsBinaryModule
:
1355 # Override the module PCD setting by platform setting
1356 ModulePcdList
= self
.ApplyPcdSetting(M
, M
.Pcds
)
1357 for PcdFromModule
in ModulePcdList
:
1358 PcdFromModule
.IsFromBinaryInf
= True
1359 PcdFromModule
.IsFromDsc
= False
1360 # Only allow the DynamicEx and Patchable PCD in AsBuild INF
1361 if PcdFromModule
.Type
not in PCD_DYNAMIC_EX_TYPE_SET
and PcdFromModule
.Type
not in TAB_PCDS_PATCHABLE_IN_MODULE
:
1362 EdkLogger
.error("build", AUTOGEN_ERROR
, "PCD setting error",
1364 ExtraData
="\n\tExisted %s PCD %s in:\n\t\t%s\n"
1365 % (PcdFromModule
.Type
, PcdFromModule
.TokenCName
, InfName
))
1366 # make sure that the "VOID*" kind of datum has MaxDatumSize set
1367 if PcdFromModule
.DatumType
== TAB_VOID
and not PcdFromModule
.MaxDatumSize
:
1368 NoDatumTypePcdList
.add("%s.%s [%s]" % (PcdFromModule
.TokenSpaceGuidCName
, PcdFromModule
.TokenCName
, InfName
))
1369 if M
.ModuleType
in SUP_MODULE_SET_PEI
:
1370 PcdFromModule
.Phase
= "PEI"
1371 if PcdFromModule
not in self
._DynaPcdList
_ and PcdFromModule
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
1372 self
._DynaPcdList
_.append(PcdFromModule
)
1373 elif PcdFromModule
not in self
._NonDynaPcdList
_ and PcdFromModule
.Type
in TAB_PCDS_PATCHABLE_IN_MODULE
:
1374 self
._NonDynaPcdList
_.append(PcdFromModule
)
1375 if PcdFromModule
in self
._DynaPcdList
_ and PcdFromModule
.Phase
== 'PEI' and PcdFromModule
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
1376 # Overwrite the phase of any the same PCD existing, if Phase is PEI.
1377 # It is to solve the case that a dynamic PCD used by a PEM module/PEI
1378 # module & DXE module at a same time.
1379 # Overwrite the type of the PCDs in source INF by the type of AsBuild
1380 # INF file as DynamicEx.
1381 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1382 self
._DynaPcdList
_[Index
].Phase
= PcdFromModule
.Phase
1383 self
._DynaPcdList
_[Index
].Type
= PcdFromModule
.Type
1384 for PcdFromModule
in self
._NonDynaPcdList
_:
1385 # If a PCD is not listed in the DSC file, but binary INF files used by
1386 # this platform all (that use this PCD) list the PCD in a [PatchPcds]
1387 # section, AND all source INF files used by this platform the build
1388 # that use the PCD list the PCD in either a [Pcds] or [PatchPcds]
1389 # section, then the tools must NOT add the PCD to the Platform's PCD
1390 # Database; the build must assign the access method for this PCD as
1391 # PcdsPatchableInModule.
1392 if PcdFromModule
not in self
._DynaPcdList
_:
1394 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1395 if PcdFromModule
.IsFromDsc
== False and \
1396 PcdFromModule
.Type
in TAB_PCDS_PATCHABLE_IN_MODULE
and \
1397 PcdFromModule
.IsFromBinaryInf
== True and \
1398 self
._DynaPcdList
_[Index
].IsFromBinaryInf
== False:
1399 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1400 self
._DynaPcdList
_.remove (self
._DynaPcdList
_[Index
])
1402 # print out error information and break the build, if error found
1403 if len(NoDatumTypePcdList
) > 0:
1404 NoDatumTypePcdListString
= "\n\t\t".join(NoDatumTypePcdList
)
1405 EdkLogger
.error("build", AUTOGEN_ERROR
, "PCD setting error",
1407 ExtraData
="\n\tPCD(s) without MaxDatumSize:\n\t\t%s\n"
1408 % NoDatumTypePcdListString
)
1409 self
._NonDynamicPcdList
= self
._NonDynaPcdList
_
1410 self
._DynamicPcdList
= self
._DynaPcdList
_
1412 # Sort dynamic PCD list to:
1413 # 1) If PCD's datum type is VOID* and value is unicode string which starts with L, the PCD item should
1414 # try to be put header of dynamicd List
1415 # 2) If PCD is HII type, the PCD item should be put after unicode type PCD
1417 # The reason of sorting is make sure the unicode string is in double-byte alignment in string table.
1419 UnicodePcdArray
= set()
1421 OtherPcdArray
= set()
1423 VpdFile
= VpdInfoFile
.VpdInfoFile()
1424 NeedProcessVpdMapFile
= False
1426 for pcd
in self
.Platform
.Pcds
:
1427 if pcd
not in self
._PlatformPcds
:
1428 self
._PlatformPcds
[pcd
] = self
.Platform
.Pcds
[pcd
]
1430 for item
in self
._PlatformPcds
:
1431 if self
._PlatformPcds
[item
].DatumType
and self
._PlatformPcds
[item
].DatumType
not in [TAB_UINT8
, TAB_UINT16
, TAB_UINT32
, TAB_UINT64
, TAB_VOID
, "BOOLEAN"]:
1432 self
._PlatformPcds
[item
].DatumType
= TAB_VOID
1434 if (self
.Workspace
.ArchList
[-1] == self
.Arch
):
1435 for Pcd
in self
._DynamicPcdList
:
1436 # just pick the a value to determine whether is unicode string type
1437 Sku
= Pcd
.SkuInfoList
.values()[0]
1438 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1440 if Pcd
.DatumType
not in [TAB_UINT8
, TAB_UINT16
, TAB_UINT32
, TAB_UINT64
, TAB_VOID
, "BOOLEAN"]:
1441 Pcd
.DatumType
= TAB_VOID
1443 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
1444 # if found HII type PCD then insert to right of UnicodeIndex
1445 if Pcd
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
]:
1446 VpdPcdDict
[(Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
)] = Pcd
1448 #Collect DynamicHii PCD values and assign it to DynamicExVpd PCD gEfiMdeModulePkgTokenSpaceGuid.PcdNvStoreDefaultValueBuffer
1449 PcdNvStoreDfBuffer
= VpdPcdDict
.get(("PcdNvStoreDefaultValueBuffer", "gEfiMdeModulePkgTokenSpaceGuid"))
1450 if PcdNvStoreDfBuffer
:
1451 self
.VariableInfo
= self
.CollectVariables(self
._DynamicPcdList
)
1452 vardump
= self
.VariableInfo
.dump()
1455 #According to PCD_DATABASE_INIT in edk2\MdeModulePkg\Include\Guid\PcdDataBaseSignatureGuid.h,
1456 #the max size for string PCD should not exceed USHRT_MAX 65535(0xffff).
1457 #typedef UINT16 SIZE_INFO;
1458 #//SIZE_INFO SizeTable[];
1459 if len(vardump
.split(",")) > 0xffff:
1460 EdkLogger
.error("build", RESOURCE_OVERFLOW
, 'The current length of PCD %s value is %d, it exceeds to the max size of String PCD.' %(".".join([PcdNvStoreDfBuffer
.TokenSpaceGuidCName
,PcdNvStoreDfBuffer
.TokenCName
]) ,len(vardump
.split(","))))
1461 PcdNvStoreDfBuffer
.DefaultValue
= vardump
1462 for skuname
in PcdNvStoreDfBuffer
.SkuInfoList
:
1463 PcdNvStoreDfBuffer
.SkuInfoList
[skuname
].DefaultValue
= vardump
1464 PcdNvStoreDfBuffer
.MaxDatumSize
= str(len(vardump
.split(",")))
1466 #If the end user define [DefaultStores] and [XXX.Menufacturing] in DSC, but forget to configure PcdNvStoreDefaultValueBuffer to PcdsDynamicVpd
1467 if [Pcd
for Pcd
in self
._DynamicPcdList
if Pcd
.UserDefinedDefaultStoresFlag
]:
1468 EdkLogger
.warn("build", "PcdNvStoreDefaultValueBuffer should be defined as PcdsDynamicExVpd in dsc file since the DefaultStores is enabled for this platform.\n%s" %self
.Platform
.MetaFile
.Path
)
1469 PlatformPcds
= sorted(self
._PlatformPcds
.keys())
1471 # Add VPD type PCD into VpdFile and determine whether the VPD PCD need to be fixed up.
1474 for PcdKey
in PlatformPcds
:
1475 Pcd
= self
._PlatformPcds
[PcdKey
]
1476 if Pcd
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
] and \
1477 PcdKey
in VpdPcdDict
:
1478 Pcd
= VpdPcdDict
[PcdKey
]
1480 DefaultSku
= Pcd
.SkuInfoList
.get(TAB_DEFAULT
)
1482 PcdValue
= DefaultSku
.DefaultValue
1483 if PcdValue
not in SkuValueMap
:
1484 SkuValueMap
[PcdValue
] = []
1485 VpdFile
.Add(Pcd
, TAB_DEFAULT
, DefaultSku
.VpdOffset
)
1486 SkuValueMap
[PcdValue
].append(DefaultSku
)
1488 for (SkuName
, Sku
) in Pcd
.SkuInfoList
.items():
1489 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1490 PcdValue
= Sku
.DefaultValue
1492 PcdValue
= Pcd
.DefaultValue
1493 if Sku
.VpdOffset
!= TAB_STAR
:
1494 if PcdValue
.startswith("{"):
1496 elif PcdValue
.startswith("L"):
1501 VpdOffset
= int(Sku
.VpdOffset
)
1504 VpdOffset
= int(Sku
.VpdOffset
, 16)
1506 EdkLogger
.error("build", FORMAT_INVALID
, "Invalid offset value %s for PCD %s.%s." % (Sku
.VpdOffset
, Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
1507 if VpdOffset
% Alignment
!= 0:
1508 if PcdValue
.startswith("{"):
1509 EdkLogger
.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
), File
=self
.MetaFile
)
1511 EdkLogger
.error("build", FORMAT_INVALID
, 'The offset value of PCD %s.%s should be %s-byte aligned.' % (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
, Alignment
))
1512 if PcdValue
not in SkuValueMap
:
1513 SkuValueMap
[PcdValue
] = []
1514 VpdFile
.Add(Pcd
, SkuName
, Sku
.VpdOffset
)
1515 SkuValueMap
[PcdValue
].append(Sku
)
1516 # if the offset of a VPD is *, then it need to be fixed up by third party tool.
1517 if not NeedProcessVpdMapFile
and Sku
.VpdOffset
== TAB_STAR
:
1518 NeedProcessVpdMapFile
= True
1519 if self
.Platform
.VpdToolGuid
is None or self
.Platform
.VpdToolGuid
== '':
1520 EdkLogger
.error("Build", FILE_NOT_FOUND
, \
1521 "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.")
1523 VpdSkuMap
[PcdKey
] = SkuValueMap
1525 # Fix the PCDs define in VPD PCD section that never referenced by module.
1526 # An example is PCD for signature usage.
1528 for DscPcd
in PlatformPcds
:
1529 DscPcdEntry
= self
._PlatformPcds
[DscPcd
]
1530 if DscPcdEntry
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
]:
1531 if not (self
.Platform
.VpdToolGuid
is None or self
.Platform
.VpdToolGuid
== ''):
1533 for VpdPcd
in VpdFile
._VpdArray
:
1534 # This PCD has been referenced by module
1535 if (VpdPcd
.TokenSpaceGuidCName
== DscPcdEntry
.TokenSpaceGuidCName
) and \
1536 (VpdPcd
.TokenCName
== DscPcdEntry
.TokenCName
):
1539 # Not found, it should be signature
1541 # just pick the a value to determine whether is unicode string type
1543 SkuObjList
= DscPcdEntry
.SkuInfoList
.items()
1544 DefaultSku
= DscPcdEntry
.SkuInfoList
.get(TAB_DEFAULT
)
1546 defaultindex
= SkuObjList
.index((TAB_DEFAULT
, DefaultSku
))
1547 SkuObjList
[0], SkuObjList
[defaultindex
] = SkuObjList
[defaultindex
], SkuObjList
[0]
1548 for (SkuName
, Sku
) in SkuObjList
:
1549 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1551 # Need to iterate DEC pcd information to get the value & datumtype
1552 for eachDec
in self
.PackageList
:
1553 for DecPcd
in eachDec
.Pcds
:
1554 DecPcdEntry
= eachDec
.Pcds
[DecPcd
]
1555 if (DecPcdEntry
.TokenSpaceGuidCName
== DscPcdEntry
.TokenSpaceGuidCName
) and \
1556 (DecPcdEntry
.TokenCName
== DscPcdEntry
.TokenCName
):
1557 # Print warning message to let the developer make a determine.
1558 EdkLogger
.warn("build", "Unreferenced vpd pcd used!",
1559 File
=self
.MetaFile
, \
1560 ExtraData
= "PCD: %s.%s used in the DSC file %s is unreferenced." \
1561 %(DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
, self
.Platform
.MetaFile
.Path
))
1563 DscPcdEntry
.DatumType
= DecPcdEntry
.DatumType
1564 DscPcdEntry
.DefaultValue
= DecPcdEntry
.DefaultValue
1565 DscPcdEntry
.TokenValue
= DecPcdEntry
.TokenValue
1566 DscPcdEntry
.TokenSpaceGuidValue
= eachDec
.Guids
[DecPcdEntry
.TokenSpaceGuidCName
]
1567 # Only fix the value while no value provided in DSC file.
1568 if not Sku
.DefaultValue
:
1569 DscPcdEntry
.SkuInfoList
[DscPcdEntry
.SkuInfoList
.keys()[0]].DefaultValue
= DecPcdEntry
.DefaultValue
1571 if DscPcdEntry
not in self
._DynamicPcdList
:
1572 self
._DynamicPcdList
.append(DscPcdEntry
)
1573 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1574 PcdValue
= Sku
.DefaultValue
1576 PcdValue
= DscPcdEntry
.DefaultValue
1577 if Sku
.VpdOffset
!= TAB_STAR
:
1578 if PcdValue
.startswith("{"):
1580 elif PcdValue
.startswith("L"):
1585 VpdOffset
= int(Sku
.VpdOffset
)
1588 VpdOffset
= int(Sku
.VpdOffset
, 16)
1590 EdkLogger
.error("build", FORMAT_INVALID
, "Invalid offset value %s for PCD %s.%s." % (Sku
.VpdOffset
, DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
))
1591 if VpdOffset
% Alignment
!= 0:
1592 if PcdValue
.startswith("{"):
1593 EdkLogger
.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
), File
=self
.MetaFile
)
1595 EdkLogger
.error("build", FORMAT_INVALID
, 'The offset value of PCD %s.%s should be %s-byte aligned.' % (DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
, Alignment
))
1596 if PcdValue
not in SkuValueMap
:
1597 SkuValueMap
[PcdValue
] = []
1598 VpdFile
.Add(DscPcdEntry
, SkuName
, Sku
.VpdOffset
)
1599 SkuValueMap
[PcdValue
].append(Sku
)
1600 if not NeedProcessVpdMapFile
and Sku
.VpdOffset
== TAB_STAR
:
1601 NeedProcessVpdMapFile
= True
1602 if DscPcdEntry
.DatumType
== TAB_VOID
and PcdValue
.startswith("L"):
1603 UnicodePcdArray
.add(DscPcdEntry
)
1604 elif len(Sku
.VariableName
) > 0:
1605 HiiPcdArray
.add(DscPcdEntry
)
1607 OtherPcdArray
.add(DscPcdEntry
)
1609 # if the offset of a VPD is *, then it need to be fixed up by third party tool.
1610 VpdSkuMap
[DscPcd
] = SkuValueMap
1611 if (self
.Platform
.FlashDefinition
is None or self
.Platform
.FlashDefinition
== '') and \
1612 VpdFile
.GetCount() != 0:
1613 EdkLogger
.error("build", ATTRIBUTE_NOT_AVAILABLE
,
1614 "Fail to get FLASH_DEFINITION definition in DSC file %s which is required when DSC contains VPD PCD." % str(self
.Platform
.MetaFile
))
1616 if VpdFile
.GetCount() != 0:
1618 self
.FixVpdOffset(VpdFile
)
1620 self
.FixVpdOffset(self
.UpdateNVStoreMaxSize(VpdFile
))
1621 PcdNvStoreDfBuffer
= [item
for item
in self
._DynamicPcdList
if item
.TokenCName
== "PcdNvStoreDefaultValueBuffer" and item
.TokenSpaceGuidCName
== "gEfiMdeModulePkgTokenSpaceGuid"]
1622 if PcdNvStoreDfBuffer
:
1623 PcdName
,PcdGuid
= PcdNvStoreDfBuffer
[0].TokenCName
, PcdNvStoreDfBuffer
[0].TokenSpaceGuidCName
1624 if (PcdName
,PcdGuid
) in VpdSkuMap
:
1625 DefaultSku
= PcdNvStoreDfBuffer
[0].SkuInfoList
.get(TAB_DEFAULT
)
1626 VpdSkuMap
[(PcdName
,PcdGuid
)] = {DefaultSku
.DefaultValue
:[DefaultSku
]}
1628 # Process VPD map file generated by third party BPDG tool
1629 if NeedProcessVpdMapFile
:
1630 VpdMapFilePath
= os
.path
.join(self
.BuildDir
, TAB_FV_DIRECTORY
, "%s.map" % self
.Platform
.VpdToolGuid
)
1631 if os
.path
.exists(VpdMapFilePath
):
1632 VpdFile
.Read(VpdMapFilePath
)
1634 # Fixup TAB_STAR offset
1635 for pcd
in VpdSkuMap
:
1636 vpdinfo
= VpdFile
.GetVpdInfo(pcd
)
1638 # just pick the a value to determine whether is unicode string type
1640 for pcdvalue
in VpdSkuMap
[pcd
]:
1641 for sku
in VpdSkuMap
[pcd
][pcdvalue
]:
1642 for item
in vpdinfo
:
1643 if item
[2] == pcdvalue
:
1644 sku
.VpdOffset
= item
[1]
1646 EdkLogger
.error("build", FILE_READ_FAILURE
, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath
)
1648 # Delete the DynamicPcdList At the last time enter into this function
1649 for Pcd
in self
._DynamicPcdList
:
1650 # just pick the a value to determine whether is unicode string type
1651 Sku
= Pcd
.SkuInfoList
.values()[0]
1652 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1654 if Pcd
.DatumType
not in [TAB_UINT8
, TAB_UINT16
, TAB_UINT32
, TAB_UINT64
, TAB_VOID
, "BOOLEAN"]:
1655 Pcd
.DatumType
= TAB_VOID
1657 PcdValue
= Sku
.DefaultValue
1658 if Pcd
.DatumType
== TAB_VOID
and PcdValue
.startswith("L"):
1659 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
1660 UnicodePcdArray
.add(Pcd
)
1661 elif len(Sku
.VariableName
) > 0:
1662 # if found HII type PCD then insert to right of UnicodeIndex
1663 HiiPcdArray
.add(Pcd
)
1665 OtherPcdArray
.add(Pcd
)
1666 del self
._DynamicPcdList
[:]
1667 self
._DynamicPcdList
.extend(list(UnicodePcdArray
))
1668 self
._DynamicPcdList
.extend(list(HiiPcdArray
))
1669 self
._DynamicPcdList
.extend(list(OtherPcdArray
))
1670 allskuset
= [(SkuName
, Sku
.SkuId
) for pcd
in self
._DynamicPcdList
for (SkuName
, Sku
) in pcd
.SkuInfoList
.items()]
1671 for pcd
in self
._DynamicPcdList
:
1672 if len(pcd
.SkuInfoList
) == 1:
1673 for (SkuName
, SkuId
) in allskuset
:
1674 if type(SkuId
) in (str, unicode) and eval(SkuId
) == 0 or SkuId
== 0:
1676 pcd
.SkuInfoList
[SkuName
] = copy
.deepcopy(pcd
.SkuInfoList
[TAB_DEFAULT
])
1677 pcd
.SkuInfoList
[SkuName
].SkuId
= SkuId
1678 pcd
.SkuInfoList
[SkuName
].SkuIdName
= SkuName
1679 self
.AllPcdList
= self
._NonDynamicPcdList
+ self
._DynamicPcdList
1681 def FixVpdOffset(self
, VpdFile
):
1682 FvPath
= os
.path
.join(self
.BuildDir
, TAB_FV_DIRECTORY
)
1683 if not os
.path
.exists(FvPath
):
1687 EdkLogger
.error("build", FILE_WRITE_FAILURE
, "Fail to create FV folder under %s" % self
.BuildDir
)
1689 VpdFilePath
= os
.path
.join(FvPath
, "%s.txt" % self
.Platform
.VpdToolGuid
)
1691 if VpdFile
.Write(VpdFilePath
):
1692 # retrieve BPDG tool's path from tool_def.txt according to VPD_TOOL_GUID defined in DSC file.
1694 for ToolDef
in self
.ToolDefinition
.values():
1695 if TAB_GUID
in ToolDef
and ToolDef
[TAB_GUID
] == self
.Platform
.VpdToolGuid
:
1696 if "PATH" not in ToolDef
:
1697 EdkLogger
.error("build", ATTRIBUTE_NOT_AVAILABLE
, "PATH attribute was not provided for BPDG guid tool %s in tools_def.txt" % self
.Platform
.VpdToolGuid
)
1698 BPDGToolName
= ToolDef
["PATH"]
1700 # Call third party GUID BPDG tool.
1701 if BPDGToolName
is not None:
1702 VpdInfoFile
.CallExtenalBPDGTool(BPDGToolName
, VpdFilePath
)
1704 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.")
1706 ## Return the platform build data object
1709 return self
.BuildDatabase
[self
.MetaFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1711 ## Return platform name
1714 return self
.Platform
.PlatformName
1716 ## Return the meta file GUID
1719 return self
.Platform
.Guid
1721 ## Return the platform version
1724 return self
.Platform
.Version
1726 ## Return the FDF file name
1729 if self
.Workspace
.FdfFile
:
1730 RetVal
= mws
.join(self
.WorkspaceDir
, self
.Workspace
.FdfFile
)
1735 ## Return the build output directory platform specifies
1737 def OutputDir(self
):
1738 return self
.Platform
.OutputDirectory
1740 ## Return the directory to store all intermediate and final files built
1743 if os
.path
.isabs(self
.OutputDir
):
1744 GlobalData
.gBuildDirectory
= RetVal
= path
.join(
1745 path
.abspath(self
.OutputDir
),
1746 self
.BuildTarget
+ "_" + self
.ToolChain
,
1749 GlobalData
.gBuildDirectory
= RetVal
= path
.join(
1752 self
.BuildTarget
+ "_" + self
.ToolChain
,
1756 ## Return directory of platform makefile
1758 # @retval string Makefile directory
1761 def MakeFileDir(self
):
1762 return path
.join(self
.BuildDir
, self
.Arch
)
1764 ## Return build command string
1766 # @retval string Build command string
1769 def BuildCommand(self
):
1771 if "MAKE" in self
.ToolDefinition
and "PATH" in self
.ToolDefinition
["MAKE"]:
1772 RetVal
+= SplitOption(self
.ToolDefinition
["MAKE"]["PATH"])
1773 if "FLAGS" in self
.ToolDefinition
["MAKE"]:
1774 NewOption
= self
.ToolDefinition
["MAKE"]["FLAGS"].strip()
1776 RetVal
+= SplitOption(NewOption
)
1777 if "MAKE" in self
.EdkIIBuildOption
:
1778 if "FLAGS" in self
.EdkIIBuildOption
["MAKE"]:
1779 Flags
= self
.EdkIIBuildOption
["MAKE"]["FLAGS"]
1780 if Flags
.startswith('='):
1781 RetVal
= [RetVal
[0]] + [Flags
[1:]]
1783 RetVal
.append(Flags
)
1786 ## Get tool chain definition
1788 # Get each tool defition for given tool chain from tools_def.txt and platform
1791 def ToolDefinition(self
):
1792 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDictionary
1793 if TAB_TOD_DEFINES_COMMAND_TYPE
not in self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
:
1794 EdkLogger
.error('build', RESOURCE_NOT_AVAILABLE
, "No tools found in configuration",
1795 ExtraData
="[%s]" % self
.MetaFile
)
1798 for Def
in ToolDefinition
:
1799 Target
, Tag
, Arch
, Tool
, Attr
= Def
.split("_")
1800 if Target
!= self
.BuildTarget
or Tag
!= self
.ToolChain
or Arch
!= self
.Arch
:
1803 Value
= ToolDefinition
[Def
]
1804 # don't record the DLL
1806 DllPathList
.add(Value
)
1809 if Tool
not in RetVal
:
1811 RetVal
[Tool
][Attr
] = Value
1814 if GlobalData
.gOptions
.SilentMode
and "MAKE" in RetVal
:
1815 if "FLAGS" not in RetVal
["MAKE"]:
1816 RetVal
["MAKE"]["FLAGS"] = ""
1817 RetVal
["MAKE"]["FLAGS"] += " -s"
1820 for Attr
in RetVal
[Tool
]:
1821 Value
= RetVal
[Tool
][Attr
]
1822 if Tool
in self
._BuildOptionWithToolDef
(RetVal
) and Attr
in self
._BuildOptionWithToolDef
(RetVal
)[Tool
]:
1823 # check if override is indicated
1824 if self
._BuildOptionWithToolDef
(RetVal
)[Tool
][Attr
].startswith('='):
1825 Value
= self
._BuildOptionWithToolDef
(RetVal
)[Tool
][Attr
][1:]
1828 Value
+= " " + self
._BuildOptionWithToolDef
(RetVal
)[Tool
][Attr
]
1830 Value
= self
._BuildOptionWithToolDef
(RetVal
)[Tool
][Attr
]
1833 # Don't put MAKE definition in the file
1835 ToolsDef
+= "%s = %s\n" % (Tool
, Value
)
1837 # Don't put MAKE definition in the file
1842 ToolsDef
+= "%s_%s = %s\n" % (Tool
, Attr
, Value
)
1845 SaveFileOnChange(self
.ToolDefinitionFile
, ToolsDef
)
1846 for DllPath
in DllPathList
:
1847 os
.environ
["PATH"] = DllPath
+ os
.pathsep
+ os
.environ
["PATH"]
1848 os
.environ
["MAKE_FLAGS"] = MakeFlags
1852 ## Return the paths of tools
1854 def ToolDefinitionFile(self
):
1855 return os
.path
.join(self
.MakeFileDir
, "TOOLS_DEF." + self
.Arch
)
1857 ## Retrieve the toolchain family of given toolchain tag. Default to 'MSFT'.
1859 def ToolChainFamily(self
):
1860 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
1861 if TAB_TOD_DEFINES_FAMILY
not in ToolDefinition \
1862 or self
.ToolChain
not in ToolDefinition
[TAB_TOD_DEFINES_FAMILY
] \
1863 or not ToolDefinition
[TAB_TOD_DEFINES_FAMILY
][self
.ToolChain
]:
1864 EdkLogger
.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
1866 RetVal
= TAB_COMPILER_MSFT
1868 RetVal
= ToolDefinition
[TAB_TOD_DEFINES_FAMILY
][self
.ToolChain
]
1872 def BuildRuleFamily(self
):
1873 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
1874 if TAB_TOD_DEFINES_BUILDRULEFAMILY
not in ToolDefinition \
1875 or self
.ToolChain
not in ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
] \
1876 or not ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
][self
.ToolChain
]:
1877 EdkLogger
.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
1879 return TAB_COMPILER_MSFT
1881 return ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
][self
.ToolChain
]
1883 ## Return the build options specific for all modules in this platform
1885 def BuildOption(self
):
1886 return self
._ExpandBuildOption
(self
.Platform
.BuildOptions
)
1888 def _BuildOptionWithToolDef(self
, ToolDef
):
1889 return self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, ToolDef
=ToolDef
)
1891 ## Return the build options specific for EDK modules in this platform
1893 def EdkBuildOption(self
):
1894 return self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, EDK_NAME
)
1896 ## Return the build options specific for EDKII modules in this platform
1898 def EdkIIBuildOption(self
):
1899 return self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, EDKII_NAME
)
1901 ## Parse build_rule.txt in Conf Directory.
1903 # @retval BuildRule object
1906 def BuildRule(self
):
1907 BuildRuleFile
= None
1908 if TAB_TAT_DEFINES_BUILD_RULE_CONF
in self
.Workspace
.TargetTxt
.TargetTxtDictionary
:
1909 BuildRuleFile
= self
.Workspace
.TargetTxt
.TargetTxtDictionary
[TAB_TAT_DEFINES_BUILD_RULE_CONF
]
1910 if not BuildRuleFile
:
1911 BuildRuleFile
= gDefaultBuildRuleFile
1912 RetVal
= BuildRule(BuildRuleFile
)
1913 if RetVal
._FileVersion
== "":
1914 RetVal
._FileVersion
= AutoGenReqBuildRuleVerNum
1916 if RetVal
._FileVersion
< AutoGenReqBuildRuleVerNum
:
1917 # If Build Rule's version is less than the version number required by the tools, halting the build.
1918 EdkLogger
.error("build", AUTOGEN_ERROR
,
1919 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])"\
1920 % (RetVal
._FileVersion
, AutoGenReqBuildRuleVerNum
))
1923 ## Summarize the packages used by modules in this platform
1925 def PackageList(self
):
1927 for La
in self
.LibraryAutoGenList
:
1928 RetVal
.update(La
.DependentPackageList
)
1929 for Ma
in self
.ModuleAutoGenList
:
1930 RetVal
.update(Ma
.DependentPackageList
)
1931 #Collect package set information from INF of FDF
1932 for ModuleFile
in self
._AsBuildModuleList
:
1933 if ModuleFile
in self
.Platform
.Modules
:
1935 ModuleData
= self
.BuildDatabase
[ModuleFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1936 RetVal
.update(ModuleData
.Packages
)
1940 def NonDynamicPcdDict(self
):
1941 return {(Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
):Pcd
for Pcd
in self
.NonDynamicPcdList
}
1943 ## Get list of non-dynamic PCDs
1945 def NonDynamicPcdList(self
):
1946 if not self
._NonDynamicPcdList
:
1947 self
.CollectPlatformDynamicPcds()
1948 return self
._NonDynamicPcdList
1950 ## Get list of dynamic PCDs
1952 def DynamicPcdList(self
):
1953 if not self
._DynamicPcdList
:
1954 self
.CollectPlatformDynamicPcds()
1955 return self
._DynamicPcdList
1957 ## Generate Token Number for all PCD
1959 def PcdTokenNumber(self
):
1960 RetVal
= OrderedDict()
1963 # Make the Dynamic and DynamicEx PCD use within different TokenNumber area.
1967 # TokenNumber 0 ~ 10
1969 # TokeNumber 11 ~ 20
1971 for Pcd
in self
.DynamicPcdList
:
1972 if Pcd
.Phase
== "PEI" and Pcd
.Type
in PCD_DYNAMIC_TYPE_SET
:
1973 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
1974 RetVal
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
1977 for Pcd
in self
.DynamicPcdList
:
1978 if Pcd
.Phase
== "PEI" and Pcd
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
1979 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
1980 RetVal
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
1983 for Pcd
in self
.DynamicPcdList
:
1984 if Pcd
.Phase
== "DXE" and Pcd
.Type
in PCD_DYNAMIC_TYPE_SET
:
1985 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
1986 RetVal
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
1989 for Pcd
in self
.DynamicPcdList
:
1990 if Pcd
.Phase
== "DXE" and Pcd
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
1991 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
1992 RetVal
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
1995 for Pcd
in self
.NonDynamicPcdList
:
1996 RetVal
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2002 for ModuleFile
in self
.Platform
.Modules
:
2011 self
.Platform
.Modules
[ModuleFile
].M
= Ma
2012 return [x
.M
for x
in self
.Platform
.Modules
.values()]
2014 ## Summarize ModuleAutoGen objects of all modules to be built for this platform
2016 def ModuleAutoGenList(self
):
2018 for Ma
in self
._MaList
:
2019 if Ma
not in RetVal
:
2023 ## Summarize ModuleAutoGen objects of all libraries to be built for this platform
2025 def LibraryAutoGenList(self
):
2027 for Ma
in self
._MaList
:
2028 for La
in Ma
.LibraryAutoGenList
:
2029 if La
not in RetVal
:
2031 if Ma
not in La
.ReferenceModules
:
2032 La
.ReferenceModules
.append(Ma
)
2035 ## Test if a module is supported by the platform
2037 # An error will be raised directly if the module or its arch is not supported
2038 # by the platform or current configuration
2040 def ValidModule(self
, Module
):
2041 return Module
in self
.Platform
.Modules
or Module
in self
.Platform
.LibraryInstances \
2042 or Module
in self
._AsBuildModuleList
2044 ## Resolve the library classes in a module to library instances
2046 # This method will not only resolve library classes but also sort the library
2047 # instances according to the dependency-ship.
2049 # @param Module The module from which the library classes will be resolved
2051 # @retval library_list List of library instances sorted
2053 def ApplyLibraryInstance(self
, Module
):
2054 # Cover the case that the binary INF file is list in the FDF file but not DSC file, return empty list directly
2055 if str(Module
) not in self
.Platform
.Modules
:
2058 return GetModuleLibInstances(Module
,
2067 ## Override PCD setting (type, value, ...)
2069 # @param ToPcd The PCD to be overrided
2070 # @param FromPcd The PCD overrideing from
2072 def _OverridePcd(self
, ToPcd
, FromPcd
, Module
="", Msg
="", Library
=""):
2074 # in case there's PCDs coming from FDF file, which have no type given.
2075 # at this point, ToPcd.Type has the type found from dependent
2078 TokenCName
= ToPcd
.TokenCName
2079 for PcdItem
in GlobalData
.MixedPcd
:
2080 if (ToPcd
.TokenCName
, ToPcd
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
2081 TokenCName
= PcdItem
[0]
2083 if FromPcd
is not None:
2084 if ToPcd
.Pending
and FromPcd
.Type
:
2085 ToPcd
.Type
= FromPcd
.Type
2086 elif ToPcd
.Type
and FromPcd
.Type\
2087 and ToPcd
.Type
!= FromPcd
.Type
and ToPcd
.Type
in FromPcd
.Type
:
2088 if ToPcd
.Type
.strip() == TAB_PCDS_DYNAMIC_EX
:
2089 ToPcd
.Type
= FromPcd
.Type
2090 elif ToPcd
.Type
and FromPcd
.Type \
2091 and ToPcd
.Type
!= FromPcd
.Type
:
2093 Module
= str(Module
) + " 's library file (" + str(Library
) + ")"
2094 EdkLogger
.error("build", OPTION_CONFLICT
, "Mismatched PCD type",
2095 ExtraData
="%s.%s is used as [%s] in module %s, but as [%s] in %s."\
2096 % (ToPcd
.TokenSpaceGuidCName
, TokenCName
,
2097 ToPcd
.Type
, Module
, FromPcd
.Type
, Msg
),
2100 if FromPcd
.MaxDatumSize
:
2101 ToPcd
.MaxDatumSize
= FromPcd
.MaxDatumSize
2102 ToPcd
.MaxSizeUserSet
= FromPcd
.MaxDatumSize
2103 if FromPcd
.DefaultValue
:
2104 ToPcd
.DefaultValue
= FromPcd
.DefaultValue
2105 if FromPcd
.TokenValue
:
2106 ToPcd
.TokenValue
= FromPcd
.TokenValue
2107 if FromPcd
.DatumType
:
2108 ToPcd
.DatumType
= FromPcd
.DatumType
2109 if FromPcd
.SkuInfoList
:
2110 ToPcd
.SkuInfoList
= FromPcd
.SkuInfoList
2111 if FromPcd
.UserDefinedDefaultStoresFlag
:
2112 ToPcd
.UserDefinedDefaultStoresFlag
= FromPcd
.UserDefinedDefaultStoresFlag
2113 # Add Flexible PCD format parse
2114 if ToPcd
.DefaultValue
:
2116 ToPcd
.DefaultValue
= ValueExpressionEx(ToPcd
.DefaultValue
, ToPcd
.DatumType
, self
.Workspace
._GuidDict
)(True)
2117 except BadExpression
as Value
:
2118 EdkLogger
.error('Parser', FORMAT_INVALID
, 'PCD [%s.%s] Value "%s", %s' %(ToPcd
.TokenSpaceGuidCName
, ToPcd
.TokenCName
, ToPcd
.DefaultValue
, Value
),
2121 # check the validation of datum
2122 IsValid
, Cause
= CheckPcdDatum(ToPcd
.DatumType
, ToPcd
.DefaultValue
)
2124 EdkLogger
.error('build', FORMAT_INVALID
, Cause
, File
=self
.MetaFile
,
2125 ExtraData
="%s.%s" % (ToPcd
.TokenSpaceGuidCName
, TokenCName
))
2126 ToPcd
.validateranges
= FromPcd
.validateranges
2127 ToPcd
.validlists
= FromPcd
.validlists
2128 ToPcd
.expressions
= FromPcd
.expressions
2129 ToPcd
.CustomAttribute
= FromPcd
.CustomAttribute
2131 if FromPcd
is not None and ToPcd
.DatumType
== TAB_VOID
and not ToPcd
.MaxDatumSize
:
2132 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "No MaxDatumSize specified for PCD %s.%s" \
2133 % (ToPcd
.TokenSpaceGuidCName
, TokenCName
))
2134 Value
= ToPcd
.DefaultValue
2136 ToPcd
.MaxDatumSize
= '1'
2137 elif Value
[0] == 'L':
2138 ToPcd
.MaxDatumSize
= str((len(Value
) - 2) * 2)
2139 elif Value
[0] == '{':
2140 ToPcd
.MaxDatumSize
= str(len(Value
.split(',')))
2142 ToPcd
.MaxDatumSize
= str(len(Value
) - 1)
2144 # apply default SKU for dynamic PCDS if specified one is not available
2145 if (ToPcd
.Type
in PCD_DYNAMIC_TYPE_SET
or ToPcd
.Type
in PCD_DYNAMIC_EX_TYPE_SET
) \
2146 and not ToPcd
.SkuInfoList
:
2147 if self
.Platform
.SkuName
in self
.Platform
.SkuIds
:
2148 SkuName
= self
.Platform
.SkuName
2150 SkuName
= TAB_DEFAULT
2151 ToPcd
.SkuInfoList
= {
2152 SkuName
: SkuInfoClass(SkuName
, self
.Platform
.SkuIds
[SkuName
][0], '', '', '', '', '', ToPcd
.DefaultValue
)
2155 ## Apply PCD setting defined platform to a module
2157 # @param Module The module from which the PCD setting will be overrided
2159 # @retval PCD_list The list PCDs with settings from platform
2161 def ApplyPcdSetting(self
, Module
, Pcds
, Library
=""):
2162 # for each PCD in module
2163 for Name
, Guid
in Pcds
:
2164 PcdInModule
= Pcds
[Name
, Guid
]
2165 # find out the PCD setting in platform
2166 if (Name
, Guid
) in self
.Platform
.Pcds
:
2167 PcdInPlatform
= self
.Platform
.Pcds
[Name
, Guid
]
2169 PcdInPlatform
= None
2170 # then override the settings if any
2171 self
._OverridePcd
(PcdInModule
, PcdInPlatform
, Module
, Msg
="DSC PCD sections", Library
=Library
)
2172 # resolve the VariableGuid value
2173 for SkuId
in PcdInModule
.SkuInfoList
:
2174 Sku
= PcdInModule
.SkuInfoList
[SkuId
]
2175 if Sku
.VariableGuid
== '': continue
2176 Sku
.VariableGuidValue
= GuidValue(Sku
.VariableGuid
, self
.PackageList
, self
.MetaFile
.Path
)
2177 if Sku
.VariableGuidValue
is None:
2178 PackageList
= "\n\t".join(str(P
) for P
in self
.PackageList
)
2181 RESOURCE_NOT_AVAILABLE
,
2182 "Value of GUID [%s] is not found in" % Sku
.VariableGuid
,
2183 ExtraData
=PackageList
+ "\n\t(used with %s.%s from module %s)" \
2184 % (Guid
, Name
, str(Module
)),
2188 # override PCD settings with module specific setting
2189 if Module
in self
.Platform
.Modules
:
2190 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
2191 for Key
in PlatformModule
.Pcds
:
2192 if GlobalData
.BuildOptionPcd
:
2193 for pcd
in GlobalData
.BuildOptionPcd
:
2194 (TokenSpaceGuidCName
, TokenCName
, FieldName
, pcdvalue
, _
) = pcd
2195 if (TokenCName
, TokenSpaceGuidCName
) == Key
and FieldName
=="":
2196 PlatformModule
.Pcds
[Key
].DefaultValue
= pcdvalue
2197 PlatformModule
.Pcds
[Key
].PcdValueFromComm
= pcdvalue
2203 elif Key
in GlobalData
.MixedPcd
:
2204 for PcdItem
in GlobalData
.MixedPcd
[Key
]:
2206 ToPcd
= Pcds
[PcdItem
]
2210 self
._OverridePcd
(ToPcd
, PlatformModule
.Pcds
[Key
], Module
, Msg
="DSC Components Module scoped PCD section", Library
=Library
)
2211 # use PCD value to calculate the MaxDatumSize when it is not specified
2212 for Name
, Guid
in Pcds
:
2213 Pcd
= Pcds
[Name
, Guid
]
2214 if Pcd
.DatumType
== TAB_VOID
and not Pcd
.MaxDatumSize
:
2215 Pcd
.MaxSizeUserSet
= None
2216 Value
= Pcd
.DefaultValue
2218 Pcd
.MaxDatumSize
= '1'
2219 elif Value
[0] == 'L':
2220 Pcd
.MaxDatumSize
= str((len(Value
) - 2) * 2)
2221 elif Value
[0] == '{':
2222 Pcd
.MaxDatumSize
= str(len(Value
.split(',')))
2224 Pcd
.MaxDatumSize
= str(len(Value
) - 1)
2225 return Pcds
.values()
2229 ## Calculate the priority value of the build option
2231 # @param Key Build option definition contain: TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
2233 # @retval Value Priority value based on the priority list.
2235 def CalculatePriorityValue(self
, Key
):
2236 Target
, ToolChain
, Arch
, CommandType
, Attr
= Key
.split('_')
2237 PriorityValue
= 0x11111
2238 if Target
== TAB_STAR
:
2239 PriorityValue
&= 0x01111
2240 if ToolChain
== TAB_STAR
:
2241 PriorityValue
&= 0x10111
2242 if Arch
== TAB_STAR
:
2243 PriorityValue
&= 0x11011
2244 if CommandType
== TAB_STAR
:
2245 PriorityValue
&= 0x11101
2246 if Attr
== TAB_STAR
:
2247 PriorityValue
&= 0x11110
2249 return self
.PrioList
["0x%0.5x" % PriorityValue
]
2252 ## Expand * in build option key
2254 # @param Options Options to be expanded
2255 # @param ToolDef Use specified ToolDef instead of full version.
2256 # This is needed during initialization to prevent
2257 # infinite recursion betweeh BuildOptions,
2258 # ToolDefinition, and this function.
2260 # @retval options Options expanded
2262 def _ExpandBuildOption(self
, Options
, ModuleStyle
=None, ToolDef
=None):
2264 ToolDef
= self
.ToolDefinition
2271 # Construct a list contain the build options which need override.
2275 # Key[0] -- tool family
2276 # Key[1] -- TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
2278 if (Key
[0] == self
.BuildRuleFamily
and
2279 (ModuleStyle
is None or len(Key
) < 3 or (len(Key
) > 2 and Key
[2] == ModuleStyle
))):
2280 Target
, ToolChain
, Arch
, CommandType
, Attr
= Key
[1].split('_')
2281 if (Target
== self
.BuildTarget
or Target
== TAB_STAR
) and\
2282 (ToolChain
== self
.ToolChain
or ToolChain
== TAB_STAR
) and\
2283 (Arch
== self
.Arch
or Arch
== TAB_STAR
) and\
2284 Options
[Key
].startswith("="):
2286 if OverrideList
.get(Key
[1]) is not None:
2287 OverrideList
.pop(Key
[1])
2288 OverrideList
[Key
[1]] = Options
[Key
]
2291 # Use the highest priority value.
2293 if (len(OverrideList
) >= 2):
2294 KeyList
= OverrideList
.keys()
2295 for Index
in range(len(KeyList
)):
2296 NowKey
= KeyList
[Index
]
2297 Target1
, ToolChain1
, Arch1
, CommandType1
, Attr1
= NowKey
.split("_")
2298 for Index1
in range(len(KeyList
) - Index
- 1):
2299 NextKey
= KeyList
[Index1
+ Index
+ 1]
2301 # Compare two Key, if one is included by another, choose the higher priority one
2303 Target2
, ToolChain2
, Arch2
, CommandType2
, Attr2
= NextKey
.split("_")
2304 if (Target1
== Target2
or Target1
== TAB_STAR
or Target2
== TAB_STAR
) and\
2305 (ToolChain1
== ToolChain2
or ToolChain1
== TAB_STAR
or ToolChain2
== TAB_STAR
) and\
2306 (Arch1
== Arch2
or Arch1
== TAB_STAR
or Arch2
== TAB_STAR
) and\
2307 (CommandType1
== CommandType2
or CommandType1
== TAB_STAR
or CommandType2
== TAB_STAR
) and\
2308 (Attr1
== Attr2
or Attr1
== TAB_STAR
or Attr2
== TAB_STAR
):
2310 if self
.CalculatePriorityValue(NowKey
) > self
.CalculatePriorityValue(NextKey
):
2311 if Options
.get((self
.BuildRuleFamily
, NextKey
)) is not None:
2312 Options
.pop((self
.BuildRuleFamily
, NextKey
))
2314 if Options
.get((self
.BuildRuleFamily
, NowKey
)) is not None:
2315 Options
.pop((self
.BuildRuleFamily
, NowKey
))
2318 if ModuleStyle
is not None and len (Key
) > 2:
2319 # Check Module style is EDK or EDKII.
2320 # Only append build option for the matched style module.
2321 if ModuleStyle
== EDK_NAME
and Key
[2] != EDK_NAME
:
2323 elif ModuleStyle
== EDKII_NAME
and Key
[2] != EDKII_NAME
:
2326 Target
, Tag
, Arch
, Tool
, Attr
= Key
[1].split("_")
2327 # if tool chain family doesn't match, skip it
2328 if Tool
in ToolDef
and Family
!= "":
2329 FamilyIsNull
= False
2330 if ToolDef
[Tool
].get(TAB_TOD_DEFINES_BUILDRULEFAMILY
, "") != "":
2331 if Family
!= ToolDef
[Tool
][TAB_TOD_DEFINES_BUILDRULEFAMILY
]:
2333 elif Family
!= ToolDef
[Tool
][TAB_TOD_DEFINES_FAMILY
]:
2336 # expand any wildcard
2337 if Target
== TAB_STAR
or Target
== self
.BuildTarget
:
2338 if Tag
== TAB_STAR
or Tag
== self
.ToolChain
:
2339 if Arch
== TAB_STAR
or Arch
== self
.Arch
:
2340 if Tool
not in BuildOptions
:
2341 BuildOptions
[Tool
] = {}
2342 if Attr
!= "FLAGS" or Attr
not in BuildOptions
[Tool
] or Options
[Key
].startswith('='):
2343 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2345 # append options for the same tool except PATH
2347 BuildOptions
[Tool
][Attr
] += " " + Options
[Key
]
2349 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2350 # Build Option Family has been checked, which need't to be checked again for family.
2351 if FamilyMatch
or FamilyIsNull
:
2355 if ModuleStyle
is not None and len (Key
) > 2:
2356 # Check Module style is EDK or EDKII.
2357 # Only append build option for the matched style module.
2358 if ModuleStyle
== EDK_NAME
and Key
[2] != EDK_NAME
:
2360 elif ModuleStyle
== EDKII_NAME
and Key
[2] != EDKII_NAME
:
2363 Target
, Tag
, Arch
, Tool
, Attr
= Key
[1].split("_")
2364 # if tool chain family doesn't match, skip it
2365 if Tool
not in ToolDef
or Family
== "":
2367 # option has been added before
2368 if Family
!= ToolDef
[Tool
][TAB_TOD_DEFINES_FAMILY
]:
2371 # expand any wildcard
2372 if Target
== TAB_STAR
or Target
== self
.BuildTarget
:
2373 if Tag
== TAB_STAR
or Tag
== self
.ToolChain
:
2374 if Arch
== TAB_STAR
or Arch
== self
.Arch
:
2375 if Tool
not in BuildOptions
:
2376 BuildOptions
[Tool
] = {}
2377 if Attr
!= "FLAGS" or Attr
not in BuildOptions
[Tool
] or Options
[Key
].startswith('='):
2378 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2380 # append options for the same tool except PATH
2382 BuildOptions
[Tool
][Attr
] += " " + Options
[Key
]
2384 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2387 ## Append build options in platform to a module
2389 # @param Module The module to which the build options will be appened
2391 # @retval options The options appended with build options in platform
2393 def ApplyBuildOption(self
, Module
):
2394 # Get the different options for the different style module
2395 PlatformOptions
= self
.EdkIIBuildOption
2396 ModuleTypeOptions
= self
.Platform
.GetBuildOptionsByModuleType(EDKII_NAME
, Module
.ModuleType
)
2397 ModuleTypeOptions
= self
._ExpandBuildOption
(ModuleTypeOptions
)
2398 ModuleOptions
= self
._ExpandBuildOption
(Module
.BuildOptions
)
2399 if Module
in self
.Platform
.Modules
:
2400 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
2401 PlatformModuleOptions
= self
._ExpandBuildOption
(PlatformModule
.BuildOptions
)
2403 PlatformModuleOptions
= {}
2405 BuildRuleOrder
= None
2406 for Options
in [self
.ToolDefinition
, ModuleOptions
, PlatformOptions
, ModuleTypeOptions
, PlatformModuleOptions
]:
2407 for Tool
in Options
:
2408 for Attr
in Options
[Tool
]:
2409 if Attr
== TAB_TOD_DEFINES_BUILDRULEORDER
:
2410 BuildRuleOrder
= Options
[Tool
][Attr
]
2412 AllTools
= set(ModuleOptions
.keys() + PlatformOptions
.keys() +
2413 PlatformModuleOptions
.keys() + ModuleTypeOptions
.keys() +
2414 self
.ToolDefinition
.keys())
2415 BuildOptions
= defaultdict(lambda: defaultdict(str))
2416 for Tool
in AllTools
:
2417 for Options
in [self
.ToolDefinition
, ModuleOptions
, PlatformOptions
, ModuleTypeOptions
, PlatformModuleOptions
]:
2418 if Tool
not in Options
:
2420 for Attr
in Options
[Tool
]:
2422 # Do not generate it in Makefile
2424 if Attr
== TAB_TOD_DEFINES_BUILDRULEORDER
:
2426 Value
= Options
[Tool
][Attr
]
2427 # check if override is indicated
2428 if Value
.startswith('='):
2429 BuildOptions
[Tool
][Attr
] = mws
.handleWsMacro(Value
[1:])
2432 BuildOptions
[Tool
][Attr
] += " " + mws
.handleWsMacro(Value
)
2434 BuildOptions
[Tool
][Attr
] = mws
.handleWsMacro(Value
)
2436 return BuildOptions
, BuildRuleOrder
2439 # extend lists contained in a dictionary with lists stored in another dictionary
2440 # if CopyToDict is not derived from DefaultDict(list) then this may raise exception
2442 def ExtendCopyDictionaryLists(CopyToDict
, CopyFromDict
):
2443 for Key
in CopyFromDict
:
2444 CopyToDict
[Key
].extend(CopyFromDict
[Key
])
2446 # Create a directory specified by a set of path elements and return the full path
2447 def _MakeDir(PathList
):
2448 RetVal
= path
.join(*PathList
)
2449 CreateDirectory(RetVal
)
2452 ## ModuleAutoGen class
2454 # This class encapsules the AutoGen behaviors for the build tools. In addition to
2455 # the generation of AutoGen.h and AutoGen.c, it will generate *.depex file according
2456 # to the [depex] section in module's inf file.
2458 class ModuleAutoGen(AutoGen
):
2459 # call super().__init__ then call the worker function with different parameter count
2460 def __init__(self
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
2461 if not hasattr(self
, "_Init"):
2462 super(ModuleAutoGen
, self
).__init
__(Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
)
2463 self
._InitWorker
(Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
)
2466 ## Cache the timestamps of metafiles of every module in a class attribute
2470 def __new__(cls
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
2471 # check if this module is employed by active platform
2472 if not PlatformAutoGen(Workspace
, args
[0], Target
, Toolchain
, Arch
).ValidModule(MetaFile
):
2473 EdkLogger
.verbose("Module [%s] for [%s] is not employed by active platform\n" \
2476 return super(ModuleAutoGen
, cls
).__new
__(cls
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
)
2478 ## Initialize ModuleAutoGen
2480 # @param Workspace EdkIIWorkspaceBuild object
2481 # @param ModuleFile The path of module file
2482 # @param Target Build target (DEBUG, RELEASE)
2483 # @param Toolchain Name of tool chain
2484 # @param Arch The arch the module supports
2485 # @param PlatformFile Platform meta-file
2487 def _InitWorker(self
, Workspace
, ModuleFile
, Target
, Toolchain
, Arch
, PlatformFile
):
2488 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "AutoGen module [%s] [%s]" % (ModuleFile
, Arch
))
2489 GlobalData
.gProcessingFile
= "%s [%s, %s, %s]" % (ModuleFile
, Arch
, Toolchain
, Target
)
2491 self
.Workspace
= Workspace
2492 self
.WorkspaceDir
= Workspace
.WorkspaceDir
2493 self
.MetaFile
= ModuleFile
2494 self
.PlatformInfo
= PlatformAutoGen(Workspace
, PlatformFile
, Target
, Toolchain
, Arch
)
2496 self
.SourceDir
= self
.MetaFile
.SubDir
2497 self
.SourceDir
= mws
.relpath(self
.SourceDir
, self
.WorkspaceDir
)
2499 self
.SourceOverrideDir
= None
2500 # use overrided path defined in DSC file
2501 if self
.MetaFile
.Key
in GlobalData
.gOverrideDir
:
2502 self
.SourceOverrideDir
= GlobalData
.gOverrideDir
[self
.MetaFile
.Key
]
2504 self
.ToolChain
= Toolchain
2505 self
.BuildTarget
= Target
2507 self
.ToolChainFamily
= self
.PlatformInfo
.ToolChainFamily
2508 self
.BuildRuleFamily
= self
.PlatformInfo
.BuildRuleFamily
2510 self
.IsCodeFileCreated
= False
2511 self
.IsAsBuiltInfCreated
= False
2512 self
.DepexGenerated
= False
2514 self
.BuildDatabase
= self
.Workspace
.BuildDatabase
2515 self
.BuildRuleOrder
= None
2518 self
._PcdComments
= OrderedListDict()
2519 self
._GuidComments
= OrderedListDict()
2520 self
._ProtocolComments
= OrderedListDict()
2521 self
._PpiComments
= OrderedListDict()
2522 self
._BuildTargets
= None
2523 self
._IntroBuildTargetList
= None
2524 self
._FinalBuildTargetList
= None
2525 self
._FileTypes
= None
2527 self
.AutoGenDepSet
= set()
2528 self
.ReferenceModules
= []
2533 return "%s [%s]" % (self
.MetaFile
, self
.Arch
)
2535 # Get FixedAtBuild Pcds of this Module
2537 def FixedAtBuildPcds(self
):
2539 for Pcd
in self
.ModulePcdList
:
2540 if Pcd
.Type
!= TAB_PCDS_FIXED_AT_BUILD
:
2542 if Pcd
not in RetVal
:
2547 def FixedVoidTypePcds(self
):
2549 for Pcd
in self
.FixedAtBuildPcds
:
2550 if Pcd
.DatumType
== TAB_VOID
:
2551 if '{}.{}'.format(Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) not in RetVal
:
2552 RetVal
['{}.{}'.format(Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
)] = Pcd
.DefaultValue
2556 def UniqueBaseName(self
):
2557 BaseName
= self
.Name
2558 for Module
in self
.PlatformInfo
.ModuleAutoGenList
:
2559 if Module
.MetaFile
== self
.MetaFile
:
2561 if Module
.Name
== self
.Name
:
2562 if uuid
.UUID(Module
.Guid
) == uuid
.UUID(self
.Guid
):
2563 EdkLogger
.error("build", FILE_DUPLICATED
, 'Modules have same BaseName and FILE_GUID:\n'
2564 ' %s\n %s' % (Module
.MetaFile
, self
.MetaFile
))
2565 BaseName
= '%s_%s' % (self
.Name
, self
.Guid
)
2568 # Macros could be used in build_rule.txt (also Makefile)
2571 return OrderedDict((
2572 ("WORKSPACE" ,self
.WorkspaceDir
),
2573 ("MODULE_NAME" ,self
.Name
),
2574 ("MODULE_NAME_GUID" ,self
.UniqueBaseName
),
2575 ("MODULE_GUID" ,self
.Guid
),
2576 ("MODULE_VERSION" ,self
.Version
),
2577 ("MODULE_TYPE" ,self
.ModuleType
),
2578 ("MODULE_FILE" ,str(self
.MetaFile
)),
2579 ("MODULE_FILE_BASE_NAME" ,self
.MetaFile
.BaseName
),
2580 ("MODULE_RELATIVE_DIR" ,self
.SourceDir
),
2581 ("MODULE_DIR" ,self
.SourceDir
),
2582 ("BASE_NAME" ,self
.Name
),
2583 ("ARCH" ,self
.Arch
),
2584 ("TOOLCHAIN" ,self
.ToolChain
),
2585 ("TOOLCHAIN_TAG" ,self
.ToolChain
),
2586 ("TOOL_CHAIN_TAG" ,self
.ToolChain
),
2587 ("TARGET" ,self
.BuildTarget
),
2588 ("BUILD_DIR" ,self
.PlatformInfo
.BuildDir
),
2589 ("BIN_DIR" ,os
.path
.join(self
.PlatformInfo
.BuildDir
, self
.Arch
)),
2590 ("LIB_DIR" ,os
.path
.join(self
.PlatformInfo
.BuildDir
, self
.Arch
)),
2591 ("MODULE_BUILD_DIR" ,self
.BuildDir
),
2592 ("OUTPUT_DIR" ,self
.OutputDir
),
2593 ("DEBUG_DIR" ,self
.DebugDir
),
2594 ("DEST_DIR_OUTPUT" ,self
.OutputDir
),
2595 ("DEST_DIR_DEBUG" ,self
.DebugDir
),
2596 ("PLATFORM_NAME" ,self
.PlatformInfo
.Name
),
2597 ("PLATFORM_GUID" ,self
.PlatformInfo
.Guid
),
2598 ("PLATFORM_VERSION" ,self
.PlatformInfo
.Version
),
2599 ("PLATFORM_RELATIVE_DIR" ,self
.PlatformInfo
.SourceDir
),
2600 ("PLATFORM_DIR" ,mws
.join(self
.WorkspaceDir
, self
.PlatformInfo
.SourceDir
)),
2601 ("PLATFORM_OUTPUT_DIR" ,self
.PlatformInfo
.OutputDir
),
2602 ("FFS_OUTPUT_DIR" ,self
.FfsOutputDir
)
2605 ## Return the module build data object
2608 return self
.BuildDatabase
[self
.MetaFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
2610 ## Return the module name
2613 return self
.Module
.BaseName
2615 ## Return the module DxsFile if exist
2618 return self
.Module
.DxsFile
2620 ## Return the module meta-file GUID
2624 # To build same module more than once, the module path with FILE_GUID overridden has
2625 # the file name FILE_GUIDmodule.inf, but the relative path (self.MetaFile.File) is the realy path
2626 # in DSC. The overridden GUID can be retrieved from file name
2628 if os
.path
.basename(self
.MetaFile
.File
) != os
.path
.basename(self
.MetaFile
.Path
):
2630 # Length of GUID is 36
2632 return os
.path
.basename(self
.MetaFile
.Path
)[:36]
2633 return self
.Module
.Guid
2635 ## Return the module version
2638 return self
.Module
.Version
2640 ## Return the module type
2642 def ModuleType(self
):
2643 return self
.Module
.ModuleType
2645 ## Return the component type (for Edk.x style of module)
2647 def ComponentType(self
):
2648 return self
.Module
.ComponentType
2650 ## Return the build type
2652 def BuildType(self
):
2653 return self
.Module
.BuildType
2655 ## Return the PCD_IS_DRIVER setting
2657 def PcdIsDriver(self
):
2658 return self
.Module
.PcdIsDriver
2660 ## Return the autogen version, i.e. module meta-file version
2662 def AutoGenVersion(self
):
2663 return self
.Module
.AutoGenVersion
2665 ## Check if the module is library or not
2667 def IsLibrary(self
):
2668 return bool(self
.Module
.LibraryClass
)
2670 ## Check if the module is binary module or not
2672 def IsBinaryModule(self
):
2673 return self
.Module
.IsBinaryModule
2675 ## Return the directory to store intermediate files of the module
2679 self
.PlatformInfo
.BuildDir
,
2682 self
.MetaFile
.BaseName
2685 ## Return the directory to store the intermediate object files of the mdoule
2687 def OutputDir(self
):
2688 return _MakeDir((self
.BuildDir
, "OUTPUT"))
2690 ## Return the directory path to store ffs file
2692 def FfsOutputDir(self
):
2693 if GlobalData
.gFdfParser
:
2694 return path
.join(self
.PlatformInfo
.BuildDir
, TAB_FV_DIRECTORY
, "Ffs", self
.Guid
+ self
.Name
)
2697 ## Return the directory to store auto-gened source files of the mdoule
2700 return _MakeDir((self
.BuildDir
, "DEBUG"))
2702 ## Return the path of custom file
2704 def CustomMakefile(self
):
2706 for Type
in self
.Module
.CustomMakefile
:
2707 MakeType
= gMakeTypeMap
[Type
] if Type
in gMakeTypeMap
else 'nmake'
2708 if self
.SourceOverrideDir
is not None:
2709 File
= os
.path
.join(self
.SourceOverrideDir
, self
.Module
.CustomMakefile
[Type
])
2710 if not os
.path
.exists(File
):
2711 File
= os
.path
.join(self
.SourceDir
, self
.Module
.CustomMakefile
[Type
])
2713 File
= os
.path
.join(self
.SourceDir
, self
.Module
.CustomMakefile
[Type
])
2714 RetVal
[MakeType
] = File
2717 ## Return the directory of the makefile
2719 # @retval string The directory string of module's makefile
2722 def MakeFileDir(self
):
2723 return self
.BuildDir
2725 ## Return build command string
2727 # @retval string Build command string
2730 def BuildCommand(self
):
2731 return self
.PlatformInfo
.BuildCommand
2733 ## Get object list of all packages the module and its dependent libraries belong to
2735 # @retval list The list of package object
2738 def DerivedPackageList(self
):
2740 for M
in [self
.Module
] + self
.DependentLibraryList
:
2741 for Package
in M
.Packages
:
2742 if Package
in PackageList
:
2744 PackageList
.append(Package
)
2747 ## Get the depex string
2749 # @return : a string contain all depex expresion.
2750 def _GetDepexExpresionString(self
):
2753 ## DPX_SOURCE IN Define section.
2754 if self
.Module
.DxsFile
:
2756 for M
in [self
.Module
] + self
.DependentLibraryList
:
2757 Filename
= M
.MetaFile
.Path
2758 InfObj
= InfSectionParser
.InfSectionParser(Filename
)
2759 DepexExpresionList
= InfObj
.GetDepexExpresionList()
2760 for DepexExpresion
in DepexExpresionList
:
2761 for key
in DepexExpresion
:
2762 Arch
, ModuleType
= key
2763 DepexExpr
= [x
for x
in DepexExpresion
[key
] if not str(x
).startswith('#')]
2764 # the type of build module is USER_DEFINED.
2765 # All different DEPEX section tags would be copied into the As Built INF file
2766 # and there would be separate DEPEX section tags
2767 if self
.ModuleType
.upper() == SUP_MODULE_USER_DEFINED
:
2768 if (Arch
.upper() == self
.Arch
.upper()) and (ModuleType
.upper() != TAB_ARCH_COMMON
):
2769 DepexList
.append({(Arch
, ModuleType
): DepexExpr
})
2771 if Arch
.upper() == TAB_ARCH_COMMON
or \
2772 (Arch
.upper() == self
.Arch
.upper() and \
2773 ModuleType
.upper() in [TAB_ARCH_COMMON
, self
.ModuleType
.upper()]):
2774 DepexList
.append({(Arch
, ModuleType
): DepexExpr
})
2776 #the type of build module is USER_DEFINED.
2777 if self
.ModuleType
.upper() == SUP_MODULE_USER_DEFINED
:
2778 for Depex
in DepexList
:
2780 DepexStr
+= '[Depex.%s.%s]\n' % key
2781 DepexStr
+= '\n'.join('# '+ val
for val
in Depex
[key
])
2784 return '[Depex.%s]\n' % self
.Arch
2787 #the type of build module not is USER_DEFINED.
2789 for Depex
in DepexList
:
2794 for D
in Depex
.values():
2795 DepexStr
+= ' '.join(val
for val
in D
)
2796 Index
= DepexStr
.find('END')
2797 if Index
> -1 and Index
== len(DepexStr
) - 3:
2798 DepexStr
= DepexStr
[:-3]
2799 DepexStr
= DepexStr
.strip()
2802 DepexStr
= DepexStr
.lstrip('(').rstrip(')').strip()
2804 return '[Depex.%s]\n' % self
.Arch
2805 return '[Depex.%s]\n# ' % self
.Arch
+ DepexStr
2807 ## Merge dependency expression
2809 # @retval list The token list of the dependency expression after parsed
2812 def DepexList(self
):
2813 if self
.DxsFile
or self
.IsLibrary
or TAB_DEPENDENCY_EXPRESSION_FILE
in self
.FileTypes
:
2818 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
2820 for M
in [self
.Module
] + self
.DependentLibraryList
:
2822 for D
in M
.Depex
[self
.Arch
, self
.ModuleType
]:
2824 DepexList
.append('AND')
2825 DepexList
.append('(')
2826 #replace D with value if D is FixedAtBuild PCD
2830 NewList
.append(item
)
2832 if item
not in self
.FixedVoidTypePcds
:
2833 EdkLogger
.error("build", FORMAT_INVALID
, "{} used in [Depex] section should be used as FixedAtBuild type and VOID* datum type in the module.".format(item
))
2835 Value
= self
.FixedVoidTypePcds
[item
]
2836 if len(Value
.split(',')) != 16:
2837 EdkLogger
.error("build", FORMAT_INVALID
,
2838 "{} used in [Depex] section should be used as FixedAtBuild type and VOID* datum type and 16 bytes in the module.".format(item
))
2839 NewList
.append(Value
)
2840 DepexList
.extend(NewList
)
2841 if DepexList
[-1] == 'END': # no need of a END at this time
2843 DepexList
.append(')')
2846 EdkLogger
.verbose("DEPEX[%s] (+%s) = %s" % (self
.Name
, M
.BaseName
, DepexList
))
2847 if 'BEFORE' in DepexList
or 'AFTER' in DepexList
:
2849 if len(DepexList
) > 0:
2850 EdkLogger
.verbose('')
2851 return {self
.ModuleType
:DepexList
}
2853 ## Merge dependency expression
2855 # @retval list The token list of the dependency expression after parsed
2858 def DepexExpressionDict(self
):
2859 if self
.DxsFile
or self
.IsLibrary
or TAB_DEPENDENCY_EXPRESSION_FILE
in self
.FileTypes
:
2862 DepexExpressionString
= ''
2864 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
2866 for M
in [self
.Module
] + self
.DependentLibraryList
:
2868 for D
in M
.DepexExpression
[self
.Arch
, self
.ModuleType
]:
2869 if DepexExpressionString
!= '':
2870 DepexExpressionString
+= ' AND '
2871 DepexExpressionString
+= '('
2872 DepexExpressionString
+= D
2873 DepexExpressionString
= DepexExpressionString
.rstrip('END').strip()
2874 DepexExpressionString
+= ')'
2877 EdkLogger
.verbose("DEPEX[%s] (+%s) = %s" % (self
.Name
, M
.BaseName
, DepexExpressionString
))
2878 if 'BEFORE' in DepexExpressionString
or 'AFTER' in DepexExpressionString
:
2880 if len(DepexExpressionString
) > 0:
2881 EdkLogger
.verbose('')
2883 return {self
.ModuleType
:DepexExpressionString
}
2885 # Get the tiano core user extension, it is contain dependent library.
2886 # @retval: a list contain tiano core userextension.
2888 def _GetTianoCoreUserExtensionList(self
):
2889 TianoCoreUserExtentionList
= []
2890 for M
in [self
.Module
] + self
.DependentLibraryList
:
2891 Filename
= M
.MetaFile
.Path
2892 InfObj
= InfSectionParser
.InfSectionParser(Filename
)
2893 TianoCoreUserExtenList
= InfObj
.GetUserExtensionTianoCore()
2894 for TianoCoreUserExtent
in TianoCoreUserExtenList
:
2895 for Section
in TianoCoreUserExtent
:
2896 ItemList
= Section
.split(TAB_SPLIT
)
2898 if len(ItemList
) == 4:
2900 if Arch
.upper() == TAB_ARCH_COMMON
or Arch
.upper() == self
.Arch
.upper():
2902 TianoCoreList
.extend([TAB_SECTION_START
+ Section
+ TAB_SECTION_END
])
2903 TianoCoreList
.extend(TianoCoreUserExtent
[Section
][:])
2904 TianoCoreList
.append('\n')
2905 TianoCoreUserExtentionList
.append(TianoCoreList
)
2907 return TianoCoreUserExtentionList
2909 ## Return the list of specification version required for the module
2911 # @retval list The list of specification defined in module file
2914 def Specification(self
):
2915 return self
.Module
.Specification
2917 ## Tool option for the module build
2919 # @param PlatformInfo The object of PlatformBuildInfo
2920 # @retval dict The dict containing valid options
2923 def BuildOption(self
):
2924 RetVal
, self
.BuildRuleOrder
= self
.PlatformInfo
.ApplyBuildOption(self
.Module
)
2925 if self
.BuildRuleOrder
:
2926 self
.BuildRuleOrder
= ['.%s' % Ext
for Ext
in self
.BuildRuleOrder
.split()]
2929 ## Get include path list from tool option for the module build
2931 # @retval list The include path list
2934 def BuildOptionIncPathList(self
):
2936 # Regular expression for finding Include Directories, the difference between MSFT and INTEL/GCC/RVCT
2937 # is the former use /I , the Latter used -I to specify include directories
2939 if self
.PlatformInfo
.ToolChainFamily
in (TAB_COMPILER_MSFT
):
2940 BuildOptIncludeRegEx
= gBuildOptIncludePatternMsft
2941 elif self
.PlatformInfo
.ToolChainFamily
in ('INTEL', 'GCC', 'RVCT'):
2942 BuildOptIncludeRegEx
= gBuildOptIncludePatternOther
2945 # New ToolChainFamily, don't known whether there is option to specify include directories
2950 for Tool
in ('CC', 'PP', 'VFRPP', 'ASLPP', 'ASLCC', 'APP', 'ASM'):
2952 FlagOption
= self
.BuildOption
[Tool
]['FLAGS']
2956 if self
.ToolChainFamily
!= 'RVCT':
2957 IncPathList
= [NormPath(Path
, self
.Macros
) for Path
in BuildOptIncludeRegEx
.findall(FlagOption
)]
2960 # RVCT may specify a list of directory seperated by commas
2963 for Path
in BuildOptIncludeRegEx
.findall(FlagOption
):
2964 PathList
= GetSplitList(Path
, TAB_COMMA_SPLIT
)
2965 IncPathList
.extend(NormPath(PathEntry
, self
.Macros
) for PathEntry
in PathList
)
2968 # EDK II modules must not reference header files outside of the packages they depend on or
2969 # within the module's directory tree. Report error if violation.
2971 for Path
in IncPathList
:
2972 if (Path
not in self
.IncludePathList
) and (CommonPath([Path
, self
.MetaFile
.Dir
]) != self
.MetaFile
.Dir
):
2973 ErrMsg
= "The include directory for the EDK II module in this line is invalid %s specified in %s FLAGS '%s'" % (Path
, Tool
, FlagOption
)
2974 EdkLogger
.error("build",
2977 File
=str(self
.MetaFile
))
2978 RetVal
+= IncPathList
2981 ## Return a list of files which can be built from source
2983 # What kind of files can be built is determined by build rules in
2984 # $(CONF_DIRECTORY)/build_rule.txt and toolchain family.
2987 def SourceFileList(self
):
2989 ToolChainTagSet
= {"", TAB_STAR
, self
.ToolChain
}
2990 ToolChainFamilySet
= {"", TAB_STAR
, self
.ToolChainFamily
, self
.BuildRuleFamily
}
2991 for F
in self
.Module
.Sources
:
2993 if F
.TagName
not in ToolChainTagSet
:
2994 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "The toolchain [%s] for processing file [%s] is found, "
2995 "but [%s] is currently used" % (F
.TagName
, str(F
), self
.ToolChain
))
2997 # match tool chain family or build rule family
2998 if F
.ToolChainFamily
not in ToolChainFamilySet
:
3001 "The file [%s] must be built by tools of [%s], " \
3002 "but current toolchain family is [%s], buildrule family is [%s]" \
3003 % (str(F
), F
.ToolChainFamily
, self
.ToolChainFamily
, self
.BuildRuleFamily
))
3006 # add the file path into search path list for file including
3007 if F
.Dir
not in self
.IncludePathList
:
3008 self
.IncludePathList
.insert(0, F
.Dir
)
3011 self
._MatchBuildRuleOrder
(RetVal
)
3014 self
._ApplyBuildRule
(F
, TAB_UNKNOWN_FILE
)
3017 def _MatchBuildRuleOrder(self
, FileList
):
3020 for SingleFile
in FileList
:
3021 if self
.BuildRuleOrder
and SingleFile
.Ext
in self
.BuildRuleOrder
and SingleFile
.Ext
in self
.BuildRules
:
3022 key
= SingleFile
.Path
.rsplit(SingleFile
.Ext
,1)[0]
3023 if key
in Order_Dict
:
3024 Order_Dict
[key
].append(SingleFile
.Ext
)
3026 Order_Dict
[key
] = [SingleFile
.Ext
]
3029 for F
in Order_Dict
:
3030 if len(Order_Dict
[F
]) > 1:
3031 Order_Dict
[F
].sort(key
=lambda i
: self
.BuildRuleOrder
.index(i
))
3032 for Ext
in Order_Dict
[F
][1:]:
3033 RemoveList
.append(F
+ Ext
)
3035 for item
in RemoveList
:
3036 FileList
.remove(item
)
3040 ## Return the list of unicode files
3042 def UnicodeFileList(self
):
3043 return self
.FileTypes
.get(TAB_UNICODE_FILE
,[])
3045 ## Return the list of vfr files
3047 def VfrFileList(self
):
3048 return self
.FileTypes
.get(TAB_VFR_FILE
, [])
3050 ## Return the list of Image Definition files
3052 def IdfFileList(self
):
3053 return self
.FileTypes
.get(TAB_IMAGE_FILE
,[])
3055 ## Return a list of files which can be built from binary
3057 # "Build" binary files are just to copy them to build directory.
3059 # @retval list The list of files which can be built later
3062 def BinaryFileList(self
):
3064 for F
in self
.Module
.Binaries
:
3065 if F
.Target
not in [TAB_ARCH_COMMON
, TAB_STAR
] and F
.Target
!= self
.BuildTarget
:
3068 self
._ApplyBuildRule
(F
, F
.Type
, BinaryFileList
=RetVal
)
3072 def BuildRules(self
):
3074 BuildRuleDatabase
= self
.PlatformInfo
.BuildRule
3075 for Type
in BuildRuleDatabase
.FileTypeList
:
3076 #first try getting build rule by BuildRuleFamily
3077 RuleObject
= BuildRuleDatabase
[Type
, self
.BuildType
, self
.Arch
, self
.BuildRuleFamily
]
3079 # build type is always module type, but ...
3080 if self
.ModuleType
!= self
.BuildType
:
3081 RuleObject
= BuildRuleDatabase
[Type
, self
.ModuleType
, self
.Arch
, self
.BuildRuleFamily
]
3082 #second try getting build rule by ToolChainFamily
3084 RuleObject
= BuildRuleDatabase
[Type
, self
.BuildType
, self
.Arch
, self
.ToolChainFamily
]
3086 # build type is always module type, but ...
3087 if self
.ModuleType
!= self
.BuildType
:
3088 RuleObject
= BuildRuleDatabase
[Type
, self
.ModuleType
, self
.Arch
, self
.ToolChainFamily
]
3091 RuleObject
= RuleObject
.Instantiate(self
.Macros
)
3092 RetVal
[Type
] = RuleObject
3093 for Ext
in RuleObject
.SourceFileExtList
:
3094 RetVal
[Ext
] = RuleObject
3097 def _ApplyBuildRule(self
, File
, FileType
, BinaryFileList
=None):
3098 if self
._BuildTargets
is None:
3099 self
._IntroBuildTargetList
= set()
3100 self
._FinalBuildTargetList
= set()
3101 self
._BuildTargets
= defaultdict(set)
3102 self
._FileTypes
= defaultdict(set)
3104 if not BinaryFileList
:
3105 BinaryFileList
= self
.BinaryFileList
3107 SubDirectory
= os
.path
.join(self
.OutputDir
, File
.SubDir
)
3108 if not os
.path
.exists(SubDirectory
):
3109 CreateDirectory(SubDirectory
)
3115 # Make sure to get build rule order value
3119 while Index
< len(SourceList
):
3120 Source
= SourceList
[Index
]
3124 CreateDirectory(Source
.Dir
)
3126 if File
.IsBinary
and File
== Source
and File
in BinaryFileList
:
3127 # Skip all files that are not binary libraries
3128 if not self
.IsLibrary
:
3130 RuleObject
= self
.BuildRules
[TAB_DEFAULT_BINARY_FILE
]
3131 elif FileType
in self
.BuildRules
:
3132 RuleObject
= self
.BuildRules
[FileType
]
3133 elif Source
.Ext
in self
.BuildRules
:
3134 RuleObject
= self
.BuildRules
[Source
.Ext
]
3136 # stop at no more rules
3138 self
._FinalBuildTargetList
.add(LastTarget
)
3141 FileType
= RuleObject
.SourceFileType
3142 self
._FileTypes
[FileType
].add(Source
)
3144 # stop at STATIC_LIBRARY for library
3145 if self
.IsLibrary
and FileType
== TAB_STATIC_LIBRARY
:
3147 self
._FinalBuildTargetList
.add(LastTarget
)
3150 Target
= RuleObject
.Apply(Source
, self
.BuildRuleOrder
)
3153 self
._FinalBuildTargetList
.add(LastTarget
)
3155 elif not Target
.Outputs
:
3156 # Only do build for target with outputs
3157 self
._FinalBuildTargetList
.add(Target
)
3159 self
._BuildTargets
[FileType
].add(Target
)
3161 if not Source
.IsBinary
and Source
== File
:
3162 self
._IntroBuildTargetList
.add(Target
)
3164 # to avoid cyclic rule
3165 if FileType
in RuleChain
:
3168 RuleChain
.add(FileType
)
3169 SourceList
.extend(Target
.Outputs
)
3171 FileType
= TAB_UNKNOWN_FILE
3175 if self
._BuildTargets
is None:
3176 self
._IntroBuildTargetList
= set()
3177 self
._FinalBuildTargetList
= set()
3178 self
._BuildTargets
= defaultdict(set)
3179 self
._FileTypes
= defaultdict(set)
3181 #TRICK: call SourceFileList property to apply build rule for source files
3184 #TRICK: call _GetBinaryFileList to apply build rule for binary files
3187 return self
._BuildTargets
3190 def IntroTargetList(self
):
3192 return self
._IntroBuildTargetList
3195 def CodaTargetList(self
):
3197 return self
._FinalBuildTargetList
3200 def FileTypes(self
):
3202 return self
._FileTypes
3204 ## Get the list of package object the module depends on
3206 # @retval list The package object list
3209 def DependentPackageList(self
):
3210 return self
.Module
.Packages
3212 ## Return the list of auto-generated code file
3214 # @retval list The list of auto-generated file
3217 def AutoGenFileList(self
):
3218 AutoGenUniIdf
= self
.BuildType
!= 'UEFI_HII'
3219 UniStringBinBuffer
= BytesIO()
3220 IdfGenBinBuffer
= BytesIO()
3222 AutoGenC
= TemplateString()
3223 AutoGenH
= TemplateString()
3224 StringH
= TemplateString()
3225 StringIdf
= TemplateString()
3226 GenC
.CreateCode(self
, AutoGenC
, AutoGenH
, StringH
, AutoGenUniIdf
, UniStringBinBuffer
, StringIdf
, AutoGenUniIdf
, IdfGenBinBuffer
)
3228 # AutoGen.c is generated if there are library classes in inf, or there are object files
3230 if str(AutoGenC
) != "" and (len(self
.Module
.LibraryClasses
) > 0
3231 or TAB_OBJECT_FILE
in self
.FileTypes
):
3232 AutoFile
= PathClass(gAutoGenCodeFileName
, self
.DebugDir
)
3233 RetVal
[AutoFile
] = str(AutoGenC
)
3234 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3235 if str(AutoGenH
) != "":
3236 AutoFile
= PathClass(gAutoGenHeaderFileName
, self
.DebugDir
)
3237 RetVal
[AutoFile
] = str(AutoGenH
)
3238 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3239 if str(StringH
) != "":
3240 AutoFile
= PathClass(gAutoGenStringFileName
% {"module_name":self
.Name
}, self
.DebugDir
)
3241 RetVal
[AutoFile
] = str(StringH
)
3242 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3243 if UniStringBinBuffer
is not None and UniStringBinBuffer
.getvalue() != "":
3244 AutoFile
= PathClass(gAutoGenStringFormFileName
% {"module_name":self
.Name
}, self
.OutputDir
)
3245 RetVal
[AutoFile
] = UniStringBinBuffer
.getvalue()
3246 AutoFile
.IsBinary
= True
3247 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3248 if UniStringBinBuffer
is not None:
3249 UniStringBinBuffer
.close()
3250 if str(StringIdf
) != "":
3251 AutoFile
= PathClass(gAutoGenImageDefFileName
% {"module_name":self
.Name
}, self
.DebugDir
)
3252 RetVal
[AutoFile
] = str(StringIdf
)
3253 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3254 if IdfGenBinBuffer
is not None and IdfGenBinBuffer
.getvalue() != "":
3255 AutoFile
= PathClass(gAutoGenIdfFileName
% {"module_name":self
.Name
}, self
.OutputDir
)
3256 RetVal
[AutoFile
] = IdfGenBinBuffer
.getvalue()
3257 AutoFile
.IsBinary
= True
3258 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3259 if IdfGenBinBuffer
is not None:
3260 IdfGenBinBuffer
.close()
3263 ## Return the list of library modules explicitly or implicityly used by this module
3265 def DependentLibraryList(self
):
3266 # only merge library classes and PCD for non-library module
3269 return self
.PlatformInfo
.ApplyLibraryInstance(self
.Module
)
3271 ## Get the list of PCDs from current module
3273 # @retval list The list of PCD
3276 def ModulePcdList(self
):
3277 # apply PCD settings from platform
3278 RetVal
= self
.PlatformInfo
.ApplyPcdSetting(self
.Module
, self
.Module
.Pcds
)
3279 ExtendCopyDictionaryLists(self
._PcdComments
, self
.Module
.PcdComments
)
3282 ## Get the list of PCDs from dependent libraries
3284 # @retval list The list of PCD
3287 def LibraryPcdList(self
):
3292 # get PCDs from dependent libraries
3293 for Library
in self
.DependentLibraryList
:
3294 PcdsInLibrary
= OrderedDict()
3295 ExtendCopyDictionaryLists(self
._PcdComments
, Library
.PcdComments
)
3296 for Key
in Library
.Pcds
:
3297 # skip duplicated PCDs
3298 if Key
in self
.Module
.Pcds
or Key
in Pcds
:
3301 PcdsInLibrary
[Key
] = copy
.copy(Library
.Pcds
[Key
])
3302 RetVal
.extend(self
.PlatformInfo
.ApplyPcdSetting(self
.Module
, PcdsInLibrary
, Library
=Library
))
3305 ## Get the GUID value mapping
3307 # @retval dict The mapping between GUID cname and its value
3311 RetVal
= OrderedDict(self
.Module
.Guids
)
3312 for Library
in self
.DependentLibraryList
:
3313 RetVal
.update(Library
.Guids
)
3314 ExtendCopyDictionaryLists(self
._GuidComments
, Library
.GuidComments
)
3315 ExtendCopyDictionaryLists(self
._GuidComments
, self
.Module
.GuidComments
)
3319 def GetGuidsUsedByPcd(self
):
3320 RetVal
= OrderedDict(self
.Module
.GetGuidsUsedByPcd())
3321 for Library
in self
.DependentLibraryList
:
3322 RetVal
.update(Library
.GetGuidsUsedByPcd())
3324 ## Get the protocol value mapping
3326 # @retval dict The mapping between protocol cname and its value
3329 def ProtocolList(self
):
3330 RetVal
= OrderedDict(self
.Module
.Protocols
)
3331 for Library
in self
.DependentLibraryList
:
3332 RetVal
.update(Library
.Protocols
)
3333 ExtendCopyDictionaryLists(self
._ProtocolComments
, Library
.ProtocolComments
)
3334 ExtendCopyDictionaryLists(self
._ProtocolComments
, self
.Module
.ProtocolComments
)
3337 ## Get the PPI value mapping
3339 # @retval dict The mapping between PPI cname and its value
3343 RetVal
= OrderedDict(self
.Module
.Ppis
)
3344 for Library
in self
.DependentLibraryList
:
3345 RetVal
.update(Library
.Ppis
)
3346 ExtendCopyDictionaryLists(self
._PpiComments
, Library
.PpiComments
)
3347 ExtendCopyDictionaryLists(self
._PpiComments
, self
.Module
.PpiComments
)
3350 ## Get the list of include search path
3352 # @retval list The list path
3355 def IncludePathList(self
):
3357 RetVal
.append(self
.MetaFile
.Dir
)
3358 RetVal
.append(self
.DebugDir
)
3360 for Package
in self
.Module
.Packages
:
3361 PackageDir
= mws
.join(self
.WorkspaceDir
, Package
.MetaFile
.Dir
)
3362 if PackageDir
not in RetVal
:
3363 RetVal
.append(PackageDir
)
3364 IncludesList
= Package
.Includes
3365 if Package
._PrivateIncludes
:
3366 if not self
.MetaFile
.Path
.startswith(PackageDir
):
3367 IncludesList
= list(set(Package
.Includes
).difference(set(Package
._PrivateIncludes
)))
3368 for Inc
in IncludesList
:
3369 if Inc
not in RetVal
:
3370 RetVal
.append(str(Inc
))
3374 def IncludePathLength(self
):
3375 return sum(len(inc
)+1 for inc
in self
.IncludePathList
)
3377 ## Get HII EX PCDs which maybe used by VFR
3379 # efivarstore used by VFR may relate with HII EX PCDs
3380 # Get the variable name and GUID from efivarstore and HII EX PCD
3381 # List the HII EX PCDs in As Built INF if both name and GUID match.
3383 # @retval list HII EX PCDs
3385 def _GetPcdsMaybeUsedByVfr(self
):
3386 if not self
.SourceFileList
:
3390 for SrcFile
in self
.SourceFileList
:
3391 if SrcFile
.Ext
.lower() != '.vfr':
3393 Vfri
= os
.path
.join(self
.OutputDir
, SrcFile
.BaseName
+ '.i')
3394 if not os
.path
.exists(Vfri
):
3396 VfriFile
= open(Vfri
, 'r')
3397 Content
= VfriFile
.read()
3399 Pos
= Content
.find('efivarstore')
3402 # Make sure 'efivarstore' is the start of efivarstore statement
3403 # In case of the value of 'name' (name = efivarstore) is equal to 'efivarstore'
3406 while Index
>= 0 and Content
[Index
] in ' \t\r\n':
3408 if Index
>= 0 and Content
[Index
] != ';':
3409 Pos
= Content
.find('efivarstore', Pos
+ len('efivarstore'))
3412 # 'efivarstore' must be followed by name and guid
3414 Name
= gEfiVarStoreNamePattern
.search(Content
, Pos
)
3417 Guid
= gEfiVarStoreGuidPattern
.search(Content
, Pos
)
3420 NameArray
= ConvertStringToByteArray('L"' + Name
.group(1) + '"')
3421 NameGuids
.add((NameArray
, GuidStructureStringToGuidString(Guid
.group(1))))
3422 Pos
= Content
.find('efivarstore', Name
.end())
3426 for Pcd
in self
.PlatformInfo
.Platform
.Pcds
.values():
3427 if Pcd
.Type
!= TAB_PCDS_DYNAMIC_EX_HII
:
3429 for SkuInfo
in Pcd
.SkuInfoList
.values():
3430 Value
= GuidValue(SkuInfo
.VariableGuid
, self
.PlatformInfo
.PackageList
, self
.MetaFile
.Path
)
3433 Name
= ConvertStringToByteArray(SkuInfo
.VariableName
)
3434 Guid
= GuidStructureStringToGuidString(Value
)
3435 if (Name
, Guid
) in NameGuids
and Pcd
not in HiiExPcds
:
3436 HiiExPcds
.append(Pcd
)
3441 def _GenOffsetBin(self
):
3443 for SourceFile
in self
.Module
.Sources
:
3444 if SourceFile
.Type
.upper() == ".VFR" :
3446 # search the .map file to find the offset of vfr binary in the PE32+/TE file.
3448 VfrUniBaseName
[SourceFile
.BaseName
] = (SourceFile
.BaseName
+ "Bin")
3449 elif SourceFile
.Type
.upper() == ".UNI" :
3451 # search the .map file to find the offset of Uni strings binary in the PE32+/TE file.
3453 VfrUniBaseName
["UniOffsetName"] = (self
.Name
+ "Strings")
3455 if not VfrUniBaseName
:
3457 MapFileName
= os
.path
.join(self
.OutputDir
, self
.Name
+ ".map")
3458 EfiFileName
= os
.path
.join(self
.OutputDir
, self
.Name
+ ".efi")
3459 VfrUniOffsetList
= GetVariableOffset(MapFileName
, EfiFileName
, VfrUniBaseName
.values())
3460 if not VfrUniOffsetList
:
3463 OutputName
= '%sOffset.bin' % self
.Name
3464 UniVfrOffsetFileName
= os
.path
.join( self
.OutputDir
, OutputName
)
3467 fInputfile
= open(UniVfrOffsetFileName
, "wb+", 0)
3469 EdkLogger
.error("build", FILE_OPEN_FAILURE
, "File open failed for %s" % UniVfrOffsetFileName
, None)
3471 # Use a instance of BytesIO to cache data
3472 fStringIO
= BytesIO('')
3474 for Item
in VfrUniOffsetList
:
3475 if (Item
[0].find("Strings") != -1):
3477 # UNI offset in image.
3479 # { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } }
3481 UniGuid
= [0xe0, 0xc5, 0x13, 0x89, 0xf6, 0x33, 0x86, 0x4d, 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66]
3482 UniGuid
= [chr(ItemGuid
) for ItemGuid
in UniGuid
]
3483 fStringIO
.write(''.join(UniGuid
))
3484 UniValue
= pack ('Q', int (Item
[1], 16))
3485 fStringIO
.write (UniValue
)
3488 # VFR binary offset in image.
3490 # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } };
3492 VfrGuid
= [0xb4, 0x7c, 0xbc, 0xd0, 0x47, 0x6a, 0x5f, 0x49, 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2]
3493 VfrGuid
= [chr(ItemGuid
) for ItemGuid
in VfrGuid
]
3494 fStringIO
.write(''.join(VfrGuid
))
3495 VfrValue
= pack ('Q', int (Item
[1], 16))
3496 fStringIO
.write (VfrValue
)
3498 # write data into file.
3501 fInputfile
.write (fStringIO
.getvalue())
3503 EdkLogger
.error("build", FILE_WRITE_FAILURE
, "Write data to file %s failed, please check whether the "
3504 "file been locked or using by other applications." %UniVfrOffsetFileName
, None)
3510 ## Create AsBuilt INF file the module
3512 def CreateAsBuiltInf(self
, IsOnlyCopy
= False):
3513 self
.OutputFile
= set()
3514 if IsOnlyCopy
and GlobalData
.gBinCacheDest
:
3515 self
.CopyModuleToCache()
3518 if self
.IsAsBuiltInfCreated
:
3521 # Skip the following code for libraries
3525 # Skip the following code for modules with no source files
3526 if not self
.SourceFileList
:
3529 # Skip the following code for modules without any binary files
3530 if self
.BinaryFileList
:
3533 ### TODO: How to handles mixed source and binary modules
3535 # Find all DynamicEx and PatchableInModule PCDs used by this module and dependent libraries
3536 # Also find all packages that the DynamicEx PCDs depend on
3541 PcdTokenSpaceList
= []
3542 for Pcd
in self
.ModulePcdList
+ self
.LibraryPcdList
:
3543 if Pcd
.Type
== TAB_PCDS_PATCHABLE_IN_MODULE
:
3544 PatchablePcds
.append(Pcd
)
3545 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, TAB_PCDS_PATCHABLE_IN_MODULE
))
3546 elif Pcd
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
3549 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, TAB_PCDS_DYNAMIC_EX
))
3550 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, TAB_PCDS_DYNAMIC
))
3551 PcdTokenSpaceList
.append(Pcd
.TokenSpaceGuidCName
)
3552 GuidList
= OrderedDict(self
.GuidList
)
3553 for TokenSpace
in self
.GetGuidsUsedByPcd
:
3554 # If token space is not referred by patch PCD or Ex PCD, remove the GUID from GUID list
3555 # The GUIDs in GUIDs section should really be the GUIDs in source INF or referred by Ex an patch PCDs
3556 if TokenSpace
not in PcdTokenSpaceList
and TokenSpace
in GuidList
:
3557 GuidList
.pop(TokenSpace
)
3558 CheckList
= (GuidList
, self
.PpiList
, self
.ProtocolList
, PcdCheckList
)
3559 for Package
in self
.DerivedPackageList
:
3560 if Package
in Packages
:
3562 BeChecked
= (Package
.Guids
, Package
.Ppis
, Package
.Protocols
, Package
.Pcds
)
3564 for Index
in range(len(BeChecked
)):
3565 for Item
in CheckList
[Index
]:
3566 if Item
in BeChecked
[Index
]:
3567 Packages
.append(Package
)
3573 VfrPcds
= self
._GetPcdsMaybeUsedByVfr
()
3574 for Pkg
in self
.PlatformInfo
.PackageList
:
3577 for VfrPcd
in VfrPcds
:
3578 if ((VfrPcd
.TokenCName
, VfrPcd
.TokenSpaceGuidCName
, TAB_PCDS_DYNAMIC_EX
) in Pkg
.Pcds
or
3579 (VfrPcd
.TokenCName
, VfrPcd
.TokenSpaceGuidCName
, TAB_PCDS_DYNAMIC
) in Pkg
.Pcds
):
3580 Packages
.append(Pkg
)
3583 ModuleType
= SUP_MODULE_DXE_DRIVER
if self
.ModuleType
== SUP_MODULE_UEFI_DRIVER
and self
.DepexGenerated
else self
.ModuleType
3584 DriverType
= self
.PcdIsDriver
if self
.PcdIsDriver
else ''
3586 MDefs
= self
.Module
.Defines
3589 'module_name' : self
.Name
,
3590 'module_guid' : Guid
,
3591 'module_module_type' : ModuleType
,
3592 'module_version_string' : [MDefs
['VERSION_STRING']] if 'VERSION_STRING' in MDefs
else [],
3593 'pcd_is_driver_string' : [],
3594 'module_uefi_specification_version' : [],
3595 'module_pi_specification_version' : [],
3596 'module_entry_point' : self
.Module
.ModuleEntryPointList
,
3597 'module_unload_image' : self
.Module
.ModuleUnloadImageList
,
3598 'module_constructor' : self
.Module
.ConstructorList
,
3599 'module_destructor' : self
.Module
.DestructorList
,
3600 'module_shadow' : [MDefs
['SHADOW']] if 'SHADOW' in MDefs
else [],
3601 'module_pci_vendor_id' : [MDefs
['PCI_VENDOR_ID']] if 'PCI_VENDOR_ID' in MDefs
else [],
3602 'module_pci_device_id' : [MDefs
['PCI_DEVICE_ID']] if 'PCI_DEVICE_ID' in MDefs
else [],
3603 'module_pci_class_code' : [MDefs
['PCI_CLASS_CODE']] if 'PCI_CLASS_CODE' in MDefs
else [],
3604 'module_pci_revision' : [MDefs
['PCI_REVISION']] if 'PCI_REVISION' in MDefs
else [],
3605 'module_build_number' : [MDefs
['BUILD_NUMBER']] if 'BUILD_NUMBER' in MDefs
else [],
3606 'module_spec' : [MDefs
['SPEC']] if 'SPEC' in MDefs
else [],
3607 'module_uefi_hii_resource_section' : [MDefs
['UEFI_HII_RESOURCE_SECTION']] if 'UEFI_HII_RESOURCE_SECTION' in MDefs
else [],
3608 'module_uni_file' : [MDefs
['MODULE_UNI_FILE']] if 'MODULE_UNI_FILE' in MDefs
else [],
3609 'module_arch' : self
.Arch
,
3610 'package_item' : [Package
.MetaFile
.File
.replace('\\', '/') for Package
in Packages
],
3612 'patchablepcd_item' : [],
3614 'protocol_item' : [],
3618 'libraryclasses_item' : []
3621 if 'MODULE_UNI_FILE' in MDefs
:
3622 UNIFile
= os
.path
.join(self
.MetaFile
.Dir
, MDefs
['MODULE_UNI_FILE'])
3623 if os
.path
.isfile(UNIFile
):
3624 shutil
.copy2(UNIFile
, self
.OutputDir
)
3626 if self
.AutoGenVersion
> int(gInfSpecVersion
, 0):
3627 AsBuiltInfDict
['module_inf_version'] = '0x%08x' % self
.AutoGenVersion
3629 AsBuiltInfDict
['module_inf_version'] = gInfSpecVersion
3632 AsBuiltInfDict
['pcd_is_driver_string'].append(DriverType
)
3634 if 'UEFI_SPECIFICATION_VERSION' in self
.Specification
:
3635 AsBuiltInfDict
['module_uefi_specification_version'].append(self
.Specification
['UEFI_SPECIFICATION_VERSION'])
3636 if 'PI_SPECIFICATION_VERSION' in self
.Specification
:
3637 AsBuiltInfDict
['module_pi_specification_version'].append(self
.Specification
['PI_SPECIFICATION_VERSION'])
3639 OutputDir
= self
.OutputDir
.replace('\\', '/').strip('/')
3640 DebugDir
= self
.DebugDir
.replace('\\', '/').strip('/')
3641 for Item
in self
.CodaTargetList
:
3642 File
= Item
.Target
.Path
.replace('\\', '/').strip('/').replace(DebugDir
, '').replace(OutputDir
, '').strip('/')
3643 self
.OutputFile
.add(File
)
3644 if os
.path
.isabs(File
):
3645 File
= File
.replace('\\', '/').strip('/').replace(OutputDir
, '').strip('/')
3646 if Item
.Target
.Ext
.lower() == '.aml':
3647 AsBuiltInfDict
['binary_item'].append('ASL|' + File
)
3648 elif Item
.Target
.Ext
.lower() == '.acpi':
3649 AsBuiltInfDict
['binary_item'].append('ACPI|' + File
)
3650 elif Item
.Target
.Ext
.lower() == '.efi':
3651 AsBuiltInfDict
['binary_item'].append('PE32|' + self
.Name
+ '.efi')
3653 AsBuiltInfDict
['binary_item'].append('BIN|' + File
)
3654 if not self
.DepexGenerated
:
3655 DepexFile
= os
.path
.join(self
.OutputDir
, self
.Name
+ '.depex')
3656 if os
.path
.exists(DepexFile
):
3657 self
.DepexGenerated
= True
3658 if self
.DepexGenerated
:
3659 self
.OutputFile
.add(self
.Name
+ '.depex')
3660 if self
.ModuleType
in [SUP_MODULE_PEIM
]:
3661 AsBuiltInfDict
['binary_item'].append('PEI_DEPEX|' + self
.Name
+ '.depex')
3662 elif self
.ModuleType
in [SUP_MODULE_DXE_DRIVER
, SUP_MODULE_DXE_RUNTIME_DRIVER
, SUP_MODULE_DXE_SAL_DRIVER
, SUP_MODULE_UEFI_DRIVER
]:
3663 AsBuiltInfDict
['binary_item'].append('DXE_DEPEX|' + self
.Name
+ '.depex')
3664 elif self
.ModuleType
in [SUP_MODULE_DXE_SMM_DRIVER
]:
3665 AsBuiltInfDict
['binary_item'].append('SMM_DEPEX|' + self
.Name
+ '.depex')
3667 Bin
= self
._GenOffsetBin
()
3669 AsBuiltInfDict
['binary_item'].append('BIN|%s' % Bin
)
3670 self
.OutputFile
.add(Bin
)
3672 for Root
, Dirs
, Files
in os
.walk(OutputDir
):
3674 if File
.lower().endswith('.pdb'):
3675 AsBuiltInfDict
['binary_item'].append('DISPOSABLE|' + File
)
3676 self
.OutputFile
.add(File
)
3677 HeaderComments
= self
.Module
.HeaderComments
3679 for Index
in range(len(HeaderComments
)):
3680 if HeaderComments
[Index
].find('@BinaryHeader') != -1:
3681 HeaderComments
[Index
] = HeaderComments
[Index
].replace('@BinaryHeader', '@file')
3684 AsBuiltInfDict
['header_comments'] = '\n'.join(HeaderComments
[StartPos
:]).replace(':#', '://')
3685 AsBuiltInfDict
['tail_comments'] = '\n'.join(self
.Module
.TailComments
)
3688 (self
.ProtocolList
, self
._ProtocolComments
, 'protocol_item'),
3689 (self
.PpiList
, self
._PpiComments
, 'ppi_item'),
3690 (GuidList
, self
._GuidComments
, 'guid_item')
3692 for Item
in GenList
:
3693 for CName
in Item
[0]:
3694 Comments
= '\n '.join(Item
[1][CName
]) if CName
in Item
[1] else ''
3695 Entry
= Comments
+ '\n ' + CName
if Comments
else CName
3696 AsBuiltInfDict
[Item
[2]].append(Entry
)
3697 PatchList
= parsePcdInfoFromMapFile(
3698 os
.path
.join(self
.OutputDir
, self
.Name
+ '.map'),
3699 os
.path
.join(self
.OutputDir
, self
.Name
+ '.efi')
3702 for Pcd
in PatchablePcds
:
3703 TokenCName
= Pcd
.TokenCName
3704 for PcdItem
in GlobalData
.MixedPcd
:
3705 if (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
3706 TokenCName
= PcdItem
[0]
3708 for PatchPcd
in PatchList
:
3709 if TokenCName
== PatchPcd
[0]:
3714 if Pcd
.DatumType
== 'BOOLEAN':
3715 BoolValue
= Pcd
.DefaultValue
.upper()
3716 if BoolValue
== 'TRUE':
3717 Pcd
.DefaultValue
= '1'
3718 elif BoolValue
== 'FALSE':
3719 Pcd
.DefaultValue
= '0'
3721 if Pcd
.DatumType
in TAB_PCD_NUMERIC_TYPES
:
3722 HexFormat
= '0x%02x'
3723 if Pcd
.DatumType
== TAB_UINT16
:
3724 HexFormat
= '0x%04x'
3725 elif Pcd
.DatumType
== TAB_UINT32
:
3726 HexFormat
= '0x%08x'
3727 elif Pcd
.DatumType
== TAB_UINT64
:
3728 HexFormat
= '0x%016x'
3729 PcdValue
= HexFormat
% int(Pcd
.DefaultValue
, 0)
3731 if Pcd
.MaxDatumSize
is None or Pcd
.MaxDatumSize
== '':
3732 EdkLogger
.error("build", AUTOGEN_ERROR
,
3733 "Unknown [MaxDatumSize] of PCD [%s.%s]" % (Pcd
.TokenSpaceGuidCName
, TokenCName
)
3735 ArraySize
= int(Pcd
.MaxDatumSize
, 0)
3736 PcdValue
= Pcd
.DefaultValue
3737 if PcdValue
[0] != '{':
3739 if PcdValue
[0] == 'L':
3741 PcdValue
= PcdValue
.lstrip('L')
3742 PcdValue
= eval(PcdValue
)
3744 for Index
in range(0, len(PcdValue
)):
3746 CharVal
= ord(PcdValue
[Index
])
3747 NewValue
= NewValue
+ '0x%02x' % (CharVal
& 0x00FF) + ', ' \
3748 + '0x%02x' % (CharVal
>> 8) + ', '
3750 NewValue
= NewValue
+ '0x%02x' % (ord(PcdValue
[Index
]) % 0x100) + ', '
3753 Padding
= Padding
* 2
3754 ArraySize
= ArraySize
/ 2
3755 if ArraySize
< (len(PcdValue
) + 1):
3756 if Pcd
.MaxSizeUserSet
:
3757 EdkLogger
.error("build", AUTOGEN_ERROR
,
3758 "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd
.TokenSpaceGuidCName
, TokenCName
)
3761 ArraySize
= len(PcdValue
) + 1
3762 if ArraySize
> len(PcdValue
) + 1:
3763 NewValue
= NewValue
+ Padding
* (ArraySize
- len(PcdValue
) - 1)
3764 PcdValue
= NewValue
+ Padding
.strip().rstrip(',') + '}'
3765 elif len(PcdValue
.split(',')) <= ArraySize
:
3766 PcdValue
= PcdValue
.rstrip('}') + ', 0x00' * (ArraySize
- len(PcdValue
.split(',')))
3769 if Pcd
.MaxSizeUserSet
:
3770 EdkLogger
.error("build", AUTOGEN_ERROR
,
3771 "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd
.TokenSpaceGuidCName
, TokenCName
)
3774 ArraySize
= len(PcdValue
) + 1
3775 PcdItem
= '%s.%s|%s|0x%X' % \
3776 (Pcd
.TokenSpaceGuidCName
, TokenCName
, PcdValue
, PatchPcd
[1])
3778 if (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) in self
._PcdComments
:
3779 PcdComments
= '\n '.join(self
._PcdComments
[Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
])
3781 PcdItem
= PcdComments
+ '\n ' + PcdItem
3782 AsBuiltInfDict
['patchablepcd_item'].append(PcdItem
)
3784 for Pcd
in Pcds
+ VfrPcds
:
3787 TokenCName
= Pcd
.TokenCName
3788 for PcdItem
in GlobalData
.MixedPcd
:
3789 if (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
3790 TokenCName
= PcdItem
[0]
3792 if Pcd
.Type
== TAB_PCDS_DYNAMIC_EX_HII
:
3793 for SkuName
in Pcd
.SkuInfoList
:
3794 SkuInfo
= Pcd
.SkuInfoList
[SkuName
]
3795 HiiInfo
= '## %s|%s|%s' % (SkuInfo
.VariableName
, SkuInfo
.VariableGuid
, SkuInfo
.VariableOffset
)
3797 if (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) in self
._PcdComments
:
3798 PcdCommentList
= self
._PcdComments
[Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
][:]
3802 for Index
, Comment
in enumerate(PcdCommentList
):
3803 for Usage
in UsageList
:
3804 if Comment
.find(Usage
) != -1:
3808 if UsageIndex
!= -1:
3809 PcdCommentList
[UsageIndex
] = '## %s %s %s' % (UsageStr
, HiiInfo
, PcdCommentList
[UsageIndex
].replace(UsageStr
, ''))
3811 PcdCommentList
.append('## UNDEFINED ' + HiiInfo
)
3812 PcdComments
= '\n '.join(PcdCommentList
)
3813 PcdEntry
= Pcd
.TokenSpaceGuidCName
+ '.' + TokenCName
3815 PcdEntry
= PcdComments
+ '\n ' + PcdEntry
3816 AsBuiltInfDict
['pcd_item'].append(PcdEntry
)
3817 for Item
in self
.BuildOption
:
3818 if 'FLAGS' in self
.BuildOption
[Item
]:
3819 AsBuiltInfDict
['flags_item'].append('%s:%s_%s_%s_%s_FLAGS = %s' % (self
.ToolChainFamily
, self
.BuildTarget
, self
.ToolChain
, self
.Arch
, Item
, self
.BuildOption
[Item
]['FLAGS'].strip()))
3821 # Generated LibraryClasses section in comments.
3822 for Library
in self
.LibraryAutoGenList
:
3823 AsBuiltInfDict
['libraryclasses_item'].append(Library
.MetaFile
.File
.replace('\\', '/'))
3825 # Generated UserExtensions TianoCore section.
3826 # All tianocore user extensions are copied.
3828 for TianoCore
in self
._GetTianoCoreUserExtensionList
():
3829 UserExtStr
+= '\n'.join(TianoCore
)
3830 ExtensionFile
= os
.path
.join(self
.MetaFile
.Dir
, TianoCore
[1])
3831 if os
.path
.isfile(ExtensionFile
):
3832 shutil
.copy2(ExtensionFile
, self
.OutputDir
)
3833 AsBuiltInfDict
['userextension_tianocore_item'] = UserExtStr
3835 # Generated depex expression section in comments.
3836 DepexExpresion
= self
._GetDepexExpresionString
()
3837 AsBuiltInfDict
['depexsection_item'] = DepexExpresion
if DepexExpresion
else ''
3839 AsBuiltInf
= TemplateString()
3840 AsBuiltInf
.Append(gAsBuiltInfHeaderString
.Replace(AsBuiltInfDict
))
3842 SaveFileOnChange(os
.path
.join(self
.OutputDir
, self
.Name
+ '.inf'), str(AsBuiltInf
), False)
3844 self
.IsAsBuiltInfCreated
= True
3845 if GlobalData
.gBinCacheDest
:
3846 self
.CopyModuleToCache()
3848 def CopyModuleToCache(self
):
3849 FileDir
= path
.join(GlobalData
.gBinCacheDest
, self
.Arch
, self
.SourceDir
, self
.MetaFile
.BaseName
)
3850 CreateDirectory (FileDir
)
3851 HashFile
= path
.join(self
.BuildDir
, self
.Name
+ '.hash')
3852 ModuleFile
= path
.join(self
.OutputDir
, self
.Name
+ '.inf')
3853 if os
.path
.exists(HashFile
):
3854 shutil
.copy2(HashFile
, FileDir
)
3855 if os
.path
.exists(ModuleFile
):
3856 shutil
.copy2(ModuleFile
, FileDir
)
3857 if not self
.OutputFile
:
3858 Ma
= self
.BuildDatabase
[PathClass(ModuleFile
), self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
3859 self
.OutputFile
= Ma
.Binaries
3861 for File
in self
.OutputFile
:
3863 if not os
.path
.isabs(File
):
3864 File
= os
.path
.join(self
.OutputDir
, File
)
3865 if os
.path
.exists(File
):
3866 shutil
.copy2(File
, FileDir
)
3868 def AttemptModuleCacheCopy(self
):
3869 if self
.IsBinaryModule
:
3871 FileDir
= path
.join(GlobalData
.gBinCacheSource
, self
.Arch
, self
.SourceDir
, self
.MetaFile
.BaseName
)
3872 HashFile
= path
.join(FileDir
, self
.Name
+ '.hash')
3873 if os
.path
.exists(HashFile
):
3874 f
= open(HashFile
, 'r')
3875 CacheHash
= f
.read()
3877 if GlobalData
.gModuleHash
[self
.Arch
][self
.Name
]:
3878 if CacheHash
== GlobalData
.gModuleHash
[self
.Arch
][self
.Name
]:
3879 for root
, dir, files
in os
.walk(FileDir
):
3881 if self
.Name
+ '.hash' in f
:
3882 shutil
.copy2(HashFile
, self
.BuildDir
)
3884 File
= path
.join(root
, f
)
3885 shutil
.copy2(File
, self
.OutputDir
)
3886 if self
.Name
== "PcdPeim" or self
.Name
== "PcdDxe":
3887 CreatePcdDatabaseCode(self
, TemplateString(), TemplateString())
3891 ## Create makefile for the module and its dependent libraries
3893 # @param CreateLibraryMakeFile Flag indicating if or not the makefiles of
3894 # dependent libraries will be created
3896 @cached_class_function
3897 def CreateMakeFile(self
, CreateLibraryMakeFile
=True, GenFfsList
= []):
3898 # nest this function inside it's only caller.
3899 def CreateTimeStamp():
3900 FileSet
= {self
.MetaFile
.Path
}
3902 for SourceFile
in self
.Module
.Sources
:
3903 FileSet
.add (SourceFile
.Path
)
3905 for Lib
in self
.DependentLibraryList
:
3906 FileSet
.add (Lib
.MetaFile
.Path
)
3908 for f
in self
.AutoGenDepSet
:
3909 FileSet
.add (f
.Path
)
3911 if os
.path
.exists (self
.TimeStampPath
):
3912 os
.remove (self
.TimeStampPath
)
3913 with
open(self
.TimeStampPath
, 'w+') as file:
3917 # Ignore generating makefile when it is a binary module
3918 if self
.IsBinaryModule
:
3921 self
.GenFfsList
= GenFfsList
3922 if not self
.IsLibrary
and CreateLibraryMakeFile
:
3923 for LibraryAutoGen
in self
.LibraryAutoGenList
:
3924 LibraryAutoGen
.CreateMakeFile()
3929 if len(self
.CustomMakefile
) == 0:
3930 Makefile
= GenMake
.ModuleMakefile(self
)
3932 Makefile
= GenMake
.CustomMakefile(self
)
3933 if Makefile
.Generate():
3934 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated makefile for module %s [%s]" %
3935 (self
.Name
, self
.Arch
))
3937 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Skipped the generation of makefile for module %s [%s]" %
3938 (self
.Name
, self
.Arch
))
3942 def CopyBinaryFiles(self
):
3943 for File
in self
.Module
.Binaries
:
3945 DstPath
= os
.path
.join(self
.OutputDir
, os
.path
.basename(SrcPath
))
3946 CopyLongFilePath(SrcPath
, DstPath
)
3947 ## Create autogen code for the module and its dependent libraries
3949 # @param CreateLibraryCodeFile Flag indicating if or not the code of
3950 # dependent libraries will be created
3952 def CreateCodeFile(self
, CreateLibraryCodeFile
=True):
3953 if self
.IsCodeFileCreated
:
3956 # Need to generate PcdDatabase even PcdDriver is binarymodule
3957 if self
.IsBinaryModule
and self
.PcdIsDriver
!= '':
3958 CreatePcdDatabaseCode(self
, TemplateString(), TemplateString())
3960 if self
.IsBinaryModule
:
3962 self
.CopyBinaryFiles()
3965 if not self
.IsLibrary
and CreateLibraryCodeFile
:
3966 for LibraryAutoGen
in self
.LibraryAutoGenList
:
3967 LibraryAutoGen
.CreateCodeFile()
3973 IgoredAutoGenList
= []
3975 for File
in self
.AutoGenFileList
:
3976 if GenC
.Generate(File
.Path
, self
.AutoGenFileList
[File
], File
.IsBinary
):
3977 AutoGenList
.append(str(File
))
3979 IgoredAutoGenList
.append(str(File
))
3982 for ModuleType
in self
.DepexList
:
3983 # Ignore empty [depex] section or [depex] section for SUP_MODULE_USER_DEFINED module
3984 if len(self
.DepexList
[ModuleType
]) == 0 or ModuleType
== SUP_MODULE_USER_DEFINED
:
3987 Dpx
= GenDepex
.DependencyExpression(self
.DepexList
[ModuleType
], ModuleType
, True)
3988 DpxFile
= gAutoGenDepexFileName
% {"module_name" : self
.Name
}
3990 if len(Dpx
.PostfixNotation
) != 0:
3991 self
.DepexGenerated
= True
3993 if Dpx
.Generate(path
.join(self
.OutputDir
, DpxFile
)):
3994 AutoGenList
.append(str(DpxFile
))
3996 IgoredAutoGenList
.append(str(DpxFile
))
3998 if IgoredAutoGenList
== []:
3999 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated [%s] files for module %s [%s]" %
4000 (" ".join(AutoGenList
), self
.Name
, self
.Arch
))
4001 elif AutoGenList
== []:
4002 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Skipped the generation of [%s] files for module %s [%s]" %
4003 (" ".join(IgoredAutoGenList
), self
.Name
, self
.Arch
))
4005 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated [%s] (skipped %s) files for module %s [%s]" %
4006 (" ".join(AutoGenList
), " ".join(IgoredAutoGenList
), self
.Name
, self
.Arch
))
4008 self
.IsCodeFileCreated
= True
4011 ## Summarize the ModuleAutoGen objects of all libraries used by this module
4013 def LibraryAutoGenList(self
):
4015 for Library
in self
.DependentLibraryList
:
4022 self
.PlatformInfo
.MetaFile
4024 if La
not in RetVal
:
4026 for Lib
in La
.CodaTargetList
:
4027 self
._ApplyBuildRule
(Lib
.Target
, TAB_UNKNOWN_FILE
)
4030 def GenModuleHash(self
):
4031 if self
.Arch
not in GlobalData
.gModuleHash
:
4032 GlobalData
.gModuleHash
[self
.Arch
] = {}
4034 # Add Platform level hash
4035 m
.update(GlobalData
.gPlatformHash
)
4036 # Add Package level hash
4037 if self
.DependentPackageList
:
4038 for Pkg
in sorted(self
.DependentPackageList
, key
=lambda x
: x
.PackageName
):
4039 if Pkg
.PackageName
in GlobalData
.gPackageHash
[self
.Arch
]:
4040 m
.update(GlobalData
.gPackageHash
[self
.Arch
][Pkg
.PackageName
])
4043 if self
.LibraryAutoGenList
:
4044 for Lib
in sorted(self
.LibraryAutoGenList
, key
=lambda x
: x
.Name
):
4045 if Lib
.Name
not in GlobalData
.gModuleHash
[self
.Arch
]:
4047 m
.update(GlobalData
.gModuleHash
[self
.Arch
][Lib
.Name
])
4050 f
= open(str(self
.MetaFile
), 'r')
4054 # Add Module's source files
4055 if self
.SourceFileList
:
4056 for File
in sorted(self
.SourceFileList
, key
=lambda x
: str(x
)):
4057 f
= open(str(File
), 'r')
4062 ModuleHashFile
= path
.join(self
.BuildDir
, self
.Name
+ ".hash")
4063 if self
.Name
not in GlobalData
.gModuleHash
[self
.Arch
]:
4064 GlobalData
.gModuleHash
[self
.Arch
][self
.Name
] = m
.hexdigest()
4065 if GlobalData
.gBinCacheSource
:
4066 if self
.AttemptModuleCacheCopy():
4068 return SaveFileOnChange(ModuleHashFile
, m
.hexdigest(), True)
4070 ## Decide whether we can skip the ModuleAutoGen process
4071 def CanSkipbyHash(self
):
4072 if GlobalData
.gUseHashCache
:
4073 return not self
.GenModuleHash()
4076 ## Decide whether we can skip the ModuleAutoGen process
4077 # If any source file is newer than the module than we cannot skip
4080 if self
.MakeFileDir
in GlobalData
.gSikpAutoGenCache
:
4082 if not os
.path
.exists(self
.TimeStampPath
):
4084 #last creation time of the module
4085 DstTimeStamp
= os
.stat(self
.TimeStampPath
)[8]
4087 SrcTimeStamp
= self
.Workspace
._SrcTimeStamp
4088 if SrcTimeStamp
> DstTimeStamp
:
4091 with
open(self
.TimeStampPath
,'r') as f
:
4093 source
= source
.rstrip('\n')
4094 if not os
.path
.exists(source
):
4096 if source
not in ModuleAutoGen
.TimeDict
:
4097 ModuleAutoGen
.TimeDict
[source
] = os
.stat(source
)[8]
4098 if ModuleAutoGen
.TimeDict
[source
] > DstTimeStamp
:
4100 GlobalData
.gSikpAutoGenCache
.add(self
.MakeFileDir
)
4104 def TimeStampPath(self
):
4105 return os
.path
.join(self
.MakeFileDir
, 'AutoGenTimeStamp')