2 # Generate AutoGen.h, AutoGen.c and *.depex files
4 # Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
5 # Copyright (c) 2018, Hewlett Packard Enterprise Development, L.P.<BR>
7 # This program and the accompanying materials
8 # are licensed and made available under the terms and conditions of the BSD License
9 # which accompanies this distribution. The full text of the license may be found at
10 # http://opensource.org/licenses/bsd-license.php
12 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 import Common
.LongFilePathOs
as os
20 import os
.path
as path
26 from . import GenDepex
27 from io
import BytesIO
29 from .StrGather
import *
30 from .BuildEngine
import BuildRule
32 from Common
.LongFilePathSupport
import CopyLongFilePath
33 from Common
.BuildToolError
import *
34 from Common
.DataType
import *
35 from Common
.Misc
import *
36 from Common
.StringUtils
import *
37 import Common
.GlobalData
as GlobalData
38 from GenFds
.FdfParser
import *
39 from CommonDataClass
.CommonClass
import SkuInfoClass
40 from GenPatchPcdTable
.GenPatchPcdTable
import parsePcdInfoFromMapFile
41 import Common
.VpdInfoFile
as VpdInfoFile
42 from .GenPcdDb
import CreatePcdDatabaseCode
43 from Workspace
.MetaFileCommentParser
import UsageList
44 from Workspace
.WorkspaceCommon
import GetModuleLibInstances
45 from Common
.MultipleWorkspace
import MultipleWorkspace
as mws
46 from . import InfSectionParser
49 from .GenVar
import VariableMgr
, var_info
50 from collections
import OrderedDict
51 from collections
import defaultdict
52 from Workspace
.WorkspaceCommon
import OrderedListDict
54 from Common
.caching
import cached_property
, cached_class_function
56 ## Regular expression for splitting Dependency Expression string into tokens
57 gDepexTokenPattern
= re
.compile("(\(|\)|\w+| \S+\.inf)")
59 ## Regular expression for match: PCD(xxxx.yyy)
60 gPCDAsGuidPattern
= re
.compile(r
"^PCD\(.+\..+\)$")
63 # Regular expression for finding Include Directories, the difference between MSFT and INTEL/GCC/RVCT
64 # is the former use /I , the Latter used -I to specify include directories
66 gBuildOptIncludePatternMsft
= re
.compile(r
"(?:.*?)/I[ \t]*([^ ]*)", re
.MULTILINE | re
.DOTALL
)
67 gBuildOptIncludePatternOther
= re
.compile(r
"(?:.*?)-I[ \t]*([^ ]*)", re
.MULTILINE | re
.DOTALL
)
70 # Match name = variable
72 gEfiVarStoreNamePattern
= re
.compile("\s*name\s*=\s*(\w+)")
74 # The format of guid in efivarstore statement likes following and must be correct:
75 # guid = {0xA04A27f4, 0xDF00, 0x4D42, {0xB5, 0x52, 0x39, 0x51, 0x13, 0x02, 0x11, 0x3D}}
77 gEfiVarStoreGuidPattern
= re
.compile("\s*guid\s*=\s*({.*?{.*?}\s*})")
79 ## Mapping Makefile type
80 gMakeTypeMap
= {TAB_COMPILER_MSFT
:"nmake", "GCC":"gmake"}
83 ## Build rule configuration file
84 gDefaultBuildRuleFile
= 'build_rule.txt'
86 ## Tools definition configuration file
87 gDefaultToolsDefFile
= 'tools_def.txt'
89 ## Build rule default version
90 AutoGenReqBuildRuleVerNum
= "0.1"
92 ## default file name for AutoGen
93 gAutoGenCodeFileName
= "AutoGen.c"
94 gAutoGenHeaderFileName
= "AutoGen.h"
95 gAutoGenStringFileName
= "%(module_name)sStrDefs.h"
96 gAutoGenStringFormFileName
= "%(module_name)sStrDefs.hpk"
97 gAutoGenDepexFileName
= "%(module_name)s.depex"
98 gAutoGenImageDefFileName
= "%(module_name)sImgDefs.h"
99 gAutoGenIdfFileName
= "%(module_name)sIdf.hpk"
100 gInfSpecVersion
= "0x00010017"
103 # Template string to generic AsBuilt INF
105 gAsBuiltInfHeaderString
= TemplateString("""${header_comments}
108 # FILE auto-generated
111 INF_VERSION = ${module_inf_version}
112 BASE_NAME = ${module_name}
113 FILE_GUID = ${module_guid}
114 MODULE_TYPE = ${module_module_type}${BEGIN}
115 VERSION_STRING = ${module_version_string}${END}${BEGIN}
116 PCD_IS_DRIVER = ${pcd_is_driver_string}${END}${BEGIN}
117 UEFI_SPECIFICATION_VERSION = ${module_uefi_specification_version}${END}${BEGIN}
118 PI_SPECIFICATION_VERSION = ${module_pi_specification_version}${END}${BEGIN}
119 ENTRY_POINT = ${module_entry_point}${END}${BEGIN}
120 UNLOAD_IMAGE = ${module_unload_image}${END}${BEGIN}
121 CONSTRUCTOR = ${module_constructor}${END}${BEGIN}
122 DESTRUCTOR = ${module_destructor}${END}${BEGIN}
123 SHADOW = ${module_shadow}${END}${BEGIN}
124 PCI_VENDOR_ID = ${module_pci_vendor_id}${END}${BEGIN}
125 PCI_DEVICE_ID = ${module_pci_device_id}${END}${BEGIN}
126 PCI_CLASS_CODE = ${module_pci_class_code}${END}${BEGIN}
127 PCI_REVISION = ${module_pci_revision}${END}${BEGIN}
128 BUILD_NUMBER = ${module_build_number}${END}${BEGIN}
129 SPEC = ${module_spec}${END}${BEGIN}
130 UEFI_HII_RESOURCE_SECTION = ${module_uefi_hii_resource_section}${END}${BEGIN}
131 MODULE_UNI_FILE = ${module_uni_file}${END}
133 [Packages.${module_arch}]${BEGIN}
134 ${package_item}${END}
136 [Binaries.${module_arch}]${BEGIN}
139 [PatchPcd.${module_arch}]${BEGIN}
143 [Protocols.${module_arch}]${BEGIN}
147 [Ppis.${module_arch}]${BEGIN}
151 [Guids.${module_arch}]${BEGIN}
155 [PcdEx.${module_arch}]${BEGIN}
159 [LibraryClasses.${module_arch}]
160 ## @LIB_INSTANCES${BEGIN}
161 # ${libraryclasses_item}${END}
165 ${userextension_tianocore_item}
169 [BuildOptions.${module_arch}]
171 ## ${flags_item}${END}
174 ## Base class for AutoGen
176 # This class just implements the cache mechanism of AutoGen objects.
178 class AutoGen(object):
179 # database to maintain the objects in each child class
180 __ObjectCache
= {} # (BuildTarget, ToolChain, ARCH, platform file): AutoGen object
184 # @param Class class object of real AutoGen class
185 # (WorkspaceAutoGen, ModuleAutoGen or PlatformAutoGen)
186 # @param Workspace Workspace directory or WorkspaceAutoGen object
187 # @param MetaFile The path of meta file
188 # @param Target Build target
189 # @param Toolchain Tool chain name
190 # @param Arch Target arch
191 # @param *args The specific class related parameters
192 # @param **kwargs The specific class related dict parameters
194 def __new__(cls
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
195 # check if the object has been created
196 Key
= (Target
, Toolchain
, Arch
, MetaFile
)
197 if Key
in cls
.__ObjectCache
:
198 # if it exists, just return it directly
199 return cls
.__ObjectCache
[Key
]
200 # it didnt exist. create it, cache it, then return it
201 RetVal
= cls
.__ObjectCache
[Key
] = super().__new
__(cls
)
204 def __init__ (self
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
209 # The file path of platform file will be used to represent hash value of this object
211 # @retval int Hash value of the file path of platform file
214 return hash(self
.MetaFile
)
218 # The file path of platform file will be used to represent this object
220 # @retval string String of platform file path
223 return str(self
.MetaFile
)
226 def __eq__(self
, Other
):
227 return Other
and self
.MetaFile
== Other
229 ## Workspace AutoGen class
231 # This class is used mainly to control the whole platform build for different
232 # architecture. This class will generate top level makefile.
234 class WorkspaceAutoGen(AutoGen
):
235 # call super().__init__ then call the worker function with different parameter count
236 def __init__(self
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
237 if not hasattr(self
, "_Init"):
238 super().__init
__(Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
)
239 self
._InitWorker
(Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
)
242 ## Initialize WorkspaceAutoGen
244 # @param WorkspaceDir Root directory of workspace
245 # @param ActivePlatform Meta-file of active platform
246 # @param Target Build target
247 # @param Toolchain Tool chain name
248 # @param ArchList List of architecture of current build
249 # @param MetaFileDb Database containing meta-files
250 # @param BuildConfig Configuration of build
251 # @param ToolDefinition Tool chain definitions
252 # @param FlashDefinitionFile File of flash definition
253 # @param Fds FD list to be generated
254 # @param Fvs FV list to be generated
255 # @param Caps Capsule list to be generated
256 # @param SkuId SKU id from command line
258 def _InitWorker(self
, WorkspaceDir
, ActivePlatform
, Target
, Toolchain
, ArchList
, MetaFileDb
,
259 BuildConfig
, ToolDefinition
, FlashDefinitionFile
='', Fds
=None, Fvs
=None, Caps
=None, SkuId
='', UniFlag
=None,
260 Progress
=None, BuildModule
=None):
261 self
.BuildDatabase
= MetaFileDb
262 self
.MetaFile
= ActivePlatform
263 self
.WorkspaceDir
= WorkspaceDir
264 self
.Platform
= self
.BuildDatabase
[self
.MetaFile
, TAB_ARCH_COMMON
, Target
, Toolchain
]
265 GlobalData
.gActivePlatform
= self
.Platform
266 self
.BuildTarget
= Target
267 self
.ToolChain
= Toolchain
268 self
.ArchList
= ArchList
270 self
.UniFlag
= UniFlag
272 self
.TargetTxt
= BuildConfig
273 self
.ToolDef
= ToolDefinition
274 self
.FdfFile
= FlashDefinitionFile
275 self
.FdTargetList
= Fds
if Fds
else []
276 self
.FvTargetList
= Fvs
if Fvs
else []
277 self
.CapTargetList
= Caps
if Caps
else []
278 self
.AutoGenObjectList
= []
281 # there's many relative directory operations, so ...
282 os
.chdir(self
.WorkspaceDir
)
287 if not self
.ArchList
:
288 ArchList
= set(self
.Platform
.SupArchList
)
290 ArchList
= set(self
.ArchList
) & set(self
.Platform
.SupArchList
)
292 EdkLogger
.error("build", PARAMETER_INVALID
,
293 ExtraData
= "Invalid ARCH specified. [Valid ARCH: %s]" % (" ".join(self
.Platform
.SupArchList
)))
294 elif self
.ArchList
and len(ArchList
) != len(self
.ArchList
):
295 SkippedArchList
= set(self
.ArchList
).symmetric_difference(set(self
.Platform
.SupArchList
))
296 EdkLogger
.verbose("\nArch [%s] is ignored because the platform supports [%s] only!"
297 % (" ".join(SkippedArchList
), " ".join(self
.Platform
.SupArchList
)))
298 self
.ArchList
= tuple(sorted(ArchList
))
300 # Validate build target
301 if self
.BuildTarget
not in self
.Platform
.BuildTargets
:
302 EdkLogger
.error("build", PARAMETER_INVALID
,
303 ExtraData
="Build target [%s] is not supported by the platform. [Valid target: %s]"
304 % (self
.BuildTarget
, " ".join(self
.Platform
.BuildTargets
)))
307 # parse FDF file to get PCDs in it, if any
309 self
.FdfFile
= self
.Platform
.FlashDefinition
313 EdkLogger
.info('%-16s = %s' % ("Architecture(s)", ' '.join(self
.ArchList
)))
314 EdkLogger
.info('%-16s = %s' % ("Build target", self
.BuildTarget
))
315 EdkLogger
.info('%-16s = %s' % ("Toolchain", self
.ToolChain
))
317 EdkLogger
.info('\n%-24s = %s' % ("Active Platform", self
.Platform
))
319 EdkLogger
.info('%-24s = %s' % ("Active Module", BuildModule
))
322 EdkLogger
.info('%-24s = %s' % ("Flash Image Definition", self
.FdfFile
))
324 EdkLogger
.verbose("\nFLASH_DEFINITION = %s" % self
.FdfFile
)
327 Progress
.Start("\nProcessing meta-data")
331 # Mark now build in AutoGen Phase
333 GlobalData
.gAutoGenPhase
= True
334 Fdf
= FdfParser(self
.FdfFile
.Path
)
336 GlobalData
.gFdfParser
= Fdf
337 GlobalData
.gAutoGenPhase
= False
338 PcdSet
= Fdf
.Profile
.PcdDict
339 if Fdf
.CurrentFdName
and Fdf
.CurrentFdName
in Fdf
.Profile
.FdDict
:
340 FdDict
= Fdf
.Profile
.FdDict
[Fdf
.CurrentFdName
]
341 for FdRegion
in FdDict
.RegionList
:
342 if str(FdRegion
.RegionType
) is 'FILE' and self
.Platform
.VpdToolGuid
in str(FdRegion
.RegionDataList
):
343 if int(FdRegion
.Offset
) % 8 != 0:
344 EdkLogger
.error("build", FORMAT_INVALID
, 'The VPD Base Address %s must be 8-byte aligned.' % (FdRegion
.Offset
))
345 ModuleList
= Fdf
.Profile
.InfList
346 self
.FdfProfile
= Fdf
.Profile
347 for fvname
in self
.FvTargetList
:
348 if fvname
.upper() not in self
.FdfProfile
.FvDict
:
349 EdkLogger
.error("build", OPTION_VALUE_INVALID
,
350 "No such an FV in FDF file: %s" % fvname
)
352 # In DSC file may use FILE_GUID to override the module, then in the Platform.Modules use FILE_GUIDmodule.inf as key,
353 # but the path (self.MetaFile.Path) is the real path
354 for key
in self
.FdfProfile
.InfDict
:
356 MetaFile_cache
= defaultdict(set)
357 for Arch
in self
.ArchList
:
358 Current_Platform_cache
= self
.BuildDatabase
[self
.MetaFile
, Arch
, Target
, Toolchain
]
359 for Pkey
in Current_Platform_cache
.Modules
:
360 MetaFile_cache
[Arch
].add(Current_Platform_cache
.Modules
[Pkey
].MetaFile
)
361 for Inf
in self
.FdfProfile
.InfDict
[key
]:
362 ModuleFile
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, Arch
)
363 for Arch
in self
.ArchList
:
364 if ModuleFile
in MetaFile_cache
[Arch
]:
367 ModuleData
= self
.BuildDatabase
[ModuleFile
, Arch
, Target
, Toolchain
]
368 if not ModuleData
.IsBinaryModule
:
369 EdkLogger
.error('build', PARSER_ERROR
, "Module %s NOT found in DSC file; Is it really a binary module?" % ModuleFile
)
372 for Arch
in self
.ArchList
:
374 Platform
= self
.BuildDatabase
[self
.MetaFile
, Arch
, Target
, Toolchain
]
376 for Pkey
in Platform
.Modules
:
377 MetaFileList
.add(Platform
.Modules
[Pkey
].MetaFile
)
378 for Inf
in self
.FdfProfile
.InfDict
[key
]:
379 ModuleFile
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, Arch
)
380 if ModuleFile
in MetaFileList
:
382 ModuleData
= self
.BuildDatabase
[ModuleFile
, Arch
, Target
, Toolchain
]
383 if not ModuleData
.IsBinaryModule
:
384 EdkLogger
.error('build', PARSER_ERROR
, "Module %s NOT found in DSC file; Is it really a binary module?" % ModuleFile
)
389 self
.FdfProfile
= None
390 if self
.FdTargetList
:
391 EdkLogger
.info("No flash definition file found. FD [%s] will be ignored." % " ".join(self
.FdTargetList
))
392 self
.FdTargetList
= []
393 if self
.FvTargetList
:
394 EdkLogger
.info("No flash definition file found. FV [%s] will be ignored." % " ".join(self
.FvTargetList
))
395 self
.FvTargetList
= []
396 if self
.CapTargetList
:
397 EdkLogger
.info("No flash definition file found. Capsule [%s] will be ignored." % " ".join(self
.CapTargetList
))
398 self
.CapTargetList
= []
400 # apply SKU and inject PCDs from Flash Definition file
401 for Arch
in self
.ArchList
:
402 Platform
= self
.BuildDatabase
[self
.MetaFile
, Arch
, Target
, Toolchain
]
403 PlatformPcds
= Platform
.Pcds
404 self
._GuidDict
= Platform
._GuidDict
405 SourcePcdDict
= {TAB_PCDS_DYNAMIC_EX
:set(), TAB_PCDS_PATCHABLE_IN_MODULE
:set(),TAB_PCDS_DYNAMIC
:set(),TAB_PCDS_FIXED_AT_BUILD
:set()}
406 BinaryPcdDict
= {TAB_PCDS_DYNAMIC_EX
:set(), TAB_PCDS_PATCHABLE_IN_MODULE
:set()}
407 SourcePcdDict_Keys
= SourcePcdDict
.keys()
408 BinaryPcdDict_Keys
= BinaryPcdDict
.keys()
410 # generate the SourcePcdDict and BinaryPcdDict
411 PGen
= PlatformAutoGen(self
, self
.MetaFile
, Target
, Toolchain
, Arch
)
412 for BuildData
in PGen
.BuildDatabase
._CACHE
_.values():
413 if BuildData
.Arch
!= Arch
:
415 if BuildData
.MetaFile
.Ext
== '.inf':
416 for key
in BuildData
.Pcds
:
417 if BuildData
.Pcds
[key
].Pending
:
418 if key
in Platform
.Pcds
:
419 PcdInPlatform
= Platform
.Pcds
[key
]
420 if PcdInPlatform
.Type
:
421 BuildData
.Pcds
[key
].Type
= PcdInPlatform
.Type
422 BuildData
.Pcds
[key
].Pending
= False
424 if BuildData
.MetaFile
in Platform
.Modules
:
425 PlatformModule
= Platform
.Modules
[str(BuildData
.MetaFile
)]
426 if key
in PlatformModule
.Pcds
:
427 PcdInPlatform
= PlatformModule
.Pcds
[key
]
428 if PcdInPlatform
.Type
:
429 BuildData
.Pcds
[key
].Type
= PcdInPlatform
.Type
430 BuildData
.Pcds
[key
].Pending
= False
432 #Pcd used in Library, Pcd Type from reference module if Pcd Type is Pending
433 if BuildData
.Pcds
[key
].Pending
:
434 MGen
= ModuleAutoGen(self
, BuildData
.MetaFile
, Target
, Toolchain
, Arch
, self
.MetaFile
)
435 if MGen
and MGen
.IsLibrary
:
436 if MGen
in PGen
.LibraryAutoGenList
:
437 ReferenceModules
= MGen
.ReferenceModules
438 for ReferenceModule
in ReferenceModules
:
439 if ReferenceModule
.MetaFile
in Platform
.Modules
:
440 RefPlatformModule
= Platform
.Modules
[str(ReferenceModule
.MetaFile
)]
441 if key
in RefPlatformModule
.Pcds
:
442 PcdInReferenceModule
= RefPlatformModule
.Pcds
[key
]
443 if PcdInReferenceModule
.Type
:
444 BuildData
.Pcds
[key
].Type
= PcdInReferenceModule
.Type
445 BuildData
.Pcds
[key
].Pending
= False
448 if TAB_PCDS_DYNAMIC_EX
in BuildData
.Pcds
[key
].Type
:
449 if BuildData
.IsBinaryModule
:
450 BinaryPcdDict
[TAB_PCDS_DYNAMIC_EX
].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
452 SourcePcdDict
[TAB_PCDS_DYNAMIC_EX
].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
454 elif TAB_PCDS_PATCHABLE_IN_MODULE
in BuildData
.Pcds
[key
].Type
:
455 if BuildData
.MetaFile
.Ext
== '.inf':
456 if BuildData
.IsBinaryModule
:
457 BinaryPcdDict
[TAB_PCDS_PATCHABLE_IN_MODULE
].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
459 SourcePcdDict
[TAB_PCDS_PATCHABLE_IN_MODULE
].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
461 elif TAB_PCDS_DYNAMIC
in BuildData
.Pcds
[key
].Type
:
462 SourcePcdDict
[TAB_PCDS_DYNAMIC
].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
463 elif TAB_PCDS_FIXED_AT_BUILD
in BuildData
.Pcds
[key
].Type
:
464 SourcePcdDict
[TAB_PCDS_FIXED_AT_BUILD
].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
468 # A PCD can only use one type for all source modules
470 for i
in SourcePcdDict_Keys
:
471 for j
in SourcePcdDict_Keys
:
473 Intersections
= SourcePcdDict
[i
].intersection(SourcePcdDict
[j
])
474 if len(Intersections
) > 0:
478 "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
),
479 ExtraData
='\n\t'.join(str(P
[1]+'.'+P
[0]) for P
in Intersections
)
483 # intersection the BinaryPCD for Mixed PCD
485 for i
in BinaryPcdDict_Keys
:
486 for j
in BinaryPcdDict_Keys
:
488 Intersections
= BinaryPcdDict
[i
].intersection(BinaryPcdDict
[j
])
489 for item
in Intersections
:
490 NewPcd1
= (item
[0] + '_' + i
, item
[1])
491 NewPcd2
= (item
[0] + '_' + j
, item
[1])
492 if item
not in GlobalData
.MixedPcd
:
493 GlobalData
.MixedPcd
[item
] = [NewPcd1
, NewPcd2
]
495 if NewPcd1
not in GlobalData
.MixedPcd
[item
]:
496 GlobalData
.MixedPcd
[item
].append(NewPcd1
)
497 if NewPcd2
not in GlobalData
.MixedPcd
[item
]:
498 GlobalData
.MixedPcd
[item
].append(NewPcd2
)
501 # intersection the SourcePCD and BinaryPCD for Mixed PCD
503 for i
in SourcePcdDict_Keys
:
504 for j
in BinaryPcdDict_Keys
:
506 Intersections
= SourcePcdDict
[i
].intersection(BinaryPcdDict
[j
])
507 for item
in Intersections
:
508 NewPcd1
= (item
[0] + '_' + i
, item
[1])
509 NewPcd2
= (item
[0] + '_' + j
, item
[1])
510 if item
not in GlobalData
.MixedPcd
:
511 GlobalData
.MixedPcd
[item
] = [NewPcd1
, NewPcd2
]
513 if NewPcd1
not in GlobalData
.MixedPcd
[item
]:
514 GlobalData
.MixedPcd
[item
].append(NewPcd1
)
515 if NewPcd2
not in GlobalData
.MixedPcd
[item
]:
516 GlobalData
.MixedPcd
[item
].append(NewPcd2
)
518 for BuildData
in PGen
.BuildDatabase
._CACHE
_.values():
519 if BuildData
.Arch
!= Arch
:
521 for key
in list(BuildData
.Pcds
.keys()):
522 for SinglePcd
in GlobalData
.MixedPcd
:
523 if (BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
) == SinglePcd
:
524 for item
in GlobalData
.MixedPcd
[SinglePcd
]:
525 Pcd_Type
= item
[0].split('_')[-1]
526 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 \
527 (Pcd_Type
== TAB_PCDS_DYNAMIC
and BuildData
.Pcds
[key
].Type
in PCD_DYNAMIC_TYPE_SET
):
528 Value
= BuildData
.Pcds
[key
]
529 Value
.TokenCName
= BuildData
.Pcds
[key
].TokenCName
+ '_' + Pcd_Type
531 newkey
= (Value
.TokenCName
, key
[1])
533 newkey
= (Value
.TokenCName
, key
[1], key
[2])
534 del BuildData
.Pcds
[key
]
535 BuildData
.Pcds
[newkey
] = Value
539 # handle the mixed pcd in FDF file
541 if key
in GlobalData
.MixedPcd
:
544 for item
in GlobalData
.MixedPcd
[key
]:
547 #Collect package set information from INF of FDF
549 for Inf
in ModuleList
:
550 ModuleFile
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, Arch
)
551 if ModuleFile
in Platform
.Modules
:
553 ModuleData
= self
.BuildDatabase
[ModuleFile
, Arch
, Target
, Toolchain
]
554 PkgSet
.update(ModuleData
.Packages
)
555 Pkgs
= list(PkgSet
) + list(PGen
.PackageList
)
560 DecPcds
.add((Pcd
[0], Pcd
[1]))
561 DecPcdsKey
.add((Pcd
[0], Pcd
[1], Pcd
[2]))
563 Platform
.SkuName
= self
.SkuId
564 for Name
, Guid
,Fileds
in PcdSet
:
565 if (Name
, Guid
) not in DecPcds
:
569 "PCD (%s.%s) used in FDF is not declared in DEC files." % (Guid
, Name
),
570 File
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
][0],
571 Line
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
][1]
574 # Check whether Dynamic or DynamicEx PCD used in FDF file. If used, build break and give a error message.
575 if (Name
, Guid
, TAB_PCDS_FIXED_AT_BUILD
) in DecPcdsKey \
576 or (Name
, Guid
, TAB_PCDS_PATCHABLE_IN_MODULE
) in DecPcdsKey \
577 or (Name
, Guid
, TAB_PCDS_FEATURE_FLAG
) in DecPcdsKey
:
579 elif (Name
, Guid
, TAB_PCDS_DYNAMIC
) in DecPcdsKey
or (Name
, Guid
, TAB_PCDS_DYNAMIC_EX
) in DecPcdsKey
:
583 "Using Dynamic or DynamicEx type of PCD [%s.%s] in FDF file is not allowed." % (Guid
, Name
),
584 File
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
][0],
585 Line
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
][1]
588 Pa
= PlatformAutoGen(self
, self
.MetaFile
, Target
, Toolchain
, Arch
)
590 # Explicitly collect platform's dynamic PCDs
592 Pa
.CollectPlatformDynamicPcds()
593 Pa
.CollectFixedAtBuildPcds()
594 self
.AutoGenObjectList
.append(Pa
)
597 # Generate Package level hash value
599 GlobalData
.gPackageHash
[Arch
] = {}
600 if GlobalData
.gUseHashCache
:
602 self
._GenPkgLevelHash
(Pkg
)
605 # Check PCDs token value conflict in each DEC file.
607 self
._CheckAllPcdsTokenValueConflict
()
610 # Check PCD type and definition between DSC and DEC
612 self
._CheckPcdDefineAndType
()
615 # Create BuildOptions Macro & PCD metafile, also add the Active Platform and FDF file.
617 content
= 'gCommandLineDefines: '
618 content
+= str(GlobalData
.gCommandLineDefines
)
620 content
+= 'BuildOptionPcd: '
621 content
+= str(GlobalData
.BuildOptionPcd
)
623 content
+= 'Active Platform: '
624 content
+= str(self
.Platform
)
627 content
+= 'Flash Image Definition: '
628 content
+= str(self
.FdfFile
)
630 SaveFileOnChange(os
.path
.join(self
.BuildDir
, 'BuildOptions'), content
, False)
633 # Create PcdToken Number file for Dynamic/DynamicEx Pcd.
635 PcdTokenNumber
= 'PcdTokenNumber: '
636 if Pa
.PcdTokenNumber
:
637 if Pa
.DynamicPcdList
:
638 for Pcd
in Pa
.DynamicPcdList
:
639 PcdTokenNumber
+= "\n"
640 PcdTokenNumber
+= str((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
))
641 PcdTokenNumber
+= ' : '
642 PcdTokenNumber
+= str(Pa
.PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
])
643 SaveFileOnChange(os
.path
.join(self
.BuildDir
, 'PcdTokenNumber'), PcdTokenNumber
, False)
646 # Get set of workspace metafiles
648 AllWorkSpaceMetaFiles
= self
._GetMetaFiles
(Target
, Toolchain
, Arch
)
651 # Retrieve latest modified time of all metafiles
654 for f
in AllWorkSpaceMetaFiles
:
655 if os
.stat(f
)[8] > SrcTimeStamp
:
656 SrcTimeStamp
= os
.stat(f
)[8]
657 self
._SrcTimeStamp
= SrcTimeStamp
659 if GlobalData
.gUseHashCache
:
661 for files
in AllWorkSpaceMetaFiles
:
662 if files
.endswith('.dec'):
664 f
= open(files
, 'rb')
668 SaveFileOnChange(os
.path
.join(self
.BuildDir
, 'AutoGen.hash'), m
.hexdigest(), True)
669 GlobalData
.gPlatformHash
= m
.hexdigest()
672 # Write metafile list to build directory
674 AutoGenFilePath
= os
.path
.join(self
.BuildDir
, 'AutoGen')
675 if os
.path
.exists (AutoGenFilePath
):
676 os
.remove(AutoGenFilePath
)
677 if not os
.path
.exists(self
.BuildDir
):
678 os
.makedirs(self
.BuildDir
)
679 with
open(os
.path
.join(self
.BuildDir
, 'AutoGen'), 'w+') as file:
680 for f
in sorted(AllWorkSpaceMetaFiles
):
684 def _GenPkgLevelHash(self
, Pkg
):
685 if Pkg
.PackageName
in GlobalData
.gPackageHash
[Pkg
.Arch
]:
688 PkgDir
= os
.path
.join(self
.BuildDir
, Pkg
.Arch
, Pkg
.PackageName
)
689 CreateDirectory(PkgDir
)
690 HashFile
= os
.path
.join(PkgDir
, Pkg
.PackageName
+ '.hash')
692 # Get .dec file's hash value
693 f
= open(Pkg
.MetaFile
.Path
, 'rb')
697 # Get include files hash value
699 for inc
in sorted(Pkg
.Includes
, key
=lambda x
: str(x
)):
700 for Root
, Dirs
, Files
in os
.walk(str(inc
)):
701 for File
in sorted(Files
):
702 File_Path
= os
.path
.join(Root
, File
)
703 f
= open(File_Path
, 'rb')
707 SaveFileOnChange(HashFile
, m
.hexdigest(), True)
708 GlobalData
.gPackageHash
[Pkg
.Arch
][Pkg
.PackageName
] = m
.hexdigest()
710 def _GetMetaFiles(self
, Target
, Toolchain
, Arch
):
711 AllWorkSpaceMetaFiles
= set()
716 AllWorkSpaceMetaFiles
.add (self
.FdfFile
.Path
)
717 for f
in GlobalData
.gFdfParser
.GetAllIncludedFile():
718 AllWorkSpaceMetaFiles
.add (f
.FileName
)
722 AllWorkSpaceMetaFiles
.add(self
.MetaFile
.Path
)
725 # add build_rule.txt & tools_def.txt
727 AllWorkSpaceMetaFiles
.add(os
.path
.join(GlobalData
.gConfDirectory
, gDefaultBuildRuleFile
))
728 AllWorkSpaceMetaFiles
.add(os
.path
.join(GlobalData
.gConfDirectory
, gDefaultToolsDefFile
))
730 # add BuildOption metafile
732 AllWorkSpaceMetaFiles
.add(os
.path
.join(self
.BuildDir
, 'BuildOptions'))
734 # add PcdToken Number file for Dynamic/DynamicEx Pcd
736 AllWorkSpaceMetaFiles
.add(os
.path
.join(self
.BuildDir
, 'PcdTokenNumber'))
738 for Arch
in self
.ArchList
:
742 for Package
in PlatformAutoGen(self
, self
.MetaFile
, Target
, Toolchain
, Arch
).PackageList
:
743 AllWorkSpaceMetaFiles
.add(Package
.MetaFile
.Path
)
748 for filePath
in self
.BuildDatabase
[self
.MetaFile
, Arch
, Target
, Toolchain
]._RawData
.IncludedFiles
:
749 AllWorkSpaceMetaFiles
.add(filePath
.Path
)
751 return AllWorkSpaceMetaFiles
753 def _CheckPcdDefineAndType(self
):
754 PcdTypeSet
= {TAB_PCDS_FIXED_AT_BUILD
,
755 TAB_PCDS_PATCHABLE_IN_MODULE
,
756 TAB_PCDS_FEATURE_FLAG
,
760 # This dict store PCDs which are not used by any modules with specified arches
761 UnusedPcd
= OrderedDict()
762 for Pa
in self
.AutoGenObjectList
:
763 # Key of DSC's Pcds dictionary is PcdCName, TokenSpaceGuid
764 for Pcd
in Pa
.Platform
.Pcds
:
765 PcdType
= Pa
.Platform
.Pcds
[Pcd
].Type
767 # If no PCD type, this PCD comes from FDF
771 # Try to remove Hii and Vpd suffix
772 if PcdType
.startswith(TAB_PCDS_DYNAMIC_EX
):
773 PcdType
= TAB_PCDS_DYNAMIC_EX
774 elif PcdType
.startswith(TAB_PCDS_DYNAMIC
):
775 PcdType
= TAB_PCDS_DYNAMIC
777 for Package
in Pa
.PackageList
:
778 # Key of DEC's Pcds dictionary is PcdCName, TokenSpaceGuid, PcdType
779 if (Pcd
[0], Pcd
[1], PcdType
) in Package
.Pcds
:
781 for Type
in PcdTypeSet
:
782 if (Pcd
[0], Pcd
[1], Type
) in Package
.Pcds
:
786 "Type [%s] of PCD [%s.%s] in DSC file doesn't match the type [%s] defined in DEC file." \
787 % (Pa
.Platform
.Pcds
[Pcd
].Type
, Pcd
[1], Pcd
[0], Type
),
792 UnusedPcd
.setdefault(Pcd
, []).append(Pa
.Arch
)
794 for Pcd
in UnusedPcd
:
797 "The PCD was not specified by any INF module in the platform for the given architecture.\n"
798 "\tPCD: [%s.%s]\n\tPlatform: [%s]\n\tArch: %s"
799 % (Pcd
[1], Pcd
[0], os
.path
.basename(str(self
.MetaFile
)), str(UnusedPcd
[Pcd
])),
804 return "%s [%s]" % (self
.MetaFile
, ", ".join(self
.ArchList
))
806 ## Return the directory to store FV files
809 return path
.join(self
.BuildDir
, TAB_FV_DIRECTORY
)
811 ## Return the directory to store all intermediate and final files built
814 return self
.AutoGenObjectList
[0].BuildDir
816 ## Return the build output directory platform specifies
819 return self
.Platform
.OutputDirectory
821 ## Return platform name
824 return self
.Platform
.PlatformName
826 ## Return meta-file GUID
829 return self
.Platform
.Guid
831 ## Return platform version
834 return self
.Platform
.Version
836 ## Return paths of tools
838 def ToolDefinition(self
):
839 return self
.AutoGenObjectList
[0].ToolDefinition
841 ## Return directory of platform makefile
843 # @retval string Makefile directory
846 def MakeFileDir(self
):
849 ## Return build command string
851 # @retval string Build command string
854 def BuildCommand(self
):
855 # BuildCommand should be all the same. So just get one from platform AutoGen
856 return self
.AutoGenObjectList
[0].BuildCommand
858 ## Check the PCDs token value conflict in each DEC file.
860 # Will cause build break and raise error message while two PCDs conflict.
864 def _CheckAllPcdsTokenValueConflict(self
):
865 for Pa
in self
.AutoGenObjectList
:
866 for Package
in Pa
.PackageList
:
867 PcdList
= list(Package
.Pcds
.values())
868 PcdList
.sort(key
=lambda x
: int(x
.TokenValue
, 0))
870 while (Count
< len(PcdList
) - 1) :
871 Item
= PcdList
[Count
]
872 ItemNext
= PcdList
[Count
+ 1]
874 # Make sure in the same token space the TokenValue should be unique
876 if (int(Item
.TokenValue
, 0) == int(ItemNext
.TokenValue
, 0)):
877 SameTokenValuePcdList
= []
878 SameTokenValuePcdList
.append(Item
)
879 SameTokenValuePcdList
.append(ItemNext
)
880 RemainPcdListLength
= len(PcdList
) - Count
- 2
881 for ValueSameCount
in range(RemainPcdListLength
):
882 if int(PcdList
[len(PcdList
) - RemainPcdListLength
+ ValueSameCount
].TokenValue
, 0) == int(Item
.TokenValue
, 0):
883 SameTokenValuePcdList
.append(PcdList
[len(PcdList
) - RemainPcdListLength
+ ValueSameCount
])
887 # Sort same token value PCD list with TokenGuid and TokenCName
889 SameTokenValuePcdList
.sort(key
=lambda x
: "%s.%s" % (x
.TokenSpaceGuidCName
, x
.TokenCName
))
890 SameTokenValuePcdListCount
= 0
891 while (SameTokenValuePcdListCount
< len(SameTokenValuePcdList
) - 1):
893 TemListItem
= SameTokenValuePcdList
[SameTokenValuePcdListCount
]
894 TemListItemNext
= SameTokenValuePcdList
[SameTokenValuePcdListCount
+ 1]
896 if (TemListItem
.TokenSpaceGuidCName
== TemListItemNext
.TokenSpaceGuidCName
) and (TemListItem
.TokenCName
!= TemListItemNext
.TokenCName
):
897 for PcdItem
in GlobalData
.MixedPcd
:
898 if (TemListItem
.TokenCName
, TemListItem
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
] or \
899 (TemListItemNext
.TokenCName
, TemListItemNext
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
905 "The TokenValue [%s] of PCD [%s.%s] is conflict with: [%s.%s] in %s"\
906 % (TemListItem
.TokenValue
, TemListItem
.TokenSpaceGuidCName
, TemListItem
.TokenCName
, TemListItemNext
.TokenSpaceGuidCName
, TemListItemNext
.TokenCName
, Package
),
909 SameTokenValuePcdListCount
+= 1
910 Count
+= SameTokenValuePcdListCount
913 PcdList
= list(Package
.Pcds
.values())
914 PcdList
.sort(key
=lambda x
: "%s.%s" % (x
.TokenSpaceGuidCName
, x
.TokenCName
))
916 while (Count
< len(PcdList
) - 1) :
917 Item
= PcdList
[Count
]
918 ItemNext
= PcdList
[Count
+ 1]
920 # Check PCDs with same TokenSpaceGuidCName.TokenCName have same token value as well.
922 if (Item
.TokenSpaceGuidCName
== ItemNext
.TokenSpaceGuidCName
) and (Item
.TokenCName
== ItemNext
.TokenCName
) and (int(Item
.TokenValue
, 0) != int(ItemNext
.TokenValue
, 0)):
926 "The TokenValue [%s] of PCD [%s.%s] in %s defined in two places should be same as well."\
927 % (Item
.TokenValue
, Item
.TokenSpaceGuidCName
, Item
.TokenCName
, Package
),
931 ## Generate fds command
933 def GenFdsCommand(self
):
934 return (GenMake
.TopLevelMakefile(self
)._TEMPLATE
_.Replace(GenMake
.TopLevelMakefile(self
)._TemplateDict
)).strip()
936 ## Create makefile for the platform and modules in it
938 # @param CreateDepsMakeFile Flag indicating if the makefile for
939 # modules will be created as well
941 def CreateMakeFile(self
, CreateDepsMakeFile
=False):
942 if not CreateDepsMakeFile
:
944 for Pa
in self
.AutoGenObjectList
:
945 Pa
.CreateMakeFile(True)
947 ## Create autogen code for platform and modules
949 # Since there's no autogen code for platform, this method will do nothing
950 # if CreateModuleCodeFile is set to False.
952 # @param CreateDepsCodeFile Flag indicating if creating module's
953 # autogen code file or not
955 def CreateCodeFile(self
, CreateDepsCodeFile
=False):
956 if not CreateDepsCodeFile
:
958 for Pa
in self
.AutoGenObjectList
:
959 Pa
.CreateCodeFile(True)
961 ## Create AsBuilt INF file the platform
963 def CreateAsBuiltInf(self
):
967 ## AutoGen class for platform
969 # PlatformAutoGen class will process the original information in platform
970 # file in order to generate makefile for platform.
972 class PlatformAutoGen(AutoGen
):
973 # call super().__init__ then call the worker function with different parameter count
974 def __init__(self
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
975 if not hasattr(self
, "_Init"):
976 super().__init
__(self
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
)
977 self
._InitWorker
(Workspace
, MetaFile
, Target
, Toolchain
, Arch
)
980 # Used to store all PCDs for both PEI and DXE phase, in order to generate
981 # correct PCD database
984 _NonDynaPcdList_
= []
988 # The priority list while override build option
990 PrioList
= {"0x11111" : 16, # TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE (Highest)
991 "0x01111" : 15, # ******_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
992 "0x10111" : 14, # TARGET_*********_ARCH_COMMANDTYPE_ATTRIBUTE
993 "0x00111" : 13, # ******_*********_ARCH_COMMANDTYPE_ATTRIBUTE
994 "0x11011" : 12, # TARGET_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
995 "0x01011" : 11, # ******_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
996 "0x10011" : 10, # TARGET_*********_****_COMMANDTYPE_ATTRIBUTE
997 "0x00011" : 9, # ******_*********_****_COMMANDTYPE_ATTRIBUTE
998 "0x11101" : 8, # TARGET_TOOLCHAIN_ARCH_***********_ATTRIBUTE
999 "0x01101" : 7, # ******_TOOLCHAIN_ARCH_***********_ATTRIBUTE
1000 "0x10101" : 6, # TARGET_*********_ARCH_***********_ATTRIBUTE
1001 "0x00101" : 5, # ******_*********_ARCH_***********_ATTRIBUTE
1002 "0x11001" : 4, # TARGET_TOOLCHAIN_****_***********_ATTRIBUTE
1003 "0x01001" : 3, # ******_TOOLCHAIN_****_***********_ATTRIBUTE
1004 "0x10001" : 2, # TARGET_*********_****_***********_ATTRIBUTE
1005 "0x00001" : 1} # ******_*********_****_***********_ATTRIBUTE (Lowest)
1007 ## Initialize PlatformAutoGen
1010 # @param Workspace WorkspaceAutoGen object
1011 # @param PlatformFile Platform file (DSC file)
1012 # @param Target Build target (DEBUG, RELEASE)
1013 # @param Toolchain Name of tool chain
1014 # @param Arch arch of the platform supports
1016 def _InitWorker(self
, Workspace
, PlatformFile
, Target
, Toolchain
, Arch
):
1017 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "AutoGen platform [%s] [%s]" % (PlatformFile
, Arch
))
1018 GlobalData
.gProcessingFile
= "%s [%s, %s, %s]" % (PlatformFile
, Arch
, Toolchain
, Target
)
1020 self
.MetaFile
= PlatformFile
1021 self
.Workspace
= Workspace
1022 self
.WorkspaceDir
= Workspace
.WorkspaceDir
1023 self
.ToolChain
= Toolchain
1024 self
.BuildTarget
= Target
1026 self
.SourceDir
= PlatformFile
.SubDir
1027 self
.SourceOverrideDir
= None
1028 self
.FdTargetList
= self
.Workspace
.FdTargetList
1029 self
.FvTargetList
= self
.Workspace
.FvTargetList
1030 self
.AllPcdList
= []
1031 # get the original module/package/platform objects
1032 self
.BuildDatabase
= Workspace
.BuildDatabase
1033 self
.DscBuildDataObj
= Workspace
.Platform
1035 # flag indicating if the makefile/C-code file has been created or not
1036 self
.IsMakeFileCreated
= False
1038 self
._DynamicPcdList
= None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
1039 self
._NonDynamicPcdList
= None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
1041 self
._AsBuildInfList
= []
1042 self
._AsBuildModuleList
= []
1044 self
.VariableInfo
= None
1046 if GlobalData
.gFdfParser
is not None:
1047 self
._AsBuildInfList
= GlobalData
.gFdfParser
.Profile
.InfList
1048 for Inf
in self
._AsBuildInfList
:
1049 InfClass
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, self
.Arch
)
1050 M
= self
.BuildDatabase
[InfClass
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1051 if not M
.IsBinaryModule
:
1053 self
._AsBuildModuleList
.append(InfClass
)
1054 # get library/modules for build
1055 self
.LibraryBuildDirectoryList
= []
1056 self
.ModuleBuildDirectoryList
= []
1060 @cached_class_function
1062 return "%s [%s]" % (self
.MetaFile
, self
.Arch
)
1064 ## Create autogen code for platform and modules
1066 # Since there's no autogen code for platform, this method will do nothing
1067 # if CreateModuleCodeFile is set to False.
1069 # @param CreateModuleCodeFile Flag indicating if creating module's
1070 # autogen code file or not
1072 @cached_class_function
1073 def CreateCodeFile(self
, CreateModuleCodeFile
=False):
1074 # only module has code to be greated, so do nothing if CreateModuleCodeFile is False
1075 if not CreateModuleCodeFile
:
1078 for Ma
in self
.ModuleAutoGenList
:
1079 Ma
.CreateCodeFile(True)
1081 ## Generate Fds Command
1083 def GenFdsCommand(self
):
1084 return self
.Workspace
.GenFdsCommand
1086 ## Create makefile for the platform and modules in it
1088 # @param CreateModuleMakeFile Flag indicating if the makefile for
1089 # modules will be created as well
1091 def CreateMakeFile(self
, CreateModuleMakeFile
=False, FfsCommand
= {}):
1092 if CreateModuleMakeFile
:
1093 for Ma
in self
._MaList
:
1094 key
= (Ma
.MetaFile
.File
, self
.Arch
)
1095 if key
in FfsCommand
:
1096 Ma
.CreateMakeFile(True, FfsCommand
[key
])
1098 Ma
.CreateMakeFile(True)
1100 # no need to create makefile for the platform more than once
1101 if self
.IsMakeFileCreated
:
1104 # create library/module build dirs for platform
1105 Makefile
= GenMake
.PlatformMakefile(self
)
1106 self
.LibraryBuildDirectoryList
= Makefile
.GetLibraryBuildDirectoryList()
1107 self
.ModuleBuildDirectoryList
= Makefile
.GetModuleBuildDirectoryList()
1109 self
.IsMakeFileCreated
= True
1111 ## Deal with Shared FixedAtBuild Pcds
1113 def CollectFixedAtBuildPcds(self
):
1114 for LibAuto
in self
.LibraryAutoGenList
:
1115 FixedAtBuildPcds
= {}
1116 ShareFixedAtBuildPcdsSameValue
= {}
1117 for Module
in LibAuto
.ReferenceModules
:
1118 for Pcd
in set(Module
.FixedAtBuildPcds
+ LibAuto
.FixedAtBuildPcds
):
1119 DefaultValue
= Pcd
.DefaultValue
1120 # Cover the case: DSC component override the Pcd value and the Pcd only used in one Lib
1121 if Pcd
in Module
.LibraryPcdList
:
1122 Index
= Module
.LibraryPcdList
.index(Pcd
)
1123 DefaultValue
= Module
.LibraryPcdList
[Index
].DefaultValue
1124 key
= ".".join((Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
1125 if key
not in FixedAtBuildPcds
:
1126 ShareFixedAtBuildPcdsSameValue
[key
] = True
1127 FixedAtBuildPcds
[key
] = DefaultValue
1129 if FixedAtBuildPcds
[key
] != DefaultValue
:
1130 ShareFixedAtBuildPcdsSameValue
[key
] = False
1131 for Pcd
in LibAuto
.FixedAtBuildPcds
:
1132 key
= ".".join((Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
1133 if (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
) not in self
.NonDynamicPcdDict
:
1136 DscPcd
= self
.NonDynamicPcdDict
[(Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
)]
1137 if DscPcd
.Type
!= TAB_PCDS_FIXED_AT_BUILD
:
1139 if key
in ShareFixedAtBuildPcdsSameValue
and ShareFixedAtBuildPcdsSameValue
[key
]:
1140 LibAuto
.ConstPcd
[key
] = FixedAtBuildPcds
[key
]
1142 def CollectVariables(self
, DynamicPcdSet
):
1145 if self
.Workspace
.FdfFile
:
1146 FdDict
= self
.Workspace
.FdfProfile
.FdDict
[GlobalData
.gFdfParser
.CurrentFdName
]
1147 for FdRegion
in FdDict
.RegionList
:
1148 for item
in FdRegion
.RegionDataList
:
1149 if self
.Platform
.VpdToolGuid
.strip() and self
.Platform
.VpdToolGuid
in item
:
1150 VpdRegionSize
= FdRegion
.Size
1151 VpdRegionBase
= FdRegion
.Offset
1154 VariableInfo
= VariableMgr(self
.DscBuildDataObj
._GetDefaultStores
(), self
.DscBuildDataObj
.SkuIds
)
1155 VariableInfo
.SetVpdRegionMaxSize(VpdRegionSize
)
1156 VariableInfo
.SetVpdRegionOffset(VpdRegionBase
)
1158 for Pcd
in DynamicPcdSet
:
1159 pcdname
= ".".join((Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
1160 for SkuName
in Pcd
.SkuInfoList
:
1161 Sku
= Pcd
.SkuInfoList
[SkuName
]
1163 if SkuId
is None or SkuId
== '':
1165 if len(Sku
.VariableName
) > 0:
1166 VariableGuidStructure
= Sku
.VariableGuidValue
1167 VariableGuid
= GuidStructureStringToGuidString(VariableGuidStructure
)
1168 for StorageName
in Sku
.DefaultStoreDict
:
1169 VariableInfo
.append_variable(var_info(Index
, pcdname
, StorageName
, SkuName
, StringToArray(Sku
.VariableName
), VariableGuid
, Sku
.VariableOffset
, Sku
.VariableAttribute
, Sku
.HiiDefaultValue
, Sku
.DefaultStoreDict
[StorageName
], Pcd
.DatumType
, Pcd
.CustomAttribute
['DscPosition'], Pcd
.CustomAttribute
.get('IsStru',False)))
1173 def UpdateNVStoreMaxSize(self
, OrgVpdFile
):
1174 if self
.VariableInfo
:
1175 VpdMapFilePath
= os
.path
.join(self
.BuildDir
, TAB_FV_DIRECTORY
, "%s.map" % self
.Platform
.VpdToolGuid
)
1176 PcdNvStoreDfBuffer
= [item
for item
in self
._DynamicPcdList
if item
.TokenCName
== "PcdNvStoreDefaultValueBuffer" and item
.TokenSpaceGuidCName
== "gEfiMdeModulePkgTokenSpaceGuid"]
1178 if PcdNvStoreDfBuffer
:
1179 if os
.path
.exists(VpdMapFilePath
):
1180 OrgVpdFile
.Read(VpdMapFilePath
)
1181 PcdItems
= OrgVpdFile
.GetOffset(PcdNvStoreDfBuffer
[0])
1182 NvStoreOffset
= list(PcdItems
.values())[0].strip() if PcdItems
else '0'
1184 EdkLogger
.error("build", FILE_READ_FAILURE
, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath
)
1186 NvStoreOffset
= int(NvStoreOffset
, 16) if NvStoreOffset
.upper().startswith("0X") else int(NvStoreOffset
)
1187 default_skuobj
= PcdNvStoreDfBuffer
[0].SkuInfoList
.get(TAB_DEFAULT
)
1188 maxsize
= self
.VariableInfo
.VpdRegionSize
- NvStoreOffset
if self
.VariableInfo
.VpdRegionSize
else len(default_skuobj
.DefaultValue
.split(","))
1189 var_data
= self
.VariableInfo
.PatchNVStoreDefaultMaxSize(maxsize
)
1191 if var_data
and default_skuobj
:
1192 default_skuobj
.DefaultValue
= var_data
1193 PcdNvStoreDfBuffer
[0].DefaultValue
= var_data
1194 PcdNvStoreDfBuffer
[0].SkuInfoList
.clear()
1195 PcdNvStoreDfBuffer
[0].SkuInfoList
[TAB_DEFAULT
] = default_skuobj
1196 PcdNvStoreDfBuffer
[0].MaxDatumSize
= str(len(default_skuobj
.DefaultValue
.split(",")))
1200 ## Collect dynamic PCDs
1202 # Gather dynamic PCDs list from each module and their settings from platform
1203 # This interface should be invoked explicitly when platform action is created.
1205 def CollectPlatformDynamicPcds(self
):
1206 for key
in self
.Platform
.Pcds
:
1207 for SinglePcd
in GlobalData
.MixedPcd
:
1208 if (self
.Platform
.Pcds
[key
].TokenCName
, self
.Platform
.Pcds
[key
].TokenSpaceGuidCName
) == SinglePcd
:
1209 for item
in GlobalData
.MixedPcd
[SinglePcd
]:
1210 Pcd_Type
= item
[0].split('_')[-1]
1211 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 \
1212 (Pcd_Type
== TAB_PCDS_DYNAMIC
and self
.Platform
.Pcds
[key
].Type
in PCD_DYNAMIC_TYPE_SET
):
1213 Value
= self
.Platform
.Pcds
[key
]
1214 Value
.TokenCName
= self
.Platform
.Pcds
[key
].TokenCName
+ '_' + Pcd_Type
1216 newkey
= (Value
.TokenCName
, key
[1])
1218 newkey
= (Value
.TokenCName
, key
[1], key
[2])
1219 del self
.Platform
.Pcds
[key
]
1220 self
.Platform
.Pcds
[newkey
] = Value
1224 # for gathering error information
1225 NoDatumTypePcdList
= set()
1227 for InfName
in self
._AsBuildInfList
:
1228 InfName
= mws
.join(self
.WorkspaceDir
, InfName
)
1229 FdfModuleList
.append(os
.path
.normpath(InfName
))
1230 for M
in self
._MaList
:
1231 # F is the Module for which M is the module autogen
1232 for PcdFromModule
in list(M
.ModulePcdList
) + list(M
.LibraryPcdList
):
1233 # make sure that the "VOID*" kind of datum has MaxDatumSize set
1234 if PcdFromModule
.DatumType
== TAB_VOID
and not PcdFromModule
.MaxDatumSize
:
1235 NoDatumTypePcdList
.add("%s.%s [%s]" % (PcdFromModule
.TokenSpaceGuidCName
, PcdFromModule
.TokenCName
, M
.MetaFile
))
1237 # Check the PCD from Binary INF or Source INF
1238 if M
.IsBinaryModule
== True:
1239 PcdFromModule
.IsFromBinaryInf
= True
1241 # Check the PCD from DSC or not
1242 PcdFromModule
.IsFromDsc
= (PcdFromModule
.TokenCName
, PcdFromModule
.TokenSpaceGuidCName
) in self
.Platform
.Pcds
1244 if PcdFromModule
.Type
in PCD_DYNAMIC_TYPE_SET
or PcdFromModule
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
1245 if M
.MetaFile
.Path
not in FdfModuleList
:
1246 # If one of the Source built modules listed in the DSC is not listed
1247 # in FDF modules, and the INF lists a PCD can only use the PcdsDynamic
1248 # access method (it is only listed in the DEC file that declares the
1249 # PCD as PcdsDynamic), then build tool will report warning message
1250 # notify the PI that they are attempting to build a module that must
1251 # be included in a flash image in order to be functional. These Dynamic
1252 # PCD will not be added into the Database unless it is used by other
1253 # modules that are included in the FDF file.
1254 if PcdFromModule
.Type
in PCD_DYNAMIC_TYPE_SET
and \
1255 PcdFromModule
.IsFromBinaryInf
== False:
1256 # Print warning message to let the developer make a determine.
1258 # If one of the Source built modules listed in the DSC is not listed in
1259 # FDF modules, and the INF lists a PCD can only use the PcdsDynamicEx
1260 # access method (it is only listed in the DEC file that declares the
1261 # PCD as PcdsDynamicEx), then DO NOT break the build; DO NOT add the
1262 # PCD to the Platform's PCD Database.
1263 if PcdFromModule
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
1266 # If a dynamic PCD used by a PEM module/PEI module & DXE module,
1267 # it should be stored in Pcd PEI database, If a dynamic only
1268 # used by DXE module, it should be stored in DXE PCD database.
1269 # The default Phase is DXE
1271 if M
.ModuleType
in SUP_MODULE_SET_PEI
:
1272 PcdFromModule
.Phase
= "PEI"
1273 if PcdFromModule
not in self
._DynaPcdList
_:
1274 self
._DynaPcdList
_.append(PcdFromModule
)
1275 elif PcdFromModule
.Phase
== 'PEI':
1276 # overwrite any the same PCD existing, if Phase is PEI
1277 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1278 self
._DynaPcdList
_[Index
] = PcdFromModule
1279 elif PcdFromModule
not in self
._NonDynaPcdList
_:
1280 self
._NonDynaPcdList
_.append(PcdFromModule
)
1281 elif PcdFromModule
in self
._NonDynaPcdList
_ and PcdFromModule
.IsFromBinaryInf
== True:
1282 Index
= self
._NonDynaPcdList
_.index(PcdFromModule
)
1283 if self
._NonDynaPcdList
_[Index
].IsFromBinaryInf
== False:
1284 #The PCD from Binary INF will override the same one from source INF
1285 self
._NonDynaPcdList
_.remove (self
._NonDynaPcdList
_[Index
])
1286 PcdFromModule
.Pending
= False
1287 self
._NonDynaPcdList
_.append (PcdFromModule
)
1288 DscModuleSet
= {os
.path
.normpath(ModuleInf
.Path
) for ModuleInf
in self
.Platform
.Modules
}
1289 # add the PCD from modules that listed in FDF but not in DSC to Database
1290 for InfName
in FdfModuleList
:
1291 if InfName
not in DscModuleSet
:
1292 InfClass
= PathClass(InfName
)
1293 M
= self
.BuildDatabase
[InfClass
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1294 # If a module INF in FDF but not in current arch's DSC module list, it must be module (either binary or source)
1295 # for different Arch. PCDs in source module for different Arch is already added before, so skip the source module here.
1296 # For binary module, if in current arch, we need to list the PCDs into database.
1297 if not M
.IsBinaryModule
:
1299 # Override the module PCD setting by platform setting
1300 ModulePcdList
= self
.ApplyPcdSetting(M
, M
.Pcds
)
1301 for PcdFromModule
in ModulePcdList
:
1302 PcdFromModule
.IsFromBinaryInf
= True
1303 PcdFromModule
.IsFromDsc
= False
1304 # Only allow the DynamicEx and Patchable PCD in AsBuild INF
1305 if PcdFromModule
.Type
not in PCD_DYNAMIC_EX_TYPE_SET
and PcdFromModule
.Type
not in TAB_PCDS_PATCHABLE_IN_MODULE
:
1306 EdkLogger
.error("build", AUTOGEN_ERROR
, "PCD setting error",
1308 ExtraData
="\n\tExisted %s PCD %s in:\n\t\t%s\n"
1309 % (PcdFromModule
.Type
, PcdFromModule
.TokenCName
, InfName
))
1310 # make sure that the "VOID*" kind of datum has MaxDatumSize set
1311 if PcdFromModule
.DatumType
== TAB_VOID
and not PcdFromModule
.MaxDatumSize
:
1312 NoDatumTypePcdList
.add("%s.%s [%s]" % (PcdFromModule
.TokenSpaceGuidCName
, PcdFromModule
.TokenCName
, InfName
))
1313 if M
.ModuleType
in SUP_MODULE_SET_PEI
:
1314 PcdFromModule
.Phase
= "PEI"
1315 if PcdFromModule
not in self
._DynaPcdList
_ and PcdFromModule
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
1316 self
._DynaPcdList
_.append(PcdFromModule
)
1317 elif PcdFromModule
not in self
._NonDynaPcdList
_ and PcdFromModule
.Type
in TAB_PCDS_PATCHABLE_IN_MODULE
:
1318 self
._NonDynaPcdList
_.append(PcdFromModule
)
1319 if PcdFromModule
in self
._DynaPcdList
_ and PcdFromModule
.Phase
== 'PEI' and PcdFromModule
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
1320 # Overwrite the phase of any the same PCD existing, if Phase is PEI.
1321 # It is to solve the case that a dynamic PCD used by a PEM module/PEI
1322 # module & DXE module at a same time.
1323 # Overwrite the type of the PCDs in source INF by the type of AsBuild
1324 # INF file as DynamicEx.
1325 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1326 self
._DynaPcdList
_[Index
].Phase
= PcdFromModule
.Phase
1327 self
._DynaPcdList
_[Index
].Type
= PcdFromModule
.Type
1328 for PcdFromModule
in self
._NonDynaPcdList
_:
1329 # If a PCD is not listed in the DSC file, but binary INF files used by
1330 # this platform all (that use this PCD) list the PCD in a [PatchPcds]
1331 # section, AND all source INF files used by this platform the build
1332 # that use the PCD list the PCD in either a [Pcds] or [PatchPcds]
1333 # section, then the tools must NOT add the PCD to the Platform's PCD
1334 # Database; the build must assign the access method for this PCD as
1335 # PcdsPatchableInModule.
1336 if PcdFromModule
not in self
._DynaPcdList
_:
1338 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1339 if PcdFromModule
.IsFromDsc
== False and \
1340 PcdFromModule
.Type
in TAB_PCDS_PATCHABLE_IN_MODULE
and \
1341 PcdFromModule
.IsFromBinaryInf
== True and \
1342 self
._DynaPcdList
_[Index
].IsFromBinaryInf
== False:
1343 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1344 self
._DynaPcdList
_.remove (self
._DynaPcdList
_[Index
])
1346 # print out error information and break the build, if error found
1347 if len(NoDatumTypePcdList
) > 0:
1348 NoDatumTypePcdListString
= "\n\t\t".join(NoDatumTypePcdList
)
1349 EdkLogger
.error("build", AUTOGEN_ERROR
, "PCD setting error",
1351 ExtraData
="\n\tPCD(s) without MaxDatumSize:\n\t\t%s\n"
1352 % NoDatumTypePcdListString
)
1353 self
._NonDynamicPcdList
= self
._NonDynaPcdList
_
1354 self
._DynamicPcdList
= self
._DynaPcdList
_
1356 # Sort dynamic PCD list to:
1357 # 1) If PCD's datum type is VOID* and value is unicode string which starts with L, the PCD item should
1358 # try to be put header of dynamicd List
1359 # 2) If PCD is HII type, the PCD item should be put after unicode type PCD
1361 # The reason of sorting is make sure the unicode string is in double-byte alignment in string table.
1363 UnicodePcdArray
= set()
1365 OtherPcdArray
= set()
1367 VpdFile
= VpdInfoFile
.VpdInfoFile()
1368 NeedProcessVpdMapFile
= False
1370 for pcd
in self
.Platform
.Pcds
:
1371 if pcd
not in self
._PlatformPcds
:
1372 self
._PlatformPcds
[pcd
] = self
.Platform
.Pcds
[pcd
]
1374 for item
in self
._PlatformPcds
:
1375 if self
._PlatformPcds
[item
].DatumType
and self
._PlatformPcds
[item
].DatumType
not in [TAB_UINT8
, TAB_UINT16
, TAB_UINT32
, TAB_UINT64
, TAB_VOID
, "BOOLEAN"]:
1376 self
._PlatformPcds
[item
].DatumType
= TAB_VOID
1378 if (self
.Workspace
.ArchList
[-1] == self
.Arch
):
1379 for Pcd
in self
._DynamicPcdList
:
1380 # just pick the a value to determine whether is unicode string type
1381 Sku
= list(Pcd
.SkuInfoList
.values())[0]
1382 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1384 if Pcd
.DatumType
not in [TAB_UINT8
, TAB_UINT16
, TAB_UINT32
, TAB_UINT64
, TAB_VOID
, "BOOLEAN"]:
1385 Pcd
.DatumType
= TAB_VOID
1387 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
1388 # if found HII type PCD then insert to right of UnicodeIndex
1389 if Pcd
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
]:
1390 VpdPcdDict
[(Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
)] = Pcd
1392 #Collect DynamicHii PCD values and assign it to DynamicExVpd PCD gEfiMdeModulePkgTokenSpaceGuid.PcdNvStoreDefaultValueBuffer
1393 PcdNvStoreDfBuffer
= VpdPcdDict
.get(("PcdNvStoreDefaultValueBuffer", "gEfiMdeModulePkgTokenSpaceGuid"))
1394 if PcdNvStoreDfBuffer
:
1395 self
.VariableInfo
= self
.CollectVariables(self
._DynamicPcdList
)
1396 vardump
= self
.VariableInfo
.dump()
1398 PcdNvStoreDfBuffer
.DefaultValue
= vardump
1399 for skuname
in PcdNvStoreDfBuffer
.SkuInfoList
:
1400 PcdNvStoreDfBuffer
.SkuInfoList
[skuname
].DefaultValue
= vardump
1401 PcdNvStoreDfBuffer
.MaxDatumSize
= str(len(vardump
.split(",")))
1403 #If the end user define [DefaultStores] and [XXX.Menufacturing] in DSC, but forget to configure PcdNvStoreDefaultValueBuffer to PcdsDynamicVpd
1404 if [Pcd
for Pcd
in self
._DynamicPcdList
if Pcd
.UserDefinedDefaultStoresFlag
]:
1405 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
)
1406 PlatformPcds
= sorted(self
._PlatformPcds
.keys())
1408 # Add VPD type PCD into VpdFile and determine whether the VPD PCD need to be fixed up.
1411 for PcdKey
in PlatformPcds
:
1412 Pcd
= self
._PlatformPcds
[PcdKey
]
1413 if Pcd
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
] and \
1414 PcdKey
in VpdPcdDict
:
1415 Pcd
= VpdPcdDict
[PcdKey
]
1417 DefaultSku
= Pcd
.SkuInfoList
.get(TAB_DEFAULT
)
1419 PcdValue
= DefaultSku
.DefaultValue
1420 if PcdValue
not in SkuValueMap
:
1421 SkuValueMap
[PcdValue
] = []
1422 VpdFile
.Add(Pcd
, TAB_DEFAULT
, DefaultSku
.VpdOffset
)
1423 SkuValueMap
[PcdValue
].append(DefaultSku
)
1425 for (SkuName
, Sku
) in Pcd
.SkuInfoList
.items():
1426 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1427 PcdValue
= Sku
.DefaultValue
1429 PcdValue
= Pcd
.DefaultValue
1430 if Sku
.VpdOffset
!= '*':
1431 if PcdValue
.startswith("{"):
1433 elif PcdValue
.startswith("L"):
1438 VpdOffset
= int(Sku
.VpdOffset
)
1441 VpdOffset
= int(Sku
.VpdOffset
, 16)
1443 EdkLogger
.error("build", FORMAT_INVALID
, "Invalid offset value %s for PCD %s.%s." % (Sku
.VpdOffset
, Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
1444 if VpdOffset
% Alignment
!= 0:
1445 if PcdValue
.startswith("{"):
1446 EdkLogger
.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
), File
=self
.MetaFile
)
1448 EdkLogger
.error("build", FORMAT_INVALID
, 'The offset value of PCD %s.%s should be %s-byte aligned.' % (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
, Alignment
))
1449 if PcdValue
not in SkuValueMap
:
1450 SkuValueMap
[PcdValue
] = []
1451 VpdFile
.Add(Pcd
, SkuName
, Sku
.VpdOffset
)
1452 SkuValueMap
[PcdValue
].append(Sku
)
1453 # if the offset of a VPD is *, then it need to be fixed up by third party tool.
1454 if not NeedProcessVpdMapFile
and Sku
.VpdOffset
== "*":
1455 NeedProcessVpdMapFile
= True
1456 if self
.Platform
.VpdToolGuid
is None or self
.Platform
.VpdToolGuid
== '':
1457 EdkLogger
.error("Build", FILE_NOT_FOUND
, \
1458 "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.")
1460 VpdSkuMap
[PcdKey
] = SkuValueMap
1462 # Fix the PCDs define in VPD PCD section that never referenced by module.
1463 # An example is PCD for signature usage.
1465 for DscPcd
in PlatformPcds
:
1466 DscPcdEntry
= self
._PlatformPcds
[DscPcd
]
1467 if DscPcdEntry
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
]:
1468 if not (self
.Platform
.VpdToolGuid
is None or self
.Platform
.VpdToolGuid
== ''):
1470 for VpdPcd
in VpdFile
._VpdArray
:
1471 # This PCD has been referenced by module
1472 if (VpdPcd
.TokenSpaceGuidCName
== DscPcdEntry
.TokenSpaceGuidCName
) and \
1473 (VpdPcd
.TokenCName
== DscPcdEntry
.TokenCName
):
1476 # Not found, it should be signature
1478 # just pick the a value to determine whether is unicode string type
1480 SkuObjList
= list(DscPcdEntry
.SkuInfoList
.items())
1481 DefaultSku
= DscPcdEntry
.SkuInfoList
.get(TAB_DEFAULT
)
1483 defaultindex
= SkuObjList
.index((TAB_DEFAULT
, DefaultSku
))
1484 SkuObjList
[0], SkuObjList
[defaultindex
] = SkuObjList
[defaultindex
], SkuObjList
[0]
1485 for (SkuName
, Sku
) in SkuObjList
:
1486 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1488 # Need to iterate DEC pcd information to get the value & datumtype
1489 for eachDec
in self
.PackageList
:
1490 for DecPcd
in eachDec
.Pcds
:
1491 DecPcdEntry
= eachDec
.Pcds
[DecPcd
]
1492 if (DecPcdEntry
.TokenSpaceGuidCName
== DscPcdEntry
.TokenSpaceGuidCName
) and \
1493 (DecPcdEntry
.TokenCName
== DscPcdEntry
.TokenCName
):
1494 # Print warning message to let the developer make a determine.
1495 EdkLogger
.warn("build", "Unreferenced vpd pcd used!",
1496 File
=self
.MetaFile
, \
1497 ExtraData
= "PCD: %s.%s used in the DSC file %s is unreferenced." \
1498 %(DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
, self
.Platform
.MetaFile
.Path
))
1500 DscPcdEntry
.DatumType
= DecPcdEntry
.DatumType
1501 DscPcdEntry
.DefaultValue
= DecPcdEntry
.DefaultValue
1502 DscPcdEntry
.TokenValue
= DecPcdEntry
.TokenValue
1503 DscPcdEntry
.TokenSpaceGuidValue
= eachDec
.Guids
[DecPcdEntry
.TokenSpaceGuidCName
]
1504 # Only fix the value while no value provided in DSC file.
1505 if not Sku
.DefaultValue
:
1506 DscPcdEntry
.SkuInfoList
[list(DscPcdEntry
.SkuInfoList
.keys())[0]].DefaultValue
= DecPcdEntry
.DefaultValue
1508 if DscPcdEntry
not in self
._DynamicPcdList
:
1509 self
._DynamicPcdList
.append(DscPcdEntry
)
1510 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1511 PcdValue
= Sku
.DefaultValue
1513 PcdValue
= DscPcdEntry
.DefaultValue
1514 if Sku
.VpdOffset
!= '*':
1515 if PcdValue
.startswith("{"):
1517 elif PcdValue
.startswith("L"):
1522 VpdOffset
= int(Sku
.VpdOffset
)
1525 VpdOffset
= int(Sku
.VpdOffset
, 16)
1527 EdkLogger
.error("build", FORMAT_INVALID
, "Invalid offset value %s for PCD %s.%s." % (Sku
.VpdOffset
, DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
))
1528 if VpdOffset
% Alignment
!= 0:
1529 if PcdValue
.startswith("{"):
1530 EdkLogger
.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
), File
=self
.MetaFile
)
1532 EdkLogger
.error("build", FORMAT_INVALID
, 'The offset value of PCD %s.%s should be %s-byte aligned.' % (DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
, Alignment
))
1533 if PcdValue
not in SkuValueMap
:
1534 SkuValueMap
[PcdValue
] = []
1535 VpdFile
.Add(DscPcdEntry
, SkuName
, Sku
.VpdOffset
)
1536 SkuValueMap
[PcdValue
].append(Sku
)
1537 if not NeedProcessVpdMapFile
and Sku
.VpdOffset
== "*":
1538 NeedProcessVpdMapFile
= True
1539 if DscPcdEntry
.DatumType
== TAB_VOID
and PcdValue
.startswith("L"):
1540 UnicodePcdArray
.add(DscPcdEntry
)
1541 elif len(Sku
.VariableName
) > 0:
1542 HiiPcdArray
.add(DscPcdEntry
)
1544 OtherPcdArray
.add(DscPcdEntry
)
1546 # if the offset of a VPD is *, then it need to be fixed up by third party tool.
1547 VpdSkuMap
[DscPcd
] = SkuValueMap
1548 if (self
.Platform
.FlashDefinition
is None or self
.Platform
.FlashDefinition
== '') and \
1549 VpdFile
.GetCount() != 0:
1550 EdkLogger
.error("build", ATTRIBUTE_NOT_AVAILABLE
,
1551 "Fail to get FLASH_DEFINITION definition in DSC file %s which is required when DSC contains VPD PCD." % str(self
.Platform
.MetaFile
))
1553 if VpdFile
.GetCount() != 0:
1555 self
.FixVpdOffset(VpdFile
)
1557 self
.FixVpdOffset(self
.UpdateNVStoreMaxSize(VpdFile
))
1559 # Process VPD map file generated by third party BPDG tool
1560 if NeedProcessVpdMapFile
:
1561 VpdMapFilePath
= os
.path
.join(self
.BuildDir
, TAB_FV_DIRECTORY
, "%s.map" % self
.Platform
.VpdToolGuid
)
1562 if os
.path
.exists(VpdMapFilePath
):
1563 VpdFile
.Read(VpdMapFilePath
)
1566 for pcd
in VpdSkuMap
:
1567 vpdinfo
= VpdFile
.GetVpdInfo(pcd
)
1569 # just pick the a value to determine whether is unicode string type
1571 for pcdvalue
in VpdSkuMap
[pcd
]:
1572 for sku
in VpdSkuMap
[pcd
][pcdvalue
]:
1573 for item
in vpdinfo
:
1574 if item
[2] == pcdvalue
:
1575 sku
.VpdOffset
= item
[1]
1577 EdkLogger
.error("build", FILE_READ_FAILURE
, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath
)
1579 # Delete the DynamicPcdList At the last time enter into this function
1580 for Pcd
in self
._DynamicPcdList
:
1581 # just pick the a value to determine whether is unicode string type
1582 Sku
= list(Pcd
.SkuInfoList
.values())[0]
1583 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1585 if Pcd
.DatumType
not in [TAB_UINT8
, TAB_UINT16
, TAB_UINT32
, TAB_UINT64
, TAB_VOID
, "BOOLEAN"]:
1586 Pcd
.DatumType
= TAB_VOID
1588 PcdValue
= Sku
.DefaultValue
1589 if Pcd
.DatumType
== TAB_VOID
and PcdValue
.startswith("L"):
1590 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
1591 UnicodePcdArray
.add(Pcd
)
1592 elif len(Sku
.VariableName
) > 0:
1593 # if found HII type PCD then insert to right of UnicodeIndex
1594 HiiPcdArray
.add(Pcd
)
1596 OtherPcdArray
.add(Pcd
)
1597 del self
._DynamicPcdList
[:]
1598 self
._DynamicPcdList
.extend(list(UnicodePcdArray
))
1599 self
._DynamicPcdList
.extend(list(HiiPcdArray
))
1600 self
._DynamicPcdList
.extend(list(OtherPcdArray
))
1601 #python3.6 set is not ordered at all
1602 self
._DynamicPcdList
= sorted(self
._DynamicPcdList
, key
=lambda x
:(x
.TokenSpaceGuidCName
, x
.TokenCName
))
1603 self
._NonDynamicPcdList
= sorted(self
._NonDynamicPcdList
, key
=lambda x
: (x
.TokenSpaceGuidCName
, x
.TokenCName
))
1604 allskuset
= [(SkuName
, Sku
.SkuId
) for pcd
in self
._DynamicPcdList
for (SkuName
, Sku
) in pcd
.SkuInfoList
.items()]
1605 for pcd
in self
._DynamicPcdList
:
1606 if len(pcd
.SkuInfoList
) == 1:
1607 for (SkuName
, SkuId
) in allskuset
:
1608 if isinstance(SkuId
, str) and eval(SkuId
) == 0 or SkuId
== 0:
1610 pcd
.SkuInfoList
[SkuName
] = copy
.deepcopy(pcd
.SkuInfoList
[TAB_DEFAULT
])
1611 pcd
.SkuInfoList
[SkuName
].SkuId
= SkuId
1612 pcd
.SkuInfoList
[SkuName
].SkuIdName
= SkuName
1613 self
.AllPcdList
= self
._NonDynamicPcdList
+ self
._DynamicPcdList
1615 def FixVpdOffset(self
, VpdFile
):
1616 FvPath
= os
.path
.join(self
.BuildDir
, TAB_FV_DIRECTORY
)
1617 if not os
.path
.exists(FvPath
):
1621 EdkLogger
.error("build", FILE_WRITE_FAILURE
, "Fail to create FV folder under %s" % self
.BuildDir
)
1623 VpdFilePath
= os
.path
.join(FvPath
, "%s.txt" % self
.Platform
.VpdToolGuid
)
1625 if VpdFile
.Write(VpdFilePath
):
1626 # retrieve BPDG tool's path from tool_def.txt according to VPD_TOOL_GUID defined in DSC file.
1628 for ToolDef
in self
.ToolDefinition
.values():
1629 if TAB_GUID
in ToolDef
and ToolDef
[TAB_GUID
] == self
.Platform
.VpdToolGuid
:
1630 if "PATH" not in ToolDef
:
1631 EdkLogger
.error("build", ATTRIBUTE_NOT_AVAILABLE
, "PATH attribute was not provided for BPDG guid tool %s in tools_def.txt" % self
.Platform
.VpdToolGuid
)
1632 BPDGToolName
= ToolDef
["PATH"]
1634 # Call third party GUID BPDG tool.
1635 if BPDGToolName
is not None:
1636 VpdInfoFile
.CallExtenalBPDGTool(BPDGToolName
, VpdFilePath
)
1638 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.")
1640 ## Return the platform build data object
1643 return self
.BuildDatabase
[self
.MetaFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1645 ## Return platform name
1648 return self
.Platform
.PlatformName
1650 ## Return the meta file GUID
1653 return self
.Platform
.Guid
1655 ## Return the platform version
1658 return self
.Platform
.Version
1660 ## Return the FDF file name
1663 if self
.Workspace
.FdfFile
:
1664 RetVal
= mws
.join(self
.WorkspaceDir
, self
.Workspace
.FdfFile
)
1669 ## Return the build output directory platform specifies
1671 def OutputDir(self
):
1672 return self
.Platform
.OutputDirectory
1674 ## Return the directory to store all intermediate and final files built
1677 if os
.path
.isabs(self
.OutputDir
):
1678 GlobalData
.gBuildDirectory
= RetVal
= path
.join(
1679 path
.abspath(self
.OutputDir
),
1680 self
.BuildTarget
+ "_" + self
.ToolChain
,
1683 GlobalData
.gBuildDirectory
= RetVal
= path
.join(
1686 self
.BuildTarget
+ "_" + self
.ToolChain
,
1690 ## Return directory of platform makefile
1692 # @retval string Makefile directory
1695 def MakeFileDir(self
):
1696 return path
.join(self
.BuildDir
, self
.Arch
)
1698 ## Return build command string
1700 # @retval string Build command string
1703 def BuildCommand(self
):
1705 if "MAKE" in self
.ToolDefinition
and "PATH" in self
.ToolDefinition
["MAKE"]:
1706 RetVal
+= SplitOption(self
.ToolDefinition
["MAKE"]["PATH"])
1707 if "FLAGS" in self
.ToolDefinition
["MAKE"]:
1708 NewOption
= self
.ToolDefinition
["MAKE"]["FLAGS"].strip()
1710 RetVal
+= SplitOption(NewOption
)
1711 if "MAKE" in self
.EdkIIBuildOption
:
1712 if "FLAGS" in self
.EdkIIBuildOption
["MAKE"]:
1713 Flags
= self
.EdkIIBuildOption
["MAKE"]["FLAGS"]
1714 if Flags
.startswith('='):
1715 RetVal
= [RetVal
[0]] + [Flags
[1:]]
1717 RetVal
.append(Flags
)
1720 ## Get tool chain definition
1722 # Get each tool defition for given tool chain from tools_def.txt and platform
1725 def ToolDefinition(self
):
1726 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDictionary
1727 if TAB_TOD_DEFINES_COMMAND_TYPE
not in self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
:
1728 EdkLogger
.error('build', RESOURCE_NOT_AVAILABLE
, "No tools found in configuration",
1729 ExtraData
="[%s]" % self
.MetaFile
)
1732 for Def
in ToolDefinition
:
1733 Target
, Tag
, Arch
, Tool
, Attr
= Def
.split("_")
1734 if Target
!= self
.BuildTarget
or Tag
!= self
.ToolChain
or Arch
!= self
.Arch
:
1737 Value
= ToolDefinition
[Def
]
1738 # don't record the DLL
1740 DllPathList
.add(Value
)
1743 if Tool
not in RetVal
:
1745 RetVal
[Tool
][Attr
] = Value
1748 if GlobalData
.gOptions
.SilentMode
and "MAKE" in RetVal
:
1749 if "FLAGS" not in RetVal
["MAKE"]:
1750 RetVal
["MAKE"]["FLAGS"] = ""
1751 RetVal
["MAKE"]["FLAGS"] += " -s"
1754 for Attr
in RetVal
[Tool
]:
1755 Value
= RetVal
[Tool
][Attr
]
1756 if Tool
in self
._BuildOptionWithToolDef
(RetVal
) and Attr
in self
._BuildOptionWithToolDef
(RetVal
)[Tool
]:
1757 # check if override is indicated
1758 if self
._BuildOptionWithToolDef
(RetVal
)[Tool
][Attr
].startswith('='):
1759 Value
= self
._BuildOptionWithToolDef
(RetVal
)[Tool
][Attr
][1:]
1762 Value
+= " " + self
._BuildOptionWithToolDef
(RetVal
)[Tool
][Attr
]
1764 Value
= self
._BuildOptionWithToolDef
(RetVal
)[Tool
][Attr
]
1767 # Don't put MAKE definition in the file
1769 ToolsDef
+= "%s = %s\n" % (Tool
, Value
)
1771 # Don't put MAKE definition in the file
1776 ToolsDef
+= "%s_%s = %s\n" % (Tool
, Attr
, Value
)
1779 SaveFileOnChange(self
.ToolDefinitionFile
, ToolsDef
)
1780 for DllPath
in DllPathList
:
1781 os
.environ
["PATH"] = DllPath
+ os
.pathsep
+ os
.environ
["PATH"]
1782 os
.environ
["MAKE_FLAGS"] = MakeFlags
1786 ## Return the paths of tools
1788 def ToolDefinitionFile(self
):
1789 return os
.path
.join(self
.MakeFileDir
, "TOOLS_DEF." + self
.Arch
)
1791 ## Retrieve the toolchain family of given toolchain tag. Default to 'MSFT'.
1793 def ToolChainFamily(self
):
1794 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
1795 if TAB_TOD_DEFINES_FAMILY
not in ToolDefinition \
1796 or self
.ToolChain
not in ToolDefinition
[TAB_TOD_DEFINES_FAMILY
] \
1797 or not ToolDefinition
[TAB_TOD_DEFINES_FAMILY
][self
.ToolChain
]:
1798 EdkLogger
.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
1800 RetVal
= TAB_COMPILER_MSFT
1802 RetVal
= ToolDefinition
[TAB_TOD_DEFINES_FAMILY
][self
.ToolChain
]
1806 def BuildRuleFamily(self
):
1807 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
1808 if TAB_TOD_DEFINES_BUILDRULEFAMILY
not in ToolDefinition \
1809 or self
.ToolChain
not in ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
] \
1810 or not ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
][self
.ToolChain
]:
1811 EdkLogger
.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
1813 return TAB_COMPILER_MSFT
1815 return ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
][self
.ToolChain
]
1817 ## Return the build options specific for all modules in this platform
1819 def BuildOption(self
):
1820 return self
._ExpandBuildOption
(self
.Platform
.BuildOptions
)
1822 def _BuildOptionWithToolDef(self
, ToolDef
):
1823 return self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, ToolDef
=ToolDef
)
1825 ## Return the build options specific for EDK modules in this platform
1827 def EdkBuildOption(self
):
1828 return self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, EDK_NAME
)
1830 ## Return the build options specific for EDKII modules in this platform
1832 def EdkIIBuildOption(self
):
1833 return self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, EDKII_NAME
)
1835 ## Parse build_rule.txt in Conf Directory.
1837 # @retval BuildRule object
1840 def BuildRule(self
):
1841 BuildRuleFile
= None
1842 if TAB_TAT_DEFINES_BUILD_RULE_CONF
in self
.Workspace
.TargetTxt
.TargetTxtDictionary
:
1843 BuildRuleFile
= self
.Workspace
.TargetTxt
.TargetTxtDictionary
[TAB_TAT_DEFINES_BUILD_RULE_CONF
]
1844 if not BuildRuleFile
:
1845 BuildRuleFile
= gDefaultBuildRuleFile
1846 RetVal
= BuildRule(BuildRuleFile
)
1847 if RetVal
._FileVersion
== "":
1848 RetVal
._FileVersion
= AutoGenReqBuildRuleVerNum
1850 if RetVal
._FileVersion
< AutoGenReqBuildRuleVerNum
:
1851 # If Build Rule's version is less than the version number required by the tools, halting the build.
1852 EdkLogger
.error("build", AUTOGEN_ERROR
,
1853 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])"\
1854 % (RetVal
._FileVersion
, AutoGenReqBuildRuleVerNum
))
1857 ## Summarize the packages used by modules in this platform
1859 def PackageList(self
):
1861 for La
in self
.LibraryAutoGenList
:
1862 RetVal
.update(La
.DependentPackageList
)
1863 for Ma
in self
.ModuleAutoGenList
:
1864 RetVal
.update(Ma
.DependentPackageList
)
1865 #Collect package set information from INF of FDF
1866 for ModuleFile
in self
._AsBuildModuleList
:
1867 if ModuleFile
in self
.Platform
.Modules
:
1869 ModuleData
= self
.BuildDatabase
[ModuleFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1870 RetVal
.update(ModuleData
.Packages
)
1874 def NonDynamicPcdDict(self
):
1875 return {(Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
):Pcd
for Pcd
in self
.NonDynamicPcdList
}
1877 ## Get list of non-dynamic PCDs
1879 def NonDynamicPcdList(self
):
1880 self
.CollectPlatformDynamicPcds()
1881 return self
._NonDynamicPcdList
1883 ## Get list of dynamic PCDs
1885 def DynamicPcdList(self
):
1886 self
.CollectPlatformDynamicPcds()
1887 return self
._DynamicPcdList
1889 ## Generate Token Number for all PCD
1891 def PcdTokenNumber(self
):
1892 RetVal
= OrderedDict()
1895 # Make the Dynamic and DynamicEx PCD use within different TokenNumber area.
1899 # TokenNumber 0 ~ 10
1901 # TokeNumber 11 ~ 20
1903 for Pcd
in self
.DynamicPcdList
:
1904 if Pcd
.Phase
== "PEI" and Pcd
.Type
in PCD_DYNAMIC_TYPE_SET
:
1905 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
1906 RetVal
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
1909 for Pcd
in self
.DynamicPcdList
:
1910 if Pcd
.Phase
== "PEI" and Pcd
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
1911 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
1912 RetVal
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
1915 for Pcd
in self
.DynamicPcdList
:
1916 if Pcd
.Phase
== "DXE" and Pcd
.Type
in PCD_DYNAMIC_TYPE_SET
:
1917 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
1918 RetVal
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
1921 for Pcd
in self
.DynamicPcdList
:
1922 if Pcd
.Phase
== "DXE" and Pcd
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
1923 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
1924 RetVal
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
1927 for Pcd
in self
.NonDynamicPcdList
:
1928 RetVal
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
1934 for ModuleFile
in self
.Platform
.Modules
:
1943 self
.Platform
.Modules
[ModuleFile
].M
= Ma
1944 return [x
.M
for x
in self
.Platform
.Modules
.values()]
1946 ## Summarize ModuleAutoGen objects of all modules to be built for this platform
1948 def ModuleAutoGenList(self
):
1950 for Ma
in self
._MaList
:
1951 if Ma
not in RetVal
:
1955 ## Summarize ModuleAutoGen objects of all libraries to be built for this platform
1957 def LibraryAutoGenList(self
):
1959 for Ma
in self
._MaList
:
1960 for La
in Ma
.LibraryAutoGenList
:
1961 if La
not in RetVal
:
1963 if Ma
not in La
.ReferenceModules
:
1964 La
.ReferenceModules
.append(Ma
)
1967 ## Test if a module is supported by the platform
1969 # An error will be raised directly if the module or its arch is not supported
1970 # by the platform or current configuration
1972 def ValidModule(self
, Module
):
1973 return Module
in self
.Platform
.Modules
or Module
in self
.Platform
.LibraryInstances \
1974 or Module
in self
._AsBuildModuleList
1976 ## Resolve the library classes in a module to library instances
1978 # This method will not only resolve library classes but also sort the library
1979 # instances according to the dependency-ship.
1981 # @param Module The module from which the library classes will be resolved
1983 # @retval library_list List of library instances sorted
1985 def ApplyLibraryInstance(self
, Module
):
1986 # Cover the case that the binary INF file is list in the FDF file but not DSC file, return empty list directly
1987 if str(Module
) not in self
.Platform
.Modules
:
1990 return GetModuleLibInstances(Module
,
1999 ## Override PCD setting (type, value, ...)
2001 # @param ToPcd The PCD to be overrided
2002 # @param FromPcd The PCD overrideing from
2004 def _OverridePcd(self
, ToPcd
, FromPcd
, Module
="", Msg
="", Library
=""):
2006 # in case there's PCDs coming from FDF file, which have no type given.
2007 # at this point, ToPcd.Type has the type found from dependent
2010 TokenCName
= ToPcd
.TokenCName
2011 for PcdItem
in GlobalData
.MixedPcd
:
2012 if (ToPcd
.TokenCName
, ToPcd
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
2013 TokenCName
= PcdItem
[0]
2015 if FromPcd
is not None:
2016 if ToPcd
.Pending
and FromPcd
.Type
:
2017 ToPcd
.Type
= FromPcd
.Type
2018 elif ToPcd
.Type
and FromPcd
.Type\
2019 and ToPcd
.Type
!= FromPcd
.Type
and ToPcd
.Type
in FromPcd
.Type
:
2020 if ToPcd
.Type
.strip() == TAB_PCDS_DYNAMIC_EX
:
2021 ToPcd
.Type
= FromPcd
.Type
2022 elif ToPcd
.Type
and FromPcd
.Type \
2023 and ToPcd
.Type
!= FromPcd
.Type
:
2025 Module
= str(Module
) + " 's library file (" + str(Library
) + ")"
2026 EdkLogger
.error("build", OPTION_CONFLICT
, "Mismatched PCD type",
2027 ExtraData
="%s.%s is used as [%s] in module %s, but as [%s] in %s."\
2028 % (ToPcd
.TokenSpaceGuidCName
, TokenCName
,
2029 ToPcd
.Type
, Module
, FromPcd
.Type
, Msg
),
2032 if FromPcd
.MaxDatumSize
:
2033 ToPcd
.MaxDatumSize
= FromPcd
.MaxDatumSize
2034 ToPcd
.MaxSizeUserSet
= FromPcd
.MaxDatumSize
2035 if FromPcd
.DefaultValue
:
2036 ToPcd
.DefaultValue
= FromPcd
.DefaultValue
2037 if FromPcd
.TokenValue
:
2038 ToPcd
.TokenValue
= FromPcd
.TokenValue
2039 if FromPcd
.DatumType
:
2040 ToPcd
.DatumType
= FromPcd
.DatumType
2041 if FromPcd
.SkuInfoList
:
2042 ToPcd
.SkuInfoList
= FromPcd
.SkuInfoList
2043 if FromPcd
.UserDefinedDefaultStoresFlag
:
2044 ToPcd
.UserDefinedDefaultStoresFlag
= FromPcd
.UserDefinedDefaultStoresFlag
2045 # Add Flexible PCD format parse
2046 if ToPcd
.DefaultValue
:
2048 ToPcd
.DefaultValue
= ValueExpressionEx(ToPcd
.DefaultValue
, ToPcd
.DatumType
, self
.Workspace
._GuidDict
)(True)
2049 except BadExpression
as Value
:
2050 EdkLogger
.error('Parser', FORMAT_INVALID
, 'PCD [%s.%s] Value "%s", %s' %(ToPcd
.TokenSpaceGuidCName
, ToPcd
.TokenCName
, ToPcd
.DefaultValue
, Value
),
2053 # check the validation of datum
2054 IsValid
, Cause
= CheckPcdDatum(ToPcd
.DatumType
, ToPcd
.DefaultValue
)
2056 EdkLogger
.error('build', FORMAT_INVALID
, Cause
, File
=self
.MetaFile
,
2057 ExtraData
="%s.%s" % (ToPcd
.TokenSpaceGuidCName
, TokenCName
))
2058 ToPcd
.validateranges
= FromPcd
.validateranges
2059 ToPcd
.validlists
= FromPcd
.validlists
2060 ToPcd
.expressions
= FromPcd
.expressions
2061 ToPcd
.CustomAttribute
= FromPcd
.CustomAttribute
2063 if FromPcd
is not None and ToPcd
.DatumType
== TAB_VOID
and not ToPcd
.MaxDatumSize
:
2064 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "No MaxDatumSize specified for PCD %s.%s" \
2065 % (ToPcd
.TokenSpaceGuidCName
, TokenCName
))
2066 Value
= ToPcd
.DefaultValue
2068 ToPcd
.MaxDatumSize
= '1'
2069 elif Value
[0] == 'L':
2070 ToPcd
.MaxDatumSize
= str((len(Value
) - 2) * 2)
2071 elif Value
[0] == '{':
2072 ToPcd
.MaxDatumSize
= str(len(Value
.split(',')))
2074 ToPcd
.MaxDatumSize
= str(len(Value
) - 1)
2076 # apply default SKU for dynamic PCDS if specified one is not available
2077 if (ToPcd
.Type
in PCD_DYNAMIC_TYPE_SET
or ToPcd
.Type
in PCD_DYNAMIC_EX_TYPE_SET
) \
2078 and not ToPcd
.SkuInfoList
:
2079 if self
.Platform
.SkuName
in self
.Platform
.SkuIds
:
2080 SkuName
= self
.Platform
.SkuName
2082 SkuName
= TAB_DEFAULT
2083 ToPcd
.SkuInfoList
= {
2084 SkuName
: SkuInfoClass(SkuName
, self
.Platform
.SkuIds
[SkuName
][0], '', '', '', '', '', ToPcd
.DefaultValue
)
2087 ## Apply PCD setting defined platform to a module
2089 # @param Module The module from which the PCD setting will be overrided
2091 # @retval PCD_list The list PCDs with settings from platform
2093 def ApplyPcdSetting(self
, Module
, Pcds
, Library
=""):
2094 # for each PCD in module
2095 for Name
, Guid
in Pcds
:
2096 PcdInModule
= Pcds
[Name
, Guid
]
2097 # find out the PCD setting in platform
2098 if (Name
, Guid
) in self
.Platform
.Pcds
:
2099 PcdInPlatform
= self
.Platform
.Pcds
[Name
, Guid
]
2101 PcdInPlatform
= None
2102 # then override the settings if any
2103 self
._OverridePcd
(PcdInModule
, PcdInPlatform
, Module
, Msg
="DSC PCD sections", Library
=Library
)
2104 # resolve the VariableGuid value
2105 for SkuId
in PcdInModule
.SkuInfoList
:
2106 Sku
= PcdInModule
.SkuInfoList
[SkuId
]
2107 if Sku
.VariableGuid
== '': continue
2108 Sku
.VariableGuidValue
= GuidValue(Sku
.VariableGuid
, self
.PackageList
, self
.MetaFile
.Path
)
2109 if Sku
.VariableGuidValue
is None:
2110 PackageList
= "\n\t".join(str(P
) for P
in self
.PackageList
)
2113 RESOURCE_NOT_AVAILABLE
,
2114 "Value of GUID [%s] is not found in" % Sku
.VariableGuid
,
2115 ExtraData
=PackageList
+ "\n\t(used with %s.%s from module %s)" \
2116 % (Guid
, Name
, str(Module
)),
2120 # override PCD settings with module specific setting
2121 if Module
in self
.Platform
.Modules
:
2122 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
2123 for Key
in PlatformModule
.Pcds
:
2128 elif Key
in GlobalData
.MixedPcd
:
2129 for PcdItem
in GlobalData
.MixedPcd
[Key
]:
2131 ToPcd
= Pcds
[PcdItem
]
2135 self
._OverridePcd
(ToPcd
, PlatformModule
.Pcds
[Key
], Module
, Msg
="DSC Components Module scoped PCD section", Library
=Library
)
2136 # use PCD value to calculate the MaxDatumSize when it is not specified
2137 for Name
, Guid
in Pcds
:
2138 Pcd
= Pcds
[Name
, Guid
]
2139 if Pcd
.DatumType
== TAB_VOID
and not Pcd
.MaxDatumSize
:
2140 Pcd
.MaxSizeUserSet
= None
2141 Value
= Pcd
.DefaultValue
2143 Pcd
.MaxDatumSize
= '1'
2144 elif Value
[0] == 'L':
2145 Pcd
.MaxDatumSize
= str((len(Value
) - 2) * 2)
2146 elif Value
[0] == '{':
2147 Pcd
.MaxDatumSize
= str(len(Value
.split(',')))
2149 Pcd
.MaxDatumSize
= str(len(Value
) - 1)
2150 return list(Pcds
.values())
2152 ## Resolve library names to library modules
2154 # (for Edk.x modules)
2156 # @param Module The module from which the library names will be resolved
2158 # @retval library_list The list of library modules
2160 def ResolveLibraryReference(self
, Module
):
2161 EdkLogger
.verbose("")
2162 EdkLogger
.verbose("Library instances of module [%s] [%s]:" % (str(Module
), self
.Arch
))
2163 LibraryConsumerList
= [Module
]
2165 # "CompilerStub" is a must for Edk modules
2166 if Module
.Libraries
:
2167 Module
.Libraries
.append("CompilerStub")
2169 while len(LibraryConsumerList
) > 0:
2170 M
= LibraryConsumerList
.pop()
2171 for LibraryName
in M
.Libraries
:
2172 Library
= self
.Platform
.LibraryClasses
[LibraryName
, ':dummy:']
2174 for Key
in self
.Platform
.LibraryClasses
.data
:
2175 if LibraryName
.upper() == Key
.upper():
2176 Library
= self
.Platform
.LibraryClasses
[Key
, ':dummy:']
2179 EdkLogger
.warn("build", "Library [%s] is not found" % LibraryName
, File
=str(M
),
2180 ExtraData
="\t%s [%s]" % (str(Module
), self
.Arch
))
2183 if Library
not in LibraryList
:
2184 LibraryList
.append(Library
)
2185 LibraryConsumerList
.append(Library
)
2186 EdkLogger
.verbose("\t" + LibraryName
+ " : " + str(Library
) + ' ' + str(type(Library
)))
2189 ## Calculate the priority value of the build option
2191 # @param Key Build option definition contain: TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
2193 # @retval Value Priority value based on the priority list.
2195 def CalculatePriorityValue(self
, Key
):
2196 Target
, ToolChain
, Arch
, CommandType
, Attr
= Key
.split('_')
2197 PriorityValue
= 0x11111
2199 PriorityValue
&= 0x01111
2200 if ToolChain
== "*":
2201 PriorityValue
&= 0x10111
2203 PriorityValue
&= 0x11011
2204 if CommandType
== "*":
2205 PriorityValue
&= 0x11101
2207 PriorityValue
&= 0x11110
2209 return self
.PrioList
["0x%0.5x" % PriorityValue
]
2212 ## Expand * in build option key
2214 # @param Options Options to be expanded
2215 # @param ToolDef Use specified ToolDef instead of full version.
2216 # This is needed during initialization to prevent
2217 # infinite recursion betweeh BuildOptions,
2218 # ToolDefinition, and this function.
2220 # @retval options Options expanded
2222 def _ExpandBuildOption(self
, Options
, ModuleStyle
=None, ToolDef
=None):
2224 ToolDef
= self
.ToolDefinition
2231 # Construct a list contain the build options which need override.
2235 # Key[0] -- tool family
2236 # Key[1] -- TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
2238 if (Key
[0] == self
.BuildRuleFamily
and
2239 (ModuleStyle
is None or len(Key
) < 3 or (len(Key
) > 2 and Key
[2] == ModuleStyle
))):
2240 Target
, ToolChain
, Arch
, CommandType
, Attr
= Key
[1].split('_')
2241 if (Target
== self
.BuildTarget
or Target
== "*") and\
2242 (ToolChain
== self
.ToolChain
or ToolChain
== "*") and\
2243 (Arch
== self
.Arch
or Arch
== "*") and\
2244 Options
[Key
].startswith("="):
2246 if OverrideList
.get(Key
[1]) is not None:
2247 OverrideList
.pop(Key
[1])
2248 OverrideList
[Key
[1]] = Options
[Key
]
2251 # Use the highest priority value.
2253 if (len(OverrideList
) >= 2):
2254 KeyList
= list(OverrideList
.keys())
2255 for Index
in range(len(KeyList
)):
2256 NowKey
= KeyList
[Index
]
2257 Target1
, ToolChain1
, Arch1
, CommandType1
, Attr1
= NowKey
.split("_")
2258 for Index1
in range(len(KeyList
) - Index
- 1):
2259 NextKey
= KeyList
[Index1
+ Index
+ 1]
2261 # Compare two Key, if one is included by another, choose the higher priority one
2263 Target2
, ToolChain2
, Arch2
, CommandType2
, Attr2
= NextKey
.split("_")
2264 if (Target1
== Target2
or Target1
== "*" or Target2
== "*") and\
2265 (ToolChain1
== ToolChain2
or ToolChain1
== "*" or ToolChain2
== "*") and\
2266 (Arch1
== Arch2
or Arch1
== "*" or Arch2
== "*") and\
2267 (CommandType1
== CommandType2
or CommandType1
== "*" or CommandType2
== "*") and\
2268 (Attr1
== Attr2
or Attr1
== "*" or Attr2
== "*"):
2270 if self
.CalculatePriorityValue(NowKey
) > self
.CalculatePriorityValue(NextKey
):
2271 if Options
.get((self
.BuildRuleFamily
, NextKey
)) is not None:
2272 Options
.pop((self
.BuildRuleFamily
, NextKey
))
2274 if Options
.get((self
.BuildRuleFamily
, NowKey
)) is not None:
2275 Options
.pop((self
.BuildRuleFamily
, NowKey
))
2278 if ModuleStyle
is not None and len (Key
) > 2:
2279 # Check Module style is EDK or EDKII.
2280 # Only append build option for the matched style module.
2281 if ModuleStyle
== EDK_NAME
and Key
[2] != EDK_NAME
:
2283 elif ModuleStyle
== EDKII_NAME
and Key
[2] != EDKII_NAME
:
2286 Target
, Tag
, Arch
, Tool
, Attr
= Key
[1].split("_")
2287 # if tool chain family doesn't match, skip it
2288 if Tool
in ToolDef
and Family
!= "":
2289 FamilyIsNull
= False
2290 if ToolDef
[Tool
].get(TAB_TOD_DEFINES_BUILDRULEFAMILY
, "") != "":
2291 if Family
!= ToolDef
[Tool
][TAB_TOD_DEFINES_BUILDRULEFAMILY
]:
2293 elif Family
!= ToolDef
[Tool
][TAB_TOD_DEFINES_FAMILY
]:
2296 # expand any wildcard
2297 if Target
== "*" or Target
== self
.BuildTarget
:
2298 if Tag
== "*" or Tag
== self
.ToolChain
:
2299 if Arch
== "*" or Arch
== self
.Arch
:
2300 if Tool
not in BuildOptions
:
2301 BuildOptions
[Tool
] = {}
2302 if Attr
!= "FLAGS" or Attr
not in BuildOptions
[Tool
] or Options
[Key
].startswith('='):
2303 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2305 # append options for the same tool except PATH
2307 BuildOptions
[Tool
][Attr
] += " " + Options
[Key
]
2309 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2310 # Build Option Family has been checked, which need't to be checked again for family.
2311 if FamilyMatch
or FamilyIsNull
:
2315 if ModuleStyle
is not None and len (Key
) > 2:
2316 # Check Module style is EDK or EDKII.
2317 # Only append build option for the matched style module.
2318 if ModuleStyle
== EDK_NAME
and Key
[2] != EDK_NAME
:
2320 elif ModuleStyle
== EDKII_NAME
and Key
[2] != EDKII_NAME
:
2323 Target
, Tag
, Arch
, Tool
, Attr
= Key
[1].split("_")
2324 # if tool chain family doesn't match, skip it
2325 if Tool
not in ToolDef
or Family
== "":
2327 # option has been added before
2328 if Family
!= ToolDef
[Tool
][TAB_TOD_DEFINES_FAMILY
]:
2331 # expand any wildcard
2332 if Target
== "*" or Target
== self
.BuildTarget
:
2333 if Tag
== "*" or Tag
== self
.ToolChain
:
2334 if Arch
== "*" or Arch
== self
.Arch
:
2335 if Tool
not in BuildOptions
:
2336 BuildOptions
[Tool
] = {}
2337 if Attr
!= "FLAGS" or Attr
not in BuildOptions
[Tool
] or Options
[Key
].startswith('='):
2338 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2340 # append options for the same tool except PATH
2342 BuildOptions
[Tool
][Attr
] += " " + Options
[Key
]
2344 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2347 ## Append build options in platform to a module
2349 # @param Module The module to which the build options will be appened
2351 # @retval options The options appended with build options in platform
2353 def ApplyBuildOption(self
, Module
):
2354 # Get the different options for the different style module
2355 if Module
.AutoGenVersion
< 0x00010005:
2356 PlatformOptions
= self
.EdkBuildOption
2357 ModuleTypeOptions
= self
.Platform
.GetBuildOptionsByModuleType(EDK_NAME
, Module
.ModuleType
)
2359 PlatformOptions
= self
.EdkIIBuildOption
2360 ModuleTypeOptions
= self
.Platform
.GetBuildOptionsByModuleType(EDKII_NAME
, Module
.ModuleType
)
2361 ModuleTypeOptions
= self
._ExpandBuildOption
(ModuleTypeOptions
)
2362 ModuleOptions
= self
._ExpandBuildOption
(Module
.BuildOptions
)
2363 if Module
in self
.Platform
.Modules
:
2364 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
2365 PlatformModuleOptions
= self
._ExpandBuildOption
(PlatformModule
.BuildOptions
)
2367 PlatformModuleOptions
= {}
2369 BuildRuleOrder
= None
2370 for Options
in [self
.ToolDefinition
, ModuleOptions
, PlatformOptions
, ModuleTypeOptions
, PlatformModuleOptions
]:
2371 for Tool
in Options
:
2372 for Attr
in Options
[Tool
]:
2373 if Attr
== TAB_TOD_DEFINES_BUILDRULEORDER
:
2374 BuildRuleOrder
= Options
[Tool
][Attr
]
2376 AllTools
= set(list(ModuleOptions
.keys()) + list(PlatformOptions
.keys()) +
2377 list(PlatformModuleOptions
.keys()) + list(ModuleTypeOptions
.keys()) +
2378 list(self
.ToolDefinition
.keys()))
2379 BuildOptions
= defaultdict(lambda: defaultdict(str))
2380 for Tool
in sorted(AllTools
):
2381 for Options
in [self
.ToolDefinition
, ModuleOptions
, PlatformOptions
, ModuleTypeOptions
, PlatformModuleOptions
]:
2382 if Tool
not in Options
:
2384 for Attr
in Options
[Tool
]:
2386 # Do not generate it in Makefile
2388 if Attr
== TAB_TOD_DEFINES_BUILDRULEORDER
:
2390 Value
= Options
[Tool
][Attr
]
2391 # check if override is indicated
2392 if Value
.startswith('='):
2393 BuildOptions
[Tool
][Attr
] = mws
.handleWsMacro(Value
[1:])
2396 BuildOptions
[Tool
][Attr
] += " " + mws
.handleWsMacro(Value
)
2398 BuildOptions
[Tool
][Attr
] = mws
.handleWsMacro(Value
)
2400 if Module
.AutoGenVersion
< 0x00010005 and self
.Workspace
.UniFlag
is not None:
2402 # Override UNI flag only for EDK module.
2404 BuildOptions
['BUILD']['FLAGS'] = self
.Workspace
.UniFlag
2405 return BuildOptions
, BuildRuleOrder
2408 # extend lists contained in a dictionary with lists stored in another dictionary
2409 # if CopyToDict is not derived from DefaultDict(list) then this may raise exception
2411 def ExtendCopyDictionaryLists(CopyToDict
, CopyFromDict
):
2412 for Key
in CopyFromDict
:
2413 CopyToDict
[Key
].extend(CopyFromDict
[Key
])
2415 # Create a directory specified by a set of path elements and return the full path
2416 def _MakeDir(PathList
):
2417 RetVal
= path
.join(*PathList
)
2418 CreateDirectory(RetVal
)
2421 ## ModuleAutoGen class
2423 # This class encapsules the AutoGen behaviors for the build tools. In addition to
2424 # the generation of AutoGen.h and AutoGen.c, it will generate *.depex file according
2425 # to the [depex] section in module's inf file.
2427 class ModuleAutoGen(AutoGen
):
2428 # call super().__init__ then call the worker function with different parameter count
2429 def __init__(self
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
2430 if not hasattr(self
, "_Init"):
2431 super().__init
__(Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
)
2432 self
._InitWorker
(Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
)
2435 ## Cache the timestamps of metafiles of every module in a class attribute
2439 def __new__(cls
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
2440 # check if this module is employed by active platform
2441 if not PlatformAutoGen(Workspace
, args
[0], Target
, Toolchain
, Arch
).ValidModule(MetaFile
):
2442 EdkLogger
.verbose("Module [%s] for [%s] is not employed by active platform\n" \
2445 return super().__new
__(cls
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
)
2447 ## Initialize ModuleAutoGen
2449 # @param Workspace EdkIIWorkspaceBuild object
2450 # @param ModuleFile The path of module file
2451 # @param Target Build target (DEBUG, RELEASE)
2452 # @param Toolchain Name of tool chain
2453 # @param Arch The arch the module supports
2454 # @param PlatformFile Platform meta-file
2456 def _InitWorker(self
, Workspace
, ModuleFile
, Target
, Toolchain
, Arch
, PlatformFile
):
2457 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "AutoGen module [%s] [%s]" % (ModuleFile
, Arch
))
2458 GlobalData
.gProcessingFile
= "%s [%s, %s, %s]" % (ModuleFile
, Arch
, Toolchain
, Target
)
2460 self
.Workspace
= Workspace
2461 self
.WorkspaceDir
= Workspace
.WorkspaceDir
2462 self
.MetaFile
= ModuleFile
2463 self
.PlatformInfo
= PlatformAutoGen(Workspace
, PlatformFile
, Target
, Toolchain
, Arch
)
2465 self
.SourceDir
= self
.MetaFile
.SubDir
2466 self
.SourceDir
= mws
.relpath(self
.SourceDir
, self
.WorkspaceDir
)
2468 self
.SourceOverrideDir
= None
2469 # use overrided path defined in DSC file
2470 if self
.MetaFile
.Key
in GlobalData
.gOverrideDir
:
2471 self
.SourceOverrideDir
= GlobalData
.gOverrideDir
[self
.MetaFile
.Key
]
2473 self
.ToolChain
= Toolchain
2474 self
.BuildTarget
= Target
2476 self
.ToolChainFamily
= self
.PlatformInfo
.ToolChainFamily
2477 self
.BuildRuleFamily
= self
.PlatformInfo
.BuildRuleFamily
2479 self
.IsCodeFileCreated
= False
2480 self
.IsAsBuiltInfCreated
= False
2481 self
.DepexGenerated
= False
2483 self
.BuildDatabase
= self
.Workspace
.BuildDatabase
2484 self
.BuildRuleOrder
= None
2487 self
._PcdComments
= OrderedListDict()
2488 self
._GuidComments
= OrderedListDict()
2489 self
._ProtocolComments
= OrderedListDict()
2490 self
._PpiComments
= OrderedListDict()
2491 self
._BuildTargets
= None
2492 self
._IntroBuildTargetList
= None
2493 self
._FinalBuildTargetList
= None
2494 self
._FileTypes
= None
2496 self
.AutoGenDepSet
= set()
2497 self
.ReferenceModules
= []
2502 return "%s [%s]" % (self
.MetaFile
, self
.Arch
)
2504 # Get FixedAtBuild Pcds of this Module
2506 def FixedAtBuildPcds(self
):
2508 for Pcd
in self
.ModulePcdList
:
2509 if Pcd
.Type
!= TAB_PCDS_FIXED_AT_BUILD
:
2511 if Pcd
not in RetVal
:
2516 def FixedVoidTypePcds(self
):
2518 for Pcd
in self
.FixedAtBuildPcds
:
2519 if Pcd
.DatumType
== TAB_VOID
:
2520 if '{}.{}'.format(Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) not in RetVal
:
2521 RetVal
['{}.{}'.format(Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
)] = Pcd
.DefaultValue
2525 def UniqueBaseName(self
):
2526 BaseName
= self
.Name
2527 for Module
in self
.PlatformInfo
.ModuleAutoGenList
:
2528 if Module
.MetaFile
== self
.MetaFile
:
2530 if Module
.Name
== self
.Name
:
2531 if uuid
.UUID(Module
.Guid
) == uuid
.UUID(self
.Guid
):
2532 EdkLogger
.error("build", FILE_DUPLICATED
, 'Modules have same BaseName and FILE_GUID:\n'
2533 ' %s\n %s' % (Module
.MetaFile
, self
.MetaFile
))
2534 BaseName
= '%s_%s' % (self
.Name
, self
.Guid
)
2537 # Macros could be used in build_rule.txt (also Makefile)
2540 return OrderedDict((
2541 ("WORKSPACE" ,self
.WorkspaceDir
),
2542 ("MODULE_NAME" ,self
.Name
),
2543 ("MODULE_NAME_GUID" ,self
.UniqueBaseName
),
2544 ("MODULE_GUID" ,self
.Guid
),
2545 ("MODULE_VERSION" ,self
.Version
),
2546 ("MODULE_TYPE" ,self
.ModuleType
),
2547 ("MODULE_FILE" ,str(self
.MetaFile
)),
2548 ("MODULE_FILE_BASE_NAME" ,self
.MetaFile
.BaseName
),
2549 ("MODULE_RELATIVE_DIR" ,self
.SourceDir
),
2550 ("MODULE_DIR" ,self
.SourceDir
),
2551 ("BASE_NAME" ,self
.Name
),
2552 ("ARCH" ,self
.Arch
),
2553 ("TOOLCHAIN" ,self
.ToolChain
),
2554 ("TOOLCHAIN_TAG" ,self
.ToolChain
),
2555 ("TOOL_CHAIN_TAG" ,self
.ToolChain
),
2556 ("TARGET" ,self
.BuildTarget
),
2557 ("BUILD_DIR" ,self
.PlatformInfo
.BuildDir
),
2558 ("BIN_DIR" ,os
.path
.join(self
.PlatformInfo
.BuildDir
, self
.Arch
)),
2559 ("LIB_DIR" ,os
.path
.join(self
.PlatformInfo
.BuildDir
, self
.Arch
)),
2560 ("MODULE_BUILD_DIR" ,self
.BuildDir
),
2561 ("OUTPUT_DIR" ,self
.OutputDir
),
2562 ("DEBUG_DIR" ,self
.DebugDir
),
2563 ("DEST_DIR_OUTPUT" ,self
.OutputDir
),
2564 ("DEST_DIR_DEBUG" ,self
.DebugDir
),
2565 ("PLATFORM_NAME" ,self
.PlatformInfo
.Name
),
2566 ("PLATFORM_GUID" ,self
.PlatformInfo
.Guid
),
2567 ("PLATFORM_VERSION" ,self
.PlatformInfo
.Version
),
2568 ("PLATFORM_RELATIVE_DIR" ,self
.PlatformInfo
.SourceDir
),
2569 ("PLATFORM_DIR" ,mws
.join(self
.WorkspaceDir
, self
.PlatformInfo
.SourceDir
)),
2570 ("PLATFORM_OUTPUT_DIR" ,self
.PlatformInfo
.OutputDir
),
2571 ("FFS_OUTPUT_DIR" ,self
.FfsOutputDir
)
2574 ## Return the module build data object
2577 return self
.BuildDatabase
[self
.MetaFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
2579 ## Return the module name
2582 return self
.Module
.BaseName
2584 ## Return the module DxsFile if exist
2587 return self
.Module
.DxsFile
2589 ## Return the module meta-file GUID
2593 # To build same module more than once, the module path with FILE_GUID overridden has
2594 # the file name FILE_GUIDmodule.inf, but the relative path (self.MetaFile.File) is the realy path
2595 # in DSC. The overridden GUID can be retrieved from file name
2597 if os
.path
.basename(self
.MetaFile
.File
) != os
.path
.basename(self
.MetaFile
.Path
):
2599 # Length of GUID is 36
2601 return os
.path
.basename(self
.MetaFile
.Path
)[:36]
2602 return self
.Module
.Guid
2604 ## Return the module version
2607 return self
.Module
.Version
2609 ## Return the module type
2611 def ModuleType(self
):
2612 return self
.Module
.ModuleType
2614 ## Return the component type (for Edk.x style of module)
2616 def ComponentType(self
):
2617 return self
.Module
.ComponentType
2619 ## Return the build type
2621 def BuildType(self
):
2622 return self
.Module
.BuildType
2624 ## Return the PCD_IS_DRIVER setting
2626 def PcdIsDriver(self
):
2627 return self
.Module
.PcdIsDriver
2629 ## Return the autogen version, i.e. module meta-file version
2631 def AutoGenVersion(self
):
2632 return self
.Module
.AutoGenVersion
2634 ## Check if the module is library or not
2636 def IsLibrary(self
):
2637 return bool(self
.Module
.LibraryClass
)
2639 ## Check if the module is binary module or not
2641 def IsBinaryModule(self
):
2642 return self
.Module
.IsBinaryModule
2644 ## Return the directory to store intermediate files of the module
2648 self
.PlatformInfo
.BuildDir
,
2651 self
.MetaFile
.BaseName
2654 ## Return the directory to store the intermediate object files of the mdoule
2656 def OutputDir(self
):
2657 return _MakeDir((self
.BuildDir
, "OUTPUT"))
2659 ## Return the directory path to store ffs file
2661 def FfsOutputDir(self
):
2662 if GlobalData
.gFdfParser
:
2663 return path
.join(self
.PlatformInfo
.BuildDir
, TAB_FV_DIRECTORY
, "Ffs", self
.Guid
+ self
.Name
)
2666 ## Return the directory to store auto-gened source files of the mdoule
2669 return _MakeDir((self
.BuildDir
, "DEBUG"))
2671 ## Return the path of custom file
2673 def CustomMakefile(self
):
2675 for Type
in self
.Module
.CustomMakefile
:
2676 MakeType
= gMakeTypeMap
[Type
] if Type
in gMakeTypeMap
else 'nmake'
2677 if self
.SourceOverrideDir
is not None:
2678 File
= os
.path
.join(self
.SourceOverrideDir
, self
.Module
.CustomMakefile
[Type
])
2679 if not os
.path
.exists(File
):
2680 File
= os
.path
.join(self
.SourceDir
, self
.Module
.CustomMakefile
[Type
])
2682 File
= os
.path
.join(self
.SourceDir
, self
.Module
.CustomMakefile
[Type
])
2683 RetVal
[MakeType
] = File
2686 ## Return the directory of the makefile
2688 # @retval string The directory string of module's makefile
2691 def MakeFileDir(self
):
2692 return self
.BuildDir
2694 ## Return build command string
2696 # @retval string Build command string
2699 def BuildCommand(self
):
2700 return self
.PlatformInfo
.BuildCommand
2702 ## Get object list of all packages the module and its dependent libraries belong to
2704 # @retval list The list of package object
2707 def DerivedPackageList(self
):
2709 for M
in [self
.Module
] + self
.DependentLibraryList
:
2710 for Package
in M
.Packages
:
2711 if Package
in PackageList
:
2713 PackageList
.append(Package
)
2716 ## Get the depex string
2718 # @return : a string contain all depex expresion.
2719 def _GetDepexExpresionString(self
):
2722 ## DPX_SOURCE IN Define section.
2723 if self
.Module
.DxsFile
:
2725 for M
in [self
.Module
] + self
.DependentLibraryList
:
2726 Filename
= M
.MetaFile
.Path
2727 InfObj
= InfSectionParser
.InfSectionParser(Filename
)
2728 DepexExpresionList
= InfObj
.GetDepexExpresionList()
2729 for DepexExpresion
in DepexExpresionList
:
2730 for key
in DepexExpresion
:
2731 Arch
, ModuleType
= key
2732 DepexExpr
= [x
for x
in DepexExpresion
[key
] if not str(x
).startswith('#')]
2733 # the type of build module is USER_DEFINED.
2734 # All different DEPEX section tags would be copied into the As Built INF file
2735 # and there would be separate DEPEX section tags
2736 if self
.ModuleType
.upper() == SUP_MODULE_USER_DEFINED
:
2737 if (Arch
.upper() == self
.Arch
.upper()) and (ModuleType
.upper() != TAB_ARCH_COMMON
):
2738 DepexList
.append({(Arch
, ModuleType
): DepexExpr
})
2740 if Arch
.upper() == TAB_ARCH_COMMON
or \
2741 (Arch
.upper() == self
.Arch
.upper() and \
2742 ModuleType
.upper() in [TAB_ARCH_COMMON
, self
.ModuleType
.upper()]):
2743 DepexList
.append({(Arch
, ModuleType
): DepexExpr
})
2745 #the type of build module is USER_DEFINED.
2746 if self
.ModuleType
.upper() == SUP_MODULE_USER_DEFINED
:
2747 for Depex
in DepexList
:
2749 DepexStr
+= '[Depex.%s.%s]\n' % key
2750 DepexStr
+= '\n'.join('# '+ val
for val
in Depex
[key
])
2753 return '[Depex.%s]\n' % self
.Arch
2756 #the type of build module not is USER_DEFINED.
2758 for Depex
in DepexList
:
2763 for D
in Depex
.values():
2764 DepexStr
+= ' '.join(val
for val
in D
)
2765 Index
= DepexStr
.find('END')
2766 if Index
> -1 and Index
== len(DepexStr
) - 3:
2767 DepexStr
= DepexStr
[:-3]
2768 DepexStr
= DepexStr
.strip()
2771 DepexStr
= DepexStr
.lstrip('(').rstrip(')').strip()
2773 return '[Depex.%s]\n' % self
.Arch
2774 return '[Depex.%s]\n# ' % self
.Arch
+ DepexStr
2776 ## Merge dependency expression
2778 # @retval list The token list of the dependency expression after parsed
2781 def DepexList(self
):
2782 if self
.DxsFile
or self
.IsLibrary
or TAB_DEPENDENCY_EXPRESSION_FILE
in self
.FileTypes
:
2787 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
2789 for M
in [self
.Module
] + self
.DependentLibraryList
:
2791 for D
in M
.Depex
[self
.Arch
, self
.ModuleType
]:
2793 DepexList
.append('AND')
2794 DepexList
.append('(')
2795 #replace D with value if D is FixedAtBuild PCD
2799 NewList
.append(item
)
2801 if item
not in self
._FixedPcdVoidTypeDict
:
2802 EdkLogger
.error("build", FORMAT_INVALID
, "{} used in [Depex] section should be used as FixedAtBuild type and VOID* datum type in the module.".format(item
))
2804 Value
= self
._FixedPcdVoidTypeDict
[item
]
2805 if len(Value
.split(',')) != 16:
2806 EdkLogger
.error("build", FORMAT_INVALID
,
2807 "{} used in [Depex] section should be used as FixedAtBuild type and VOID* datum type and 16 bytes in the module.".format(item
))
2808 NewList
.append(Value
)
2809 DepexList
.extend(NewList
)
2810 if DepexList
[-1] == 'END': # no need of a END at this time
2812 DepexList
.append(')')
2815 EdkLogger
.verbose("DEPEX[%s] (+%s) = %s" % (self
.Name
, M
.BaseName
, DepexList
))
2816 if 'BEFORE' in DepexList
or 'AFTER' in DepexList
:
2818 if len(DepexList
) > 0:
2819 EdkLogger
.verbose('')
2820 return {self
.ModuleType
:DepexList
}
2822 ## Merge dependency expression
2824 # @retval list The token list of the dependency expression after parsed
2827 def DepexExpressionDict(self
):
2828 if self
.DxsFile
or self
.IsLibrary
or TAB_DEPENDENCY_EXPRESSION_FILE
in self
.FileTypes
:
2831 DepexExpressionString
= ''
2833 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
2835 for M
in [self
.Module
] + self
.DependentLibraryList
:
2837 for D
in M
.DepexExpression
[self
.Arch
, self
.ModuleType
]:
2838 if DepexExpressionString
!= '':
2839 DepexExpressionString
+= ' AND '
2840 DepexExpressionString
+= '('
2841 DepexExpressionString
+= D
2842 DepexExpressionString
= DepexExpressionString
.rstrip('END').strip()
2843 DepexExpressionString
+= ')'
2846 EdkLogger
.verbose("DEPEX[%s] (+%s) = %s" % (self
.Name
, M
.BaseName
, DepexExpressionString
))
2847 if 'BEFORE' in DepexExpressionString
or 'AFTER' in DepexExpressionString
:
2849 if len(DepexExpressionString
) > 0:
2850 EdkLogger
.verbose('')
2852 return {self
.ModuleType
:DepexExpressionString
}
2854 # Get the tiano core user extension, it is contain dependent library.
2855 # @retval: a list contain tiano core userextension.
2857 def _GetTianoCoreUserExtensionList(self
):
2858 TianoCoreUserExtentionList
= []
2859 for M
in [self
.Module
] + self
.DependentLibraryList
:
2860 Filename
= M
.MetaFile
.Path
2861 InfObj
= InfSectionParser
.InfSectionParser(Filename
)
2862 TianoCoreUserExtenList
= InfObj
.GetUserExtensionTianoCore()
2863 for TianoCoreUserExtent
in TianoCoreUserExtenList
:
2864 for Section
in TianoCoreUserExtent
:
2865 ItemList
= Section
.split(TAB_SPLIT
)
2867 if len(ItemList
) == 4:
2869 if Arch
.upper() == TAB_ARCH_COMMON
or Arch
.upper() == self
.Arch
.upper():
2871 TianoCoreList
.extend([TAB_SECTION_START
+ Section
+ TAB_SECTION_END
])
2872 TianoCoreList
.extend(TianoCoreUserExtent
[Section
][:])
2873 TianoCoreList
.append('\n')
2874 TianoCoreUserExtentionList
.append(TianoCoreList
)
2876 return TianoCoreUserExtentionList
2878 ## Return the list of specification version required for the module
2880 # @retval list The list of specification defined in module file
2883 def Specification(self
):
2884 return self
.Module
.Specification
2886 ## Tool option for the module build
2888 # @param PlatformInfo The object of PlatformBuildInfo
2889 # @retval dict The dict containing valid options
2892 def BuildOption(self
):
2893 RetVal
, self
.BuildRuleOrder
= self
.PlatformInfo
.ApplyBuildOption(self
.Module
)
2894 if self
.BuildRuleOrder
:
2895 self
.BuildRuleOrder
= ['.%s' % Ext
for Ext
in self
.BuildRuleOrder
.split()]
2898 ## Get include path list from tool option for the module build
2900 # @retval list The include path list
2903 def BuildOptionIncPathList(self
):
2905 # Regular expression for finding Include Directories, the difference between MSFT and INTEL/GCC/RVCT
2906 # is the former use /I , the Latter used -I to specify include directories
2908 if self
.PlatformInfo
.ToolChainFamily
in (TAB_COMPILER_MSFT
):
2909 BuildOptIncludeRegEx
= gBuildOptIncludePatternMsft
2910 elif self
.PlatformInfo
.ToolChainFamily
in ('INTEL', 'GCC', 'RVCT'):
2911 BuildOptIncludeRegEx
= gBuildOptIncludePatternOther
2914 # New ToolChainFamily, don't known whether there is option to specify include directories
2919 for Tool
in ('CC', 'PP', 'VFRPP', 'ASLPP', 'ASLCC', 'APP', 'ASM'):
2921 FlagOption
= self
.BuildOption
[Tool
]['FLAGS']
2925 if self
.ToolChainFamily
!= 'RVCT':
2926 IncPathList
= [NormPath(Path
, self
.Macros
) for Path
in BuildOptIncludeRegEx
.findall(FlagOption
)]
2929 # RVCT may specify a list of directory seperated by commas
2932 for Path
in BuildOptIncludeRegEx
.findall(FlagOption
):
2933 PathList
= GetSplitList(Path
, TAB_COMMA_SPLIT
)
2934 IncPathList
.extend(NormPath(PathEntry
, self
.Macros
) for PathEntry
in PathList
)
2937 # EDK II modules must not reference header files outside of the packages they depend on or
2938 # within the module's directory tree. Report error if violation.
2940 if self
.AutoGenVersion
>= 0x00010005:
2941 for Path
in IncPathList
:
2942 if (Path
not in self
.IncludePathList
) and (CommonPath([Path
, self
.MetaFile
.Dir
]) != self
.MetaFile
.Dir
):
2943 ErrMsg
= "The include directory for the EDK II module in this line is invalid %s specified in %s FLAGS '%s'" % (Path
, Tool
, FlagOption
)
2944 EdkLogger
.error("build",
2947 File
=str(self
.MetaFile
))
2948 RetVal
+= IncPathList
2951 ## Return a list of files which can be built from source
2953 # What kind of files can be built is determined by build rules in
2954 # $(CONF_DIRECTORY)/build_rule.txt and toolchain family.
2957 def SourceFileList(self
):
2959 ToolChainTagSet
= {"", "*", self
.ToolChain
}
2960 ToolChainFamilySet
= {"", "*", self
.ToolChainFamily
, self
.BuildRuleFamily
}
2961 for F
in self
.Module
.Sources
:
2963 if F
.TagName
not in ToolChainTagSet
:
2964 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "The toolchain [%s] for processing file [%s] is found, "
2965 "but [%s] is currently used" % (F
.TagName
, str(F
), self
.ToolChain
))
2967 # match tool chain family or build rule family
2968 if F
.ToolChainFamily
not in ToolChainFamilySet
:
2971 "The file [%s] must be built by tools of [%s], " \
2972 "but current toolchain family is [%s], buildrule family is [%s]" \
2973 % (str(F
), F
.ToolChainFamily
, self
.ToolChainFamily
, self
.BuildRuleFamily
))
2976 # add the file path into search path list for file including
2977 if F
.Dir
not in self
.IncludePathList
and self
.AutoGenVersion
>= 0x00010005:
2978 self
.IncludePathList
.insert(0, F
.Dir
)
2981 self
._MatchBuildRuleOrder
(RetVal
)
2984 self
._ApplyBuildRule
(F
, TAB_UNKNOWN_FILE
)
2987 def _MatchBuildRuleOrder(self
, FileList
):
2990 for SingleFile
in FileList
:
2991 if self
.BuildRuleOrder
and SingleFile
.Ext
in self
.BuildRuleOrder
and SingleFile
.Ext
in self
.BuildRules
:
2992 key
= SingleFile
.Path
.split(SingleFile
.Ext
)[0]
2993 if key
in Order_Dict
:
2994 Order_Dict
[key
].append(SingleFile
.Ext
)
2996 Order_Dict
[key
] = [SingleFile
.Ext
]
2999 for F
in Order_Dict
:
3000 if len(Order_Dict
[F
]) > 1:
3001 Order_Dict
[F
].sort(key
=lambda i
: self
.BuildRuleOrder
.index(i
))
3002 for Ext
in Order_Dict
[F
][1:]:
3003 RemoveList
.append(F
+ Ext
)
3005 for item
in RemoveList
:
3006 FileList
.remove(item
)
3010 ## Return the list of unicode files
3012 def UnicodeFileList(self
):
3013 return self
.FileTypes
.get(TAB_UNICODE_FILE
,[])
3015 ## Return the list of vfr files
3017 def VfrFileList(self
):
3018 return self
.FileTypes
.get(TAB_VFR_FILE
, [])
3020 ## Return the list of Image Definition files
3022 def IdfFileList(self
):
3023 return self
.FileTypes
.get(TAB_IMAGE_FILE
,[])
3025 ## Return a list of files which can be built from binary
3027 # "Build" binary files are just to copy them to build directory.
3029 # @retval list The list of files which can be built later
3032 def BinaryFileList(self
):
3034 for F
in self
.Module
.Binaries
:
3035 if F
.Target
not in [TAB_ARCH_COMMON
, '*'] and F
.Target
!= self
.BuildTarget
:
3038 self
._ApplyBuildRule
(F
, F
.Type
, BinaryFileList
=RetVal
)
3042 def BuildRules(self
):
3044 BuildRuleDatabase
= self
.PlatformInfo
.BuildRule
3045 for Type
in BuildRuleDatabase
.FileTypeList
:
3046 #first try getting build rule by BuildRuleFamily
3047 RuleObject
= BuildRuleDatabase
[Type
, self
.BuildType
, self
.Arch
, self
.BuildRuleFamily
]
3049 # build type is always module type, but ...
3050 if self
.ModuleType
!= self
.BuildType
:
3051 RuleObject
= BuildRuleDatabase
[Type
, self
.ModuleType
, self
.Arch
, self
.BuildRuleFamily
]
3052 #second try getting build rule by ToolChainFamily
3054 RuleObject
= BuildRuleDatabase
[Type
, self
.BuildType
, self
.Arch
, self
.ToolChainFamily
]
3056 # build type is always module type, but ...
3057 if self
.ModuleType
!= self
.BuildType
:
3058 RuleObject
= BuildRuleDatabase
[Type
, self
.ModuleType
, self
.Arch
, self
.ToolChainFamily
]
3061 RuleObject
= RuleObject
.Instantiate(self
.Macros
)
3062 RetVal
[Type
] = RuleObject
3063 for Ext
in RuleObject
.SourceFileExtList
:
3064 RetVal
[Ext
] = RuleObject
3067 def _ApplyBuildRule(self
, File
, FileType
, BinaryFileList
=None):
3068 if self
._BuildTargets
is None:
3069 self
._IntroBuildTargetList
= set()
3070 self
._FinalBuildTargetList
= set()
3071 self
._BuildTargets
= defaultdict(set)
3072 self
._FileTypes
= defaultdict(set)
3074 if not BinaryFileList
:
3075 BinaryFileList
= self
.BinaryFileList
3077 SubDirectory
= os
.path
.join(self
.OutputDir
, File
.SubDir
)
3078 if not os
.path
.exists(SubDirectory
):
3079 CreateDirectory(SubDirectory
)
3085 # Make sure to get build rule order value
3089 while Index
< len(SourceList
):
3090 Source
= SourceList
[Index
]
3094 CreateDirectory(Source
.Dir
)
3096 if File
.IsBinary
and File
== Source
and File
in BinaryFileList
:
3097 # Skip all files that are not binary libraries
3098 if not self
.IsLibrary
:
3100 RuleObject
= self
.BuildRules
[TAB_DEFAULT_BINARY_FILE
]
3101 elif FileType
in self
.BuildRules
:
3102 RuleObject
= self
.BuildRules
[FileType
]
3103 elif Source
.Ext
in self
.BuildRules
:
3104 RuleObject
= self
.BuildRules
[Source
.Ext
]
3106 # stop at no more rules
3108 self
._FinalBuildTargetList
.add(LastTarget
)
3111 FileType
= RuleObject
.SourceFileType
3112 self
._FileTypes
[FileType
].add(Source
)
3114 # stop at STATIC_LIBRARY for library
3115 if self
.IsLibrary
and FileType
== TAB_STATIC_LIBRARY
:
3117 self
._FinalBuildTargetList
.add(LastTarget
)
3120 Target
= RuleObject
.Apply(Source
, self
.BuildRuleOrder
)
3123 self
._FinalBuildTargetList
.add(LastTarget
)
3125 elif not Target
.Outputs
:
3126 # Only do build for target with outputs
3127 self
._FinalBuildTargetList
.add(Target
)
3129 self
._BuildTargets
[FileType
].add(Target
)
3131 if not Source
.IsBinary
and Source
== File
:
3132 self
._IntroBuildTargetList
.add(Target
)
3134 # to avoid cyclic rule
3135 if FileType
in RuleChain
:
3138 RuleChain
.add(FileType
)
3139 SourceList
.extend(Target
.Outputs
)
3141 FileType
= TAB_UNKNOWN_FILE
3145 if self
._BuildTargets
is None:
3146 self
._IntroBuildTargetList
= set()
3147 self
._FinalBuildTargetList
= set()
3148 self
._BuildTargets
= defaultdict(set)
3149 self
._FileTypes
= defaultdict(set)
3151 #TRICK: call SourceFileList property to apply build rule for source files
3154 #TRICK: call _GetBinaryFileList to apply build rule for binary files
3157 return self
._BuildTargets
3160 def IntroTargetList(self
):
3162 return sorted(self
._IntroBuildTargetList
, key
=lambda x
: str(x
.Target
))
3165 def CodaTargetList(self
):
3167 return sorted(self
._FinalBuildTargetList
, key
=lambda x
: str(x
.Target
))
3170 def FileTypes(self
):
3172 return self
._FileTypes
3174 ## Get the list of package object the module depends on
3176 # @retval list The package object list
3179 def DependentPackageList(self
):
3180 return self
.Module
.Packages
3182 ## Return the list of auto-generated code file
3184 # @retval list The list of auto-generated file
3187 def AutoGenFileList(self
):
3188 AutoGenUniIdf
= self
.BuildType
!= 'UEFI_HII'
3189 UniStringBinBuffer
= BytesIO()
3190 IdfGenBinBuffer
= BytesIO()
3192 AutoGenC
= TemplateString()
3193 AutoGenH
= TemplateString()
3194 StringH
= TemplateString()
3195 StringIdf
= TemplateString()
3196 GenC
.CreateCode(self
, AutoGenC
, AutoGenH
, StringH
, AutoGenUniIdf
, UniStringBinBuffer
, StringIdf
, AutoGenUniIdf
, IdfGenBinBuffer
)
3198 # AutoGen.c is generated if there are library classes in inf, or there are object files
3200 if str(AutoGenC
) != "" and (len(self
.Module
.LibraryClasses
) > 0
3201 or TAB_OBJECT_FILE
in self
.FileTypes
):
3202 AutoFile
= PathClass(gAutoGenCodeFileName
, self
.DebugDir
)
3203 RetVal
[AutoFile
] = str(AutoGenC
)
3204 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3205 if str(AutoGenH
) != "":
3206 AutoFile
= PathClass(gAutoGenHeaderFileName
, self
.DebugDir
)
3207 RetVal
[AutoFile
] = str(AutoGenH
)
3208 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3209 if str(StringH
) != "":
3210 AutoFile
= PathClass(gAutoGenStringFileName
% {"module_name":self
.Name
}, self
.DebugDir
)
3211 RetVal
[AutoFile
] = str(StringH
)
3212 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3213 if UniStringBinBuffer
is not None and UniStringBinBuffer
.getvalue() != b
"":
3214 AutoFile
= PathClass(gAutoGenStringFormFileName
% {"module_name":self
.Name
}, self
.OutputDir
)
3215 RetVal
[AutoFile
] = UniStringBinBuffer
.getvalue()
3216 AutoFile
.IsBinary
= True
3217 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3218 if UniStringBinBuffer
is not None:
3219 UniStringBinBuffer
.close()
3220 if str(StringIdf
) != "":
3221 AutoFile
= PathClass(gAutoGenImageDefFileName
% {"module_name":self
.Name
}, self
.DebugDir
)
3222 RetVal
[AutoFile
] = str(StringIdf
)
3223 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3224 if IdfGenBinBuffer
is not None and IdfGenBinBuffer
.getvalue() != b
"":
3225 AutoFile
= PathClass(gAutoGenIdfFileName
% {"module_name":self
.Name
}, self
.OutputDir
)
3226 RetVal
[AutoFile
] = IdfGenBinBuffer
.getvalue()
3227 AutoFile
.IsBinary
= True
3228 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3229 if IdfGenBinBuffer
is not None:
3230 IdfGenBinBuffer
.close()
3233 ## Return the list of library modules explicitly or implicityly used by this module
3235 def DependentLibraryList(self
):
3236 # only merge library classes and PCD for non-library module
3239 if self
.AutoGenVersion
< 0x00010005:
3240 return self
.PlatformInfo
.ResolveLibraryReference(self
.Module
)
3241 return self
.PlatformInfo
.ApplyLibraryInstance(self
.Module
)
3243 ## Get the list of PCDs from current module
3245 # @retval list The list of PCD
3248 def ModulePcdList(self
):
3249 # apply PCD settings from platform
3250 RetVal
= self
.PlatformInfo
.ApplyPcdSetting(self
.Module
, self
.Module
.Pcds
)
3251 ExtendCopyDictionaryLists(self
._PcdComments
, self
.Module
.PcdComments
)
3254 ## Get the list of PCDs from dependent libraries
3256 # @retval list The list of PCD
3259 def LibraryPcdList(self
):
3264 # get PCDs from dependent libraries
3265 for Library
in self
.DependentLibraryList
:
3266 PcdsInLibrary
= OrderedDict()
3267 ExtendCopyDictionaryLists(self
._PcdComments
, Library
.PcdComments
)
3268 for Key
in Library
.Pcds
:
3269 # skip duplicated PCDs
3270 if Key
in self
.Module
.Pcds
or Key
in Pcds
:
3273 PcdsInLibrary
[Key
] = copy
.copy(Library
.Pcds
[Key
])
3274 RetVal
.extend(self
.PlatformInfo
.ApplyPcdSetting(self
.Module
, PcdsInLibrary
, Library
=Library
))
3277 ## Get the GUID value mapping
3279 # @retval dict The mapping between GUID cname and its value
3283 RetVal
= OrderedDict(self
.Module
.Guids
)
3284 for Library
in self
.DependentLibraryList
:
3285 RetVal
.update(Library
.Guids
)
3286 ExtendCopyDictionaryLists(self
._GuidComments
, Library
.GuidComments
)
3287 ExtendCopyDictionaryLists(self
._GuidComments
, self
.Module
.GuidComments
)
3291 def GetGuidsUsedByPcd(self
):
3292 RetVal
= OrderedDict(self
.Module
.GetGuidsUsedByPcd())
3293 for Library
in self
.DependentLibraryList
:
3294 RetVal
.update(Library
.GetGuidsUsedByPcd())
3296 ## Get the protocol value mapping
3298 # @retval dict The mapping between protocol cname and its value
3301 def ProtocolList(self
):
3302 RetVal
= OrderedDict(self
.Module
.Protocols
)
3303 for Library
in self
.DependentLibraryList
:
3304 RetVal
.update(Library
.Protocols
)
3305 ExtendCopyDictionaryLists(self
._ProtocolComments
, Library
.ProtocolComments
)
3306 ExtendCopyDictionaryLists(self
._ProtocolComments
, self
.Module
.ProtocolComments
)
3309 ## Get the PPI value mapping
3311 # @retval dict The mapping between PPI cname and its value
3315 RetVal
= OrderedDict(self
.Module
.Ppis
)
3316 for Library
in self
.DependentLibraryList
:
3317 RetVal
.update(Library
.Ppis
)
3318 ExtendCopyDictionaryLists(self
._PpiComments
, Library
.PpiComments
)
3319 ExtendCopyDictionaryLists(self
._PpiComments
, self
.Module
.PpiComments
)
3322 ## Get the list of include search path
3324 # @retval list The list path
3327 def IncludePathList(self
):
3329 if self
.AutoGenVersion
< 0x00010005:
3330 for Inc
in self
.Module
.Includes
:
3331 if Inc
not in RetVal
:
3334 Inc
= path
.join(Inc
, self
.Arch
.capitalize())
3335 if os
.path
.exists(Inc
) and Inc
not in RetVal
:
3337 # Edk module needs to put DEBUG_DIR at the end of search path and not to use SOURCE_DIR all the time
3338 RetVal
.append(self
.DebugDir
)
3340 RetVal
.append(self
.MetaFile
.Dir
)
3341 RetVal
.append(self
.DebugDir
)
3343 for Package
in self
.Module
.Packages
:
3344 PackageDir
= mws
.join(self
.WorkspaceDir
, Package
.MetaFile
.Dir
)
3345 if PackageDir
not in RetVal
:
3346 RetVal
.append(PackageDir
)
3347 IncludesList
= Package
.Includes
3348 if Package
._PrivateIncludes
:
3349 if not self
.MetaFile
.Path
.startswith(PackageDir
):
3350 IncludesList
= list(set(Package
.Includes
).difference(set(Package
._PrivateIncludes
)))
3351 for Inc
in IncludesList
:
3352 if Inc
not in RetVal
:
3353 RetVal
.append(str(Inc
))
3357 def IncludePathLength(self
):
3358 return sum(len(inc
)+1 for inc
in self
.IncludePathList
)
3360 ## Get HII EX PCDs which maybe used by VFR
3362 # efivarstore used by VFR may relate with HII EX PCDs
3363 # Get the variable name and GUID from efivarstore and HII EX PCD
3364 # List the HII EX PCDs in As Built INF if both name and GUID match.
3366 # @retval list HII EX PCDs
3368 def _GetPcdsMaybeUsedByVfr(self
):
3369 if not self
.SourceFileList
:
3373 for SrcFile
in self
.SourceFileList
:
3374 if SrcFile
.Ext
.lower() != '.vfr':
3376 Vfri
= os
.path
.join(self
.OutputDir
, SrcFile
.BaseName
+ '.i')
3377 if not os
.path
.exists(Vfri
):
3379 VfriFile
= open(Vfri
, 'r')
3380 Content
= VfriFile
.read()
3382 Pos
= Content
.find('efivarstore')
3385 # Make sure 'efivarstore' is the start of efivarstore statement
3386 # In case of the value of 'name' (name = efivarstore) is equal to 'efivarstore'
3389 while Index
>= 0 and Content
[Index
] in ' \t\r\n':
3391 if Index
>= 0 and Content
[Index
] != ';':
3392 Pos
= Content
.find('efivarstore', Pos
+ len('efivarstore'))
3395 # 'efivarstore' must be followed by name and guid
3397 Name
= gEfiVarStoreNamePattern
.search(Content
, Pos
)
3400 Guid
= gEfiVarStoreGuidPattern
.search(Content
, Pos
)
3403 NameArray
= ConvertStringToByteArray('L"' + Name
.group(1) + '"')
3404 NameGuids
.add((NameArray
, GuidStructureStringToGuidString(Guid
.group(1))))
3405 Pos
= Content
.find('efivarstore', Name
.end())
3409 for Pcd
in self
.PlatformInfo
.Platform
.Pcds
.values():
3410 if Pcd
.Type
!= TAB_PCDS_DYNAMIC_EX_HII
:
3412 for SkuInfo
in Pcd
.SkuInfoList
.values():
3413 Value
= GuidValue(SkuInfo
.VariableGuid
, self
.PlatformInfo
.PackageList
, self
.MetaFile
.Path
)
3416 Name
= ConvertStringToByteArray(SkuInfo
.VariableName
)
3417 Guid
= GuidStructureStringToGuidString(Value
)
3418 if (Name
, Guid
) in NameGuids
and Pcd
not in HiiExPcds
:
3419 HiiExPcds
.append(Pcd
)
3424 def _GenOffsetBin(self
):
3426 for SourceFile
in self
.Module
.Sources
:
3427 if SourceFile
.Type
.upper() == ".VFR" :
3429 # search the .map file to find the offset of vfr binary in the PE32+/TE file.
3431 VfrUniBaseName
[SourceFile
.BaseName
] = (SourceFile
.BaseName
+ "Bin")
3432 elif SourceFile
.Type
.upper() == ".UNI" :
3434 # search the .map file to find the offset of Uni strings binary in the PE32+/TE file.
3436 VfrUniBaseName
["UniOffsetName"] = (self
.Name
+ "Strings")
3438 if not VfrUniBaseName
:
3440 MapFileName
= os
.path
.join(self
.OutputDir
, self
.Name
+ ".map")
3441 EfiFileName
= os
.path
.join(self
.OutputDir
, self
.Name
+ ".efi")
3442 VfrUniOffsetList
= GetVariableOffset(MapFileName
, EfiFileName
, list(VfrUniBaseName
.values()))
3443 if not VfrUniOffsetList
:
3446 OutputName
= '%sOffset.bin' % self
.Name
3447 UniVfrOffsetFileName
= os
.path
.join( self
.OutputDir
, OutputName
)
3450 fInputfile
= open(UniVfrOffsetFileName
, "wb+", 0)
3452 EdkLogger
.error("build", FILE_OPEN_FAILURE
, "File open failed for %s" % UniVfrOffsetFileName
, None)
3454 # Use a instance of BytesIO to cache data
3455 fStringIO
= BytesIO()
3457 for Item
in VfrUniOffsetList
:
3458 if (Item
[0].find("Strings") != -1):
3460 # UNI offset in image.
3462 # { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } }
3464 UniGuid
= [0xe0, 0xc5, 0x13, 0x89, 0xf6, 0x33, 0x86, 0x4d, 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66]
3465 fStringIO
.write(bytes(UniGuid
))
3466 UniValue
= pack ('Q', int (Item
[1], 16))
3467 fStringIO
.write (UniValue
)
3470 # VFR binary offset in image.
3472 # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } };
3474 VfrGuid
= [0xb4, 0x7c, 0xbc, 0xd0, 0x47, 0x6a, 0x5f, 0x49, 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2]
3475 fStringIO
.write(bytes(VfrGuid
))
3476 VfrValue
= pack ('Q', int (Item
[1], 16))
3477 fStringIO
.write (VfrValue
)
3479 # write data into file.
3482 fInputfile
.write (fStringIO
.getvalue())
3484 EdkLogger
.error("build", FILE_WRITE_FAILURE
, "Write data to file %s failed, please check whether the "
3485 "file been locked or using by other applications." %UniVfrOffsetFileName
, None)
3491 ## Create AsBuilt INF file the module
3493 def CreateAsBuiltInf(self
, IsOnlyCopy
= False):
3494 self
.OutputFile
= set()
3495 if IsOnlyCopy
and GlobalData
.gBinCacheDest
:
3496 self
.CopyModuleToCache()
3499 if self
.IsAsBuiltInfCreated
:
3502 # Skip the following code for EDK I inf
3503 if self
.AutoGenVersion
< 0x00010005:
3506 # Skip the following code for libraries
3510 # Skip the following code for modules with no source files
3511 if not self
.SourceFileList
:
3514 # Skip the following code for modules without any binary files
3515 if self
.BinaryFileList
:
3518 ### TODO: How to handles mixed source and binary modules
3520 # Find all DynamicEx and PatchableInModule PCDs used by this module and dependent libraries
3521 # Also find all packages that the DynamicEx PCDs depend on
3526 PcdTokenSpaceList
= []
3527 for Pcd
in list(self
.ModulePcdList
) + list(self
.LibraryPcdList
):
3528 if Pcd
.Type
== TAB_PCDS_PATCHABLE_IN_MODULE
:
3529 PatchablePcds
.append(Pcd
)
3530 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, TAB_PCDS_PATCHABLE_IN_MODULE
))
3531 elif Pcd
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
3534 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, TAB_PCDS_DYNAMIC_EX
))
3535 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, TAB_PCDS_DYNAMIC
))
3536 PcdTokenSpaceList
.append(Pcd
.TokenSpaceGuidCName
)
3537 GuidList
= OrderedDict(self
.GuidList
)
3538 for TokenSpace
in self
.GetGuidsUsedByPcd
:
3539 # If token space is not referred by patch PCD or Ex PCD, remove the GUID from GUID list
3540 # The GUIDs in GUIDs section should really be the GUIDs in source INF or referred by Ex an patch PCDs
3541 if TokenSpace
not in PcdTokenSpaceList
and TokenSpace
in GuidList
:
3542 GuidList
.pop(TokenSpace
)
3543 CheckList
= (GuidList
, self
.PpiList
, self
.ProtocolList
, PcdCheckList
)
3544 for Package
in self
.DerivedPackageList
:
3545 if Package
in Packages
:
3547 BeChecked
= (Package
.Guids
, Package
.Ppis
, Package
.Protocols
, Package
.Pcds
)
3549 for Index
in range(len(BeChecked
)):
3550 for Item
in CheckList
[Index
]:
3551 if Item
in BeChecked
[Index
]:
3552 Packages
.append(Package
)
3558 VfrPcds
= self
._GetPcdsMaybeUsedByVfr
()
3559 for Pkg
in self
.PlatformInfo
.PackageList
:
3562 for VfrPcd
in VfrPcds
:
3563 if ((VfrPcd
.TokenCName
, VfrPcd
.TokenSpaceGuidCName
, TAB_PCDS_DYNAMIC_EX
) in Pkg
.Pcds
or
3564 (VfrPcd
.TokenCName
, VfrPcd
.TokenSpaceGuidCName
, TAB_PCDS_DYNAMIC
) in Pkg
.Pcds
):
3565 Packages
.append(Pkg
)
3568 ModuleType
= SUP_MODULE_DXE_DRIVER
if self
.ModuleType
== SUP_MODULE_UEFI_DRIVER
and self
.DepexGenerated
else self
.ModuleType
3569 DriverType
= self
.PcdIsDriver
if self
.PcdIsDriver
else ''
3571 MDefs
= self
.Module
.Defines
3574 'module_name' : self
.Name
,
3575 'module_guid' : Guid
,
3576 'module_module_type' : ModuleType
,
3577 'module_version_string' : [MDefs
['VERSION_STRING']] if 'VERSION_STRING' in MDefs
else [],
3578 'pcd_is_driver_string' : [],
3579 'module_uefi_specification_version' : [],
3580 'module_pi_specification_version' : [],
3581 'module_entry_point' : self
.Module
.ModuleEntryPointList
,
3582 'module_unload_image' : self
.Module
.ModuleUnloadImageList
,
3583 'module_constructor' : self
.Module
.ConstructorList
,
3584 'module_destructor' : self
.Module
.DestructorList
,
3585 'module_shadow' : [MDefs
['SHADOW']] if 'SHADOW' in MDefs
else [],
3586 'module_pci_vendor_id' : [MDefs
['PCI_VENDOR_ID']] if 'PCI_VENDOR_ID' in MDefs
else [],
3587 'module_pci_device_id' : [MDefs
['PCI_DEVICE_ID']] if 'PCI_DEVICE_ID' in MDefs
else [],
3588 'module_pci_class_code' : [MDefs
['PCI_CLASS_CODE']] if 'PCI_CLASS_CODE' in MDefs
else [],
3589 'module_pci_revision' : [MDefs
['PCI_REVISION']] if 'PCI_REVISION' in MDefs
else [],
3590 'module_build_number' : [MDefs
['BUILD_NUMBER']] if 'BUILD_NUMBER' in MDefs
else [],
3591 'module_spec' : [MDefs
['SPEC']] if 'SPEC' in MDefs
else [],
3592 'module_uefi_hii_resource_section' : [MDefs
['UEFI_HII_RESOURCE_SECTION']] if 'UEFI_HII_RESOURCE_SECTION' in MDefs
else [],
3593 'module_uni_file' : [MDefs
['MODULE_UNI_FILE']] if 'MODULE_UNI_FILE' in MDefs
else [],
3594 'module_arch' : self
.Arch
,
3595 'package_item' : [Package
.MetaFile
.File
.replace('\\', '/') for Package
in Packages
],
3597 'patchablepcd_item' : [],
3599 'protocol_item' : [],
3603 'libraryclasses_item' : []
3606 if 'MODULE_UNI_FILE' in MDefs
:
3607 UNIFile
= os
.path
.join(self
.MetaFile
.Dir
, MDefs
['MODULE_UNI_FILE'])
3608 if os
.path
.isfile(UNIFile
):
3609 shutil
.copy2(UNIFile
, self
.OutputDir
)
3611 if self
.AutoGenVersion
> int(gInfSpecVersion
, 0):
3612 AsBuiltInfDict
['module_inf_version'] = '0x%08x' % self
.AutoGenVersion
3614 AsBuiltInfDict
['module_inf_version'] = gInfSpecVersion
3617 AsBuiltInfDict
['pcd_is_driver_string'].append(DriverType
)
3619 if 'UEFI_SPECIFICATION_VERSION' in self
.Specification
:
3620 AsBuiltInfDict
['module_uefi_specification_version'].append(self
.Specification
['UEFI_SPECIFICATION_VERSION'])
3621 if 'PI_SPECIFICATION_VERSION' in self
.Specification
:
3622 AsBuiltInfDict
['module_pi_specification_version'].append(self
.Specification
['PI_SPECIFICATION_VERSION'])
3624 OutputDir
= self
.OutputDir
.replace('\\', '/').strip('/')
3625 DebugDir
= self
.DebugDir
.replace('\\', '/').strip('/')
3626 for Item
in self
.CodaTargetList
:
3627 File
= Item
.Target
.Path
.replace('\\', '/').strip('/').replace(DebugDir
, '').replace(OutputDir
, '').strip('/')
3628 self
.OutputFile
.add(File
)
3629 if os
.path
.isabs(File
):
3630 File
= File
.replace('\\', '/').strip('/').replace(OutputDir
, '').strip('/')
3631 if Item
.Target
.Ext
.lower() == '.aml':
3632 AsBuiltInfDict
['binary_item'].append('ASL|' + File
)
3633 elif Item
.Target
.Ext
.lower() == '.acpi':
3634 AsBuiltInfDict
['binary_item'].append('ACPI|' + File
)
3635 elif Item
.Target
.Ext
.lower() == '.efi':
3636 AsBuiltInfDict
['binary_item'].append('PE32|' + self
.Name
+ '.efi')
3638 AsBuiltInfDict
['binary_item'].append('BIN|' + File
)
3639 if not self
.DepexGenerated
:
3640 DepexFile
= os
.path
.join(self
.OutputDir
, self
.Name
+ '.depex')
3641 if os
.path
.exists(DepexFile
):
3642 self
.DepexGenerated
= True
3643 if self
.DepexGenerated
:
3644 self
.OutputFile
.add(self
.Name
+ '.depex')
3645 if self
.ModuleType
in [SUP_MODULE_PEIM
]:
3646 AsBuiltInfDict
['binary_item'].append('PEI_DEPEX|' + self
.Name
+ '.depex')
3647 elif self
.ModuleType
in [SUP_MODULE_DXE_DRIVER
, SUP_MODULE_DXE_RUNTIME_DRIVER
, SUP_MODULE_DXE_SAL_DRIVER
, SUP_MODULE_UEFI_DRIVER
]:
3648 AsBuiltInfDict
['binary_item'].append('DXE_DEPEX|' + self
.Name
+ '.depex')
3649 elif self
.ModuleType
in [SUP_MODULE_DXE_SMM_DRIVER
]:
3650 AsBuiltInfDict
['binary_item'].append('SMM_DEPEX|' + self
.Name
+ '.depex')
3652 Bin
= self
._GenOffsetBin
()
3654 AsBuiltInfDict
['binary_item'].append('BIN|%s' % Bin
)
3655 self
.OutputFile
.add(Bin
)
3657 for Root
, Dirs
, Files
in os
.walk(OutputDir
):
3659 if File
.lower().endswith('.pdb'):
3660 AsBuiltInfDict
['binary_item'].append('DISPOSABLE|' + File
)
3661 self
.OutputFile
.add(File
)
3662 HeaderComments
= self
.Module
.HeaderComments
3664 for Index
in range(len(HeaderComments
)):
3665 if HeaderComments
[Index
].find('@BinaryHeader') != -1:
3666 HeaderComments
[Index
] = HeaderComments
[Index
].replace('@BinaryHeader', '@file')
3669 AsBuiltInfDict
['header_comments'] = '\n'.join(HeaderComments
[StartPos
:]).replace(':#', '://')
3670 AsBuiltInfDict
['tail_comments'] = '\n'.join(self
.Module
.TailComments
)
3673 (self
.ProtocolList
, self
._ProtocolComments
, 'protocol_item'),
3674 (self
.PpiList
, self
._PpiComments
, 'ppi_item'),
3675 (GuidList
, self
._GuidComments
, 'guid_item')
3677 for Item
in GenList
:
3678 for CName
in Item
[0]:
3679 Comments
= '\n '.join(Item
[1][CName
]) if CName
in Item
[1] else ''
3680 Entry
= Comments
+ '\n ' + CName
if Comments
else CName
3681 AsBuiltInfDict
[Item
[2]].append(Entry
)
3682 PatchList
= parsePcdInfoFromMapFile(
3683 os
.path
.join(self
.OutputDir
, self
.Name
+ '.map'),
3684 os
.path
.join(self
.OutputDir
, self
.Name
+ '.efi')
3687 for Pcd
in PatchablePcds
:
3688 TokenCName
= Pcd
.TokenCName
3689 for PcdItem
in GlobalData
.MixedPcd
:
3690 if (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
3691 TokenCName
= PcdItem
[0]
3693 for PatchPcd
in PatchList
:
3694 if TokenCName
== PatchPcd
[0]:
3699 if Pcd
.DatumType
== 'BOOLEAN':
3700 BoolValue
= Pcd
.DefaultValue
.upper()
3701 if BoolValue
== 'TRUE':
3702 Pcd
.DefaultValue
= '1'
3703 elif BoolValue
== 'FALSE':
3704 Pcd
.DefaultValue
= '0'
3706 if Pcd
.DatumType
in TAB_PCD_NUMERIC_TYPES
:
3707 HexFormat
= '0x%02x'
3708 if Pcd
.DatumType
== TAB_UINT16
:
3709 HexFormat
= '0x%04x'
3710 elif Pcd
.DatumType
== TAB_UINT32
:
3711 HexFormat
= '0x%08x'
3712 elif Pcd
.DatumType
== TAB_UINT64
:
3713 HexFormat
= '0x%016x'
3714 PcdValue
= HexFormat
% int(Pcd
.DefaultValue
, 0)
3716 if Pcd
.MaxDatumSize
is None or Pcd
.MaxDatumSize
== '':
3717 EdkLogger
.error("build", AUTOGEN_ERROR
,
3718 "Unknown [MaxDatumSize] of PCD [%s.%s]" % (Pcd
.TokenSpaceGuidCName
, TokenCName
)
3720 ArraySize
= int(Pcd
.MaxDatumSize
, 0)
3721 PcdValue
= Pcd
.DefaultValue
3722 if PcdValue
[0] != '{':
3724 if PcdValue
[0] == 'L':
3726 PcdValue
= PcdValue
.lstrip('L')
3727 PcdValue
= eval(PcdValue
)
3729 for Index
in range(0, len(PcdValue
)):
3731 CharVal
= ord(PcdValue
[Index
])
3732 NewValue
= NewValue
+ '0x%02x' % (CharVal
& 0x00FF) + ', ' \
3733 + '0x%02x' % (CharVal
>> 8) + ', '
3735 NewValue
= NewValue
+ '0x%02x' % (ord(PcdValue
[Index
]) % 0x100) + ', '
3738 Padding
= Padding
* 2
3739 ArraySize
= ArraySize
// 2
3740 if ArraySize
< (len(PcdValue
) + 1):
3741 if Pcd
.MaxSizeUserSet
:
3742 EdkLogger
.error("build", AUTOGEN_ERROR
,
3743 "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd
.TokenSpaceGuidCName
, TokenCName
)
3746 ArraySize
= len(PcdValue
) + 1
3747 if ArraySize
> len(PcdValue
) + 1:
3748 NewValue
= NewValue
+ Padding
* (ArraySize
- len(PcdValue
) - 1)
3749 PcdValue
= NewValue
+ Padding
.strip().rstrip(',') + '}'
3750 elif len(PcdValue
.split(',')) <= ArraySize
:
3751 PcdValue
= PcdValue
.rstrip('}') + ', 0x00' * (ArraySize
- len(PcdValue
.split(',')))
3754 if Pcd
.MaxSizeUserSet
:
3755 EdkLogger
.error("build", AUTOGEN_ERROR
,
3756 "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd
.TokenSpaceGuidCName
, TokenCName
)
3759 ArraySize
= len(PcdValue
) + 1
3760 PcdItem
= '%s.%s|%s|0x%X' % \
3761 (Pcd
.TokenSpaceGuidCName
, TokenCName
, PcdValue
, PatchPcd
[1])
3763 if (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) in self
._PcdComments
:
3764 PcdComments
= '\n '.join(self
._PcdComments
[Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
])
3766 PcdItem
= PcdComments
+ '\n ' + PcdItem
3767 AsBuiltInfDict
['patchablepcd_item'].append(PcdItem
)
3769 for Pcd
in Pcds
+ VfrPcds
:
3772 TokenCName
= Pcd
.TokenCName
3773 for PcdItem
in GlobalData
.MixedPcd
:
3774 if (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
3775 TokenCName
= PcdItem
[0]
3777 if Pcd
.Type
== TAB_PCDS_DYNAMIC_EX_HII
:
3778 for SkuName
in Pcd
.SkuInfoList
:
3779 SkuInfo
= Pcd
.SkuInfoList
[SkuName
]
3780 HiiInfo
= '## %s|%s|%s' % (SkuInfo
.VariableName
, SkuInfo
.VariableGuid
, SkuInfo
.VariableOffset
)
3782 if (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) in self
._PcdComments
:
3783 PcdCommentList
= self
._PcdComments
[Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
][:]
3787 for Index
, Comment
in enumerate(PcdCommentList
):
3788 for Usage
in UsageList
:
3789 if Comment
.find(Usage
) != -1:
3793 if UsageIndex
!= -1:
3794 PcdCommentList
[UsageIndex
] = '## %s %s %s' % (UsageStr
, HiiInfo
, PcdCommentList
[UsageIndex
].replace(UsageStr
, ''))
3796 PcdCommentList
.append('## UNDEFINED ' + HiiInfo
)
3797 PcdComments
= '\n '.join(PcdCommentList
)
3798 PcdEntry
= Pcd
.TokenSpaceGuidCName
+ '.' + TokenCName
3800 PcdEntry
= PcdComments
+ '\n ' + PcdEntry
3801 AsBuiltInfDict
['pcd_item'].append(PcdEntry
)
3802 for Item
in self
.BuildOption
:
3803 if 'FLAGS' in self
.BuildOption
[Item
]:
3804 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()))
3806 # Generated LibraryClasses section in comments.
3807 for Library
in self
.LibraryAutoGenList
:
3808 AsBuiltInfDict
['libraryclasses_item'].append(Library
.MetaFile
.File
.replace('\\', '/'))
3810 # Generated UserExtensions TianoCore section.
3811 # All tianocore user extensions are copied.
3813 for TianoCore
in self
._GetTianoCoreUserExtensionList
():
3814 UserExtStr
+= '\n'.join(TianoCore
)
3815 ExtensionFile
= os
.path
.join(self
.MetaFile
.Dir
, TianoCore
[1])
3816 if os
.path
.isfile(ExtensionFile
):
3817 shutil
.copy2(ExtensionFile
, self
.OutputDir
)
3818 AsBuiltInfDict
['userextension_tianocore_item'] = UserExtStr
3820 # Generated depex expression section in comments.
3821 DepexExpresion
= self
._GetDepexExpresionString
()
3822 AsBuiltInfDict
['depexsection_item'] = DepexExpresion
if DepexExpresion
else ''
3824 AsBuiltInf
= TemplateString()
3825 AsBuiltInf
.Append(gAsBuiltInfHeaderString
.Replace(AsBuiltInfDict
))
3827 SaveFileOnChange(os
.path
.join(self
.OutputDir
, self
.Name
+ '.inf'), str(AsBuiltInf
), False)
3829 self
.IsAsBuiltInfCreated
= True
3830 if GlobalData
.gBinCacheDest
:
3831 self
.CopyModuleToCache()
3833 def CopyModuleToCache(self
):
3834 FileDir
= path
.join(GlobalData
.gBinCacheDest
, self
.Arch
, self
.SourceDir
, self
.MetaFile
.BaseName
)
3835 CreateDirectory (FileDir
)
3836 HashFile
= path
.join(self
.BuildDir
, self
.Name
+ '.hash')
3837 ModuleFile
= path
.join(self
.OutputDir
, self
.Name
+ '.inf')
3838 if os
.path
.exists(HashFile
):
3839 shutil
.copy2(HashFile
, FileDir
)
3840 if os
.path
.exists(ModuleFile
):
3841 shutil
.copy2(ModuleFile
, FileDir
)
3842 if not self
.OutputFile
:
3843 Ma
= self
.BuildDatabase
[PathClass(ModuleFile
), self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
3844 self
.OutputFile
= Ma
.Binaries
3846 for File
in self
.OutputFile
:
3848 if not os
.path
.isabs(File
):
3849 File
= os
.path
.join(self
.OutputDir
, File
)
3850 if os
.path
.exists(File
):
3851 shutil
.copy2(File
, FileDir
)
3853 def AttemptModuleCacheCopy(self
):
3854 if self
.IsBinaryModule
:
3856 FileDir
= path
.join(GlobalData
.gBinCacheSource
, self
.Arch
, self
.SourceDir
, self
.MetaFile
.BaseName
)
3857 HashFile
= path
.join(FileDir
, self
.Name
+ '.hash')
3858 if os
.path
.exists(HashFile
):
3859 f
= open(HashFile
, 'r')
3860 CacheHash
= f
.read()
3862 if GlobalData
.gModuleHash
[self
.Arch
][self
.Name
]:
3863 if CacheHash
== GlobalData
.gModuleHash
[self
.Arch
][self
.Name
]:
3864 for root
, dir, files
in os
.walk(FileDir
):
3866 if self
.Name
+ '.hash' in f
:
3867 shutil
.copy2(HashFile
, self
.BuildDir
)
3869 File
= path
.join(root
, f
)
3870 shutil
.copy2(File
, self
.OutputDir
)
3871 if self
.Name
== "PcdPeim" or self
.Name
== "PcdDxe":
3872 CreatePcdDatabaseCode(self
, TemplateString(), TemplateString())
3876 ## Create makefile for the module and its dependent libraries
3878 # @param CreateLibraryMakeFile Flag indicating if or not the makefiles of
3879 # dependent libraries will be created
3881 @cached_class_function
3882 def CreateMakeFile(self
, CreateLibraryMakeFile
=True, GenFfsList
= []):
3883 # nest this function inside it's only caller.
3884 def CreateTimeStamp():
3885 FileSet
= {self
.MetaFile
.Path
}
3887 for SourceFile
in self
.Module
.Sources
:
3888 FileSet
.add (SourceFile
.Path
)
3890 for Lib
in self
.DependentLibraryList
:
3891 FileSet
.add (Lib
.MetaFile
.Path
)
3893 for f
in self
.AutoGenDepSet
:
3894 FileSet
.add (f
.Path
)
3896 if os
.path
.exists (self
.TimeStampPath
):
3897 os
.remove (self
.TimeStampPath
)
3898 with
open(self
.TimeStampPath
, 'w+') as file:
3899 for f
in sorted(FileSet
):
3902 # Ignore generating makefile when it is a binary module
3903 if self
.IsBinaryModule
:
3906 self
.GenFfsList
= GenFfsList
3907 if not self
.IsLibrary
and CreateLibraryMakeFile
:
3908 for LibraryAutoGen
in self
.LibraryAutoGenList
:
3909 LibraryAutoGen
.CreateMakeFile()
3914 if len(self
.CustomMakefile
) == 0:
3915 Makefile
= GenMake
.ModuleMakefile(self
)
3917 Makefile
= GenMake
.CustomMakefile(self
)
3918 if Makefile
.Generate():
3919 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated makefile for module %s [%s]" %
3920 (self
.Name
, self
.Arch
))
3922 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Skipped the generation of makefile for module %s [%s]" %
3923 (self
.Name
, self
.Arch
))
3927 def CopyBinaryFiles(self
):
3928 for File
in self
.Module
.Binaries
:
3930 DstPath
= os
.path
.join(self
.OutputDir
, os
.path
.basename(SrcPath
))
3931 CopyLongFilePath(SrcPath
, DstPath
)
3932 ## Create autogen code for the module and its dependent libraries
3934 # @param CreateLibraryCodeFile Flag indicating if or not the code of
3935 # dependent libraries will be created
3937 def CreateCodeFile(self
, CreateLibraryCodeFile
=True):
3938 if self
.IsCodeFileCreated
:
3941 # Need to generate PcdDatabase even PcdDriver is binarymodule
3942 if self
.IsBinaryModule
and self
.PcdIsDriver
!= '':
3943 CreatePcdDatabaseCode(self
, TemplateString(), TemplateString())
3945 if self
.IsBinaryModule
:
3947 self
.CopyBinaryFiles()
3950 if not self
.IsLibrary
and CreateLibraryCodeFile
:
3951 for LibraryAutoGen
in self
.LibraryAutoGenList
:
3952 LibraryAutoGen
.CreateCodeFile()
3958 IgoredAutoGenList
= []
3960 for File
in self
.AutoGenFileList
:
3961 if GenC
.Generate(File
.Path
, self
.AutoGenFileList
[File
], File
.IsBinary
):
3962 #Ignore Edk AutoGen.c
3963 if self
.AutoGenVersion
< 0x00010005 and File
.Name
== 'AutoGen.c':
3966 AutoGenList
.append(str(File
))
3968 IgoredAutoGenList
.append(str(File
))
3970 # Skip the following code for EDK I inf
3971 if self
.AutoGenVersion
< 0x00010005:
3974 for ModuleType
in self
.DepexList
:
3975 # Ignore empty [depex] section or [depex] section for SUP_MODULE_USER_DEFINED module
3976 if len(self
.DepexList
[ModuleType
]) == 0 or ModuleType
== SUP_MODULE_USER_DEFINED
:
3979 Dpx
= GenDepex
.DependencyExpression(self
.DepexList
[ModuleType
], ModuleType
, True)
3980 DpxFile
= gAutoGenDepexFileName
% {"module_name" : self
.Name
}
3982 if len(Dpx
.PostfixNotation
) != 0:
3983 self
.DepexGenerated
= True
3985 if Dpx
.Generate(path
.join(self
.OutputDir
, DpxFile
)):
3986 AutoGenList
.append(str(DpxFile
))
3988 IgoredAutoGenList
.append(str(DpxFile
))
3990 if IgoredAutoGenList
== []:
3991 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated [%s] files for module %s [%s]" %
3992 (" ".join(AutoGenList
), self
.Name
, self
.Arch
))
3993 elif AutoGenList
== []:
3994 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Skipped the generation of [%s] files for module %s [%s]" %
3995 (" ".join(IgoredAutoGenList
), self
.Name
, self
.Arch
))
3997 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated [%s] (skipped %s) files for module %s [%s]" %
3998 (" ".join(AutoGenList
), " ".join(IgoredAutoGenList
), self
.Name
, self
.Arch
))
4000 self
.IsCodeFileCreated
= True
4003 ## Summarize the ModuleAutoGen objects of all libraries used by this module
4005 def LibraryAutoGenList(self
):
4007 for Library
in self
.DependentLibraryList
:
4014 self
.PlatformInfo
.MetaFile
4016 if La
not in RetVal
:
4018 for Lib
in La
.CodaTargetList
:
4019 self
._ApplyBuildRule
(Lib
.Target
, TAB_UNKNOWN_FILE
)
4022 def GenModuleHash(self
):
4023 if self
.Arch
not in GlobalData
.gModuleHash
:
4024 GlobalData
.gModuleHash
[self
.Arch
] = {}
4026 # Add Platform level hash
4027 m
.update(GlobalData
.gPlatformHash
.encode('utf-8'))
4028 # Add Package level hash
4029 if self
.DependentPackageList
:
4030 for Pkg
in sorted(self
.DependentPackageList
, key
=lambda x
: x
.PackageName
):
4031 if Pkg
.PackageName
in GlobalData
.gPackageHash
[self
.Arch
]:
4032 m
.update(GlobalData
.gPackageHash
[self
.Arch
][Pkg
.PackageName
].encode('utf-8'))
4035 if self
.LibraryAutoGenList
:
4036 for Lib
in sorted(self
.LibraryAutoGenList
, key
=lambda x
: x
.Name
):
4037 if Lib
.Name
not in GlobalData
.gModuleHash
[self
.Arch
]:
4039 m
.update(GlobalData
.gModuleHash
[self
.Arch
][Lib
.Name
].encode('utf-8'))
4042 f
= open(str(self
.MetaFile
), 'rb')
4046 # Add Module's source files
4047 if self
.SourceFileList
:
4048 for File
in sorted(self
.SourceFileList
, key
=lambda x
: str(x
)):
4049 f
= open(str(File
), 'rb')
4054 ModuleHashFile
= path
.join(self
.BuildDir
, self
.Name
+ ".hash")
4055 if self
.Name
not in GlobalData
.gModuleHash
[self
.Arch
]:
4056 GlobalData
.gModuleHash
[self
.Arch
][self
.Name
] = m
.hexdigest()
4057 if GlobalData
.gBinCacheSource
:
4058 if self
.AttemptModuleCacheCopy():
4060 return SaveFileOnChange(ModuleHashFile
, m
.hexdigest(), True)
4062 ## Decide whether we can skip the ModuleAutoGen process
4063 def CanSkipbyHash(self
):
4064 if GlobalData
.gUseHashCache
:
4065 return not self
.GenModuleHash()
4068 ## Decide whether we can skip the ModuleAutoGen process
4069 # If any source file is newer than the module than we cannot skip
4072 if self
.MakeFileDir
in GlobalData
.gSikpAutoGenCache
:
4074 if not os
.path
.exists(self
.TimeStampPath
):
4076 #last creation time of the module
4077 DstTimeStamp
= os
.stat(self
.TimeStampPath
)[8]
4079 SrcTimeStamp
= self
.Workspace
._SrcTimeStamp
4080 if SrcTimeStamp
> DstTimeStamp
:
4083 with
open(self
.TimeStampPath
,'r') as f
:
4085 source
= source
.rstrip('\n')
4086 if not os
.path
.exists(source
):
4088 if source
not in ModuleAutoGen
.TimeDict
:
4089 ModuleAutoGen
.TimeDict
[source
] = os
.stat(source
)[8]
4090 if ModuleAutoGen
.TimeDict
[source
] > DstTimeStamp
:
4092 GlobalData
.gSikpAutoGenCache
.add(self
.MakeFileDir
)
4096 def TimeStampPath(self
):
4097 return os
.path
.join(self
.MakeFileDir
, 'AutoGenTimeStamp')