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 from __future__
import print_function
19 from __future__
import absolute_import
20 import Common
.LongFilePathOs
as os
22 import os
.path
as path
28 from . import GenDepex
29 from io
import BytesIO
31 from .StrGather
import *
32 from .BuildEngine
import BuildRule
34 from Common
.LongFilePathSupport
import CopyLongFilePath
35 from Common
.BuildToolError
import *
36 from Common
.DataType
import *
37 from Common
.Misc
import *
38 from Common
.StringUtils
import *
39 import Common
.GlobalData
as GlobalData
40 from GenFds
.FdfParser
import *
41 from CommonDataClass
.CommonClass
import SkuInfoClass
42 from Workspace
.BuildClassObject
import *
43 from GenPatchPcdTable
.GenPatchPcdTable
import parsePcdInfoFromMapFile
44 import Common
.VpdInfoFile
as VpdInfoFile
45 from .GenPcdDb
import CreatePcdDatabaseCode
46 from Workspace
.MetaFileCommentParser
import UsageList
47 from Workspace
.WorkspaceCommon
import GetModuleLibInstances
48 from Common
.MultipleWorkspace
import MultipleWorkspace
as mws
49 from . import InfSectionParser
52 from .GenVar
import VariableMgr
, var_info
53 from collections
import OrderedDict
54 from collections
import defaultdict
55 from Workspace
.WorkspaceCommon
import OrderedListDict
57 ## Regular expression for splitting Dependency Expression string into tokens
58 gDepexTokenPattern
= re
.compile("(\(|\)|\w+| \S+\.inf)")
60 ## Regular expression for match: PCD(xxxx.yyy)
61 gPCDAsGuidPattern
= re
.compile(r
"^PCD\(.+\..+\)$")
64 # Regular expression for finding Include Directories, the difference between MSFT and INTEL/GCC/RVCT
65 # is the former use /I , the Latter used -I to specify include directories
67 gBuildOptIncludePatternMsft
= re
.compile(r
"(?:.*?)/I[ \t]*([^ ]*)", re
.MULTILINE | re
.DOTALL
)
68 gBuildOptIncludePatternOther
= re
.compile(r
"(?:.*?)-I[ \t]*([^ ]*)", re
.MULTILINE | re
.DOTALL
)
71 # Match name = variable
73 gEfiVarStoreNamePattern
= re
.compile("\s*name\s*=\s*(\w+)")
75 # The format of guid in efivarstore statement likes following and must be correct:
76 # guid = {0xA04A27f4, 0xDF00, 0x4D42, {0xB5, 0x52, 0x39, 0x51, 0x13, 0x02, 0x11, 0x3D}}
78 gEfiVarStoreGuidPattern
= re
.compile("\s*guid\s*=\s*({.*?{.*?}\s*})")
80 ## Mapping Makefile type
81 gMakeTypeMap
= {"MSFT":"nmake", "GCC":"gmake"}
84 ## Build rule configuration file
85 gDefaultBuildRuleFile
= 'build_rule.txt'
87 ## Tools definition configuration file
88 gDefaultToolsDefFile
= 'tools_def.txt'
90 ## Build rule default version
91 AutoGenReqBuildRuleVerNum
= "0.1"
93 ## default file name for AutoGen
94 gAutoGenCodeFileName
= "AutoGen.c"
95 gAutoGenHeaderFileName
= "AutoGen.h"
96 gAutoGenStringFileName
= "%(module_name)sStrDefs.h"
97 gAutoGenStringFormFileName
= "%(module_name)sStrDefs.hpk"
98 gAutoGenDepexFileName
= "%(module_name)s.depex"
99 gAutoGenImageDefFileName
= "%(module_name)sImgDefs.h"
100 gAutoGenIdfFileName
= "%(module_name)sIdf.hpk"
101 gInfSpecVersion
= "0x00010017"
104 # Template string to generic AsBuilt INF
106 gAsBuiltInfHeaderString
= TemplateString("""${header_comments}
109 # FILE auto-generated
112 INF_VERSION = ${module_inf_version}
113 BASE_NAME = ${module_name}
114 FILE_GUID = ${module_guid}
115 MODULE_TYPE = ${module_module_type}${BEGIN}
116 VERSION_STRING = ${module_version_string}${END}${BEGIN}
117 PCD_IS_DRIVER = ${pcd_is_driver_string}${END}${BEGIN}
118 UEFI_SPECIFICATION_VERSION = ${module_uefi_specification_version}${END}${BEGIN}
119 PI_SPECIFICATION_VERSION = ${module_pi_specification_version}${END}${BEGIN}
120 ENTRY_POINT = ${module_entry_point}${END}${BEGIN}
121 UNLOAD_IMAGE = ${module_unload_image}${END}${BEGIN}
122 CONSTRUCTOR = ${module_constructor}${END}${BEGIN}
123 DESTRUCTOR = ${module_destructor}${END}${BEGIN}
124 SHADOW = ${module_shadow}${END}${BEGIN}
125 PCI_VENDOR_ID = ${module_pci_vendor_id}${END}${BEGIN}
126 PCI_DEVICE_ID = ${module_pci_device_id}${END}${BEGIN}
127 PCI_CLASS_CODE = ${module_pci_class_code}${END}${BEGIN}
128 PCI_REVISION = ${module_pci_revision}${END}${BEGIN}
129 BUILD_NUMBER = ${module_build_number}${END}${BEGIN}
130 SPEC = ${module_spec}${END}${BEGIN}
131 UEFI_HII_RESOURCE_SECTION = ${module_uefi_hii_resource_section}${END}${BEGIN}
132 MODULE_UNI_FILE = ${module_uni_file}${END}
134 [Packages.${module_arch}]${BEGIN}
135 ${package_item}${END}
137 [Binaries.${module_arch}]${BEGIN}
140 [PatchPcd.${module_arch}]${BEGIN}
144 [Protocols.${module_arch}]${BEGIN}
148 [Ppis.${module_arch}]${BEGIN}
152 [Guids.${module_arch}]${BEGIN}
156 [PcdEx.${module_arch}]${BEGIN}
160 [LibraryClasses.${module_arch}]
161 ## @LIB_INSTANCES${BEGIN}
162 # ${libraryclasses_item}${END}
166 ${userextension_tianocore_item}
170 [BuildOptions.${module_arch}]
172 ## ${flags_item}${END}
175 ## Base class for AutoGen
177 # This class just implements the cache mechanism of AutoGen objects.
179 class AutoGen(object):
180 # database to maintain the objects in each child class
181 __ObjectCache
= {} # (BuildTarget, ToolChain, ARCH, platform file): AutoGen object
185 # @param Class class object of real AutoGen class
186 # (WorkspaceAutoGen, ModuleAutoGen or PlatformAutoGen)
187 # @param Workspace Workspace directory or WorkspaceAutoGen object
188 # @param MetaFile The path of meta file
189 # @param Target Build target
190 # @param Toolchain Tool chain name
191 # @param Arch Target arch
192 # @param *args The specific class related parameters
193 # @param **kwargs The specific class related dict parameters
195 def __new__(cls
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
196 # check if the object has been created
197 Key
= (Target
, Toolchain
, Arch
, MetaFile
)
199 # if it exists, just return it directly
200 return cls
.__ObjectCache
[Key
]
202 # it didnt exist. create it, cache it, then return it
203 cls
.__ObjectCache
[Key
] = super(AutoGen
, cls
).__new
__(cls
)
204 return cls
.__ObjectCache
[Key
]
206 def __init__ (self
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
207 super(AutoGen
, self
).__init
__(self
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
)
211 # The file path of platform file will be used to represent hash value of this object
213 # @retval int Hash value of the file path of platform file
216 return hash(self
.MetaFile
)
220 # The file path of platform file will be used to represent this object
222 # @retval string String of platform file path
225 return str(self
.MetaFile
)
228 def __eq__(self
, Other
):
229 return Other
and self
.MetaFile
== Other
231 ## Workspace AutoGen class
233 # This class is used mainly to control the whole platform build for different
234 # architecture. This class will generate top level makefile.
236 class WorkspaceAutoGen(AutoGen
):
237 # call super().__init__ then call the worker function with different parameter count
238 def __init__(self
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
242 super(WorkspaceAutoGen
, self
).__init
__(Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
)
243 self
._InitWorker
(Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
)
246 ## Initialize WorkspaceAutoGen
248 # @param WorkspaceDir Root directory of workspace
249 # @param ActivePlatform Meta-file of active platform
250 # @param Target Build target
251 # @param Toolchain Tool chain name
252 # @param ArchList List of architecture of current build
253 # @param MetaFileDb Database containing meta-files
254 # @param BuildConfig Configuration of build
255 # @param ToolDefinition Tool chain definitions
256 # @param FlashDefinitionFile File of flash definition
257 # @param Fds FD list to be generated
258 # @param Fvs FV list to be generated
259 # @param Caps Capsule list to be generated
260 # @param SkuId SKU id from command line
262 def _InitWorker(self
, WorkspaceDir
, ActivePlatform
, Target
, Toolchain
, ArchList
, MetaFileDb
,
263 BuildConfig
, ToolDefinition
, FlashDefinitionFile
='', Fds
=None, Fvs
=None, Caps
=None, SkuId
='', UniFlag
=None,
264 Progress
=None, BuildModule
=None):
265 self
.BuildDatabase
= MetaFileDb
266 self
.MetaFile
= ActivePlatform
267 self
.WorkspaceDir
= WorkspaceDir
268 self
.Platform
= self
.BuildDatabase
[self
.MetaFile
, TAB_ARCH_COMMON
, Target
, Toolchain
]
269 GlobalData
.gActivePlatform
= self
.Platform
270 self
.BuildTarget
= Target
271 self
.ToolChain
= Toolchain
272 self
.ArchList
= ArchList
274 self
.UniFlag
= UniFlag
276 self
.TargetTxt
= BuildConfig
277 self
.ToolDef
= ToolDefinition
278 self
.FdfFile
= FlashDefinitionFile
279 self
.FdTargetList
= Fds
if Fds
else []
280 self
.FvTargetList
= Fvs
if Fvs
else []
281 self
.CapTargetList
= Caps
if Caps
else []
282 self
.AutoGenObjectList
= []
283 self
._BuildDir
= None
285 self
._MakeFileDir
= None
286 self
._BuildCommand
= None
289 # there's many relative directory operations, so ...
290 os
.chdir(self
.WorkspaceDir
)
295 if not self
.ArchList
:
296 ArchList
= set(self
.Platform
.SupArchList
)
298 ArchList
= set(self
.ArchList
) & set(self
.Platform
.SupArchList
)
300 EdkLogger
.error("build", PARAMETER_INVALID
,
301 ExtraData
= "Invalid ARCH specified. [Valid ARCH: %s]" % (" ".join(self
.Platform
.SupArchList
)))
302 elif self
.ArchList
and len(ArchList
) != len(self
.ArchList
):
303 SkippedArchList
= set(self
.ArchList
).symmetric_difference(set(self
.Platform
.SupArchList
))
304 EdkLogger
.verbose("\nArch [%s] is ignored because the platform supports [%s] only!"
305 % (" ".join(SkippedArchList
), " ".join(self
.Platform
.SupArchList
)))
306 self
.ArchList
= tuple(ArchList
)
308 # Validate build target
309 if self
.BuildTarget
not in self
.Platform
.BuildTargets
:
310 EdkLogger
.error("build", PARAMETER_INVALID
,
311 ExtraData
="Build target [%s] is not supported by the platform. [Valid target: %s]"
312 % (self
.BuildTarget
, " ".join(self
.Platform
.BuildTargets
)))
315 # parse FDF file to get PCDs in it, if any
317 self
.FdfFile
= self
.Platform
.FlashDefinition
321 EdkLogger
.info('%-16s = %s' % ("Architecture(s)", ' '.join(self
.ArchList
)))
322 EdkLogger
.info('%-16s = %s' % ("Build target", self
.BuildTarget
))
323 EdkLogger
.info('%-16s = %s' % ("Toolchain", self
.ToolChain
))
325 EdkLogger
.info('\n%-24s = %s' % ("Active Platform", self
.Platform
))
327 EdkLogger
.info('%-24s = %s' % ("Active Module", BuildModule
))
330 EdkLogger
.info('%-24s = %s' % ("Flash Image Definition", self
.FdfFile
))
332 EdkLogger
.verbose("\nFLASH_DEFINITION = %s" % self
.FdfFile
)
335 Progress
.Start("\nProcessing meta-data")
339 # Mark now build in AutoGen Phase
341 GlobalData
.gAutoGenPhase
= True
342 Fdf
= FdfParser(self
.FdfFile
.Path
)
344 GlobalData
.gFdfParser
= Fdf
345 GlobalData
.gAutoGenPhase
= False
346 PcdSet
= Fdf
.Profile
.PcdDict
347 if Fdf
.CurrentFdName
and Fdf
.CurrentFdName
in Fdf
.Profile
.FdDict
:
348 FdDict
= Fdf
.Profile
.FdDict
[Fdf
.CurrentFdName
]
349 for FdRegion
in FdDict
.RegionList
:
350 if str(FdRegion
.RegionType
) is 'FILE' and self
.Platform
.VpdToolGuid
in str(FdRegion
.RegionDataList
):
351 if int(FdRegion
.Offset
) % 8 != 0:
352 EdkLogger
.error("build", FORMAT_INVALID
, 'The VPD Base Address %s must be 8-byte aligned.' % (FdRegion
.Offset
))
353 ModuleList
= Fdf
.Profile
.InfList
354 self
.FdfProfile
= Fdf
.Profile
355 for fvname
in self
.FvTargetList
:
356 if fvname
.upper() not in self
.FdfProfile
.FvDict
:
357 EdkLogger
.error("build", OPTION_VALUE_INVALID
,
358 "No such an FV in FDF file: %s" % fvname
)
360 # In DSC file may use FILE_GUID to override the module, then in the Platform.Modules use FILE_GUIDmodule.inf as key,
361 # but the path (self.MetaFile.Path) is the real path
362 for key
in self
.FdfProfile
.InfDict
:
364 MetaFile_cache
= defaultdict(set)
365 for Arch
in self
.ArchList
:
366 Current_Platform_cache
= self
.BuildDatabase
[self
.MetaFile
, Arch
, Target
, Toolchain
]
367 for Pkey
in Current_Platform_cache
.Modules
:
368 MetaFile_cache
[Arch
].add(Current_Platform_cache
.Modules
[Pkey
].MetaFile
)
369 for Inf
in self
.FdfProfile
.InfDict
[key
]:
370 ModuleFile
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, Arch
)
371 for Arch
in self
.ArchList
:
372 if ModuleFile
in MetaFile_cache
[Arch
]:
375 ModuleData
= self
.BuildDatabase
[ModuleFile
, Arch
, Target
, Toolchain
]
376 if not ModuleData
.IsBinaryModule
:
377 EdkLogger
.error('build', PARSER_ERROR
, "Module %s NOT found in DSC file; Is it really a binary module?" % ModuleFile
)
380 for Arch
in self
.ArchList
:
382 Platform
= self
.BuildDatabase
[self
.MetaFile
, Arch
, Target
, Toolchain
]
384 for Pkey
in Platform
.Modules
:
385 MetaFileList
.add(Platform
.Modules
[Pkey
].MetaFile
)
386 for Inf
in self
.FdfProfile
.InfDict
[key
]:
387 ModuleFile
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, Arch
)
388 if ModuleFile
in MetaFileList
:
390 ModuleData
= self
.BuildDatabase
[ModuleFile
, Arch
, Target
, Toolchain
]
391 if not ModuleData
.IsBinaryModule
:
392 EdkLogger
.error('build', PARSER_ERROR
, "Module %s NOT found in DSC file; Is it really a binary module?" % ModuleFile
)
397 self
.FdfProfile
= None
398 if self
.FdTargetList
:
399 EdkLogger
.info("No flash definition file found. FD [%s] will be ignored." % " ".join(self
.FdTargetList
))
400 self
.FdTargetList
= []
401 if self
.FvTargetList
:
402 EdkLogger
.info("No flash definition file found. FV [%s] will be ignored." % " ".join(self
.FvTargetList
))
403 self
.FvTargetList
= []
404 if self
.CapTargetList
:
405 EdkLogger
.info("No flash definition file found. Capsule [%s] will be ignored." % " ".join(self
.CapTargetList
))
406 self
.CapTargetList
= []
408 # apply SKU and inject PCDs from Flash Definition file
409 for Arch
in self
.ArchList
:
410 Platform
= self
.BuildDatabase
[self
.MetaFile
, Arch
, Target
, Toolchain
]
411 PlatformPcds
= Platform
.Pcds
412 self
._GuidDict
= Platform
._GuidDict
413 SourcePcdDict
= {TAB_PCDS_DYNAMIC_EX
:set(), TAB_PCDS_PATCHABLE_IN_MODULE
:set(),TAB_PCDS_DYNAMIC
:set(),TAB_PCDS_FIXED_AT_BUILD
:set()}
414 BinaryPcdDict
= {TAB_PCDS_DYNAMIC_EX
:set(), TAB_PCDS_PATCHABLE_IN_MODULE
:set()}
415 SourcePcdDict_Keys
= SourcePcdDict
.keys()
416 BinaryPcdDict_Keys
= BinaryPcdDict
.keys()
418 # generate the SourcePcdDict and BinaryPcdDict
419 PGen
= PlatformAutoGen(self
, self
.MetaFile
, Target
, Toolchain
, Arch
)
420 for BuildData
in PGen
.BuildDatabase
._CACHE
_.values():
421 if BuildData
.Arch
!= Arch
:
423 if BuildData
.MetaFile
.Ext
== '.inf':
424 for key
in BuildData
.Pcds
:
425 if BuildData
.Pcds
[key
].Pending
:
426 if key
in Platform
.Pcds
:
427 PcdInPlatform
= Platform
.Pcds
[key
]
428 if PcdInPlatform
.Type
:
429 BuildData
.Pcds
[key
].Type
= PcdInPlatform
.Type
430 BuildData
.Pcds
[key
].Pending
= False
432 if BuildData
.MetaFile
in Platform
.Modules
:
433 PlatformModule
= Platform
.Modules
[str(BuildData
.MetaFile
)]
434 if key
in PlatformModule
.Pcds
:
435 PcdInPlatform
= PlatformModule
.Pcds
[key
]
436 if PcdInPlatform
.Type
:
437 BuildData
.Pcds
[key
].Type
= PcdInPlatform
.Type
438 BuildData
.Pcds
[key
].Pending
= False
440 #Pcd used in Library, Pcd Type from reference module if Pcd Type is Pending
441 if BuildData
.Pcds
[key
].Pending
:
442 MGen
= ModuleAutoGen(self
, BuildData
.MetaFile
, Target
, Toolchain
, Arch
, self
.MetaFile
)
443 if MGen
and MGen
.IsLibrary
:
444 if MGen
in PGen
.LibraryAutoGenList
:
445 ReferenceModules
= MGen
._ReferenceModules
446 for ReferenceModule
in ReferenceModules
:
447 if ReferenceModule
.MetaFile
in Platform
.Modules
:
448 RefPlatformModule
= Platform
.Modules
[str(ReferenceModule
.MetaFile
)]
449 if key
in RefPlatformModule
.Pcds
:
450 PcdInReferenceModule
= RefPlatformModule
.Pcds
[key
]
451 if PcdInReferenceModule
.Type
:
452 BuildData
.Pcds
[key
].Type
= PcdInReferenceModule
.Type
453 BuildData
.Pcds
[key
].Pending
= False
456 if TAB_PCDS_DYNAMIC_EX
in BuildData
.Pcds
[key
].Type
:
457 if BuildData
.IsBinaryModule
:
458 BinaryPcdDict
[TAB_PCDS_DYNAMIC_EX
].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
460 SourcePcdDict
[TAB_PCDS_DYNAMIC_EX
].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
462 elif TAB_PCDS_PATCHABLE_IN_MODULE
in BuildData
.Pcds
[key
].Type
:
463 if BuildData
.MetaFile
.Ext
== '.inf':
464 if BuildData
.IsBinaryModule
:
465 BinaryPcdDict
[TAB_PCDS_PATCHABLE_IN_MODULE
].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
467 SourcePcdDict
[TAB_PCDS_PATCHABLE_IN_MODULE
].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
469 elif TAB_PCDS_DYNAMIC
in BuildData
.Pcds
[key
].Type
:
470 SourcePcdDict
[TAB_PCDS_DYNAMIC
].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
471 elif TAB_PCDS_FIXED_AT_BUILD
in BuildData
.Pcds
[key
].Type
:
472 SourcePcdDict
[TAB_PCDS_FIXED_AT_BUILD
].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
476 # A PCD can only use one type for all source modules
478 for i
in SourcePcdDict_Keys
:
479 for j
in SourcePcdDict_Keys
:
481 Intersections
= SourcePcdDict
[i
].intersection(SourcePcdDict
[j
])
482 if len(Intersections
) > 0:
486 "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
),
487 ExtraData
='\n\t'.join(str(P
[1]+'.'+P
[0]) for P
in Intersections
)
491 # intersection the BinaryPCD for Mixed PCD
493 for i
in BinaryPcdDict_Keys
:
494 for j
in BinaryPcdDict_Keys
:
496 Intersections
= BinaryPcdDict
[i
].intersection(BinaryPcdDict
[j
])
497 for item
in Intersections
:
498 NewPcd1
= (item
[0] + '_' + i
, item
[1])
499 NewPcd2
= (item
[0] + '_' + j
, item
[1])
500 if item
not in GlobalData
.MixedPcd
:
501 GlobalData
.MixedPcd
[item
] = [NewPcd1
, NewPcd2
]
503 if NewPcd1
not in GlobalData
.MixedPcd
[item
]:
504 GlobalData
.MixedPcd
[item
].append(NewPcd1
)
505 if NewPcd2
not in GlobalData
.MixedPcd
[item
]:
506 GlobalData
.MixedPcd
[item
].append(NewPcd2
)
509 # intersection the SourcePCD and BinaryPCD for Mixed PCD
511 for i
in SourcePcdDict_Keys
:
512 for j
in BinaryPcdDict_Keys
:
514 Intersections
= SourcePcdDict
[i
].intersection(BinaryPcdDict
[j
])
515 for item
in Intersections
:
516 NewPcd1
= (item
[0] + '_' + i
, item
[1])
517 NewPcd2
= (item
[0] + '_' + j
, item
[1])
518 if item
not in GlobalData
.MixedPcd
:
519 GlobalData
.MixedPcd
[item
] = [NewPcd1
, NewPcd2
]
521 if NewPcd1
not in GlobalData
.MixedPcd
[item
]:
522 GlobalData
.MixedPcd
[item
].append(NewPcd1
)
523 if NewPcd2
not in GlobalData
.MixedPcd
[item
]:
524 GlobalData
.MixedPcd
[item
].append(NewPcd2
)
526 for BuildData
in PGen
.BuildDatabase
._CACHE
_.values():
527 if BuildData
.Arch
!= Arch
:
529 for key
in BuildData
.Pcds
:
530 for SinglePcd
in GlobalData
.MixedPcd
:
531 if (BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
) == SinglePcd
:
532 for item
in GlobalData
.MixedPcd
[SinglePcd
]:
533 Pcd_Type
= item
[0].split('_')[-1]
534 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 \
535 (Pcd_Type
== TAB_PCDS_DYNAMIC
and BuildData
.Pcds
[key
].Type
in PCD_DYNAMIC_TYPE_SET
):
536 Value
= BuildData
.Pcds
[key
]
537 Value
.TokenCName
= BuildData
.Pcds
[key
].TokenCName
+ '_' + Pcd_Type
539 newkey
= (Value
.TokenCName
, key
[1])
541 newkey
= (Value
.TokenCName
, key
[1], key
[2])
542 del BuildData
.Pcds
[key
]
543 BuildData
.Pcds
[newkey
] = Value
547 # handle the mixed pcd in FDF file
549 if key
in GlobalData
.MixedPcd
:
552 for item
in GlobalData
.MixedPcd
[key
]:
555 #Collect package set information from INF of FDF
557 for Inf
in ModuleList
:
558 ModuleFile
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, Arch
)
559 if ModuleFile
in Platform
.Modules
:
561 ModuleData
= self
.BuildDatabase
[ModuleFile
, Arch
, Target
, Toolchain
]
562 PkgSet
.update(ModuleData
.Packages
)
563 Pkgs
= list(PkgSet
) + list(PGen
.PackageList
)
568 DecPcds
.add((Pcd
[0], Pcd
[1]))
569 DecPcdsKey
.add((Pcd
[0], Pcd
[1], Pcd
[2]))
571 Platform
.SkuName
= self
.SkuId
572 for Name
, Guid
,Fileds
in PcdSet
:
573 if (Name
, Guid
) not in DecPcds
:
577 "PCD (%s.%s) used in FDF is not declared in DEC files." % (Guid
, Name
),
578 File
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
][0],
579 Line
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
][1]
582 # Check whether Dynamic or DynamicEx PCD used in FDF file. If used, build break and give a error message.
583 if (Name
, Guid
, TAB_PCDS_FIXED_AT_BUILD
) in DecPcdsKey \
584 or (Name
, Guid
, TAB_PCDS_PATCHABLE_IN_MODULE
) in DecPcdsKey \
585 or (Name
, Guid
, TAB_PCDS_FEATURE_FLAG
) in DecPcdsKey
:
587 elif (Name
, Guid
, TAB_PCDS_DYNAMIC
) in DecPcdsKey
or (Name
, Guid
, TAB_PCDS_DYNAMIC_EX
) in DecPcdsKey
:
591 "Using Dynamic or DynamicEx type of PCD [%s.%s] in FDF file is not allowed." % (Guid
, Name
),
592 File
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
][0],
593 Line
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
][1]
596 Pa
= PlatformAutoGen(self
, self
.MetaFile
, Target
, Toolchain
, Arch
)
598 # Explicitly collect platform's dynamic PCDs
600 Pa
.CollectPlatformDynamicPcds()
601 Pa
.CollectFixedAtBuildPcds()
602 self
.AutoGenObjectList
.append(Pa
)
605 # Generate Package level hash value
607 GlobalData
.gPackageHash
[Arch
] = {}
608 if GlobalData
.gUseHashCache
:
610 self
._GenPkgLevelHash
(Pkg
)
613 # Check PCDs token value conflict in each DEC file.
615 self
._CheckAllPcdsTokenValueConflict
()
618 # Check PCD type and definition between DSC and DEC
620 self
._CheckPcdDefineAndType
()
623 # Create BuildOptions Macro & PCD metafile, also add the Active Platform and FDF file.
625 content
= 'gCommandLineDefines: '
626 content
+= str(GlobalData
.gCommandLineDefines
)
627 content
+= os
.linesep
628 content
+= 'BuildOptionPcd: '
629 content
+= str(GlobalData
.BuildOptionPcd
)
630 content
+= os
.linesep
631 content
+= 'Active Platform: '
632 content
+= str(self
.Platform
)
633 content
+= os
.linesep
635 content
+= 'Flash Image Definition: '
636 content
+= str(self
.FdfFile
)
637 content
+= os
.linesep
638 SaveFileOnChange(os
.path
.join(self
.BuildDir
, 'BuildOptions'), content
, False)
641 # Create PcdToken Number file for Dynamic/DynamicEx Pcd.
643 PcdTokenNumber
= 'PcdTokenNumber: '
644 if Pa
.PcdTokenNumber
:
645 if Pa
.DynamicPcdList
:
646 for Pcd
in Pa
.DynamicPcdList
:
647 PcdTokenNumber
+= os
.linesep
648 PcdTokenNumber
+= str((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
))
649 PcdTokenNumber
+= ' : '
650 PcdTokenNumber
+= str(Pa
.PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
])
651 SaveFileOnChange(os
.path
.join(self
.BuildDir
, 'PcdTokenNumber'), PcdTokenNumber
, False)
654 # Get set of workspace metafiles
656 AllWorkSpaceMetaFiles
= self
._GetMetaFiles
(Target
, Toolchain
, Arch
)
659 # Retrieve latest modified time of all metafiles
662 for f
in AllWorkSpaceMetaFiles
:
663 if os
.stat(f
)[8] > SrcTimeStamp
:
664 SrcTimeStamp
= os
.stat(f
)[8]
665 self
._SrcTimeStamp
= SrcTimeStamp
667 if GlobalData
.gUseHashCache
:
669 for files
in AllWorkSpaceMetaFiles
:
670 if files
.endswith('.dec'):
676 SaveFileOnChange(os
.path
.join(self
.BuildDir
, 'AutoGen.hash'), m
.hexdigest(), True)
677 GlobalData
.gPlatformHash
= m
.hexdigest()
680 # Write metafile list to build directory
682 AutoGenFilePath
= os
.path
.join(self
.BuildDir
, 'AutoGen')
683 if os
.path
.exists (AutoGenFilePath
):
684 os
.remove(AutoGenFilePath
)
685 if not os
.path
.exists(self
.BuildDir
):
686 os
.makedirs(self
.BuildDir
)
687 with
open(os
.path
.join(self
.BuildDir
, 'AutoGen'), 'w+') as file:
688 for f
in AllWorkSpaceMetaFiles
:
692 def _GenPkgLevelHash(self
, Pkg
):
693 if Pkg
.PackageName
in GlobalData
.gPackageHash
[Pkg
.Arch
]:
696 PkgDir
= os
.path
.join(self
.BuildDir
, Pkg
.Arch
, Pkg
.PackageName
)
697 CreateDirectory(PkgDir
)
698 HashFile
= os
.path
.join(PkgDir
, Pkg
.PackageName
+ '.hash')
700 # Get .dec file's hash value
701 f
= open(Pkg
.MetaFile
.Path
, 'r')
705 # Get include files hash value
707 for inc
in sorted(Pkg
.Includes
, key
=lambda x
: str(x
)):
708 for Root
, Dirs
, Files
in os
.walk(str(inc
)):
709 for File
in sorted(Files
):
710 File_Path
= os
.path
.join(Root
, File
)
711 f
= open(File_Path
, 'r')
715 SaveFileOnChange(HashFile
, m
.hexdigest(), True)
716 GlobalData
.gPackageHash
[Pkg
.Arch
][Pkg
.PackageName
] = m
.hexdigest()
718 def _GetMetaFiles(self
, Target
, Toolchain
, Arch
):
719 AllWorkSpaceMetaFiles
= set()
724 AllWorkSpaceMetaFiles
.add (self
.FdfFile
.Path
)
725 for f
in GlobalData
.gFdfParser
.GetAllIncludedFile():
726 AllWorkSpaceMetaFiles
.add (f
.FileName
)
730 AllWorkSpaceMetaFiles
.add(self
.MetaFile
.Path
)
733 # add build_rule.txt & tools_def.txt
735 AllWorkSpaceMetaFiles
.add(os
.path
.join(GlobalData
.gConfDirectory
, gDefaultBuildRuleFile
))
736 AllWorkSpaceMetaFiles
.add(os
.path
.join(GlobalData
.gConfDirectory
, gDefaultToolsDefFile
))
738 # add BuildOption metafile
740 AllWorkSpaceMetaFiles
.add(os
.path
.join(self
.BuildDir
, 'BuildOptions'))
742 # add PcdToken Number file for Dynamic/DynamicEx Pcd
744 AllWorkSpaceMetaFiles
.add(os
.path
.join(self
.BuildDir
, 'PcdTokenNumber'))
746 for Arch
in self
.ArchList
:
750 for Package
in PlatformAutoGen(self
, self
.MetaFile
, Target
, Toolchain
, Arch
).PackageList
:
751 AllWorkSpaceMetaFiles
.add(Package
.MetaFile
.Path
)
756 for filePath
in self
.BuildDatabase
[self
.MetaFile
, Arch
, Target
, Toolchain
]._RawData
.IncludedFiles
:
757 AllWorkSpaceMetaFiles
.add(filePath
.Path
)
759 return AllWorkSpaceMetaFiles
761 def _CheckPcdDefineAndType(self
):
762 PcdTypeSet
= {TAB_PCDS_FIXED_AT_BUILD
,
763 TAB_PCDS_PATCHABLE_IN_MODULE
,
764 TAB_PCDS_FEATURE_FLAG
,
768 # This dict store PCDs which are not used by any modules with specified arches
769 UnusedPcd
= OrderedDict()
770 for Pa
in self
.AutoGenObjectList
:
771 # Key of DSC's Pcds dictionary is PcdCName, TokenSpaceGuid
772 for Pcd
in Pa
.Platform
.Pcds
:
773 PcdType
= Pa
.Platform
.Pcds
[Pcd
].Type
775 # If no PCD type, this PCD comes from FDF
779 # Try to remove Hii and Vpd suffix
780 if PcdType
.startswith(TAB_PCDS_DYNAMIC_EX
):
781 PcdType
= TAB_PCDS_DYNAMIC_EX
782 elif PcdType
.startswith(TAB_PCDS_DYNAMIC
):
783 PcdType
= TAB_PCDS_DYNAMIC
785 for Package
in Pa
.PackageList
:
786 # Key of DEC's Pcds dictionary is PcdCName, TokenSpaceGuid, PcdType
787 if (Pcd
[0], Pcd
[1], PcdType
) in Package
.Pcds
:
789 for Type
in PcdTypeSet
:
790 if (Pcd
[0], Pcd
[1], Type
) in Package
.Pcds
:
794 "Type [%s] of PCD [%s.%s] in DSC file doesn't match the type [%s] defined in DEC file." \
795 % (Pa
.Platform
.Pcds
[Pcd
].Type
, Pcd
[1], Pcd
[0], Type
),
800 UnusedPcd
.setdefault(Pcd
, []).append(Pa
.Arch
)
802 for Pcd
in UnusedPcd
:
805 "The PCD was not specified by any INF module in the platform for the given architecture.\n"
806 "\tPCD: [%s.%s]\n\tPlatform: [%s]\n\tArch: %s"
807 % (Pcd
[1], Pcd
[0], os
.path
.basename(str(self
.MetaFile
)), str(UnusedPcd
[Pcd
])),
812 return "%s [%s]" % (self
.MetaFile
, ", ".join(self
.ArchList
))
814 ## Return the directory to store FV files
816 if self
._FvDir
is None:
817 self
._FvDir
= path
.join(self
.BuildDir
, TAB_FV_DIRECTORY
)
820 ## Return the directory to store all intermediate and final files built
821 def _GetBuildDir(self
):
822 if self
._BuildDir
is None:
823 return self
.AutoGenObjectList
[0].BuildDir
825 ## Return the build output directory platform specifies
826 def _GetOutputDir(self
):
827 return self
.Platform
.OutputDirectory
829 ## Return platform name
831 return self
.Platform
.PlatformName
833 ## Return meta-file GUID
835 return self
.Platform
.Guid
837 ## Return platform version
838 def _GetVersion(self
):
839 return self
.Platform
.Version
841 ## Return paths of tools
842 def _GetToolDefinition(self
):
843 return self
.AutoGenObjectList
[0].ToolDefinition
845 ## Return directory of platform makefile
847 # @retval string Makefile directory
849 def _GetMakeFileDir(self
):
850 if self
._MakeFileDir
is None:
851 self
._MakeFileDir
= self
.BuildDir
852 return self
._MakeFileDir
854 ## Return build command string
856 # @retval string Build command string
858 def _GetBuildCommand(self
):
859 if self
._BuildCommand
is None:
860 # BuildCommand should be all the same. So just get one from platform AutoGen
861 self
._BuildCommand
= self
.AutoGenObjectList
[0].BuildCommand
862 return self
._BuildCommand
864 ## Check the PCDs token value conflict in each DEC file.
866 # Will cause build break and raise error message while two PCDs conflict.
870 def _CheckAllPcdsTokenValueConflict(self
):
871 for Pa
in self
.AutoGenObjectList
:
872 for Package
in Pa
.PackageList
:
873 PcdList
= Package
.Pcds
.values()
874 PcdList
.sort(lambda x
, y
: cmp(int(x
.TokenValue
, 0), int(y
.TokenValue
, 0)))
876 while (Count
< len(PcdList
) - 1) :
877 Item
= PcdList
[Count
]
878 ItemNext
= PcdList
[Count
+ 1]
880 # Make sure in the same token space the TokenValue should be unique
882 if (int(Item
.TokenValue
, 0) == int(ItemNext
.TokenValue
, 0)):
883 SameTokenValuePcdList
= []
884 SameTokenValuePcdList
.append(Item
)
885 SameTokenValuePcdList
.append(ItemNext
)
886 RemainPcdListLength
= len(PcdList
) - Count
- 2
887 for ValueSameCount
in range(RemainPcdListLength
):
888 if int(PcdList
[len(PcdList
) - RemainPcdListLength
+ ValueSameCount
].TokenValue
, 0) == int(Item
.TokenValue
, 0):
889 SameTokenValuePcdList
.append(PcdList
[len(PcdList
) - RemainPcdListLength
+ ValueSameCount
])
893 # Sort same token value PCD list with TokenGuid and TokenCName
895 SameTokenValuePcdList
.sort(lambda x
, y
: cmp("%s.%s" % (x
.TokenSpaceGuidCName
, x
.TokenCName
), "%s.%s" % (y
.TokenSpaceGuidCName
, y
.TokenCName
)))
896 SameTokenValuePcdListCount
= 0
897 while (SameTokenValuePcdListCount
< len(SameTokenValuePcdList
) - 1):
899 TemListItem
= SameTokenValuePcdList
[SameTokenValuePcdListCount
]
900 TemListItemNext
= SameTokenValuePcdList
[SameTokenValuePcdListCount
+ 1]
902 if (TemListItem
.TokenSpaceGuidCName
== TemListItemNext
.TokenSpaceGuidCName
) and (TemListItem
.TokenCName
!= TemListItemNext
.TokenCName
):
903 for PcdItem
in GlobalData
.MixedPcd
:
904 if (TemListItem
.TokenCName
, TemListItem
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
] or \
905 (TemListItemNext
.TokenCName
, TemListItemNext
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
911 "The TokenValue [%s] of PCD [%s.%s] is conflict with: [%s.%s] in %s"\
912 % (TemListItem
.TokenValue
, TemListItem
.TokenSpaceGuidCName
, TemListItem
.TokenCName
, TemListItemNext
.TokenSpaceGuidCName
, TemListItemNext
.TokenCName
, Package
),
915 SameTokenValuePcdListCount
+= 1
916 Count
+= SameTokenValuePcdListCount
919 PcdList
= Package
.Pcds
.values()
920 PcdList
.sort(lambda x
, y
: cmp("%s.%s" % (x
.TokenSpaceGuidCName
, x
.TokenCName
), "%s.%s" % (y
.TokenSpaceGuidCName
, y
.TokenCName
)))
922 while (Count
< len(PcdList
) - 1) :
923 Item
= PcdList
[Count
]
924 ItemNext
= PcdList
[Count
+ 1]
926 # Check PCDs with same TokenSpaceGuidCName.TokenCName have same token value as well.
928 if (Item
.TokenSpaceGuidCName
== ItemNext
.TokenSpaceGuidCName
) and (Item
.TokenCName
== ItemNext
.TokenCName
) and (int(Item
.TokenValue
, 0) != int(ItemNext
.TokenValue
, 0)):
932 "The TokenValue [%s] of PCD [%s.%s] in %s defined in two places should be same as well."\
933 % (Item
.TokenValue
, Item
.TokenSpaceGuidCName
, Item
.TokenCName
, Package
),
937 ## Generate fds command
938 def _GenFdsCommand(self
):
939 return (GenMake
.TopLevelMakefile(self
)._TEMPLATE
_.Replace(GenMake
.TopLevelMakefile(self
)._TemplateDict
)).strip()
941 ## Create makefile for the platform and modules in it
943 # @param CreateDepsMakeFile Flag indicating if the makefile for
944 # modules will be created as well
946 def CreateMakeFile(self
, CreateDepsMakeFile
=False):
947 if not CreateDepsMakeFile
:
949 for Pa
in self
.AutoGenObjectList
:
950 Pa
.CreateMakeFile(True)
952 ## Create autogen code for platform and modules
954 # Since there's no autogen code for platform, this method will do nothing
955 # if CreateModuleCodeFile is set to False.
957 # @param CreateDepsCodeFile Flag indicating if creating module's
958 # autogen code file or not
960 def CreateCodeFile(self
, CreateDepsCodeFile
=False):
961 if not CreateDepsCodeFile
:
963 for Pa
in self
.AutoGenObjectList
:
964 Pa
.CreateCodeFile(True)
966 ## Create AsBuilt INF file the platform
968 def CreateAsBuiltInf(self
):
971 Name
= property(_GetName
)
972 Guid
= property(_GetGuid
)
973 Version
= property(_GetVersion
)
974 OutputDir
= property(_GetOutputDir
)
976 ToolDefinition
= property(_GetToolDefinition
) # toolcode : tool path
978 BuildDir
= property(_GetBuildDir
)
979 FvDir
= property(_GetFvDir
)
980 MakeFileDir
= property(_GetMakeFileDir
)
981 BuildCommand
= property(_GetBuildCommand
)
982 GenFdsCommand
= property(_GenFdsCommand
)
984 ## AutoGen class for platform
986 # PlatformAutoGen class will process the original information in platform
987 # file in order to generate makefile for platform.
989 class PlatformAutoGen(AutoGen
):
990 # call super().__init__ then call the worker function with different parameter count
991 def __init__(self
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
995 super(PlatformAutoGen
, self
).__init
__(self
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
)
996 self
._InitWorker
(Workspace
, MetaFile
, Target
, Toolchain
, Arch
)
999 # Used to store all PCDs for both PEI and DXE phase, in order to generate
1000 # correct PCD database
1003 _NonDynaPcdList_
= []
1007 # The priority list while override build option
1009 PrioList
= {"0x11111" : 16, # TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE (Highest)
1010 "0x01111" : 15, # ******_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
1011 "0x10111" : 14, # TARGET_*********_ARCH_COMMANDTYPE_ATTRIBUTE
1012 "0x00111" : 13, # ******_*********_ARCH_COMMANDTYPE_ATTRIBUTE
1013 "0x11011" : 12, # TARGET_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
1014 "0x01011" : 11, # ******_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
1015 "0x10011" : 10, # TARGET_*********_****_COMMANDTYPE_ATTRIBUTE
1016 "0x00011" : 9, # ******_*********_****_COMMANDTYPE_ATTRIBUTE
1017 "0x11101" : 8, # TARGET_TOOLCHAIN_ARCH_***********_ATTRIBUTE
1018 "0x01101" : 7, # ******_TOOLCHAIN_ARCH_***********_ATTRIBUTE
1019 "0x10101" : 6, # TARGET_*********_ARCH_***********_ATTRIBUTE
1020 "0x00101" : 5, # ******_*********_ARCH_***********_ATTRIBUTE
1021 "0x11001" : 4, # TARGET_TOOLCHAIN_****_***********_ATTRIBUTE
1022 "0x01001" : 3, # ******_TOOLCHAIN_****_***********_ATTRIBUTE
1023 "0x10001" : 2, # TARGET_*********_****_***********_ATTRIBUTE
1024 "0x00001" : 1} # ******_*********_****_***********_ATTRIBUTE (Lowest)
1026 ## Initialize PlatformAutoGen
1029 # @param Workspace WorkspaceAutoGen object
1030 # @param PlatformFile Platform file (DSC file)
1031 # @param Target Build target (DEBUG, RELEASE)
1032 # @param Toolchain Name of tool chain
1033 # @param Arch arch of the platform supports
1035 def _InitWorker(self
, Workspace
, PlatformFile
, Target
, Toolchain
, Arch
):
1036 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "AutoGen platform [%s] [%s]" % (PlatformFile
, Arch
))
1037 GlobalData
.gProcessingFile
= "%s [%s, %s, %s]" % (PlatformFile
, Arch
, Toolchain
, Target
)
1039 self
.MetaFile
= PlatformFile
1040 self
.Workspace
= Workspace
1041 self
.WorkspaceDir
= Workspace
.WorkspaceDir
1042 self
.ToolChain
= Toolchain
1043 self
.BuildTarget
= Target
1045 self
.SourceDir
= PlatformFile
.SubDir
1046 self
.SourceOverrideDir
= None
1047 self
.FdTargetList
= self
.Workspace
.FdTargetList
1048 self
.FvTargetList
= self
.Workspace
.FvTargetList
1049 self
.AllPcdList
= []
1050 # get the original module/package/platform objects
1051 self
.BuildDatabase
= Workspace
.BuildDatabase
1052 self
.DscBuildDataObj
= Workspace
.Platform
1053 self
._GuidDict
= Workspace
._GuidDict
1055 # flag indicating if the makefile/C-code file has been created or not
1056 self
.IsMakeFileCreated
= False
1057 self
.IsCodeFileCreated
= False
1059 self
._Platform
= None
1062 self
._Version
= None
1064 self
._BuildRule
= None
1065 self
._SourceDir
= None
1066 self
._BuildDir
= None
1067 self
._OutputDir
= None
1069 self
._MakeFileDir
= None
1070 self
._FdfFile
= None
1072 self
._PcdTokenNumber
= None # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber
1073 self
._DynamicPcdList
= None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
1074 self
._NonDynamicPcdList
= None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
1075 self
._NonDynamicPcdDict
= {}
1077 self
._ToolDefinitions
= None
1078 self
._ToolDefFile
= None # toolcode : tool path
1079 self
._ToolChainFamily
= None
1080 self
._BuildRuleFamily
= None
1081 self
._BuildOption
= None # toolcode : option
1082 self
._EdkBuildOption
= None # edktoolcode : option
1083 self
._EdkIIBuildOption
= None # edkiitoolcode : option
1084 self
._PackageList
= None
1085 self
._ModuleAutoGenList
= None
1086 self
._LibraryAutoGenList
= None
1087 self
._BuildCommand
= None
1088 self
._AsBuildInfList
= []
1089 self
._AsBuildModuleList
= []
1091 self
.VariableInfo
= None
1093 if GlobalData
.gFdfParser
is not None:
1094 self
._AsBuildInfList
= GlobalData
.gFdfParser
.Profile
.InfList
1095 for Inf
in self
._AsBuildInfList
:
1096 InfClass
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, self
.Arch
)
1097 M
= self
.BuildDatabase
[InfClass
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1098 if not M
.IsSupportedArch
:
1100 self
._AsBuildModuleList
.append(InfClass
)
1101 # get library/modules for build
1102 self
.LibraryBuildDirectoryList
= []
1103 self
.ModuleBuildDirectoryList
= []
1108 return "%s [%s]" % (self
.MetaFile
, self
.Arch
)
1110 ## Create autogen code for platform and modules
1112 # Since there's no autogen code for platform, this method will do nothing
1113 # if CreateModuleCodeFile is set to False.
1115 # @param CreateModuleCodeFile Flag indicating if creating module's
1116 # autogen code file or not
1118 def CreateCodeFile(self
, CreateModuleCodeFile
=False):
1119 # only module has code to be greated, so do nothing if CreateModuleCodeFile is False
1120 if self
.IsCodeFileCreated
or not CreateModuleCodeFile
:
1123 for Ma
in self
.ModuleAutoGenList
:
1124 Ma
.CreateCodeFile(True)
1126 # don't do this twice
1127 self
.IsCodeFileCreated
= True
1129 ## Generate Fds Command
1130 def _GenFdsCommand(self
):
1131 return self
.Workspace
.GenFdsCommand
1133 ## Create makefile for the platform and mdoules in it
1135 # @param CreateModuleMakeFile Flag indicating if the makefile for
1136 # modules will be created as well
1138 def CreateMakeFile(self
, CreateModuleMakeFile
=False, FfsCommand
= {}):
1139 if CreateModuleMakeFile
:
1140 for ModuleFile
in self
.Platform
.Modules
:
1141 Ma
= ModuleAutoGen(self
.Workspace
, ModuleFile
, self
.BuildTarget
,
1142 self
.ToolChain
, self
.Arch
, self
.MetaFile
)
1143 if (ModuleFile
.File
, self
.Arch
) in FfsCommand
:
1144 Ma
.CreateMakeFile(True, FfsCommand
[ModuleFile
.File
, self
.Arch
])
1146 Ma
.CreateMakeFile(True)
1147 #Ma.CreateAsBuiltInf()
1149 # no need to create makefile for the platform more than once
1150 if self
.IsMakeFileCreated
:
1153 # create library/module build dirs for platform
1154 Makefile
= GenMake
.PlatformMakefile(self
)
1155 self
.LibraryBuildDirectoryList
= Makefile
.GetLibraryBuildDirectoryList()
1156 self
.ModuleBuildDirectoryList
= Makefile
.GetModuleBuildDirectoryList()
1158 self
.IsMakeFileCreated
= True
1160 ## Deal with Shared FixedAtBuild Pcds
1162 def CollectFixedAtBuildPcds(self
):
1163 for LibAuto
in self
.LibraryAutoGenList
:
1164 FixedAtBuildPcds
= {}
1165 ShareFixedAtBuildPcdsSameValue
= {}
1166 for Module
in LibAuto
._ReferenceModules
:
1167 for Pcd
in set(Module
.FixedAtBuildPcds
+ LibAuto
.FixedAtBuildPcds
):
1168 DefaultValue
= Pcd
.DefaultValue
1169 # Cover the case: DSC component override the Pcd value and the Pcd only used in one Lib
1170 if Pcd
in Module
.LibraryPcdList
:
1171 Index
= Module
.LibraryPcdList
.index(Pcd
)
1172 DefaultValue
= Module
.LibraryPcdList
[Index
].DefaultValue
1173 key
= ".".join((Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
1174 if key
not in FixedAtBuildPcds
:
1175 ShareFixedAtBuildPcdsSameValue
[key
] = True
1176 FixedAtBuildPcds
[key
] = DefaultValue
1178 if FixedAtBuildPcds
[key
] != DefaultValue
:
1179 ShareFixedAtBuildPcdsSameValue
[key
] = False
1180 for Pcd
in LibAuto
.FixedAtBuildPcds
:
1181 key
= ".".join((Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
1182 if (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
) not in self
.NonDynamicPcdDict
:
1185 DscPcd
= self
.NonDynamicPcdDict
[(Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
)]
1186 if DscPcd
.Type
!= TAB_PCDS_FIXED_AT_BUILD
:
1188 if key
in ShareFixedAtBuildPcdsSameValue
and ShareFixedAtBuildPcdsSameValue
[key
]:
1189 LibAuto
.ConstPcd
[key
] = FixedAtBuildPcds
[key
]
1191 def CollectVariables(self
, DynamicPcdSet
):
1195 if self
.Workspace
.FdfFile
:
1196 FdDict
= self
.Workspace
.FdfProfile
.FdDict
[GlobalData
.gFdfParser
.CurrentFdName
]
1197 for FdRegion
in FdDict
.RegionList
:
1198 for item
in FdRegion
.RegionDataList
:
1199 if self
.Platform
.VpdToolGuid
.strip() and self
.Platform
.VpdToolGuid
in item
:
1200 VpdRegionSize
= FdRegion
.Size
1201 VpdRegionBase
= FdRegion
.Offset
1205 VariableInfo
= VariableMgr(self
.DscBuildDataObj
._GetDefaultStores
(), self
.DscBuildDataObj
._GetSkuIds
())
1206 VariableInfo
.SetVpdRegionMaxSize(VpdRegionSize
)
1207 VariableInfo
.SetVpdRegionOffset(VpdRegionBase
)
1209 for Pcd
in DynamicPcdSet
:
1210 pcdname
= ".".join((Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
1211 for SkuName
in Pcd
.SkuInfoList
:
1212 Sku
= Pcd
.SkuInfoList
[SkuName
]
1214 if SkuId
is None or SkuId
== '':
1216 if len(Sku
.VariableName
) > 0:
1217 VariableGuidStructure
= Sku
.VariableGuidValue
1218 VariableGuid
= GuidStructureStringToGuidString(VariableGuidStructure
)
1219 for StorageName
in Sku
.DefaultStoreDict
:
1220 VariableInfo
.append_variable(var_info(Index
, pcdname
, StorageName
, SkuName
, StringToArray(Sku
.VariableName
), VariableGuid
, Sku
.VariableOffset
, Sku
.VariableAttribute
, Sku
.HiiDefaultValue
, Sku
.DefaultStoreDict
[StorageName
], Pcd
.DatumType
))
1224 def UpdateNVStoreMaxSize(self
, OrgVpdFile
):
1225 if self
.VariableInfo
:
1226 VpdMapFilePath
= os
.path
.join(self
.BuildDir
, TAB_FV_DIRECTORY
, "%s.map" % self
.Platform
.VpdToolGuid
)
1227 PcdNvStoreDfBuffer
= [item
for item
in self
._DynamicPcdList
if item
.TokenCName
== "PcdNvStoreDefaultValueBuffer" and item
.TokenSpaceGuidCName
== "gEfiMdeModulePkgTokenSpaceGuid"]
1229 if PcdNvStoreDfBuffer
:
1230 if os
.path
.exists(VpdMapFilePath
):
1231 OrgVpdFile
.Read(VpdMapFilePath
)
1232 PcdItems
= OrgVpdFile
.GetOffset(PcdNvStoreDfBuffer
[0])
1233 NvStoreOffset
= PcdItems
.values()[0].strip() if PcdItems
else '0'
1235 EdkLogger
.error("build", FILE_READ_FAILURE
, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath
)
1237 NvStoreOffset
= int(NvStoreOffset
, 16) if NvStoreOffset
.upper().startswith("0X") else int(NvStoreOffset
)
1238 default_skuobj
= PcdNvStoreDfBuffer
[0].SkuInfoList
.get(TAB_DEFAULT
)
1239 maxsize
= self
.VariableInfo
.VpdRegionSize
- NvStoreOffset
if self
.VariableInfo
.VpdRegionSize
else len(default_skuobj
.DefaultValue
.split(","))
1240 var_data
= self
.VariableInfo
.PatchNVStoreDefaultMaxSize(maxsize
)
1242 if var_data
and default_skuobj
:
1243 default_skuobj
.DefaultValue
= var_data
1244 PcdNvStoreDfBuffer
[0].DefaultValue
= var_data
1245 PcdNvStoreDfBuffer
[0].SkuInfoList
.clear()
1246 PcdNvStoreDfBuffer
[0].SkuInfoList
[TAB_DEFAULT
] = default_skuobj
1247 PcdNvStoreDfBuffer
[0].MaxDatumSize
= str(len(default_skuobj
.DefaultValue
.split(",")))
1251 ## Collect dynamic PCDs
1253 # Gather dynamic PCDs list from each module and their settings from platform
1254 # This interface should be invoked explicitly when platform action is created.
1256 def CollectPlatformDynamicPcds(self
):
1258 for key
in self
.Platform
.Pcds
:
1259 for SinglePcd
in GlobalData
.MixedPcd
:
1260 if (self
.Platform
.Pcds
[key
].TokenCName
, self
.Platform
.Pcds
[key
].TokenSpaceGuidCName
) == SinglePcd
:
1261 for item
in GlobalData
.MixedPcd
[SinglePcd
]:
1262 Pcd_Type
= item
[0].split('_')[-1]
1263 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 \
1264 (Pcd_Type
== TAB_PCDS_DYNAMIC
and self
.Platform
.Pcds
[key
].Type
in PCD_DYNAMIC_TYPE_SET
):
1265 Value
= self
.Platform
.Pcds
[key
]
1266 Value
.TokenCName
= self
.Platform
.Pcds
[key
].TokenCName
+ '_' + Pcd_Type
1268 newkey
= (Value
.TokenCName
, key
[1])
1270 newkey
= (Value
.TokenCName
, key
[1], key
[2])
1271 del self
.Platform
.Pcds
[key
]
1272 self
.Platform
.Pcds
[newkey
] = Value
1276 # for gathering error information
1277 NoDatumTypePcdList
= set()
1279 for InfName
in self
._AsBuildInfList
:
1280 InfName
= mws
.join(self
.WorkspaceDir
, InfName
)
1281 FdfModuleList
.append(os
.path
.normpath(InfName
))
1282 for F
in self
.Platform
.Modules
.keys():
1283 M
= ModuleAutoGen(self
.Workspace
, F
, self
.BuildTarget
, self
.ToolChain
, self
.Arch
, self
.MetaFile
)
1284 #GuidValue.update(M.Guids)
1286 self
.Platform
.Modules
[F
].M
= M
1288 for PcdFromModule
in M
.ModulePcdList
+ M
.LibraryPcdList
:
1289 # make sure that the "VOID*" kind of datum has MaxDatumSize set
1290 if PcdFromModule
.DatumType
== TAB_VOID
and not PcdFromModule
.MaxDatumSize
:
1291 NoDatumTypePcdList
.add("%s.%s [%s]" % (PcdFromModule
.TokenSpaceGuidCName
, PcdFromModule
.TokenCName
, F
))
1293 # Check the PCD from Binary INF or Source INF
1294 if M
.IsBinaryModule
== True:
1295 PcdFromModule
.IsFromBinaryInf
= True
1297 # Check the PCD from DSC or not
1298 PcdFromModule
.IsFromDsc
= (PcdFromModule
.TokenCName
, PcdFromModule
.TokenSpaceGuidCName
) in self
.Platform
.Pcds
1300 if PcdFromModule
.Type
in PCD_DYNAMIC_TYPE_SET
or PcdFromModule
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
1301 if F
.Path
not in FdfModuleList
:
1302 # If one of the Source built modules listed in the DSC is not listed
1303 # in FDF modules, and the INF lists a PCD can only use the PcdsDynamic
1304 # access method (it is only listed in the DEC file that declares the
1305 # PCD as PcdsDynamic), then build tool will report warning message
1306 # notify the PI that they are attempting to build a module that must
1307 # be included in a flash image in order to be functional. These Dynamic
1308 # PCD will not be added into the Database unless it is used by other
1309 # modules that are included in the FDF file.
1310 if PcdFromModule
.Type
in PCD_DYNAMIC_TYPE_SET
and \
1311 PcdFromModule
.IsFromBinaryInf
== False:
1312 # Print warning message to let the developer make a determine.
1314 # If one of the Source built modules listed in the DSC is not listed in
1315 # FDF modules, and the INF lists a PCD can only use the PcdsDynamicEx
1316 # access method (it is only listed in the DEC file that declares the
1317 # PCD as PcdsDynamicEx), then DO NOT break the build; DO NOT add the
1318 # PCD to the Platform's PCD Database.
1319 if PcdFromModule
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
1322 # If a dynamic PCD used by a PEM module/PEI module & DXE module,
1323 # it should be stored in Pcd PEI database, If a dynamic only
1324 # used by DXE module, it should be stored in DXE PCD database.
1325 # The default Phase is DXE
1327 if M
.ModuleType
in SUP_MODULE_SET_PEI
:
1328 PcdFromModule
.Phase
= "PEI"
1329 if PcdFromModule
not in self
._DynaPcdList
_:
1330 self
._DynaPcdList
_.append(PcdFromModule
)
1331 elif PcdFromModule
.Phase
== 'PEI':
1332 # overwrite any the same PCD existing, if Phase is PEI
1333 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1334 self
._DynaPcdList
_[Index
] = PcdFromModule
1335 elif PcdFromModule
not in self
._NonDynaPcdList
_:
1336 self
._NonDynaPcdList
_.append(PcdFromModule
)
1337 elif PcdFromModule
in self
._NonDynaPcdList
_ and PcdFromModule
.IsFromBinaryInf
== True:
1338 Index
= self
._NonDynaPcdList
_.index(PcdFromModule
)
1339 if self
._NonDynaPcdList
_[Index
].IsFromBinaryInf
== False:
1340 #The PCD from Binary INF will override the same one from source INF
1341 self
._NonDynaPcdList
_.remove (self
._NonDynaPcdList
_[Index
])
1342 PcdFromModule
.Pending
= False
1343 self
._NonDynaPcdList
_.append (PcdFromModule
)
1344 DscModuleSet
= {os
.path
.normpath(ModuleInf
.Path
) for ModuleInf
in self
.Platform
.Modules
}
1345 # add the PCD from modules that listed in FDF but not in DSC to Database
1346 for InfName
in FdfModuleList
:
1347 if InfName
not in DscModuleSet
:
1348 InfClass
= PathClass(InfName
)
1349 M
= self
.BuildDatabase
[InfClass
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1350 # If a module INF in FDF but not in current arch's DSC module list, it must be module (either binary or source)
1351 # for different Arch. PCDs in source module for different Arch is already added before, so skip the source module here.
1352 # For binary module, if in current arch, we need to list the PCDs into database.
1353 if not M
.IsSupportedArch
:
1355 # Override the module PCD setting by platform setting
1356 ModulePcdList
= self
.ApplyPcdSetting(M
, M
.Pcds
)
1357 for PcdFromModule
in ModulePcdList
:
1358 PcdFromModule
.IsFromBinaryInf
= True
1359 PcdFromModule
.IsFromDsc
= False
1360 # Only allow the DynamicEx and Patchable PCD in AsBuild INF
1361 if PcdFromModule
.Type
not in PCD_DYNAMIC_EX_TYPE_SET
and PcdFromModule
.Type
not in TAB_PCDS_PATCHABLE_IN_MODULE
:
1362 EdkLogger
.error("build", AUTOGEN_ERROR
, "PCD setting error",
1364 ExtraData
="\n\tExisted %s PCD %s in:\n\t\t%s\n"
1365 % (PcdFromModule
.Type
, PcdFromModule
.TokenCName
, InfName
))
1366 # make sure that the "VOID*" kind of datum has MaxDatumSize set
1367 if PcdFromModule
.DatumType
== TAB_VOID
and not PcdFromModule
.MaxDatumSize
:
1368 NoDatumTypePcdList
.add("%s.%s [%s]" % (PcdFromModule
.TokenSpaceGuidCName
, PcdFromModule
.TokenCName
, InfName
))
1369 if M
.ModuleType
in SUP_MODULE_SET_PEI
:
1370 PcdFromModule
.Phase
= "PEI"
1371 if PcdFromModule
not in self
._DynaPcdList
_ and PcdFromModule
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
1372 self
._DynaPcdList
_.append(PcdFromModule
)
1373 elif PcdFromModule
not in self
._NonDynaPcdList
_ and PcdFromModule
.Type
in TAB_PCDS_PATCHABLE_IN_MODULE
:
1374 self
._NonDynaPcdList
_.append(PcdFromModule
)
1375 if PcdFromModule
in self
._DynaPcdList
_ and PcdFromModule
.Phase
== 'PEI' and PcdFromModule
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
1376 # Overwrite the phase of any the same PCD existing, if Phase is PEI.
1377 # It is to solve the case that a dynamic PCD used by a PEM module/PEI
1378 # module & DXE module at a same time.
1379 # Overwrite the type of the PCDs in source INF by the type of AsBuild
1380 # INF file as DynamicEx.
1381 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1382 self
._DynaPcdList
_[Index
].Phase
= PcdFromModule
.Phase
1383 self
._DynaPcdList
_[Index
].Type
= PcdFromModule
.Type
1384 for PcdFromModule
in self
._NonDynaPcdList
_:
1385 # If a PCD is not listed in the DSC file, but binary INF files used by
1386 # this platform all (that use this PCD) list the PCD in a [PatchPcds]
1387 # section, AND all source INF files used by this platform the build
1388 # that use the PCD list the PCD in either a [Pcds] or [PatchPcds]
1389 # section, then the tools must NOT add the PCD to the Platform's PCD
1390 # Database; the build must assign the access method for this PCD as
1391 # PcdsPatchableInModule.
1392 if PcdFromModule
not in self
._DynaPcdList
_:
1394 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1395 if PcdFromModule
.IsFromDsc
== False and \
1396 PcdFromModule
.Type
in TAB_PCDS_PATCHABLE_IN_MODULE
and \
1397 PcdFromModule
.IsFromBinaryInf
== True and \
1398 self
._DynaPcdList
_[Index
].IsFromBinaryInf
== False:
1399 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1400 self
._DynaPcdList
_.remove (self
._DynaPcdList
_[Index
])
1402 # print out error information and break the build, if error found
1403 if len(NoDatumTypePcdList
) > 0:
1404 NoDatumTypePcdListString
= "\n\t\t".join(NoDatumTypePcdList
)
1405 EdkLogger
.error("build", AUTOGEN_ERROR
, "PCD setting error",
1407 ExtraData
="\n\tPCD(s) without MaxDatumSize:\n\t\t%s\n"
1408 % NoDatumTypePcdListString
)
1409 self
._NonDynamicPcdList
= self
._NonDynaPcdList
_
1410 self
._DynamicPcdList
= self
._DynaPcdList
_
1412 # Sort dynamic PCD list to:
1413 # 1) If PCD's datum type is VOID* and value is unicode string which starts with L, the PCD item should
1414 # try to be put header of dynamicd List
1415 # 2) If PCD is HII type, the PCD item should be put after unicode type PCD
1417 # The reason of sorting is make sure the unicode string is in double-byte alignment in string table.
1419 UnicodePcdArray
= set()
1421 OtherPcdArray
= set()
1423 VpdFile
= VpdInfoFile
.VpdInfoFile()
1424 NeedProcessVpdMapFile
= False
1426 for pcd
in self
.Platform
.Pcds
:
1427 if pcd
not in self
._PlatformPcds
:
1428 self
._PlatformPcds
[pcd
] = self
.Platform
.Pcds
[pcd
]
1430 for item
in self
._PlatformPcds
:
1431 if self
._PlatformPcds
[item
].DatumType
and self
._PlatformPcds
[item
].DatumType
not in [TAB_UINT8
, TAB_UINT16
, TAB_UINT32
, TAB_UINT64
, TAB_VOID
, "BOOLEAN"]:
1432 self
._PlatformPcds
[item
].DatumType
= TAB_VOID
1434 if (self
.Workspace
.ArchList
[-1] == self
.Arch
):
1435 for Pcd
in self
._DynamicPcdList
:
1436 # just pick the a value to determine whether is unicode string type
1437 Sku
= Pcd
.SkuInfoList
.values()[0]
1438 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1440 if Pcd
.DatumType
not in [TAB_UINT8
, TAB_UINT16
, TAB_UINT32
, TAB_UINT64
, TAB_VOID
, "BOOLEAN"]:
1441 Pcd
.DatumType
= TAB_VOID
1443 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
1444 # if found HII type PCD then insert to right of UnicodeIndex
1445 if Pcd
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
]:
1446 VpdPcdDict
[(Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
)] = Pcd
1448 #Collect DynamicHii PCD values and assign it to DynamicExVpd PCD gEfiMdeModulePkgTokenSpaceGuid.PcdNvStoreDefaultValueBuffer
1449 PcdNvStoreDfBuffer
= VpdPcdDict
.get(("PcdNvStoreDefaultValueBuffer", "gEfiMdeModulePkgTokenSpaceGuid"))
1450 if PcdNvStoreDfBuffer
:
1451 self
.VariableInfo
= self
.CollectVariables(self
._DynamicPcdList
)
1452 vardump
= self
.VariableInfo
.dump()
1454 PcdNvStoreDfBuffer
.DefaultValue
= vardump
1455 for skuname
in PcdNvStoreDfBuffer
.SkuInfoList
:
1456 PcdNvStoreDfBuffer
.SkuInfoList
[skuname
].DefaultValue
= vardump
1457 PcdNvStoreDfBuffer
.MaxDatumSize
= str(len(vardump
.split(",")))
1459 PlatformPcds
= sorted(self
._PlatformPcds
.keys())
1461 # Add VPD type PCD into VpdFile and determine whether the VPD PCD need to be fixed up.
1464 for PcdKey
in PlatformPcds
:
1465 Pcd
= self
._PlatformPcds
[PcdKey
]
1466 if Pcd
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
] and \
1467 PcdKey
in VpdPcdDict
:
1468 Pcd
= VpdPcdDict
[PcdKey
]
1470 DefaultSku
= Pcd
.SkuInfoList
.get(TAB_DEFAULT
)
1472 PcdValue
= DefaultSku
.DefaultValue
1473 if PcdValue
not in SkuValueMap
:
1474 SkuValueMap
[PcdValue
] = []
1475 VpdFile
.Add(Pcd
, TAB_DEFAULT
, DefaultSku
.VpdOffset
)
1476 SkuValueMap
[PcdValue
].append(DefaultSku
)
1478 for (SkuName
, Sku
) in Pcd
.SkuInfoList
.items():
1479 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1480 PcdValue
= Sku
.DefaultValue
1482 PcdValue
= Pcd
.DefaultValue
1483 if Sku
.VpdOffset
!= '*':
1484 if PcdValue
.startswith("{"):
1486 elif PcdValue
.startswith("L"):
1491 VpdOffset
= int(Sku
.VpdOffset
)
1494 VpdOffset
= int(Sku
.VpdOffset
, 16)
1496 EdkLogger
.error("build", FORMAT_INVALID
, "Invalid offset value %s for PCD %s.%s." % (Sku
.VpdOffset
, Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
1497 if VpdOffset
% Alignment
!= 0:
1498 if PcdValue
.startswith("{"):
1499 EdkLogger
.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
), File
=self
.MetaFile
)
1501 EdkLogger
.error("build", FORMAT_INVALID
, 'The offset value of PCD %s.%s should be %s-byte aligned.' % (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
, Alignment
))
1502 if PcdValue
not in SkuValueMap
:
1503 SkuValueMap
[PcdValue
] = []
1504 VpdFile
.Add(Pcd
, SkuName
, Sku
.VpdOffset
)
1505 SkuValueMap
[PcdValue
].append(Sku
)
1506 # if the offset of a VPD is *, then it need to be fixed up by third party tool.
1507 if not NeedProcessVpdMapFile
and Sku
.VpdOffset
== "*":
1508 NeedProcessVpdMapFile
= True
1509 if self
.Platform
.VpdToolGuid
is None or self
.Platform
.VpdToolGuid
== '':
1510 EdkLogger
.error("Build", FILE_NOT_FOUND
, \
1511 "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.")
1513 VpdSkuMap
[PcdKey
] = SkuValueMap
1515 # Fix the PCDs define in VPD PCD section that never referenced by module.
1516 # An example is PCD for signature usage.
1518 for DscPcd
in PlatformPcds
:
1519 DscPcdEntry
= self
._PlatformPcds
[DscPcd
]
1520 if DscPcdEntry
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
]:
1521 if not (self
.Platform
.VpdToolGuid
is None or self
.Platform
.VpdToolGuid
== ''):
1523 for VpdPcd
in VpdFile
._VpdArray
:
1524 # This PCD has been referenced by module
1525 if (VpdPcd
.TokenSpaceGuidCName
== DscPcdEntry
.TokenSpaceGuidCName
) and \
1526 (VpdPcd
.TokenCName
== DscPcdEntry
.TokenCName
):
1529 # Not found, it should be signature
1531 # just pick the a value to determine whether is unicode string type
1533 SkuObjList
= DscPcdEntry
.SkuInfoList
.items()
1534 DefaultSku
= DscPcdEntry
.SkuInfoList
.get(TAB_DEFAULT
)
1536 defaultindex
= SkuObjList
.index((TAB_DEFAULT
, DefaultSku
))
1537 SkuObjList
[0], SkuObjList
[defaultindex
] = SkuObjList
[defaultindex
], SkuObjList
[0]
1538 for (SkuName
, Sku
) in SkuObjList
:
1539 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1541 # Need to iterate DEC pcd information to get the value & datumtype
1542 for eachDec
in self
.PackageList
:
1543 for DecPcd
in eachDec
.Pcds
:
1544 DecPcdEntry
= eachDec
.Pcds
[DecPcd
]
1545 if (DecPcdEntry
.TokenSpaceGuidCName
== DscPcdEntry
.TokenSpaceGuidCName
) and \
1546 (DecPcdEntry
.TokenCName
== DscPcdEntry
.TokenCName
):
1547 # Print warning message to let the developer make a determine.
1548 EdkLogger
.warn("build", "Unreferenced vpd pcd used!",
1549 File
=self
.MetaFile
, \
1550 ExtraData
= "PCD: %s.%s used in the DSC file %s is unreferenced." \
1551 %(DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
, self
.Platform
.MetaFile
.Path
))
1553 DscPcdEntry
.DatumType
= DecPcdEntry
.DatumType
1554 DscPcdEntry
.DefaultValue
= DecPcdEntry
.DefaultValue
1555 DscPcdEntry
.TokenValue
= DecPcdEntry
.TokenValue
1556 DscPcdEntry
.TokenSpaceGuidValue
= eachDec
.Guids
[DecPcdEntry
.TokenSpaceGuidCName
]
1557 # Only fix the value while no value provided in DSC file.
1558 if not Sku
.DefaultValue
:
1559 DscPcdEntry
.SkuInfoList
[DscPcdEntry
.SkuInfoList
.keys()[0]].DefaultValue
= DecPcdEntry
.DefaultValue
1561 if DscPcdEntry
not in self
._DynamicPcdList
:
1562 self
._DynamicPcdList
.append(DscPcdEntry
)
1563 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1564 PcdValue
= Sku
.DefaultValue
1566 PcdValue
= DscPcdEntry
.DefaultValue
1567 if Sku
.VpdOffset
!= '*':
1568 if PcdValue
.startswith("{"):
1570 elif PcdValue
.startswith("L"):
1575 VpdOffset
= int(Sku
.VpdOffset
)
1578 VpdOffset
= int(Sku
.VpdOffset
, 16)
1580 EdkLogger
.error("build", FORMAT_INVALID
, "Invalid offset value %s for PCD %s.%s." % (Sku
.VpdOffset
, DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
))
1581 if VpdOffset
% Alignment
!= 0:
1582 if PcdValue
.startswith("{"):
1583 EdkLogger
.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
), File
=self
.MetaFile
)
1585 EdkLogger
.error("build", FORMAT_INVALID
, 'The offset value of PCD %s.%s should be %s-byte aligned.' % (DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
, Alignment
))
1586 if PcdValue
not in SkuValueMap
:
1587 SkuValueMap
[PcdValue
] = []
1588 VpdFile
.Add(DscPcdEntry
, SkuName
, Sku
.VpdOffset
)
1589 SkuValueMap
[PcdValue
].append(Sku
)
1590 if not NeedProcessVpdMapFile
and Sku
.VpdOffset
== "*":
1591 NeedProcessVpdMapFile
= True
1592 if DscPcdEntry
.DatumType
== TAB_VOID
and PcdValue
.startswith("L"):
1593 UnicodePcdArray
.add(DscPcdEntry
)
1594 elif len(Sku
.VariableName
) > 0:
1595 HiiPcdArray
.add(DscPcdEntry
)
1597 OtherPcdArray
.add(DscPcdEntry
)
1599 # if the offset of a VPD is *, then it need to be fixed up by third party tool.
1600 VpdSkuMap
[DscPcd
] = SkuValueMap
1601 if (self
.Platform
.FlashDefinition
is None or self
.Platform
.FlashDefinition
== '') and \
1602 VpdFile
.GetCount() != 0:
1603 EdkLogger
.error("build", ATTRIBUTE_NOT_AVAILABLE
,
1604 "Fail to get FLASH_DEFINITION definition in DSC file %s which is required when DSC contains VPD PCD." % str(self
.Platform
.MetaFile
))
1606 if VpdFile
.GetCount() != 0:
1608 self
.FixVpdOffset(VpdFile
)
1610 self
.FixVpdOffset(self
.UpdateNVStoreMaxSize(VpdFile
))
1612 # Process VPD map file generated by third party BPDG tool
1613 if NeedProcessVpdMapFile
:
1614 VpdMapFilePath
= os
.path
.join(self
.BuildDir
, TAB_FV_DIRECTORY
, "%s.map" % self
.Platform
.VpdToolGuid
)
1615 if os
.path
.exists(VpdMapFilePath
):
1616 VpdFile
.Read(VpdMapFilePath
)
1619 for pcd
in VpdSkuMap
:
1620 vpdinfo
= VpdFile
.GetVpdInfo(pcd
)
1622 # just pick the a value to determine whether is unicode string type
1624 for pcdvalue
in VpdSkuMap
[pcd
]:
1625 for sku
in VpdSkuMap
[pcd
][pcdvalue
]:
1626 for item
in vpdinfo
:
1627 if item
[2] == pcdvalue
:
1628 sku
.VpdOffset
= item
[1]
1630 EdkLogger
.error("build", FILE_READ_FAILURE
, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath
)
1632 # Delete the DynamicPcdList At the last time enter into this function
1633 for Pcd
in self
._DynamicPcdList
:
1634 # just pick the a value to determine whether is unicode string type
1635 Sku
= Pcd
.SkuInfoList
.values()[0]
1636 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1638 if Pcd
.DatumType
not in [TAB_UINT8
, TAB_UINT16
, TAB_UINT32
, TAB_UINT64
, TAB_VOID
, "BOOLEAN"]:
1639 Pcd
.DatumType
= TAB_VOID
1641 PcdValue
= Sku
.DefaultValue
1642 if Pcd
.DatumType
== TAB_VOID
and PcdValue
.startswith("L"):
1643 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
1644 UnicodePcdArray
.add(Pcd
)
1645 elif len(Sku
.VariableName
) > 0:
1646 # if found HII type PCD then insert to right of UnicodeIndex
1647 HiiPcdArray
.add(Pcd
)
1649 OtherPcdArray
.add(Pcd
)
1650 del self
._DynamicPcdList
[:]
1651 self
._DynamicPcdList
.extend(list(UnicodePcdArray
))
1652 self
._DynamicPcdList
.extend(list(HiiPcdArray
))
1653 self
._DynamicPcdList
.extend(list(OtherPcdArray
))
1654 allskuset
= [(SkuName
, Sku
.SkuId
) for pcd
in self
._DynamicPcdList
for (SkuName
, Sku
) in pcd
.SkuInfoList
.items()]
1655 for pcd
in self
._DynamicPcdList
:
1656 if len(pcd
.SkuInfoList
) == 1:
1657 for (SkuName
, SkuId
) in allskuset
:
1658 if type(SkuId
) in (str, unicode) and eval(SkuId
) == 0 or SkuId
== 0:
1660 pcd
.SkuInfoList
[SkuName
] = copy
.deepcopy(pcd
.SkuInfoList
[TAB_DEFAULT
])
1661 pcd
.SkuInfoList
[SkuName
].SkuId
= SkuId
1662 self
.AllPcdList
= self
._NonDynamicPcdList
+ self
._DynamicPcdList
1664 def FixVpdOffset(self
, VpdFile
):
1665 FvPath
= os
.path
.join(self
.BuildDir
, TAB_FV_DIRECTORY
)
1666 if not os
.path
.exists(FvPath
):
1670 EdkLogger
.error("build", FILE_WRITE_FAILURE
, "Fail to create FV folder under %s" % self
.BuildDir
)
1672 VpdFilePath
= os
.path
.join(FvPath
, "%s.txt" % self
.Platform
.VpdToolGuid
)
1674 if VpdFile
.Write(VpdFilePath
):
1675 # retrieve BPDG tool's path from tool_def.txt according to VPD_TOOL_GUID defined in DSC file.
1677 for ToolDef
in self
.ToolDefinition
.values():
1678 if TAB_GUID
in ToolDef
and ToolDef
[TAB_GUID
] == self
.Platform
.VpdToolGuid
:
1679 if "PATH" not in ToolDef
:
1680 EdkLogger
.error("build", ATTRIBUTE_NOT_AVAILABLE
, "PATH attribute was not provided for BPDG guid tool %s in tools_def.txt" % self
.Platform
.VpdToolGuid
)
1681 BPDGToolName
= ToolDef
["PATH"]
1683 # Call third party GUID BPDG tool.
1684 if BPDGToolName
is not None:
1685 VpdInfoFile
.CallExtenalBPDGTool(BPDGToolName
, VpdFilePath
)
1687 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.")
1689 ## Return the platform build data object
1690 def _GetPlatform(self
):
1691 if self
._Platform
is None:
1692 self
._Platform
= self
.BuildDatabase
[self
.MetaFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1693 return self
._Platform
1695 ## Return platform name
1697 return self
.Platform
.PlatformName
1699 ## Return the meta file GUID
1701 return self
.Platform
.Guid
1703 ## Return the platform version
1704 def _GetVersion(self
):
1705 return self
.Platform
.Version
1707 ## Return the FDF file name
1708 def _GetFdfFile(self
):
1709 if self
._FdfFile
is None:
1710 if self
.Workspace
.FdfFile
!= "":
1711 self
._FdfFile
= mws
.join(self
.WorkspaceDir
, self
.Workspace
.FdfFile
)
1714 return self
._FdfFile
1716 ## Return the build output directory platform specifies
1717 def _GetOutputDir(self
):
1718 return self
.Platform
.OutputDirectory
1720 ## Return the directory to store all intermediate and final files built
1721 def _GetBuildDir(self
):
1722 if self
._BuildDir
is None:
1723 if os
.path
.isabs(self
.OutputDir
):
1724 self
._BuildDir
= path
.join(
1725 path
.abspath(self
.OutputDir
),
1726 self
.BuildTarget
+ "_" + self
.ToolChain
,
1729 self
._BuildDir
= path
.join(
1732 self
.BuildTarget
+ "_" + self
.ToolChain
,
1734 GlobalData
.gBuildDirectory
= self
._BuildDir
1735 return self
._BuildDir
1737 ## Return directory of platform makefile
1739 # @retval string Makefile directory
1741 def _GetMakeFileDir(self
):
1742 if self
._MakeFileDir
is None:
1743 self
._MakeFileDir
= path
.join(self
.BuildDir
, self
.Arch
)
1744 return self
._MakeFileDir
1746 ## Return build command string
1748 # @retval string Build command string
1750 def _GetBuildCommand(self
):
1751 if self
._BuildCommand
is None:
1752 self
._BuildCommand
= []
1753 if "MAKE" in self
.ToolDefinition
and "PATH" in self
.ToolDefinition
["MAKE"]:
1754 self
._BuildCommand
+= SplitOption(self
.ToolDefinition
["MAKE"]["PATH"])
1755 if "FLAGS" in self
.ToolDefinition
["MAKE"]:
1756 NewOption
= self
.ToolDefinition
["MAKE"]["FLAGS"].strip()
1758 self
._BuildCommand
+= SplitOption(NewOption
)
1759 if "MAKE" in self
.EdkIIBuildOption
:
1760 if "FLAGS" in self
.EdkIIBuildOption
["MAKE"]:
1761 Flags
= self
.EdkIIBuildOption
["MAKE"]["FLAGS"]
1762 if Flags
.startswith('='):
1763 self
._BuildCommand
= [self
._BuildCommand
[0]] + [Flags
[1:]]
1765 self
._BuildCommand
.append(Flags
)
1766 return self
._BuildCommand
1768 ## Get tool chain definition
1770 # Get each tool defition for given tool chain from tools_def.txt and platform
1772 def _GetToolDefinition(self
):
1773 if self
._ToolDefinitions
is None:
1774 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDictionary
1775 if TAB_TOD_DEFINES_COMMAND_TYPE
not in self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
:
1776 EdkLogger
.error('build', RESOURCE_NOT_AVAILABLE
, "No tools found in configuration",
1777 ExtraData
="[%s]" % self
.MetaFile
)
1778 self
._ToolDefinitions
= {}
1780 for Def
in ToolDefinition
:
1781 Target
, Tag
, Arch
, Tool
, Attr
= Def
.split("_")
1782 if Target
!= self
.BuildTarget
or Tag
!= self
.ToolChain
or Arch
!= self
.Arch
:
1785 Value
= ToolDefinition
[Def
]
1786 # don't record the DLL
1788 DllPathList
.add(Value
)
1791 if Tool
not in self
._ToolDefinitions
:
1792 self
._ToolDefinitions
[Tool
] = {}
1793 self
._ToolDefinitions
[Tool
][Attr
] = Value
1796 if GlobalData
.gOptions
.SilentMode
and "MAKE" in self
._ToolDefinitions
:
1797 if "FLAGS" not in self
._ToolDefinitions
["MAKE"]:
1798 self
._ToolDefinitions
["MAKE"]["FLAGS"] = ""
1799 self
._ToolDefinitions
["MAKE"]["FLAGS"] += " -s"
1801 for Tool
in self
._ToolDefinitions
:
1802 for Attr
in self
._ToolDefinitions
[Tool
]:
1803 Value
= self
._ToolDefinitions
[Tool
][Attr
]
1804 if Tool
in self
.BuildOption
and Attr
in self
.BuildOption
[Tool
]:
1805 # check if override is indicated
1806 if self
.BuildOption
[Tool
][Attr
].startswith('='):
1807 Value
= self
.BuildOption
[Tool
][Attr
][1:]
1810 Value
+= " " + self
.BuildOption
[Tool
][Attr
]
1812 Value
= self
.BuildOption
[Tool
][Attr
]
1815 # Don't put MAKE definition in the file
1817 ToolsDef
+= "%s = %s\n" % (Tool
, Value
)
1819 # Don't put MAKE definition in the file
1824 ToolsDef
+= "%s_%s = %s\n" % (Tool
, Attr
, Value
)
1827 SaveFileOnChange(self
.ToolDefinitionFile
, ToolsDef
)
1828 for DllPath
in DllPathList
:
1829 os
.environ
["PATH"] = DllPath
+ os
.pathsep
+ os
.environ
["PATH"]
1830 os
.environ
["MAKE_FLAGS"] = MakeFlags
1832 return self
._ToolDefinitions
1834 ## Return the paths of tools
1835 def _GetToolDefFile(self
):
1836 if self
._ToolDefFile
is None:
1837 self
._ToolDefFile
= os
.path
.join(self
.MakeFileDir
, "TOOLS_DEF." + self
.Arch
)
1838 return self
._ToolDefFile
1840 ## Retrieve the toolchain family of given toolchain tag. Default to 'MSFT'.
1841 def _GetToolChainFamily(self
):
1842 if self
._ToolChainFamily
is None:
1843 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
1844 if TAB_TOD_DEFINES_FAMILY
not in ToolDefinition \
1845 or self
.ToolChain
not in ToolDefinition
[TAB_TOD_DEFINES_FAMILY
] \
1846 or not ToolDefinition
[TAB_TOD_DEFINES_FAMILY
][self
.ToolChain
]:
1847 EdkLogger
.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
1849 self
._ToolChainFamily
= "MSFT"
1851 self
._ToolChainFamily
= ToolDefinition
[TAB_TOD_DEFINES_FAMILY
][self
.ToolChain
]
1852 return self
._ToolChainFamily
1854 def _GetBuildRuleFamily(self
):
1855 if self
._BuildRuleFamily
is None:
1856 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
1857 if TAB_TOD_DEFINES_BUILDRULEFAMILY
not in ToolDefinition \
1858 or self
.ToolChain
not in ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
] \
1859 or not ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
][self
.ToolChain
]:
1860 EdkLogger
.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
1862 self
._BuildRuleFamily
= "MSFT"
1864 self
._BuildRuleFamily
= ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
][self
.ToolChain
]
1865 return self
._BuildRuleFamily
1867 ## Return the build options specific for all modules in this platform
1868 def _GetBuildOptions(self
):
1869 if self
._BuildOption
is None:
1870 self
._BuildOption
= self
._ExpandBuildOption
(self
.Platform
.BuildOptions
)
1871 return self
._BuildOption
1873 ## Return the build options specific for EDK modules in this platform
1874 def _GetEdkBuildOptions(self
):
1875 if self
._EdkBuildOption
is None:
1876 self
._EdkBuildOption
= self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, EDK_NAME
)
1877 return self
._EdkBuildOption
1879 ## Return the build options specific for EDKII modules in this platform
1880 def _GetEdkIIBuildOptions(self
):
1881 if self
._EdkIIBuildOption
is None:
1882 self
._EdkIIBuildOption
= self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, EDKII_NAME
)
1883 return self
._EdkIIBuildOption
1885 ## Parse build_rule.txt in Conf Directory.
1887 # @retval BuildRule object
1889 def _GetBuildRule(self
):
1890 if self
._BuildRule
is None:
1891 BuildRuleFile
= None
1892 if TAB_TAT_DEFINES_BUILD_RULE_CONF
in self
.Workspace
.TargetTxt
.TargetTxtDictionary
:
1893 BuildRuleFile
= self
.Workspace
.TargetTxt
.TargetTxtDictionary
[TAB_TAT_DEFINES_BUILD_RULE_CONF
]
1894 if not BuildRuleFile
:
1895 BuildRuleFile
= gDefaultBuildRuleFile
1896 self
._BuildRule
= BuildRule(BuildRuleFile
)
1897 if self
._BuildRule
._FileVersion
== "":
1898 self
._BuildRule
._FileVersion
= AutoGenReqBuildRuleVerNum
1900 if self
._BuildRule
._FileVersion
< AutoGenReqBuildRuleVerNum
:
1901 # If Build Rule's version is less than the version number required by the tools, halting the build.
1902 EdkLogger
.error("build", AUTOGEN_ERROR
,
1903 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])"\
1904 % (self
._BuildRule
._FileVersion
, AutoGenReqBuildRuleVerNum
))
1906 return self
._BuildRule
1908 ## Summarize the packages used by modules in this platform
1909 def _GetPackageList(self
):
1910 if self
._PackageList
is None:
1911 self
._PackageList
= set()
1912 for La
in self
.LibraryAutoGenList
:
1913 self
._PackageList
.update(La
.DependentPackageList
)
1914 for Ma
in self
.ModuleAutoGenList
:
1915 self
._PackageList
.update(Ma
.DependentPackageList
)
1916 #Collect package set information from INF of FDF
1918 for ModuleFile
in self
._AsBuildModuleList
:
1919 if ModuleFile
in self
.Platform
.Modules
:
1921 ModuleData
= self
.BuildDatabase
[ModuleFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1922 PkgSet
.update(ModuleData
.Packages
)
1923 self
._PackageList
= list(self
._PackageList
) + list (PkgSet
)
1924 return self
._PackageList
1926 def _GetNonDynamicPcdDict(self
):
1927 if self
._NonDynamicPcdDict
:
1928 return self
._NonDynamicPcdDict
1929 for Pcd
in self
.NonDynamicPcdList
:
1930 self
._NonDynamicPcdDict
[(Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
)] = Pcd
1931 return self
._NonDynamicPcdDict
1933 ## Get list of non-dynamic PCDs
1934 def _GetNonDynamicPcdList(self
):
1935 if self
._NonDynamicPcdList
is None:
1936 self
.CollectPlatformDynamicPcds()
1937 return self
._NonDynamicPcdList
1939 ## Get list of dynamic PCDs
1940 def _GetDynamicPcdList(self
):
1941 if self
._DynamicPcdList
is None:
1942 self
.CollectPlatformDynamicPcds()
1943 return self
._DynamicPcdList
1945 ## Generate Token Number for all PCD
1946 def _GetPcdTokenNumbers(self
):
1947 if self
._PcdTokenNumber
is None:
1948 self
._PcdTokenNumber
= OrderedDict()
1951 # Make the Dynamic and DynamicEx PCD use within different TokenNumber area.
1955 # TokenNumber 0 ~ 10
1957 # TokeNumber 11 ~ 20
1959 for Pcd
in self
.DynamicPcdList
:
1960 if Pcd
.Phase
== "PEI" and Pcd
.Type
in PCD_DYNAMIC_TYPE_SET
:
1961 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
1962 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
1965 for Pcd
in self
.DynamicPcdList
:
1966 if Pcd
.Phase
== "PEI" and Pcd
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
1967 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
1968 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
1971 for Pcd
in self
.DynamicPcdList
:
1972 if Pcd
.Phase
== "DXE" and Pcd
.Type
in PCD_DYNAMIC_TYPE_SET
:
1973 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
1974 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
1977 for Pcd
in self
.DynamicPcdList
:
1978 if Pcd
.Phase
== "DXE" and Pcd
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
1979 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
1980 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
1983 for Pcd
in self
.NonDynamicPcdList
:
1984 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
1986 return self
._PcdTokenNumber
1988 ## Summarize ModuleAutoGen objects of all modules/libraries to be built for this platform
1989 def _GetAutoGenObjectList(self
):
1990 self
._ModuleAutoGenList
= []
1991 self
._LibraryAutoGenList
= []
1992 for ModuleFile
in self
.Platform
.Modules
:
2001 if Ma
not in self
._ModuleAutoGenList
:
2002 self
._ModuleAutoGenList
.append(Ma
)
2003 for La
in Ma
.LibraryAutoGenList
:
2004 if La
not in self
._LibraryAutoGenList
:
2005 self
._LibraryAutoGenList
.append(La
)
2006 if Ma
not in La
._ReferenceModules
:
2007 La
._ReferenceModules
.append(Ma
)
2009 ## Summarize ModuleAutoGen objects of all modules to be built for this platform
2010 def _GetModuleAutoGenList(self
):
2011 if self
._ModuleAutoGenList
is None:
2012 self
._GetAutoGenObjectList
()
2013 return self
._ModuleAutoGenList
2015 ## Summarize ModuleAutoGen objects of all libraries to be built for this platform
2016 def _GetLibraryAutoGenList(self
):
2017 if self
._LibraryAutoGenList
is None:
2018 self
._GetAutoGenObjectList
()
2019 return self
._LibraryAutoGenList
2021 ## Test if a module is supported by the platform
2023 # An error will be raised directly if the module or its arch is not supported
2024 # by the platform or current configuration
2026 def ValidModule(self
, Module
):
2027 return Module
in self
.Platform
.Modules
or Module
in self
.Platform
.LibraryInstances \
2028 or Module
in self
._AsBuildModuleList
2030 ## Resolve the library classes in a module to library instances
2032 # This method will not only resolve library classes but also sort the library
2033 # instances according to the dependency-ship.
2035 # @param Module The module from which the library classes will be resolved
2037 # @retval library_list List of library instances sorted
2039 def ApplyLibraryInstance(self
, Module
):
2040 # Cover the case that the binary INF file is list in the FDF file but not DSC file, return empty list directly
2041 if str(Module
) not in self
.Platform
.Modules
:
2044 return GetModuleLibInstances(Module
,
2053 ## Override PCD setting (type, value, ...)
2055 # @param ToPcd The PCD to be overrided
2056 # @param FromPcd The PCD overrideing from
2058 def _OverridePcd(self
, ToPcd
, FromPcd
, Module
="", Msg
="", Library
=""):
2060 # in case there's PCDs coming from FDF file, which have no type given.
2061 # at this point, ToPcd.Type has the type found from dependent
2064 TokenCName
= ToPcd
.TokenCName
2065 for PcdItem
in GlobalData
.MixedPcd
:
2066 if (ToPcd
.TokenCName
, ToPcd
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
2067 TokenCName
= PcdItem
[0]
2069 if FromPcd
is not None:
2070 if ToPcd
.Pending
and FromPcd
.Type
:
2071 ToPcd
.Type
= FromPcd
.Type
2072 elif ToPcd
.Type
and FromPcd
.Type\
2073 and ToPcd
.Type
!= FromPcd
.Type
and ToPcd
.Type
in FromPcd
.Type
:
2074 if ToPcd
.Type
.strip() == TAB_PCDS_DYNAMIC_EX
:
2075 ToPcd
.Type
= FromPcd
.Type
2076 elif ToPcd
.Type
and FromPcd
.Type \
2077 and ToPcd
.Type
!= FromPcd
.Type
:
2079 Module
= str(Module
) + " 's library file (" + str(Library
) + ")"
2080 EdkLogger
.error("build", OPTION_CONFLICT
, "Mismatched PCD type",
2081 ExtraData
="%s.%s is used as [%s] in module %s, but as [%s] in %s."\
2082 % (ToPcd
.TokenSpaceGuidCName
, TokenCName
,
2083 ToPcd
.Type
, Module
, FromPcd
.Type
, Msg
),
2086 if FromPcd
.MaxDatumSize
:
2087 ToPcd
.MaxDatumSize
= FromPcd
.MaxDatumSize
2088 ToPcd
.MaxSizeUserSet
= FromPcd
.MaxDatumSize
2089 if FromPcd
.DefaultValue
:
2090 ToPcd
.DefaultValue
= FromPcd
.DefaultValue
2091 if FromPcd
.TokenValue
:
2092 ToPcd
.TokenValue
= FromPcd
.TokenValue
2093 if FromPcd
.DatumType
:
2094 ToPcd
.DatumType
= FromPcd
.DatumType
2095 if FromPcd
.SkuInfoList
:
2096 ToPcd
.SkuInfoList
= FromPcd
.SkuInfoList
2097 # Add Flexible PCD format parse
2098 if ToPcd
.DefaultValue
:
2100 ToPcd
.DefaultValue
= ValueExpressionEx(ToPcd
.DefaultValue
, ToPcd
.DatumType
, self
._GuidDict
)(True)
2101 except BadExpression
as Value
:
2102 EdkLogger
.error('Parser', FORMAT_INVALID
, 'PCD [%s.%s] Value "%s", %s' %(ToPcd
.TokenSpaceGuidCName
, ToPcd
.TokenCName
, ToPcd
.DefaultValue
, Value
),
2105 # check the validation of datum
2106 IsValid
, Cause
= CheckPcdDatum(ToPcd
.DatumType
, ToPcd
.DefaultValue
)
2108 EdkLogger
.error('build', FORMAT_INVALID
, Cause
, File
=self
.MetaFile
,
2109 ExtraData
="%s.%s" % (ToPcd
.TokenSpaceGuidCName
, TokenCName
))
2110 ToPcd
.validateranges
= FromPcd
.validateranges
2111 ToPcd
.validlists
= FromPcd
.validlists
2112 ToPcd
.expressions
= FromPcd
.expressions
2114 if FromPcd
is not None and ToPcd
.DatumType
== TAB_VOID
and not ToPcd
.MaxDatumSize
:
2115 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "No MaxDatumSize specified for PCD %s.%s" \
2116 % (ToPcd
.TokenSpaceGuidCName
, TokenCName
))
2117 Value
= ToPcd
.DefaultValue
2119 ToPcd
.MaxDatumSize
= '1'
2120 elif Value
[0] == 'L':
2121 ToPcd
.MaxDatumSize
= str((len(Value
) - 2) * 2)
2122 elif Value
[0] == '{':
2123 ToPcd
.MaxDatumSize
= str(len(Value
.split(',')))
2125 ToPcd
.MaxDatumSize
= str(len(Value
) - 1)
2127 # apply default SKU for dynamic PCDS if specified one is not available
2128 if (ToPcd
.Type
in PCD_DYNAMIC_TYPE_SET
or ToPcd
.Type
in PCD_DYNAMIC_EX_TYPE_SET
) \
2129 and not ToPcd
.SkuInfoList
:
2130 if self
.Platform
.SkuName
in self
.Platform
.SkuIds
:
2131 SkuName
= self
.Platform
.SkuName
2133 SkuName
= TAB_DEFAULT
2134 ToPcd
.SkuInfoList
= {
2135 SkuName
: SkuInfoClass(SkuName
, self
.Platform
.SkuIds
[SkuName
][0], '', '', '', '', '', ToPcd
.DefaultValue
)
2138 ## Apply PCD setting defined platform to a module
2140 # @param Module The module from which the PCD setting will be overrided
2142 # @retval PCD_list The list PCDs with settings from platform
2144 def ApplyPcdSetting(self
, Module
, Pcds
, Library
=""):
2145 # for each PCD in module
2146 for Name
, Guid
in Pcds
:
2147 PcdInModule
= Pcds
[Name
, Guid
]
2148 # find out the PCD setting in platform
2149 if (Name
, Guid
) in self
.Platform
.Pcds
:
2150 PcdInPlatform
= self
.Platform
.Pcds
[Name
, Guid
]
2152 PcdInPlatform
= None
2153 # then override the settings if any
2154 self
._OverridePcd
(PcdInModule
, PcdInPlatform
, Module
, Msg
="DSC PCD sections", Library
=Library
)
2155 # resolve the VariableGuid value
2156 for SkuId
in PcdInModule
.SkuInfoList
:
2157 Sku
= PcdInModule
.SkuInfoList
[SkuId
]
2158 if Sku
.VariableGuid
== '': continue
2159 Sku
.VariableGuidValue
= GuidValue(Sku
.VariableGuid
, self
.PackageList
, self
.MetaFile
.Path
)
2160 if Sku
.VariableGuidValue
is None:
2161 PackageList
= "\n\t".join(str(P
) for P
in self
.PackageList
)
2164 RESOURCE_NOT_AVAILABLE
,
2165 "Value of GUID [%s] is not found in" % Sku
.VariableGuid
,
2166 ExtraData
=PackageList
+ "\n\t(used with %s.%s from module %s)" \
2167 % (Guid
, Name
, str(Module
)),
2171 # override PCD settings with module specific setting
2172 if Module
in self
.Platform
.Modules
:
2173 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
2174 for Key
in PlatformModule
.Pcds
:
2179 elif Key
in GlobalData
.MixedPcd
:
2180 for PcdItem
in GlobalData
.MixedPcd
[Key
]:
2182 ToPcd
= Pcds
[PcdItem
]
2186 self
._OverridePcd
(ToPcd
, PlatformModule
.Pcds
[Key
], Module
, Msg
="DSC Components Module scoped PCD section", Library
=Library
)
2187 # use PCD value to calculate the MaxDatumSize when it is not specified
2188 for Name
, Guid
in Pcds
:
2189 Pcd
= Pcds
[Name
, Guid
]
2190 if Pcd
.DatumType
== TAB_VOID
and not Pcd
.MaxDatumSize
:
2191 Pcd
.MaxSizeUserSet
= None
2192 Value
= Pcd
.DefaultValue
2194 Pcd
.MaxDatumSize
= '1'
2195 elif Value
[0] == 'L':
2196 Pcd
.MaxDatumSize
= str((len(Value
) - 2) * 2)
2197 elif Value
[0] == '{':
2198 Pcd
.MaxDatumSize
= str(len(Value
.split(',')))
2200 Pcd
.MaxDatumSize
= str(len(Value
) - 1)
2201 return Pcds
.values()
2203 ## Resolve library names to library modules
2205 # (for Edk.x modules)
2207 # @param Module The module from which the library names will be resolved
2209 # @retval library_list The list of library modules
2211 def ResolveLibraryReference(self
, Module
):
2212 EdkLogger
.verbose("")
2213 EdkLogger
.verbose("Library instances of module [%s] [%s]:" % (str(Module
), self
.Arch
))
2214 LibraryConsumerList
= [Module
]
2216 # "CompilerStub" is a must for Edk modules
2217 if Module
.Libraries
:
2218 Module
.Libraries
.append("CompilerStub")
2220 while len(LibraryConsumerList
) > 0:
2221 M
= LibraryConsumerList
.pop()
2222 for LibraryName
in M
.Libraries
:
2223 Library
= self
.Platform
.LibraryClasses
[LibraryName
, ':dummy:']
2225 for Key
in self
.Platform
.LibraryClasses
.data
:
2226 if LibraryName
.upper() == Key
.upper():
2227 Library
= self
.Platform
.LibraryClasses
[Key
, ':dummy:']
2230 EdkLogger
.warn("build", "Library [%s] is not found" % LibraryName
, File
=str(M
),
2231 ExtraData
="\t%s [%s]" % (str(Module
), self
.Arch
))
2234 if Library
not in LibraryList
:
2235 LibraryList
.append(Library
)
2236 LibraryConsumerList
.append(Library
)
2237 EdkLogger
.verbose("\t" + LibraryName
+ " : " + str(Library
) + ' ' + str(type(Library
)))
2240 ## Calculate the priority value of the build option
2242 # @param Key Build option definition contain: TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
2244 # @retval Value Priority value based on the priority list.
2246 def CalculatePriorityValue(self
, Key
):
2247 Target
, ToolChain
, Arch
, CommandType
, Attr
= Key
.split('_')
2248 PriorityValue
= 0x11111
2250 PriorityValue
&= 0x01111
2251 if ToolChain
== "*":
2252 PriorityValue
&= 0x10111
2254 PriorityValue
&= 0x11011
2255 if CommandType
== "*":
2256 PriorityValue
&= 0x11101
2258 PriorityValue
&= 0x11110
2260 return self
.PrioList
["0x%0.5x" % PriorityValue
]
2263 ## Expand * in build option key
2265 # @param Options Options to be expanded
2267 # @retval options Options expanded
2269 def _ExpandBuildOption(self
, Options
, ModuleStyle
=None):
2276 # Construct a list contain the build options which need override.
2280 # Key[0] -- tool family
2281 # Key[1] -- TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
2283 if (Key
[0] == self
.BuildRuleFamily
and
2284 (ModuleStyle
is None or len(Key
) < 3 or (len(Key
) > 2 and Key
[2] == ModuleStyle
))):
2285 Target
, ToolChain
, Arch
, CommandType
, Attr
= Key
[1].split('_')
2286 if (Target
== self
.BuildTarget
or Target
== "*") and\
2287 (ToolChain
== self
.ToolChain
or ToolChain
== "*") and\
2288 (Arch
== self
.Arch
or Arch
== "*") and\
2289 Options
[Key
].startswith("="):
2291 if OverrideList
.get(Key
[1]) is not None:
2292 OverrideList
.pop(Key
[1])
2293 OverrideList
[Key
[1]] = Options
[Key
]
2296 # Use the highest priority value.
2298 if (len(OverrideList
) >= 2):
2299 KeyList
= OverrideList
.keys()
2300 for Index
in range(len(KeyList
)):
2301 NowKey
= KeyList
[Index
]
2302 Target1
, ToolChain1
, Arch1
, CommandType1
, Attr1
= NowKey
.split("_")
2303 for Index1
in range(len(KeyList
) - Index
- 1):
2304 NextKey
= KeyList
[Index1
+ Index
+ 1]
2306 # Compare two Key, if one is included by another, choose the higher priority one
2308 Target2
, ToolChain2
, Arch2
, CommandType2
, Attr2
= NextKey
.split("_")
2309 if (Target1
== Target2
or Target1
== "*" or Target2
== "*") and\
2310 (ToolChain1
== ToolChain2
or ToolChain1
== "*" or ToolChain2
== "*") and\
2311 (Arch1
== Arch2
or Arch1
== "*" or Arch2
== "*") and\
2312 (CommandType1
== CommandType2
or CommandType1
== "*" or CommandType2
== "*") and\
2313 (Attr1
== Attr2
or Attr1
== "*" or Attr2
== "*"):
2315 if self
.CalculatePriorityValue(NowKey
) > self
.CalculatePriorityValue(NextKey
):
2316 if Options
.get((self
.BuildRuleFamily
, NextKey
)) is not None:
2317 Options
.pop((self
.BuildRuleFamily
, NextKey
))
2319 if Options
.get((self
.BuildRuleFamily
, NowKey
)) is not None:
2320 Options
.pop((self
.BuildRuleFamily
, NowKey
))
2323 if ModuleStyle
is not None and len (Key
) > 2:
2324 # Check Module style is EDK or EDKII.
2325 # Only append build option for the matched style module.
2326 if ModuleStyle
== EDK_NAME
and Key
[2] != EDK_NAME
:
2328 elif ModuleStyle
== EDKII_NAME
and Key
[2] != EDKII_NAME
:
2331 Target
, Tag
, Arch
, Tool
, Attr
= Key
[1].split("_")
2332 # if tool chain family doesn't match, skip it
2333 if Tool
in self
.ToolDefinition
and Family
!= "":
2334 FamilyIsNull
= False
2335 if self
.ToolDefinition
[Tool
].get(TAB_TOD_DEFINES_BUILDRULEFAMILY
, "") != "":
2336 if Family
!= self
.ToolDefinition
[Tool
][TAB_TOD_DEFINES_BUILDRULEFAMILY
]:
2338 elif Family
!= self
.ToolDefinition
[Tool
][TAB_TOD_DEFINES_FAMILY
]:
2341 # expand any wildcard
2342 if Target
== "*" or Target
== self
.BuildTarget
:
2343 if Tag
== "*" or Tag
== self
.ToolChain
:
2344 if Arch
== "*" or Arch
== self
.Arch
:
2345 if Tool
not in BuildOptions
:
2346 BuildOptions
[Tool
] = {}
2347 if Attr
!= "FLAGS" or Attr
not in BuildOptions
[Tool
] or Options
[Key
].startswith('='):
2348 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2350 # append options for the same tool except PATH
2352 BuildOptions
[Tool
][Attr
] += " " + Options
[Key
]
2354 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2355 # Build Option Family has been checked, which need't to be checked again for family.
2356 if FamilyMatch
or FamilyIsNull
:
2360 if ModuleStyle
is not None and len (Key
) > 2:
2361 # Check Module style is EDK or EDKII.
2362 # Only append build option for the matched style module.
2363 if ModuleStyle
== EDK_NAME
and Key
[2] != EDK_NAME
:
2365 elif ModuleStyle
== EDKII_NAME
and Key
[2] != EDKII_NAME
:
2368 Target
, Tag
, Arch
, Tool
, Attr
= Key
[1].split("_")
2369 # if tool chain family doesn't match, skip it
2370 if Tool
not in self
.ToolDefinition
or Family
== "":
2372 # option has been added before
2373 if Family
!= self
.ToolDefinition
[Tool
][TAB_TOD_DEFINES_FAMILY
]:
2376 # expand any wildcard
2377 if Target
== "*" or Target
== self
.BuildTarget
:
2378 if Tag
== "*" or Tag
== self
.ToolChain
:
2379 if Arch
== "*" or Arch
== self
.Arch
:
2380 if Tool
not in BuildOptions
:
2381 BuildOptions
[Tool
] = {}
2382 if Attr
!= "FLAGS" or Attr
not in BuildOptions
[Tool
] or Options
[Key
].startswith('='):
2383 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2385 # append options for the same tool except PATH
2387 BuildOptions
[Tool
][Attr
] += " " + Options
[Key
]
2389 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2392 ## Append build options in platform to a module
2394 # @param Module The module to which the build options will be appened
2396 # @retval options The options appended with build options in platform
2398 def ApplyBuildOption(self
, Module
):
2399 # Get the different options for the different style module
2400 if Module
.AutoGenVersion
< 0x00010005:
2401 PlatformOptions
= self
.EdkBuildOption
2402 ModuleTypeOptions
= self
.Platform
.GetBuildOptionsByModuleType(EDK_NAME
, Module
.ModuleType
)
2404 PlatformOptions
= self
.EdkIIBuildOption
2405 ModuleTypeOptions
= self
.Platform
.GetBuildOptionsByModuleType(EDKII_NAME
, Module
.ModuleType
)
2406 ModuleTypeOptions
= self
._ExpandBuildOption
(ModuleTypeOptions
)
2407 ModuleOptions
= self
._ExpandBuildOption
(Module
.BuildOptions
)
2408 if Module
in self
.Platform
.Modules
:
2409 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
2410 PlatformModuleOptions
= self
._ExpandBuildOption
(PlatformModule
.BuildOptions
)
2412 PlatformModuleOptions
= {}
2414 BuildRuleOrder
= None
2415 for Options
in [self
.ToolDefinition
, ModuleOptions
, PlatformOptions
, ModuleTypeOptions
, PlatformModuleOptions
]:
2416 for Tool
in Options
:
2417 for Attr
in Options
[Tool
]:
2418 if Attr
== TAB_TOD_DEFINES_BUILDRULEORDER
:
2419 BuildRuleOrder
= Options
[Tool
][Attr
]
2421 AllTools
= set(ModuleOptions
.keys() + PlatformOptions
.keys() +
2422 PlatformModuleOptions
.keys() + ModuleTypeOptions
.keys() +
2423 self
.ToolDefinition
.keys())
2424 BuildOptions
= defaultdict(lambda: defaultdict(str))
2425 for Tool
in AllTools
:
2426 for Options
in [self
.ToolDefinition
, ModuleOptions
, PlatformOptions
, ModuleTypeOptions
, PlatformModuleOptions
]:
2427 if Tool
not in Options
:
2429 for Attr
in Options
[Tool
]:
2431 # Do not generate it in Makefile
2433 if Attr
== TAB_TOD_DEFINES_BUILDRULEORDER
:
2435 Value
= Options
[Tool
][Attr
]
2436 # check if override is indicated
2437 if Value
.startswith('='):
2438 BuildOptions
[Tool
][Attr
] = mws
.handleWsMacro(Value
[1:])
2441 BuildOptions
[Tool
][Attr
] += " " + mws
.handleWsMacro(Value
)
2443 BuildOptions
[Tool
][Attr
] = mws
.handleWsMacro(Value
)
2445 if Module
.AutoGenVersion
< 0x00010005 and self
.Workspace
.UniFlag
is not None:
2447 # Override UNI flag only for EDK module.
2449 BuildOptions
['BUILD']['FLAGS'] = self
.Workspace
.UniFlag
2450 return BuildOptions
, BuildRuleOrder
2452 Platform
= property(_GetPlatform
)
2453 Name
= property(_GetName
)
2454 Guid
= property(_GetGuid
)
2455 Version
= property(_GetVersion
)
2457 OutputDir
= property(_GetOutputDir
)
2458 BuildDir
= property(_GetBuildDir
)
2459 MakeFileDir
= property(_GetMakeFileDir
)
2460 FdfFile
= property(_GetFdfFile
)
2462 PcdTokenNumber
= property(_GetPcdTokenNumbers
) # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber
2463 DynamicPcdList
= property(_GetDynamicPcdList
) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
2464 NonDynamicPcdList
= property(_GetNonDynamicPcdList
) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
2465 NonDynamicPcdDict
= property(_GetNonDynamicPcdDict
)
2466 PackageList
= property(_GetPackageList
)
2468 ToolDefinition
= property(_GetToolDefinition
) # toolcode : tool path
2469 ToolDefinitionFile
= property(_GetToolDefFile
) # toolcode : lib path
2470 ToolChainFamily
= property(_GetToolChainFamily
)
2471 BuildRuleFamily
= property(_GetBuildRuleFamily
)
2472 BuildOption
= property(_GetBuildOptions
) # toolcode : option
2473 EdkBuildOption
= property(_GetEdkBuildOptions
) # edktoolcode : option
2474 EdkIIBuildOption
= property(_GetEdkIIBuildOptions
) # edkiitoolcode : option
2476 BuildCommand
= property(_GetBuildCommand
)
2477 BuildRule
= property(_GetBuildRule
)
2478 ModuleAutoGenList
= property(_GetModuleAutoGenList
)
2479 LibraryAutoGenList
= property(_GetLibraryAutoGenList
)
2480 GenFdsCommand
= property(_GenFdsCommand
)
2483 # extend lists contained in a dictionary with lists stored in another dictionary
2484 # if CopyToDict is not derived from DefaultDict(list) then this may raise exception
2486 def ExtendCopyDictionaryLists(CopyToDict
, CopyFromDict
):
2487 for Key
in CopyFromDict
:
2488 CopyToDict
[Key
].extend(CopyFromDict
[Key
])
2491 ## ModuleAutoGen class
2493 # This class encapsules the AutoGen behaviors for the build tools. In addition to
2494 # the generation of AutoGen.h and AutoGen.c, it will generate *.depex file according
2495 # to the [depex] section in module's inf file.
2497 class ModuleAutoGen(AutoGen
):
2498 # call super().__init__ then call the worker function with different parameter count
2499 def __init__(self
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
2503 super(ModuleAutoGen
, self
).__init
__(Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
)
2504 self
._InitWorker
(Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
)
2507 ## Cache the timestamps of metafiles of every module in a class variable
2511 def __new__(cls
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
2512 obj
= super(ModuleAutoGen
, cls
).__new
__(cls
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
)
2513 # check if this module is employed by active platform
2514 if not PlatformAutoGen(Workspace
, args
[0], Target
, Toolchain
, Arch
).ValidModule(MetaFile
):
2515 EdkLogger
.verbose("Module [%s] for [%s] is not employed by active platform\n" \
2520 ## Initialize ModuleAutoGen
2522 # @param Workspace EdkIIWorkspaceBuild object
2523 # @param ModuleFile The path of module file
2524 # @param Target Build target (DEBUG, RELEASE)
2525 # @param Toolchain Name of tool chain
2526 # @param Arch The arch the module supports
2527 # @param PlatformFile Platform meta-file
2529 def _InitWorker(self
, Workspace
, ModuleFile
, Target
, Toolchain
, Arch
, PlatformFile
):
2530 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "AutoGen module [%s] [%s]" % (ModuleFile
, Arch
))
2531 GlobalData
.gProcessingFile
= "%s [%s, %s, %s]" % (ModuleFile
, Arch
, Toolchain
, Target
)
2533 self
.Workspace
= Workspace
2534 self
.WorkspaceDir
= Workspace
.WorkspaceDir
2535 self
._GuidDict
= Workspace
._GuidDict
2536 self
.MetaFile
= ModuleFile
2537 self
.PlatformInfo
= PlatformAutoGen(Workspace
, PlatformFile
, Target
, Toolchain
, Arch
)
2539 self
.SourceDir
= self
.MetaFile
.SubDir
2540 self
.SourceDir
= mws
.relpath(self
.SourceDir
, self
.WorkspaceDir
)
2542 self
.SourceOverrideDir
= None
2543 # use overrided path defined in DSC file
2544 if self
.MetaFile
.Key
in GlobalData
.gOverrideDir
:
2545 self
.SourceOverrideDir
= GlobalData
.gOverrideDir
[self
.MetaFile
.Key
]
2547 self
.ToolChain
= Toolchain
2548 self
.BuildTarget
= Target
2550 self
.ToolChainFamily
= self
.PlatformInfo
.ToolChainFamily
2551 self
.BuildRuleFamily
= self
.PlatformInfo
.BuildRuleFamily
2553 self
.IsMakeFileCreated
= False
2554 self
.IsCodeFileCreated
= False
2555 self
.IsAsBuiltInfCreated
= False
2556 self
.DepexGenerated
= False
2558 self
.BuildDatabase
= self
.Workspace
.BuildDatabase
2559 self
.BuildRuleOrder
= None
2565 self
._Version
= None
2566 self
._ModuleType
= None
2567 self
._ComponentType
= None
2568 self
._PcdIsDriver
= None
2569 self
._AutoGenVersion
= None
2570 self
._LibraryFlag
= None
2571 self
._CustomMakefile
= None
2574 self
._BuildDir
= None
2575 self
._OutputDir
= None
2576 self
._FfsOutputDir
= None
2577 self
._DebugDir
= None
2578 self
._MakeFileDir
= None
2580 self
._IncludePathList
= None
2581 self
._AutoGenFileList
= None
2582 self
._UnicodeFileList
= None
2583 self
._VfrFileList
= None
2584 self
._IdfFileList
= None
2585 self
._SourceFileList
= None
2586 self
._ObjectFileList
= None
2587 self
._BinaryFileList
= None
2589 self
._DependentPackageList
= None
2590 self
._DependentLibraryList
= None
2591 self
._LibraryAutoGenList
= None
2592 self
._DerivedPackageList
= None
2593 self
._ModulePcdList
= None
2594 self
._LibraryPcdList
= None
2595 self
._PcdComments
= OrderedListDict()
2596 self
._GuidList
= None
2597 self
._GuidsUsedByPcd
= None
2598 self
._GuidComments
= OrderedListDict()
2599 self
._ProtocolList
= None
2600 self
._ProtocolComments
= OrderedListDict()
2601 self
._PpiList
= None
2602 self
._PpiComments
= OrderedListDict()
2603 self
._DepexDict
= None
2604 self
._DepexExpressionDict
= None
2605 self
._BuildOption
= None
2606 self
._BuildOptionIncPathList
= None
2607 self
._BuildTargets
= None
2608 self
._IntroBuildTargetList
= None
2609 self
._FinalBuildTargetList
= None
2610 self
._FileTypes
= None
2611 self
._BuildRules
= None
2613 self
._TimeStampPath
= None
2615 self
.AutoGenDepSet
= set()
2618 ## The Modules referenced to this Library
2619 # Only Library has this attribute
2620 self
._ReferenceModules
= []
2622 ## Store the FixedAtBuild Pcds
2624 self
._FixedAtBuildPcds
= []
2627 ##Store the VOID* type FixedAtBuild Pcds
2629 self
._FixedPcdVoidTypeDict
= {}
2632 return "%s [%s]" % (self
.MetaFile
, self
.Arch
)
2634 # Get FixedAtBuild Pcds of this Module
2635 def _GetFixedAtBuildPcds(self
):
2636 if self
._FixedAtBuildPcds
:
2637 return self
._FixedAtBuildPcds
2638 for Pcd
in self
.ModulePcdList
:
2639 if Pcd
.Type
!= TAB_PCDS_FIXED_AT_BUILD
:
2641 if Pcd
not in self
._FixedAtBuildPcds
:
2642 self
._FixedAtBuildPcds
.append(Pcd
)
2644 return self
._FixedAtBuildPcds
2646 def _GetFixedAtBuildVoidTypePcds(self
):
2647 if self
._FixedPcdVoidTypeDict
:
2648 return self
._FixedPcdVoidTypeDict
2649 for Pcd
in self
.ModulePcdList
:
2650 if Pcd
.Type
== TAB_PCDS_FIXED_AT_BUILD
and Pcd
.DatumType
== TAB_VOID
:
2651 if '{}.{}'.format(Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) not in self
._FixedPcdVoidTypeDict
:
2652 self
._FixedPcdVoidTypeDict
['{}.{}'.format(Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
)] = Pcd
.DefaultValue
2653 return self
._FixedPcdVoidTypeDict
2655 def _GetUniqueBaseName(self
):
2656 BaseName
= self
.Name
2657 for Module
in self
.PlatformInfo
.ModuleAutoGenList
:
2658 if Module
.MetaFile
== self
.MetaFile
:
2660 if Module
.Name
== self
.Name
:
2661 if uuid
.UUID(Module
.Guid
) == uuid
.UUID(self
.Guid
):
2662 EdkLogger
.error("build", FILE_DUPLICATED
, 'Modules have same BaseName and FILE_GUID:\n'
2663 ' %s\n %s' % (Module
.MetaFile
, self
.MetaFile
))
2664 BaseName
= '%s_%s' % (self
.Name
, self
.Guid
)
2667 # Macros could be used in build_rule.txt (also Makefile)
2668 def _GetMacros(self
):
2669 if self
._Macro
is None:
2670 self
._Macro
= OrderedDict()
2671 self
._Macro
["WORKSPACE" ] = self
.WorkspaceDir
2672 self
._Macro
["MODULE_NAME" ] = self
.Name
2673 self
._Macro
["MODULE_NAME_GUID" ] = self
.UniqueBaseName
2674 self
._Macro
["MODULE_GUID" ] = self
.Guid
2675 self
._Macro
["MODULE_VERSION" ] = self
.Version
2676 self
._Macro
["MODULE_TYPE" ] = self
.ModuleType
2677 self
._Macro
["MODULE_FILE" ] = str(self
.MetaFile
)
2678 self
._Macro
["MODULE_FILE_BASE_NAME" ] = self
.MetaFile
.BaseName
2679 self
._Macro
["MODULE_RELATIVE_DIR" ] = self
.SourceDir
2680 self
._Macro
["MODULE_DIR" ] = self
.SourceDir
2682 self
._Macro
["BASE_NAME" ] = self
.Name
2684 self
._Macro
["ARCH" ] = self
.Arch
2685 self
._Macro
["TOOLCHAIN" ] = self
.ToolChain
2686 self
._Macro
["TOOLCHAIN_TAG" ] = self
.ToolChain
2687 self
._Macro
["TOOL_CHAIN_TAG" ] = self
.ToolChain
2688 self
._Macro
["TARGET" ] = self
.BuildTarget
2690 self
._Macro
["BUILD_DIR" ] = self
.PlatformInfo
.BuildDir
2691 self
._Macro
["BIN_DIR" ] = os
.path
.join(self
.PlatformInfo
.BuildDir
, self
.Arch
)
2692 self
._Macro
["LIB_DIR" ] = os
.path
.join(self
.PlatformInfo
.BuildDir
, self
.Arch
)
2693 self
._Macro
["MODULE_BUILD_DIR" ] = self
.BuildDir
2694 self
._Macro
["OUTPUT_DIR" ] = self
.OutputDir
2695 self
._Macro
["DEBUG_DIR" ] = self
.DebugDir
2696 self
._Macro
["DEST_DIR_OUTPUT" ] = self
.OutputDir
2697 self
._Macro
["DEST_DIR_DEBUG" ] = self
.DebugDir
2698 self
._Macro
["PLATFORM_NAME" ] = self
.PlatformInfo
.Name
2699 self
._Macro
["PLATFORM_GUID" ] = self
.PlatformInfo
.Guid
2700 self
._Macro
["PLATFORM_VERSION" ] = self
.PlatformInfo
.Version
2701 self
._Macro
["PLATFORM_RELATIVE_DIR" ] = self
.PlatformInfo
.SourceDir
2702 self
._Macro
["PLATFORM_DIR" ] = mws
.join(self
.WorkspaceDir
, self
.PlatformInfo
.SourceDir
)
2703 self
._Macro
["PLATFORM_OUTPUT_DIR" ] = self
.PlatformInfo
.OutputDir
2704 self
._Macro
["FFS_OUTPUT_DIR" ] = self
.FfsOutputDir
2707 ## Return the module build data object
2708 def _GetModule(self
):
2709 if self
._Module
is None:
2710 self
._Module
= self
.Workspace
.BuildDatabase
[self
.MetaFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
2713 ## Return the module name
2714 def _GetBaseName(self
):
2715 return self
.Module
.BaseName
2717 ## Return the module DxsFile if exist
2718 def _GetDxsFile(self
):
2719 return self
.Module
.DxsFile
2721 ## Return the module SourceOverridePath
2722 def _GetSourceOverridePath(self
):
2723 return self
.Module
.SourceOverridePath
2725 ## Return the module meta-file GUID
2728 # To build same module more than once, the module path with FILE_GUID overridden has
2729 # the file name FILE_GUIDmodule.inf, but the relative path (self.MetaFile.File) is the realy path
2730 # in DSC. The overridden GUID can be retrieved from file name
2732 if os
.path
.basename(self
.MetaFile
.File
) != os
.path
.basename(self
.MetaFile
.Path
):
2734 # Length of GUID is 36
2736 return os
.path
.basename(self
.MetaFile
.Path
)[:36]
2737 return self
.Module
.Guid
2739 ## Return the module version
2740 def _GetVersion(self
):
2741 return self
.Module
.Version
2743 ## Return the module type
2744 def _GetModuleType(self
):
2745 return self
.Module
.ModuleType
2747 ## Return the component type (for Edk.x style of module)
2748 def _GetComponentType(self
):
2749 return self
.Module
.ComponentType
2751 ## Return the build type
2752 def _GetBuildType(self
):
2753 return self
.Module
.BuildType
2755 ## Return the PCD_IS_DRIVER setting
2756 def _GetPcdIsDriver(self
):
2757 return self
.Module
.PcdIsDriver
2759 ## Return the autogen version, i.e. module meta-file version
2760 def _GetAutoGenVersion(self
):
2761 return self
.Module
.AutoGenVersion
2763 ## Check if the module is library or not
2764 def _IsLibrary(self
):
2765 if self
._LibraryFlag
is None:
2766 self
._LibraryFlag
= True if self
.Module
.LibraryClass
else False
2767 return self
._LibraryFlag
2769 ## Check if the module is binary module or not
2770 def _IsBinaryModule(self
):
2771 return self
.Module
.IsBinaryModule
2773 ## Return the directory to store intermediate files of the module
2774 def _GetBuildDir(self
):
2775 if self
._BuildDir
is None:
2776 self
._BuildDir
= path
.join(
2777 self
.PlatformInfo
.BuildDir
,
2780 self
.MetaFile
.BaseName
2782 CreateDirectory(self
._BuildDir
)
2783 return self
._BuildDir
2785 ## Return the directory to store the intermediate object files of the mdoule
2786 def _GetOutputDir(self
):
2787 if self
._OutputDir
is None:
2788 self
._OutputDir
= path
.join(self
.BuildDir
, "OUTPUT")
2789 CreateDirectory(self
._OutputDir
)
2790 return self
._OutputDir
2792 ## Return the directory to store ffs file
2793 def _GetFfsOutputDir(self
):
2794 if self
._FfsOutputDir
is None:
2795 if GlobalData
.gFdfParser
is not None:
2796 self
._FfsOutputDir
= path
.join(self
.PlatformInfo
.BuildDir
, TAB_FV_DIRECTORY
, "Ffs", self
.Guid
+ self
.Name
)
2798 self
._FfsOutputDir
= ''
2799 return self
._FfsOutputDir
2801 ## Return the directory to store auto-gened source files of the mdoule
2802 def _GetDebugDir(self
):
2803 if self
._DebugDir
is None:
2804 self
._DebugDir
= path
.join(self
.BuildDir
, "DEBUG")
2805 CreateDirectory(self
._DebugDir
)
2806 return self
._DebugDir
2808 ## Return the path of custom file
2809 def _GetCustomMakefile(self
):
2810 if self
._CustomMakefile
is None:
2811 self
._CustomMakefile
= {}
2812 for Type
in self
.Module
.CustomMakefile
:
2813 if Type
in gMakeTypeMap
:
2814 MakeType
= gMakeTypeMap
[Type
]
2817 if self
.SourceOverrideDir
is not None:
2818 File
= os
.path
.join(self
.SourceOverrideDir
, self
.Module
.CustomMakefile
[Type
])
2819 if not os
.path
.exists(File
):
2820 File
= os
.path
.join(self
.SourceDir
, self
.Module
.CustomMakefile
[Type
])
2822 File
= os
.path
.join(self
.SourceDir
, self
.Module
.CustomMakefile
[Type
])
2823 self
._CustomMakefile
[MakeType
] = File
2824 return self
._CustomMakefile
2826 ## Return the directory of the makefile
2828 # @retval string The directory string of module's makefile
2830 def _GetMakeFileDir(self
):
2831 return self
.BuildDir
2833 ## Return build command string
2835 # @retval string Build command string
2837 def _GetBuildCommand(self
):
2838 return self
.PlatformInfo
.BuildCommand
2840 ## Get object list of all packages the module and its dependent libraries belong to
2842 # @retval list The list of package object
2844 def _GetDerivedPackageList(self
):
2846 for M
in [self
.Module
] + self
.DependentLibraryList
:
2847 for Package
in M
.Packages
:
2848 if Package
in PackageList
:
2850 PackageList
.append(Package
)
2853 ## Get the depex string
2855 # @return : a string contain all depex expresion.
2856 def _GetDepexExpresionString(self
):
2859 ## DPX_SOURCE IN Define section.
2860 if self
.Module
.DxsFile
:
2862 for M
in [self
.Module
] + self
.DependentLibraryList
:
2863 Filename
= M
.MetaFile
.Path
2864 InfObj
= InfSectionParser
.InfSectionParser(Filename
)
2865 DepexExpresionList
= InfObj
.GetDepexExpresionList()
2866 for DepexExpresion
in DepexExpresionList
:
2867 for key
in DepexExpresion
:
2868 Arch
, ModuleType
= key
2869 DepexExpr
= [x
for x
in DepexExpresion
[key
] if not str(x
).startswith('#')]
2870 # the type of build module is USER_DEFINED.
2871 # All different DEPEX section tags would be copied into the As Built INF file
2872 # and there would be separate DEPEX section tags
2873 if self
.ModuleType
.upper() == SUP_MODULE_USER_DEFINED
:
2874 if (Arch
.upper() == self
.Arch
.upper()) and (ModuleType
.upper() != TAB_ARCH_COMMON
):
2875 DepexList
.append({(Arch
, ModuleType
): DepexExpr
})
2877 if Arch
.upper() == TAB_ARCH_COMMON
or \
2878 (Arch
.upper() == self
.Arch
.upper() and \
2879 ModuleType
.upper() in [TAB_ARCH_COMMON
, self
.ModuleType
.upper()]):
2880 DepexList
.append({(Arch
, ModuleType
): DepexExpr
})
2882 #the type of build module is USER_DEFINED.
2883 if self
.ModuleType
.upper() == SUP_MODULE_USER_DEFINED
:
2884 for Depex
in DepexList
:
2886 DepexStr
+= '[Depex.%s.%s]\n' % key
2887 DepexStr
+= '\n'.join('# '+ val
for val
in Depex
[key
])
2890 return '[Depex.%s]\n' % self
.Arch
2893 #the type of build module not is USER_DEFINED.
2895 for Depex
in DepexList
:
2900 for D
in Depex
.values():
2901 DepexStr
+= ' '.join(val
for val
in D
)
2902 Index
= DepexStr
.find('END')
2903 if Index
> -1 and Index
== len(DepexStr
) - 3:
2904 DepexStr
= DepexStr
[:-3]
2905 DepexStr
= DepexStr
.strip()
2908 DepexStr
= DepexStr
.lstrip('(').rstrip(')').strip()
2910 return '[Depex.%s]\n' % self
.Arch
2911 return '[Depex.%s]\n# ' % self
.Arch
+ DepexStr
2913 ## Merge dependency expression
2915 # @retval list The token list of the dependency expression after parsed
2917 def _GetDepexTokenList(self
):
2918 if self
._DepexDict
is None:
2919 self
._DepexDict
= {}
2920 if self
.DxsFile
or self
.IsLibrary
or TAB_DEPENDENCY_EXPRESSION_FILE
in self
.FileTypes
:
2921 return self
._DepexDict
2923 self
._DepexDict
[self
.ModuleType
] = []
2924 self
._GetFixedAtBuildVoidTypePcds
()
2925 for ModuleType
in self
._DepexDict
:
2926 DepexList
= self
._DepexDict
[ModuleType
]
2928 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
2930 for M
in [self
.Module
] + self
.DependentLibraryList
:
2932 for D
in M
.Depex
[self
.Arch
, ModuleType
]:
2934 DepexList
.append('AND')
2935 DepexList
.append('(')
2936 #replace D with value if D is FixedAtBuild PCD
2940 NewList
.append(item
)
2942 if item
not in self
._FixedPcdVoidTypeDict
:
2943 EdkLogger
.error("build", FORMAT_INVALID
, "{} used in [Depex] section should be used as FixedAtBuild type and VOID* datum type in the module.".format(item
))
2945 Value
= self
._FixedPcdVoidTypeDict
[item
]
2946 if len(Value
.split(',')) != 16:
2947 EdkLogger
.error("build", FORMAT_INVALID
,
2948 "{} used in [Depex] section should be used as FixedAtBuild type and VOID* datum type and 16 bytes in the module.".format(item
))
2949 NewList
.append(Value
)
2950 DepexList
.extend(NewList
)
2951 if DepexList
[-1] == 'END': # no need of a END at this time
2953 DepexList
.append(')')
2956 EdkLogger
.verbose("DEPEX[%s] (+%s) = %s" % (self
.Name
, M
.BaseName
, DepexList
))
2957 if 'BEFORE' in DepexList
or 'AFTER' in DepexList
:
2959 if len(DepexList
) > 0:
2960 EdkLogger
.verbose('')
2961 return self
._DepexDict
2963 ## Merge dependency expression
2965 # @retval list The token list of the dependency expression after parsed
2967 def _GetDepexExpressionTokenList(self
):
2968 if self
._DepexExpressionDict
is None:
2969 self
._DepexExpressionDict
= {}
2970 if self
.DxsFile
or self
.IsLibrary
or TAB_DEPENDENCY_EXPRESSION_FILE
in self
.FileTypes
:
2971 return self
._DepexExpressionDict
2973 self
._DepexExpressionDict
[self
.ModuleType
] = ''
2975 for ModuleType
in self
._DepexExpressionDict
:
2976 DepexExpressionString
= self
._DepexExpressionDict
[ModuleType
]
2978 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
2980 for M
in [self
.Module
] + self
.DependentLibraryList
:
2982 for D
in M
.DepexExpression
[self
.Arch
, ModuleType
]:
2983 if DepexExpressionString
!= '':
2984 DepexExpressionString
+= ' AND '
2985 DepexExpressionString
+= '('
2986 DepexExpressionString
+= D
2987 DepexExpressionString
= DepexExpressionString
.rstrip('END').strip()
2988 DepexExpressionString
+= ')'
2991 EdkLogger
.verbose("DEPEX[%s] (+%s) = %s" % (self
.Name
, M
.BaseName
, DepexExpressionString
))
2992 if 'BEFORE' in DepexExpressionString
or 'AFTER' in DepexExpressionString
:
2994 if len(DepexExpressionString
) > 0:
2995 EdkLogger
.verbose('')
2996 self
._DepexExpressionDict
[ModuleType
] = DepexExpressionString
2997 return self
._DepexExpressionDict
2999 # Get the tiano core user extension, it is contain dependent library.
3000 # @retval: a list contain tiano core userextension.
3002 def _GetTianoCoreUserExtensionList(self
):
3003 TianoCoreUserExtentionList
= []
3004 for M
in [self
.Module
] + self
.DependentLibraryList
:
3005 Filename
= M
.MetaFile
.Path
3006 InfObj
= InfSectionParser
.InfSectionParser(Filename
)
3007 TianoCoreUserExtenList
= InfObj
.GetUserExtensionTianoCore()
3008 for TianoCoreUserExtent
in TianoCoreUserExtenList
:
3009 for Section
in TianoCoreUserExtent
:
3010 ItemList
= Section
.split(TAB_SPLIT
)
3012 if len(ItemList
) == 4:
3014 if Arch
.upper() == TAB_ARCH_COMMON
or Arch
.upper() == self
.Arch
.upper():
3016 TianoCoreList
.extend([TAB_SECTION_START
+ Section
+ TAB_SECTION_END
])
3017 TianoCoreList
.extend(TianoCoreUserExtent
[Section
][:])
3018 TianoCoreList
.append('\n')
3019 TianoCoreUserExtentionList
.append(TianoCoreList
)
3021 return TianoCoreUserExtentionList
3023 ## Return the list of specification version required for the module
3025 # @retval list The list of specification defined in module file
3027 def _GetSpecification(self
):
3028 return self
.Module
.Specification
3030 ## Tool option for the module build
3032 # @param PlatformInfo The object of PlatformBuildInfo
3033 # @retval dict The dict containing valid options
3035 def _GetModuleBuildOption(self
):
3036 if self
._BuildOption
is None:
3037 self
._BuildOption
, self
.BuildRuleOrder
= self
.PlatformInfo
.ApplyBuildOption(self
.Module
)
3038 if self
.BuildRuleOrder
:
3039 self
.BuildRuleOrder
= ['.%s' % Ext
for Ext
in self
.BuildRuleOrder
.split()]
3040 return self
._BuildOption
3042 ## Get include path list from tool option for the module build
3044 # @retval list The include path list
3046 def _GetBuildOptionIncPathList(self
):
3047 if self
._BuildOptionIncPathList
is None:
3049 # Regular expression for finding Include Directories, the difference between MSFT and INTEL/GCC/RVCT
3050 # is the former use /I , the Latter used -I to specify include directories
3052 if self
.PlatformInfo
.ToolChainFamily
in ('MSFT'):
3053 BuildOptIncludeRegEx
= gBuildOptIncludePatternMsft
3054 elif self
.PlatformInfo
.ToolChainFamily
in ('INTEL', 'GCC', 'RVCT'):
3055 BuildOptIncludeRegEx
= gBuildOptIncludePatternOther
3058 # New ToolChainFamily, don't known whether there is option to specify include directories
3060 self
._BuildOptionIncPathList
= []
3061 return self
._BuildOptionIncPathList
3063 BuildOptionIncPathList
= []
3064 for Tool
in ('CC', 'PP', 'VFRPP', 'ASLPP', 'ASLCC', 'APP', 'ASM'):
3066 FlagOption
= self
.BuildOption
[Tool
]['FLAGS']
3070 if self
.PlatformInfo
.ToolChainFamily
!= 'RVCT':
3071 IncPathList
= [NormPath(Path
, self
.Macros
) for Path
in BuildOptIncludeRegEx
.findall(FlagOption
)]
3074 # RVCT may specify a list of directory seperated by commas
3077 for Path
in BuildOptIncludeRegEx
.findall(FlagOption
):
3078 PathList
= GetSplitList(Path
, TAB_COMMA_SPLIT
)
3079 IncPathList
.extend(NormPath(PathEntry
, self
.Macros
) for PathEntry
in PathList
)
3082 # EDK II modules must not reference header files outside of the packages they depend on or
3083 # within the module's directory tree. Report error if violation.
3085 if self
.AutoGenVersion
>= 0x00010005:
3086 for Path
in IncPathList
:
3087 if (Path
not in self
.IncludePathList
) and (CommonPath([Path
, self
.MetaFile
.Dir
]) != self
.MetaFile
.Dir
):
3088 ErrMsg
= "The include directory for the EDK II module in this line is invalid %s specified in %s FLAGS '%s'" % (Path
, Tool
, FlagOption
)
3089 EdkLogger
.error("build",
3092 File
=str(self
.MetaFile
))
3095 BuildOptionIncPathList
+= IncPathList
3097 self
._BuildOptionIncPathList
= BuildOptionIncPathList
3099 return self
._BuildOptionIncPathList
3101 ## Return a list of files which can be built from source
3103 # What kind of files can be built is determined by build rules in
3104 # $(CONF_DIRECTORY)/build_rule.txt and toolchain family.
3106 def _GetSourceFileList(self
):
3107 if self
._SourceFileList
is None:
3108 self
._SourceFileList
= []
3109 ToolChainTagSet
= {"", "*", self
.ToolChain
}
3110 ToolChainFamilySet
= {"", "*", self
.ToolChainFamily
, self
.BuildRuleFamily
}
3111 for F
in self
.Module
.Sources
:
3113 if F
.TagName
not in ToolChainTagSet
:
3114 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "The toolchain [%s] for processing file [%s] is found, "
3115 "but [%s] is currently used" % (F
.TagName
, str(F
), self
.ToolChain
))
3117 # match tool chain family or build rule family
3118 if F
.ToolChainFamily
not in ToolChainFamilySet
:
3121 "The file [%s] must be built by tools of [%s], " \
3122 "but current toolchain family is [%s], buildrule family is [%s]" \
3123 % (str(F
), F
.ToolChainFamily
, self
.ToolChainFamily
, self
.BuildRuleFamily
))
3126 # add the file path into search path list for file including
3127 if F
.Dir
not in self
.IncludePathList
and self
.AutoGenVersion
>= 0x00010005:
3128 self
.IncludePathList
.insert(0, F
.Dir
)
3129 self
._SourceFileList
.append(F
)
3131 self
._MatchBuildRuleOrder
(self
._SourceFileList
)
3133 for F
in self
._SourceFileList
:
3134 self
._ApplyBuildRule
(F
, TAB_UNKNOWN_FILE
)
3135 return self
._SourceFileList
3137 def _MatchBuildRuleOrder(self
, FileList
):
3139 self
._GetModuleBuildOption
()
3140 for SingleFile
in FileList
:
3141 if self
.BuildRuleOrder
and SingleFile
.Ext
in self
.BuildRuleOrder
and SingleFile
.Ext
in self
.BuildRules
:
3142 key
= SingleFile
.Path
.split(SingleFile
.Ext
)[0]
3143 if key
in Order_Dict
:
3144 Order_Dict
[key
].append(SingleFile
.Ext
)
3146 Order_Dict
[key
] = [SingleFile
.Ext
]
3149 for F
in Order_Dict
:
3150 if len(Order_Dict
[F
]) > 1:
3151 Order_Dict
[F
].sort(key
=lambda i
: self
.BuildRuleOrder
.index(i
))
3152 for Ext
in Order_Dict
[F
][1:]:
3153 RemoveList
.append(F
+ Ext
)
3155 for item
in RemoveList
:
3156 FileList
.remove(item
)
3160 ## Return the list of unicode files
3161 def _GetUnicodeFileList(self
):
3162 if self
._UnicodeFileList
is None:
3163 if TAB_UNICODE_FILE
in self
.FileTypes
:
3164 self
._UnicodeFileList
= self
.FileTypes
[TAB_UNICODE_FILE
]
3166 self
._UnicodeFileList
= []
3167 return self
._UnicodeFileList
3169 ## Return the list of vfr files
3170 def _GetVfrFileList(self
):
3171 if self
._VfrFileList
is None:
3172 if TAB_VFR_FILE
in self
.FileTypes
:
3173 self
._VfrFileList
= self
.FileTypes
[TAB_VFR_FILE
]
3175 self
._VfrFileList
= []
3176 return self
._VfrFileList
3178 ## Return the list of Image Definition files
3179 def _GetIdfFileList(self
):
3180 if self
._IdfFileList
is None:
3181 if TAB_IMAGE_FILE
in self
.FileTypes
:
3182 self
._IdfFileList
= self
.FileTypes
[TAB_IMAGE_FILE
]
3184 self
._IdfFileList
= []
3185 return self
._IdfFileList
3187 ## Return a list of files which can be built from binary
3189 # "Build" binary files are just to copy them to build directory.
3191 # @retval list The list of files which can be built later
3193 def _GetBinaryFiles(self
):
3194 if self
._BinaryFileList
is None:
3195 self
._BinaryFileList
= []
3196 for F
in self
.Module
.Binaries
:
3197 if F
.Target
not in [TAB_ARCH_COMMON
, '*'] and F
.Target
!= self
.BuildTarget
:
3199 self
._BinaryFileList
.append(F
)
3200 self
._ApplyBuildRule
(F
, F
.Type
)
3201 return self
._BinaryFileList
3203 def _GetBuildRules(self
):
3204 if self
._BuildRules
is None:
3206 BuildRuleDatabase
= self
.PlatformInfo
.BuildRule
3207 for Type
in BuildRuleDatabase
.FileTypeList
:
3208 #first try getting build rule by BuildRuleFamily
3209 RuleObject
= BuildRuleDatabase
[Type
, self
.BuildType
, self
.Arch
, self
.BuildRuleFamily
]
3211 # build type is always module type, but ...
3212 if self
.ModuleType
!= self
.BuildType
:
3213 RuleObject
= BuildRuleDatabase
[Type
, self
.ModuleType
, self
.Arch
, self
.BuildRuleFamily
]
3214 #second try getting build rule by ToolChainFamily
3216 RuleObject
= BuildRuleDatabase
[Type
, self
.BuildType
, self
.Arch
, self
.ToolChainFamily
]
3218 # build type is always module type, but ...
3219 if self
.ModuleType
!= self
.BuildType
:
3220 RuleObject
= BuildRuleDatabase
[Type
, self
.ModuleType
, self
.Arch
, self
.ToolChainFamily
]
3223 RuleObject
= RuleObject
.Instantiate(self
.Macros
)
3224 BuildRules
[Type
] = RuleObject
3225 for Ext
in RuleObject
.SourceFileExtList
:
3226 BuildRules
[Ext
] = RuleObject
3227 self
._BuildRules
= BuildRules
3228 return self
._BuildRules
3230 def _ApplyBuildRule(self
, File
, FileType
):
3231 if self
._BuildTargets
is None:
3232 self
._IntroBuildTargetList
= set()
3233 self
._FinalBuildTargetList
= set()
3234 self
._BuildTargets
= defaultdict(set)
3235 self
._FileTypes
= defaultdict(set)
3237 SubDirectory
= os
.path
.join(self
.OutputDir
, File
.SubDir
)
3238 if not os
.path
.exists(SubDirectory
):
3239 CreateDirectory(SubDirectory
)
3245 # Make sure to get build rule order value
3247 self
._GetModuleBuildOption
()
3249 while Index
< len(SourceList
):
3250 Source
= SourceList
[Index
]
3254 CreateDirectory(Source
.Dir
)
3256 if File
.IsBinary
and File
== Source
and self
._BinaryFileList
is not None and File
in self
._BinaryFileList
:
3257 # Skip all files that are not binary libraries
3258 if not self
.IsLibrary
:
3260 RuleObject
= self
.BuildRules
[TAB_DEFAULT_BINARY_FILE
]
3261 elif FileType
in self
.BuildRules
:
3262 RuleObject
= self
.BuildRules
[FileType
]
3263 elif Source
.Ext
in self
.BuildRules
:
3264 RuleObject
= self
.BuildRules
[Source
.Ext
]
3266 # stop at no more rules
3268 self
._FinalBuildTargetList
.add(LastTarget
)
3271 FileType
= RuleObject
.SourceFileType
3272 self
._FileTypes
[FileType
].add(Source
)
3274 # stop at STATIC_LIBRARY for library
3275 if self
.IsLibrary
and FileType
== TAB_STATIC_LIBRARY
:
3277 self
._FinalBuildTargetList
.add(LastTarget
)
3280 Target
= RuleObject
.Apply(Source
, self
.BuildRuleOrder
)
3283 self
._FinalBuildTargetList
.add(LastTarget
)
3285 elif not Target
.Outputs
:
3286 # Only do build for target with outputs
3287 self
._FinalBuildTargetList
.add(Target
)
3289 self
._BuildTargets
[FileType
].add(Target
)
3291 if not Source
.IsBinary
and Source
== File
:
3292 self
._IntroBuildTargetList
.add(Target
)
3294 # to avoid cyclic rule
3295 if FileType
in RuleChain
:
3298 RuleChain
.add(FileType
)
3299 SourceList
.extend(Target
.Outputs
)
3301 FileType
= TAB_UNKNOWN_FILE
3303 def _GetTargets(self
):
3304 if self
._BuildTargets
is None:
3305 self
._IntroBuildTargetList
= set()
3306 self
._FinalBuildTargetList
= set()
3307 self
._BuildTargets
= defaultdict(set)
3308 self
._FileTypes
= defaultdict(set)
3310 #TRICK: call _GetSourceFileList to apply build rule for source files
3311 if self
.SourceFileList
:
3314 #TRICK: call _GetBinaryFileList to apply build rule for binary files
3315 if self
.BinaryFileList
:
3318 return self
._BuildTargets
3320 def _GetIntroTargetList(self
):
3322 return self
._IntroBuildTargetList
3324 def _GetFinalTargetList(self
):
3326 return self
._FinalBuildTargetList
3328 def _GetFileTypes(self
):
3330 return self
._FileTypes
3332 ## Get the list of package object the module depends on
3334 # @retval list The package object list
3336 def _GetDependentPackageList(self
):
3337 return self
.Module
.Packages
3339 ## Return the list of auto-generated code file
3341 # @retval list The list of auto-generated file
3343 def _GetAutoGenFileList(self
):
3344 UniStringAutoGenC
= True
3345 IdfStringAutoGenC
= True
3346 UniStringBinBuffer
= BytesIO()
3347 IdfGenBinBuffer
= BytesIO()
3348 if self
.BuildType
== 'UEFI_HII':
3349 UniStringAutoGenC
= False
3350 IdfStringAutoGenC
= False
3351 if self
._AutoGenFileList
is None:
3352 self
._AutoGenFileList
= {}
3353 AutoGenC
= TemplateString()
3354 AutoGenH
= TemplateString()
3355 StringH
= TemplateString()
3356 StringIdf
= TemplateString()
3357 GenC
.CreateCode(self
, AutoGenC
, AutoGenH
, StringH
, UniStringAutoGenC
, UniStringBinBuffer
, StringIdf
, IdfStringAutoGenC
, IdfGenBinBuffer
)
3359 # AutoGen.c is generated if there are library classes in inf, or there are object files
3361 if str(AutoGenC
) != "" and (len(self
.Module
.LibraryClasses
) > 0
3362 or TAB_OBJECT_FILE
in self
.FileTypes
):
3363 AutoFile
= PathClass(gAutoGenCodeFileName
, self
.DebugDir
)
3364 self
._AutoGenFileList
[AutoFile
] = str(AutoGenC
)
3365 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3366 if str(AutoGenH
) != "":
3367 AutoFile
= PathClass(gAutoGenHeaderFileName
, self
.DebugDir
)
3368 self
._AutoGenFileList
[AutoFile
] = str(AutoGenH
)
3369 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3370 if str(StringH
) != "":
3371 AutoFile
= PathClass(gAutoGenStringFileName
% {"module_name":self
.Name
}, self
.DebugDir
)
3372 self
._AutoGenFileList
[AutoFile
] = str(StringH
)
3373 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3374 if UniStringBinBuffer
is not None and UniStringBinBuffer
.getvalue() != "":
3375 AutoFile
= PathClass(gAutoGenStringFormFileName
% {"module_name":self
.Name
}, self
.OutputDir
)
3376 self
._AutoGenFileList
[AutoFile
] = UniStringBinBuffer
.getvalue()
3377 AutoFile
.IsBinary
= True
3378 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3379 if UniStringBinBuffer
is not None:
3380 UniStringBinBuffer
.close()
3381 if str(StringIdf
) != "":
3382 AutoFile
= PathClass(gAutoGenImageDefFileName
% {"module_name":self
.Name
}, self
.DebugDir
)
3383 self
._AutoGenFileList
[AutoFile
] = str(StringIdf
)
3384 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3385 if IdfGenBinBuffer
is not None and IdfGenBinBuffer
.getvalue() != "":
3386 AutoFile
= PathClass(gAutoGenIdfFileName
% {"module_name":self
.Name
}, self
.OutputDir
)
3387 self
._AutoGenFileList
[AutoFile
] = IdfGenBinBuffer
.getvalue()
3388 AutoFile
.IsBinary
= True
3389 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3390 if IdfGenBinBuffer
is not None:
3391 IdfGenBinBuffer
.close()
3392 return self
._AutoGenFileList
3394 ## Return the list of library modules explicitly or implicityly used by this module
3395 def _GetLibraryList(self
):
3396 if self
._DependentLibraryList
is None:
3397 # only merge library classes and PCD for non-library module
3399 self
._DependentLibraryList
= []
3401 if self
.AutoGenVersion
< 0x00010005:
3402 self
._DependentLibraryList
= self
.PlatformInfo
.ResolveLibraryReference(self
.Module
)
3404 self
._DependentLibraryList
= self
.PlatformInfo
.ApplyLibraryInstance(self
.Module
)
3405 return self
._DependentLibraryList
3407 ## Get the list of PCDs from current module
3409 # @retval list The list of PCD
3411 def _GetModulePcdList(self
):
3412 if self
._ModulePcdList
is None:
3413 # apply PCD settings from platform
3414 self
._ModulePcdList
= self
.PlatformInfo
.ApplyPcdSetting(self
.Module
, self
.Module
.Pcds
)
3415 ExtendCopyDictionaryLists(self
._PcdComments
, self
.Module
.PcdComments
)
3416 return self
._ModulePcdList
3418 ## Get the list of PCDs from dependent libraries
3420 # @retval list The list of PCD
3422 def _GetLibraryPcdList(self
):
3423 if self
._LibraryPcdList
is None:
3424 Pcds
= OrderedDict()
3425 if not self
.IsLibrary
:
3426 # get PCDs from dependent libraries
3427 self
._LibraryPcdList
= []
3428 for Library
in self
.DependentLibraryList
:
3429 PcdsInLibrary
= OrderedDict()
3430 ExtendCopyDictionaryLists(self
._PcdComments
, Library
.PcdComments
)
3431 for Key
in Library
.Pcds
:
3432 # skip duplicated PCDs
3433 if Key
in self
.Module
.Pcds
or Key
in Pcds
:
3435 Pcds
[Key
] = copy
.copy(Library
.Pcds
[Key
])
3436 PcdsInLibrary
[Key
] = Pcds
[Key
]
3437 self
._LibraryPcdList
.extend(self
.PlatformInfo
.ApplyPcdSetting(self
.Module
, PcdsInLibrary
, Library
=Library
))
3439 self
._LibraryPcdList
= []
3440 return self
._LibraryPcdList
3442 ## Get the GUID value mapping
3444 # @retval dict The mapping between GUID cname and its value
3446 def _GetGuidList(self
):
3447 if self
._GuidList
is None:
3448 self
._GuidList
= OrderedDict()
3449 self
._GuidList
.update(self
.Module
.Guids
)
3450 for Library
in self
.DependentLibraryList
:
3451 self
._GuidList
.update(Library
.Guids
)
3452 ExtendCopyDictionaryLists(self
._GuidComments
, Library
.GuidComments
)
3453 ExtendCopyDictionaryLists(self
._GuidComments
, self
.Module
.GuidComments
)
3454 return self
._GuidList
3456 def GetGuidsUsedByPcd(self
):
3457 if self
._GuidsUsedByPcd
is None:
3458 self
._GuidsUsedByPcd
= OrderedDict()
3459 self
._GuidsUsedByPcd
.update(self
.Module
.GetGuidsUsedByPcd())
3460 for Library
in self
.DependentLibraryList
:
3461 self
._GuidsUsedByPcd
.update(Library
.GetGuidsUsedByPcd())
3462 return self
._GuidsUsedByPcd
3463 ## Get the protocol value mapping
3465 # @retval dict The mapping between protocol cname and its value
3467 def _GetProtocolList(self
):
3468 if self
._ProtocolList
is None:
3469 self
._ProtocolList
= OrderedDict()
3470 self
._ProtocolList
.update(self
.Module
.Protocols
)
3471 for Library
in self
.DependentLibraryList
:
3472 self
._ProtocolList
.update(Library
.Protocols
)
3473 ExtendCopyDictionaryLists(self
._ProtocolComments
, Library
.ProtocolComments
)
3474 ExtendCopyDictionaryLists(self
._ProtocolComments
, self
.Module
.ProtocolComments
)
3475 return self
._ProtocolList
3477 ## Get the PPI value mapping
3479 # @retval dict The mapping between PPI cname and its value
3481 def _GetPpiList(self
):
3482 if self
._PpiList
is None:
3483 self
._PpiList
= OrderedDict()
3484 self
._PpiList
.update(self
.Module
.Ppis
)
3485 for Library
in self
.DependentLibraryList
:
3486 self
._PpiList
.update(Library
.Ppis
)
3487 ExtendCopyDictionaryLists(self
._PpiComments
, Library
.PpiComments
)
3488 ExtendCopyDictionaryLists(self
._PpiComments
, self
.Module
.PpiComments
)
3489 return self
._PpiList
3491 ## Get the list of include search path
3493 # @retval list The list path
3495 def _GetIncludePathList(self
):
3496 if self
._IncludePathList
is None:
3497 self
._IncludePathList
= []
3498 if self
.AutoGenVersion
< 0x00010005:
3499 for Inc
in self
.Module
.Includes
:
3500 if Inc
not in self
._IncludePathList
:
3501 self
._IncludePathList
.append(Inc
)
3503 Inc
= path
.join(Inc
, self
.Arch
.capitalize())
3504 if os
.path
.exists(Inc
) and Inc
not in self
._IncludePathList
:
3505 self
._IncludePathList
.append(Inc
)
3506 # Edk module needs to put DEBUG_DIR at the end of search path and not to use SOURCE_DIR all the time
3507 self
._IncludePathList
.append(self
.DebugDir
)
3509 self
._IncludePathList
.append(self
.MetaFile
.Dir
)
3510 self
._IncludePathList
.append(self
.DebugDir
)
3512 for Package
in self
.Module
.Packages
:
3513 PackageDir
= mws
.join(self
.WorkspaceDir
, Package
.MetaFile
.Dir
)
3514 if PackageDir
not in self
._IncludePathList
:
3515 self
._IncludePathList
.append(PackageDir
)
3516 IncludesList
= Package
.Includes
3517 if Package
._PrivateIncludes
:
3518 if not self
.MetaFile
.Path
.startswith(PackageDir
):
3519 IncludesList
= list(set(Package
.Includes
).difference(set(Package
._PrivateIncludes
)))
3520 for Inc
in IncludesList
:
3521 if Inc
not in self
._IncludePathList
:
3522 self
._IncludePathList
.append(str(Inc
))
3523 return self
._IncludePathList
3525 def _GetIncludePathLength(self
):
3526 return sum(len(inc
)+1 for inc
in self
._IncludePathList
)
3528 ## Get HII EX PCDs which maybe used by VFR
3530 # efivarstore used by VFR may relate with HII EX PCDs
3531 # Get the variable name and GUID from efivarstore and HII EX PCD
3532 # List the HII EX PCDs in As Built INF if both name and GUID match.
3534 # @retval list HII EX PCDs
3536 def _GetPcdsMaybeUsedByVfr(self
):
3537 if not self
.SourceFileList
:
3541 for SrcFile
in self
.SourceFileList
:
3542 if SrcFile
.Ext
.lower() != '.vfr':
3544 Vfri
= os
.path
.join(self
.OutputDir
, SrcFile
.BaseName
+ '.i')
3545 if not os
.path
.exists(Vfri
):
3547 VfriFile
= open(Vfri
, 'r')
3548 Content
= VfriFile
.read()
3550 Pos
= Content
.find('efivarstore')
3553 # Make sure 'efivarstore' is the start of efivarstore statement
3554 # In case of the value of 'name' (name = efivarstore) is equal to 'efivarstore'
3557 while Index
>= 0 and Content
[Index
] in ' \t\r\n':
3559 if Index
>= 0 and Content
[Index
] != ';':
3560 Pos
= Content
.find('efivarstore', Pos
+ len('efivarstore'))
3563 # 'efivarstore' must be followed by name and guid
3565 Name
= gEfiVarStoreNamePattern
.search(Content
, Pos
)
3568 Guid
= gEfiVarStoreGuidPattern
.search(Content
, Pos
)
3571 NameArray
= ConvertStringToByteArray('L"' + Name
.group(1) + '"')
3572 NameGuids
.add((NameArray
, GuidStructureStringToGuidString(Guid
.group(1))))
3573 Pos
= Content
.find('efivarstore', Name
.end())
3577 for Pcd
in self
.PlatformInfo
.Platform
.Pcds
.values():
3578 if Pcd
.Type
!= TAB_PCDS_DYNAMIC_EX_HII
:
3580 for SkuInfo
in Pcd
.SkuInfoList
.values():
3581 Value
= GuidValue(SkuInfo
.VariableGuid
, self
.PlatformInfo
.PackageList
, self
.MetaFile
.Path
)
3584 Name
= ConvertStringToByteArray(SkuInfo
.VariableName
)
3585 Guid
= GuidStructureStringToGuidString(Value
)
3586 if (Name
, Guid
) in NameGuids
and Pcd
not in HiiExPcds
:
3587 HiiExPcds
.append(Pcd
)
3592 def _GenOffsetBin(self
):
3594 for SourceFile
in self
.Module
.Sources
:
3595 if SourceFile
.Type
.upper() == ".VFR" :
3597 # search the .map file to find the offset of vfr binary in the PE32+/TE file.
3599 VfrUniBaseName
[SourceFile
.BaseName
] = (SourceFile
.BaseName
+ "Bin")
3600 elif SourceFile
.Type
.upper() == ".UNI" :
3602 # search the .map file to find the offset of Uni strings binary in the PE32+/TE file.
3604 VfrUniBaseName
["UniOffsetName"] = (self
.Name
+ "Strings")
3606 if not VfrUniBaseName
:
3608 MapFileName
= os
.path
.join(self
.OutputDir
, self
.Name
+ ".map")
3609 EfiFileName
= os
.path
.join(self
.OutputDir
, self
.Name
+ ".efi")
3610 VfrUniOffsetList
= GetVariableOffset(MapFileName
, EfiFileName
, VfrUniBaseName
.values())
3611 if not VfrUniOffsetList
:
3614 OutputName
= '%sOffset.bin' % self
.Name
3615 UniVfrOffsetFileName
= os
.path
.join( self
.OutputDir
, OutputName
)
3618 fInputfile
= open(UniVfrOffsetFileName
, "wb+", 0)
3620 EdkLogger
.error("build", FILE_OPEN_FAILURE
, "File open failed for %s" % UniVfrOffsetFileName
, None)
3622 # Use a instance of BytesIO to cache data
3623 fStringIO
= BytesIO('')
3625 for Item
in VfrUniOffsetList
:
3626 if (Item
[0].find("Strings") != -1):
3628 # UNI offset in image.
3630 # { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } }
3632 UniGuid
= [0xe0, 0xc5, 0x13, 0x89, 0xf6, 0x33, 0x86, 0x4d, 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66]
3633 UniGuid
= [chr(ItemGuid
) for ItemGuid
in UniGuid
]
3634 fStringIO
.write(''.join(UniGuid
))
3635 UniValue
= pack ('Q', int (Item
[1], 16))
3636 fStringIO
.write (UniValue
)
3639 # VFR binary offset in image.
3641 # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } };
3643 VfrGuid
= [0xb4, 0x7c, 0xbc, 0xd0, 0x47, 0x6a, 0x5f, 0x49, 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2]
3644 VfrGuid
= [chr(ItemGuid
) for ItemGuid
in VfrGuid
]
3645 fStringIO
.write(''.join(VfrGuid
))
3646 VfrValue
= pack ('Q', int (Item
[1], 16))
3647 fStringIO
.write (VfrValue
)
3649 # write data into file.
3652 fInputfile
.write (fStringIO
.getvalue())
3654 EdkLogger
.error("build", FILE_WRITE_FAILURE
, "Write data to file %s failed, please check whether the "
3655 "file been locked or using by other applications." %UniVfrOffsetFileName
, None)
3661 ## Create AsBuilt INF file the module
3663 def CreateAsBuiltInf(self
, IsOnlyCopy
= False):
3664 self
.OutputFile
= set()
3665 if IsOnlyCopy
and GlobalData
.gBinCacheDest
:
3666 self
.CopyModuleToCache()
3669 if self
.IsAsBuiltInfCreated
:
3672 # Skip the following code for EDK I inf
3673 if self
.AutoGenVersion
< 0x00010005:
3676 # Skip the following code for libraries
3680 # Skip the following code for modules with no source files
3681 if not self
.SourceFileList
:
3684 # Skip the following code for modules without any binary files
3685 if self
.BinaryFileList
:
3688 ### TODO: How to handles mixed source and binary modules
3690 # Find all DynamicEx and PatchableInModule PCDs used by this module and dependent libraries
3691 # Also find all packages that the DynamicEx PCDs depend on
3696 PcdTokenSpaceList
= []
3697 for Pcd
in self
.ModulePcdList
+ self
.LibraryPcdList
:
3698 if Pcd
.Type
== TAB_PCDS_PATCHABLE_IN_MODULE
:
3699 PatchablePcds
.append(Pcd
)
3700 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, TAB_PCDS_PATCHABLE_IN_MODULE
))
3701 elif Pcd
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
3704 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, TAB_PCDS_DYNAMIC_EX
))
3705 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, TAB_PCDS_DYNAMIC
))
3706 PcdTokenSpaceList
.append(Pcd
.TokenSpaceGuidCName
)
3707 GuidList
= OrderedDict()
3708 GuidList
.update(self
.GuidList
)
3709 for TokenSpace
in self
.GetGuidsUsedByPcd():
3710 # If token space is not referred by patch PCD or Ex PCD, remove the GUID from GUID list
3711 # The GUIDs in GUIDs section should really be the GUIDs in source INF or referred by Ex an patch PCDs
3712 if TokenSpace
not in PcdTokenSpaceList
and TokenSpace
in GuidList
:
3713 GuidList
.pop(TokenSpace
)
3714 CheckList
= (GuidList
, self
.PpiList
, self
.ProtocolList
, PcdCheckList
)
3715 for Package
in self
.DerivedPackageList
:
3716 if Package
in Packages
:
3718 BeChecked
= (Package
.Guids
, Package
.Ppis
, Package
.Protocols
, Package
.Pcds
)
3720 for Index
in range(len(BeChecked
)):
3721 for Item
in CheckList
[Index
]:
3722 if Item
in BeChecked
[Index
]:
3723 Packages
.append(Package
)
3729 VfrPcds
= self
._GetPcdsMaybeUsedByVfr
()
3730 for Pkg
in self
.PlatformInfo
.PackageList
:
3733 for VfrPcd
in VfrPcds
:
3734 if ((VfrPcd
.TokenCName
, VfrPcd
.TokenSpaceGuidCName
, TAB_PCDS_DYNAMIC_EX
) in Pkg
.Pcds
or
3735 (VfrPcd
.TokenCName
, VfrPcd
.TokenSpaceGuidCName
, TAB_PCDS_DYNAMIC
) in Pkg
.Pcds
):
3736 Packages
.append(Pkg
)
3739 ModuleType
= SUP_MODULE_DXE_DRIVER
if self
.ModuleType
== SUP_MODULE_UEFI_DRIVER
and self
.DepexGenerated
else self
.ModuleType
3740 DriverType
= self
.PcdIsDriver
if self
.PcdIsDriver
else ''
3742 MDefs
= self
.Module
.Defines
3745 'module_name' : self
.Name
,
3746 'module_guid' : Guid
,
3747 'module_module_type' : ModuleType
,
3748 'module_version_string' : [MDefs
['VERSION_STRING']] if 'VERSION_STRING' in MDefs
else [],
3749 'pcd_is_driver_string' : [],
3750 'module_uefi_specification_version' : [],
3751 'module_pi_specification_version' : [],
3752 'module_entry_point' : self
.Module
.ModuleEntryPointList
,
3753 'module_unload_image' : self
.Module
.ModuleUnloadImageList
,
3754 'module_constructor' : self
.Module
.ConstructorList
,
3755 'module_destructor' : self
.Module
.DestructorList
,
3756 'module_shadow' : [MDefs
['SHADOW']] if 'SHADOW' in MDefs
else [],
3757 'module_pci_vendor_id' : [MDefs
['PCI_VENDOR_ID']] if 'PCI_VENDOR_ID' in MDefs
else [],
3758 'module_pci_device_id' : [MDefs
['PCI_DEVICE_ID']] if 'PCI_DEVICE_ID' in MDefs
else [],
3759 'module_pci_class_code' : [MDefs
['PCI_CLASS_CODE']] if 'PCI_CLASS_CODE' in MDefs
else [],
3760 'module_pci_revision' : [MDefs
['PCI_REVISION']] if 'PCI_REVISION' in MDefs
else [],
3761 'module_build_number' : [MDefs
['BUILD_NUMBER']] if 'BUILD_NUMBER' in MDefs
else [],
3762 'module_spec' : [MDefs
['SPEC']] if 'SPEC' in MDefs
else [],
3763 'module_uefi_hii_resource_section' : [MDefs
['UEFI_HII_RESOURCE_SECTION']] if 'UEFI_HII_RESOURCE_SECTION' in MDefs
else [],
3764 'module_uni_file' : [MDefs
['MODULE_UNI_FILE']] if 'MODULE_UNI_FILE' in MDefs
else [],
3765 'module_arch' : self
.Arch
,
3766 'package_item' : [Package
.MetaFile
.File
.replace('\\', '/') for Package
in Packages
],
3768 'patchablepcd_item' : [],
3770 'protocol_item' : [],
3774 'libraryclasses_item' : []
3777 if 'MODULE_UNI_FILE' in MDefs
:
3778 UNIFile
= os
.path
.join(self
.MetaFile
.Dir
, MDefs
['MODULE_UNI_FILE'])
3779 if os
.path
.isfile(UNIFile
):
3780 shutil
.copy2(UNIFile
, self
.OutputDir
)
3782 if self
.AutoGenVersion
> int(gInfSpecVersion
, 0):
3783 AsBuiltInfDict
['module_inf_version'] = '0x%08x' % self
.AutoGenVersion
3785 AsBuiltInfDict
['module_inf_version'] = gInfSpecVersion
3788 AsBuiltInfDict
['pcd_is_driver_string'].append(DriverType
)
3790 if 'UEFI_SPECIFICATION_VERSION' in self
.Specification
:
3791 AsBuiltInfDict
['module_uefi_specification_version'].append(self
.Specification
['UEFI_SPECIFICATION_VERSION'])
3792 if 'PI_SPECIFICATION_VERSION' in self
.Specification
:
3793 AsBuiltInfDict
['module_pi_specification_version'].append(self
.Specification
['PI_SPECIFICATION_VERSION'])
3795 OutputDir
= self
.OutputDir
.replace('\\', '/').strip('/')
3796 DebugDir
= self
.DebugDir
.replace('\\', '/').strip('/')
3797 for Item
in self
.CodaTargetList
:
3798 File
= Item
.Target
.Path
.replace('\\', '/').strip('/').replace(DebugDir
, '').replace(OutputDir
, '').strip('/')
3799 self
.OutputFile
.add(File
)
3800 if os
.path
.isabs(File
):
3801 File
= File
.replace('\\', '/').strip('/').replace(OutputDir
, '').strip('/')
3802 if Item
.Target
.Ext
.lower() == '.aml':
3803 AsBuiltInfDict
['binary_item'].append('ASL|' + File
)
3804 elif Item
.Target
.Ext
.lower() == '.acpi':
3805 AsBuiltInfDict
['binary_item'].append('ACPI|' + File
)
3806 elif Item
.Target
.Ext
.lower() == '.efi':
3807 AsBuiltInfDict
['binary_item'].append('PE32|' + self
.Name
+ '.efi')
3809 AsBuiltInfDict
['binary_item'].append('BIN|' + File
)
3810 if self
.DepexGenerated
:
3811 self
.OutputFile
.add(self
.Name
+ '.depex')
3812 if self
.ModuleType
in [SUP_MODULE_PEIM
]:
3813 AsBuiltInfDict
['binary_item'].append('PEI_DEPEX|' + self
.Name
+ '.depex')
3814 elif self
.ModuleType
in [SUP_MODULE_DXE_DRIVER
, SUP_MODULE_DXE_RUNTIME_DRIVER
, SUP_MODULE_DXE_SAL_DRIVER
, SUP_MODULE_UEFI_DRIVER
]:
3815 AsBuiltInfDict
['binary_item'].append('DXE_DEPEX|' + self
.Name
+ '.depex')
3816 elif self
.ModuleType
in [SUP_MODULE_DXE_SMM_DRIVER
]:
3817 AsBuiltInfDict
['binary_item'].append('SMM_DEPEX|' + self
.Name
+ '.depex')
3819 Bin
= self
._GenOffsetBin
()
3821 AsBuiltInfDict
['binary_item'].append('BIN|%s' % Bin
)
3822 self
.OutputFile
.add(Bin
)
3824 for Root
, Dirs
, Files
in os
.walk(OutputDir
):
3826 if File
.lower().endswith('.pdb'):
3827 AsBuiltInfDict
['binary_item'].append('DISPOSABLE|' + File
)
3828 self
.OutputFile
.add(File
)
3829 HeaderComments
= self
.Module
.HeaderComments
3831 for Index
in range(len(HeaderComments
)):
3832 if HeaderComments
[Index
].find('@BinaryHeader') != -1:
3833 HeaderComments
[Index
] = HeaderComments
[Index
].replace('@BinaryHeader', '@file')
3836 AsBuiltInfDict
['header_comments'] = '\n'.join(HeaderComments
[StartPos
:]).replace(':#', '://')
3837 AsBuiltInfDict
['tail_comments'] = '\n'.join(self
.Module
.TailComments
)
3840 (self
.ProtocolList
, self
._ProtocolComments
, 'protocol_item'),
3841 (self
.PpiList
, self
._PpiComments
, 'ppi_item'),
3842 (GuidList
, self
._GuidComments
, 'guid_item')
3844 for Item
in GenList
:
3845 for CName
in Item
[0]:
3846 Comments
= '\n '.join(Item
[1][CName
]) if CName
in Item
[1] else ''
3847 Entry
= Comments
+ '\n ' + CName
if Comments
else CName
3848 AsBuiltInfDict
[Item
[2]].append(Entry
)
3849 PatchList
= parsePcdInfoFromMapFile(
3850 os
.path
.join(self
.OutputDir
, self
.Name
+ '.map'),
3851 os
.path
.join(self
.OutputDir
, self
.Name
+ '.efi')
3854 for Pcd
in PatchablePcds
:
3855 TokenCName
= Pcd
.TokenCName
3856 for PcdItem
in GlobalData
.MixedPcd
:
3857 if (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
3858 TokenCName
= PcdItem
[0]
3860 for PatchPcd
in PatchList
:
3861 if TokenCName
== PatchPcd
[0]:
3866 if Pcd
.DatumType
== 'BOOLEAN':
3867 BoolValue
= Pcd
.DefaultValue
.upper()
3868 if BoolValue
== 'TRUE':
3869 Pcd
.DefaultValue
= '1'
3870 elif BoolValue
== 'FALSE':
3871 Pcd
.DefaultValue
= '0'
3873 if Pcd
.DatumType
in TAB_PCD_NUMERIC_TYPES
:
3874 HexFormat
= '0x%02x'
3875 if Pcd
.DatumType
== TAB_UINT16
:
3876 HexFormat
= '0x%04x'
3877 elif Pcd
.DatumType
== TAB_UINT32
:
3878 HexFormat
= '0x%08x'
3879 elif Pcd
.DatumType
== TAB_UINT64
:
3880 HexFormat
= '0x%016x'
3881 PcdValue
= HexFormat
% int(Pcd
.DefaultValue
, 0)
3883 if Pcd
.MaxDatumSize
is None or Pcd
.MaxDatumSize
== '':
3884 EdkLogger
.error("build", AUTOGEN_ERROR
,
3885 "Unknown [MaxDatumSize] of PCD [%s.%s]" % (Pcd
.TokenSpaceGuidCName
, TokenCName
)
3887 ArraySize
= int(Pcd
.MaxDatumSize
, 0)
3888 PcdValue
= Pcd
.DefaultValue
3889 if PcdValue
[0] != '{':
3891 if PcdValue
[0] == 'L':
3893 PcdValue
= PcdValue
.lstrip('L')
3894 PcdValue
= eval(PcdValue
)
3896 for Index
in range(0, len(PcdValue
)):
3898 CharVal
= ord(PcdValue
[Index
])
3899 NewValue
= NewValue
+ '0x%02x' % (CharVal
& 0x00FF) + ', ' \
3900 + '0x%02x' % (CharVal
>> 8) + ', '
3902 NewValue
= NewValue
+ '0x%02x' % (ord(PcdValue
[Index
]) % 0x100) + ', '
3905 Padding
= Padding
* 2
3906 ArraySize
= ArraySize
/ 2
3907 if ArraySize
< (len(PcdValue
) + 1):
3908 if Pcd
.MaxSizeUserSet
:
3909 EdkLogger
.error("build", AUTOGEN_ERROR
,
3910 "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd
.TokenSpaceGuidCName
, TokenCName
)
3913 ArraySize
= len(PcdValue
) + 1
3914 if ArraySize
> len(PcdValue
) + 1:
3915 NewValue
= NewValue
+ Padding
* (ArraySize
- len(PcdValue
) - 1)
3916 PcdValue
= NewValue
+ Padding
.strip().rstrip(',') + '}'
3917 elif len(PcdValue
.split(',')) <= ArraySize
:
3918 PcdValue
= PcdValue
.rstrip('}') + ', 0x00' * (ArraySize
- len(PcdValue
.split(',')))
3921 if Pcd
.MaxSizeUserSet
:
3922 EdkLogger
.error("build", AUTOGEN_ERROR
,
3923 "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd
.TokenSpaceGuidCName
, TokenCName
)
3926 ArraySize
= len(PcdValue
) + 1
3927 PcdItem
= '%s.%s|%s|0x%X' % \
3928 (Pcd
.TokenSpaceGuidCName
, TokenCName
, PcdValue
, PatchPcd
[1])
3930 if (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) in self
._PcdComments
:
3931 PcdComments
= '\n '.join(self
._PcdComments
[Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
])
3933 PcdItem
= PcdComments
+ '\n ' + PcdItem
3934 AsBuiltInfDict
['patchablepcd_item'].append(PcdItem
)
3936 for Pcd
in Pcds
+ VfrPcds
:
3939 TokenCName
= Pcd
.TokenCName
3940 for PcdItem
in GlobalData
.MixedPcd
:
3941 if (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
3942 TokenCName
= PcdItem
[0]
3944 if Pcd
.Type
== TAB_PCDS_DYNAMIC_EX_HII
:
3945 for SkuName
in Pcd
.SkuInfoList
:
3946 SkuInfo
= Pcd
.SkuInfoList
[SkuName
]
3947 HiiInfo
= '## %s|%s|%s' % (SkuInfo
.VariableName
, SkuInfo
.VariableGuid
, SkuInfo
.VariableOffset
)
3949 if (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) in self
._PcdComments
:
3950 PcdCommentList
= self
._PcdComments
[Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
][:]
3954 for Index
, Comment
in enumerate(PcdCommentList
):
3955 for Usage
in UsageList
:
3956 if Comment
.find(Usage
) != -1:
3960 if UsageIndex
!= -1:
3961 PcdCommentList
[UsageIndex
] = '## %s %s %s' % (UsageStr
, HiiInfo
, PcdCommentList
[UsageIndex
].replace(UsageStr
, ''))
3963 PcdCommentList
.append('## UNDEFINED ' + HiiInfo
)
3964 PcdComments
= '\n '.join(PcdCommentList
)
3965 PcdEntry
= Pcd
.TokenSpaceGuidCName
+ '.' + TokenCName
3967 PcdEntry
= PcdComments
+ '\n ' + PcdEntry
3968 AsBuiltInfDict
['pcd_item'].append(PcdEntry
)
3969 for Item
in self
.BuildOption
:
3970 if 'FLAGS' in self
.BuildOption
[Item
]:
3971 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()))
3973 # Generated LibraryClasses section in comments.
3974 for Library
in self
.LibraryAutoGenList
:
3975 AsBuiltInfDict
['libraryclasses_item'].append(Library
.MetaFile
.File
.replace('\\', '/'))
3977 # Generated UserExtensions TianoCore section.
3978 # All tianocore user extensions are copied.
3980 for TianoCore
in self
._GetTianoCoreUserExtensionList
():
3981 UserExtStr
+= '\n'.join(TianoCore
)
3982 ExtensionFile
= os
.path
.join(self
.MetaFile
.Dir
, TianoCore
[1])
3983 if os
.path
.isfile(ExtensionFile
):
3984 shutil
.copy2(ExtensionFile
, self
.OutputDir
)
3985 AsBuiltInfDict
['userextension_tianocore_item'] = UserExtStr
3987 # Generated depex expression section in comments.
3988 DepexExpresion
= self
._GetDepexExpresionString
()
3989 AsBuiltInfDict
['depexsection_item'] = DepexExpresion
if DepexExpresion
else ''
3991 AsBuiltInf
= TemplateString()
3992 AsBuiltInf
.Append(gAsBuiltInfHeaderString
.Replace(AsBuiltInfDict
))
3994 SaveFileOnChange(os
.path
.join(self
.OutputDir
, self
.Name
+ '.inf'), str(AsBuiltInf
), False)
3996 self
.IsAsBuiltInfCreated
= True
3997 if GlobalData
.gBinCacheDest
:
3998 self
.CopyModuleToCache()
4000 def CopyModuleToCache(self
):
4001 FileDir
= path
.join(GlobalData
.gBinCacheDest
, self
.Arch
, self
.SourceDir
, self
.MetaFile
.BaseName
)
4002 CreateDirectory (FileDir
)
4003 HashFile
= path
.join(self
.BuildDir
, self
.Name
+ '.hash')
4004 ModuleFile
= path
.join(self
.OutputDir
, self
.Name
+ '.inf')
4005 if os
.path
.exists(HashFile
):
4006 shutil
.copy2(HashFile
, FileDir
)
4007 if os
.path
.exists(ModuleFile
):
4008 shutil
.copy2(ModuleFile
, FileDir
)
4009 if not self
.OutputFile
:
4010 Ma
= self
.Workspace
.BuildDatabase
[PathClass(ModuleFile
), self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
4011 self
.OutputFile
= Ma
.Binaries
4013 for File
in self
.OutputFile
:
4015 if not os
.path
.isabs(File
):
4016 File
= os
.path
.join(self
.OutputDir
, File
)
4017 if os
.path
.exists(File
):
4018 shutil
.copy2(File
, FileDir
)
4020 def AttemptModuleCacheCopy(self
):
4021 if self
.IsBinaryModule
:
4023 FileDir
= path
.join(GlobalData
.gBinCacheSource
, self
.Arch
, self
.SourceDir
, self
.MetaFile
.BaseName
)
4024 HashFile
= path
.join(FileDir
, self
.Name
+ '.hash')
4025 if os
.path
.exists(HashFile
):
4026 f
= open(HashFile
, 'r')
4027 CacheHash
= f
.read()
4029 if GlobalData
.gModuleHash
[self
.Arch
][self
.Name
]:
4030 if CacheHash
== GlobalData
.gModuleHash
[self
.Arch
][self
.Name
]:
4031 for root
, dir, files
in os
.walk(FileDir
):
4033 if self
.Name
+ '.hash' in f
:
4034 shutil
.copy2(HashFile
, self
.BuildDir
)
4036 File
= path
.join(root
, f
)
4037 shutil
.copy2(File
, self
.OutputDir
)
4038 if self
.Name
== "PcdPeim" or self
.Name
== "PcdDxe":
4039 CreatePcdDatabaseCode(self
, TemplateString(), TemplateString())
4043 ## Create makefile for the module and its dependent libraries
4045 # @param CreateLibraryMakeFile Flag indicating if or not the makefiles of
4046 # dependent libraries will be created
4048 def CreateMakeFile(self
, CreateLibraryMakeFile
=True, GenFfsList
= []):
4049 # Ignore generating makefile when it is a binary module
4050 if self
.IsBinaryModule
:
4053 if self
.IsMakeFileCreated
:
4055 self
.GenFfsList
= GenFfsList
4056 if not self
.IsLibrary
and CreateLibraryMakeFile
:
4057 for LibraryAutoGen
in self
.LibraryAutoGenList
:
4058 LibraryAutoGen
.CreateMakeFile()
4063 if len(self
.CustomMakefile
) == 0:
4064 Makefile
= GenMake
.ModuleMakefile(self
)
4066 Makefile
= GenMake
.CustomMakefile(self
)
4067 if Makefile
.Generate():
4068 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated makefile for module %s [%s]" %
4069 (self
.Name
, self
.Arch
))
4071 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Skipped the generation of makefile for module %s [%s]" %
4072 (self
.Name
, self
.Arch
))
4074 self
.CreateTimeStamp(Makefile
)
4075 self
.IsMakeFileCreated
= True
4077 def CopyBinaryFiles(self
):
4078 for File
in self
.Module
.Binaries
:
4080 DstPath
= os
.path
.join(self
.OutputDir
, os
.path
.basename(SrcPath
))
4081 CopyLongFilePath(SrcPath
, DstPath
)
4082 ## Create autogen code for the module and its dependent libraries
4084 # @param CreateLibraryCodeFile Flag indicating if or not the code of
4085 # dependent libraries will be created
4087 def CreateCodeFile(self
, CreateLibraryCodeFile
=True):
4088 if self
.IsCodeFileCreated
:
4091 # Need to generate PcdDatabase even PcdDriver is binarymodule
4092 if self
.IsBinaryModule
and self
.PcdIsDriver
!= '':
4093 CreatePcdDatabaseCode(self
, TemplateString(), TemplateString())
4095 if self
.IsBinaryModule
:
4097 self
.CopyBinaryFiles()
4100 if not self
.IsLibrary
and CreateLibraryCodeFile
:
4101 for LibraryAutoGen
in self
.LibraryAutoGenList
:
4102 LibraryAutoGen
.CreateCodeFile()
4108 IgoredAutoGenList
= []
4110 for File
in self
.AutoGenFileList
:
4111 if GenC
.Generate(File
.Path
, self
.AutoGenFileList
[File
], File
.IsBinary
):
4112 #Ignore Edk AutoGen.c
4113 if self
.AutoGenVersion
< 0x00010005 and File
.Name
== 'AutoGen.c':
4116 AutoGenList
.append(str(File
))
4118 IgoredAutoGenList
.append(str(File
))
4120 # Skip the following code for EDK I inf
4121 if self
.AutoGenVersion
< 0x00010005:
4124 for ModuleType
in self
.DepexList
:
4125 # Ignore empty [depex] section or [depex] section for SUP_MODULE_USER_DEFINED module
4126 if len(self
.DepexList
[ModuleType
]) == 0 or ModuleType
== SUP_MODULE_USER_DEFINED
:
4129 Dpx
= GenDepex
.DependencyExpression(self
.DepexList
[ModuleType
], ModuleType
, True)
4130 DpxFile
= gAutoGenDepexFileName
% {"module_name" : self
.Name
}
4132 if len(Dpx
.PostfixNotation
) != 0:
4133 self
.DepexGenerated
= True
4135 if Dpx
.Generate(path
.join(self
.OutputDir
, DpxFile
)):
4136 AutoGenList
.append(str(DpxFile
))
4138 IgoredAutoGenList
.append(str(DpxFile
))
4140 if IgoredAutoGenList
== []:
4141 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated [%s] files for module %s [%s]" %
4142 (" ".join(AutoGenList
), self
.Name
, self
.Arch
))
4143 elif AutoGenList
== []:
4144 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Skipped the generation of [%s] files for module %s [%s]" %
4145 (" ".join(IgoredAutoGenList
), self
.Name
, self
.Arch
))
4147 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated [%s] (skipped %s) files for module %s [%s]" %
4148 (" ".join(AutoGenList
), " ".join(IgoredAutoGenList
), self
.Name
, self
.Arch
))
4150 self
.IsCodeFileCreated
= True
4153 ## Summarize the ModuleAutoGen objects of all libraries used by this module
4154 def _GetLibraryAutoGenList(self
):
4155 if self
._LibraryAutoGenList
is None:
4156 self
._LibraryAutoGenList
= []
4157 for Library
in self
.DependentLibraryList
:
4164 self
.PlatformInfo
.MetaFile
4166 if La
not in self
._LibraryAutoGenList
:
4167 self
._LibraryAutoGenList
.append(La
)
4168 for Lib
in La
.CodaTargetList
:
4169 self
._ApplyBuildRule
(Lib
.Target
, TAB_UNKNOWN_FILE
)
4170 return self
._LibraryAutoGenList
4172 def GenModuleHash(self
):
4173 if self
.Arch
not in GlobalData
.gModuleHash
:
4174 GlobalData
.gModuleHash
[self
.Arch
] = {}
4176 # Add Platform level hash
4177 m
.update(GlobalData
.gPlatformHash
)
4178 # Add Package level hash
4179 if self
.DependentPackageList
:
4180 for Pkg
in sorted(self
.DependentPackageList
, key
=lambda x
: x
.PackageName
):
4181 if Pkg
.PackageName
in GlobalData
.gPackageHash
[self
.Arch
]:
4182 m
.update(GlobalData
.gPackageHash
[self
.Arch
][Pkg
.PackageName
])
4185 if self
.LibraryAutoGenList
:
4186 for Lib
in sorted(self
.LibraryAutoGenList
, key
=lambda x
: x
.Name
):
4187 if Lib
.Name
not in GlobalData
.gModuleHash
[self
.Arch
]:
4189 m
.update(GlobalData
.gModuleHash
[self
.Arch
][Lib
.Name
])
4192 f
= open(str(self
.MetaFile
), 'r')
4196 # Add Module's source files
4197 if self
.SourceFileList
:
4198 for File
in sorted(self
.SourceFileList
, key
=lambda x
: str(x
)):
4199 f
= open(str(File
), 'r')
4204 ModuleHashFile
= path
.join(self
.BuildDir
, self
.Name
+ ".hash")
4205 if self
.Name
not in GlobalData
.gModuleHash
[self
.Arch
]:
4206 GlobalData
.gModuleHash
[self
.Arch
][self
.Name
] = m
.hexdigest()
4207 if GlobalData
.gBinCacheSource
:
4208 if self
.AttemptModuleCacheCopy():
4210 return SaveFileOnChange(ModuleHashFile
, m
.hexdigest(), True)
4212 ## Decide whether we can skip the ModuleAutoGen process
4213 def CanSkipbyHash(self
):
4214 if GlobalData
.gUseHashCache
:
4215 return not self
.GenModuleHash()
4218 ## Decide whether we can skip the ModuleAutoGen process
4219 # If any source file is newer than the module than we cannot skip
4222 if self
.MakeFileDir
in GlobalData
.gSikpAutoGenCache
:
4224 if not os
.path
.exists(self
.GetTimeStampPath()):
4226 #last creation time of the module
4227 DstTimeStamp
= os
.stat(self
.GetTimeStampPath())[8]
4229 SrcTimeStamp
= self
.Workspace
._SrcTimeStamp
4230 if SrcTimeStamp
> DstTimeStamp
:
4233 with
open(self
.GetTimeStampPath(), 'r') as f
:
4235 source
= source
.rstrip('\n')
4236 if not os
.path
.exists(source
):
4238 if source
not in ModuleAutoGen
.TimeDict
:
4239 ModuleAutoGen
.TimeDict
[source
] = os
.stat(source
)[8]
4240 if ModuleAutoGen
.TimeDict
[source
] > DstTimeStamp
:
4242 GlobalData
.gSikpAutoGenCache
.add(self
.MakeFileDir
)
4245 def GetTimeStampPath(self
):
4246 if self
._TimeStampPath
is None:
4247 self
._TimeStampPath
= os
.path
.join(self
.MakeFileDir
, 'AutoGenTimeStamp')
4248 return self
._TimeStampPath
4249 def CreateTimeStamp(self
, Makefile
):
4251 FileSet
= {self
.MetaFile
.Path
}
4253 for SourceFile
in self
.Module
.Sources
:
4254 FileSet
.add (SourceFile
.Path
)
4256 for Lib
in self
.DependentLibraryList
:
4257 FileSet
.add (Lib
.MetaFile
.Path
)
4259 for f
in self
.AutoGenDepSet
:
4260 FileSet
.add (f
.Path
)
4262 if os
.path
.exists (self
.GetTimeStampPath()):
4263 os
.remove (self
.GetTimeStampPath())
4264 with
open(self
.GetTimeStampPath(), 'w+') as file:
4268 Module
= property(_GetModule
)
4269 Name
= property(_GetBaseName
)
4270 Guid
= property(_GetGuid
)
4271 Version
= property(_GetVersion
)
4272 ModuleType
= property(_GetModuleType
)
4273 ComponentType
= property(_GetComponentType
)
4274 BuildType
= property(_GetBuildType
)
4275 PcdIsDriver
= property(_GetPcdIsDriver
)
4276 AutoGenVersion
= property(_GetAutoGenVersion
)
4277 Macros
= property(_GetMacros
)
4278 Specification
= property(_GetSpecification
)
4280 IsLibrary
= property(_IsLibrary
)
4281 IsBinaryModule
= property(_IsBinaryModule
)
4282 BuildDir
= property(_GetBuildDir
)
4283 OutputDir
= property(_GetOutputDir
)
4284 FfsOutputDir
= property(_GetFfsOutputDir
)
4285 DebugDir
= property(_GetDebugDir
)
4286 MakeFileDir
= property(_GetMakeFileDir
)
4287 CustomMakefile
= property(_GetCustomMakefile
)
4289 IncludePathList
= property(_GetIncludePathList
)
4290 IncludePathLength
= property(_GetIncludePathLength
)
4291 AutoGenFileList
= property(_GetAutoGenFileList
)
4292 UnicodeFileList
= property(_GetUnicodeFileList
)
4293 VfrFileList
= property(_GetVfrFileList
)
4294 SourceFileList
= property(_GetSourceFileList
)
4295 BinaryFileList
= property(_GetBinaryFiles
) # FileType : [File List]
4296 Targets
= property(_GetTargets
)
4297 IntroTargetList
= property(_GetIntroTargetList
)
4298 CodaTargetList
= property(_GetFinalTargetList
)
4299 FileTypes
= property(_GetFileTypes
)
4300 BuildRules
= property(_GetBuildRules
)
4301 IdfFileList
= property(_GetIdfFileList
)
4303 DependentPackageList
= property(_GetDependentPackageList
)
4304 DependentLibraryList
= property(_GetLibraryList
)
4305 LibraryAutoGenList
= property(_GetLibraryAutoGenList
)
4306 DerivedPackageList
= property(_GetDerivedPackageList
)
4308 ModulePcdList
= property(_GetModulePcdList
)
4309 LibraryPcdList
= property(_GetLibraryPcdList
)
4310 GuidList
= property(_GetGuidList
)
4311 ProtocolList
= property(_GetProtocolList
)
4312 PpiList
= property(_GetPpiList
)
4313 DepexList
= property(_GetDepexTokenList
)
4314 DxsFile
= property(_GetDxsFile
)
4315 DepexExpressionDict
= property(_GetDepexExpressionTokenList
)
4316 BuildOption
= property(_GetModuleBuildOption
)
4317 BuildOptionIncPathList
= property(_GetBuildOptionIncPathList
)
4318 BuildCommand
= property(_GetBuildCommand
)
4320 FixedAtBuildPcds
= property(_GetFixedAtBuildPcds
)
4321 UniqueBaseName
= property(_GetUniqueBaseName
)
4322 FixedVoidTypePcds
= property(_GetFixedAtBuildVoidTypePcds
)
4324 # This acts like the main() function for the script, unless it is 'import'ed into another script.
4325 if __name__
== '__main__':