2 # Generate AutoGen.h, AutoGen.c and *.depex files
4 # Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.<BR>
5 # Copyright (c) 2018, Hewlett Packard Enterprise Development, L.P.<BR>
6 # Copyright (c) 2019, American Megatrends, Inc. All rights reserved.<BR>
8 # SPDX-License-Identifier: BSD-2-Clause-Patent
13 from __future__
import print_function
14 from __future__
import absolute_import
15 import Common
.LongFilePathOs
as os
17 import os
.path
as path
23 from . import GenDepex
24 from io
import BytesIO
26 from .StrGather
import *
27 from .BuildEngine
import BuildRule
29 from Common
.LongFilePathSupport
import CopyLongFilePath
30 from Common
.BuildToolError
import *
31 from Common
.DataType
import *
32 from Common
.Misc
import *
33 from Common
.StringUtils
import *
34 import Common
.GlobalData
as GlobalData
35 from GenFds
.FdfParser
import *
36 from CommonDataClass
.CommonClass
import SkuInfoClass
37 from GenPatchPcdTable
.GenPatchPcdTable
import parsePcdInfoFromMapFile
38 import Common
.VpdInfoFile
as VpdInfoFile
39 from .GenPcdDb
import CreatePcdDatabaseCode
40 from Workspace
.MetaFileCommentParser
import UsageList
41 from Workspace
.WorkspaceCommon
import GetModuleLibInstances
42 from Common
.MultipleWorkspace
import MultipleWorkspace
as mws
43 from . import InfSectionParser
46 from .GenVar
import VariableMgr
, var_info
47 from collections
import OrderedDict
48 from collections
import defaultdict
49 from Workspace
.WorkspaceCommon
import OrderedListDict
50 from Common
.ToolDefClassObject
import gDefaultToolsDefFile
52 from Common
.caching
import cached_property
, cached_class_function
54 ## Regular expression for splitting Dependency Expression string into tokens
55 gDepexTokenPattern
= re
.compile("(\(|\)|\w+| \S+\.inf)")
57 ## Regular expression for match: PCD(xxxx.yyy)
58 gPCDAsGuidPattern
= re
.compile(r
"^PCD\(.+\..+\)$")
61 # Regular expression for finding Include Directories, the difference between MSFT and INTEL/GCC/RVCT
62 # is the former use /I , the Latter used -I to specify include directories
64 gBuildOptIncludePatternMsft
= re
.compile(r
"(?:.*?)/I[ \t]*([^ ]*)", re
.MULTILINE | re
.DOTALL
)
65 gBuildOptIncludePatternOther
= re
.compile(r
"(?:.*?)-I[ \t]*([^ ]*)", re
.MULTILINE | re
.DOTALL
)
68 # Match name = variable
70 gEfiVarStoreNamePattern
= re
.compile("\s*name\s*=\s*(\w+)")
72 # The format of guid in efivarstore statement likes following and must be correct:
73 # guid = {0xA04A27f4, 0xDF00, 0x4D42, {0xB5, 0x52, 0x39, 0x51, 0x13, 0x02, 0x11, 0x3D}}
75 gEfiVarStoreGuidPattern
= re
.compile("\s*guid\s*=\s*({.*?{.*?}\s*})")
77 ## Mapping Makefile type
78 gMakeTypeMap
= {TAB_COMPILER_MSFT
:"nmake", "GCC":"gmake"}
81 ## Build rule configuration file
82 gDefaultBuildRuleFile
= 'build_rule.txt'
84 ## Build rule default version
85 AutoGenReqBuildRuleVerNum
= "0.1"
87 ## default file name for AutoGen
88 gAutoGenCodeFileName
= "AutoGen.c"
89 gAutoGenHeaderFileName
= "AutoGen.h"
90 gAutoGenStringFileName
= "%(module_name)sStrDefs.h"
91 gAutoGenStringFormFileName
= "%(module_name)sStrDefs.hpk"
92 gAutoGenDepexFileName
= "%(module_name)s.depex"
93 gAutoGenImageDefFileName
= "%(module_name)sImgDefs.h"
94 gAutoGenIdfFileName
= "%(module_name)sIdf.hpk"
95 gInfSpecVersion
= "0x00010017"
98 # Template string to generic AsBuilt INF
100 gAsBuiltInfHeaderString
= TemplateString("""${header_comments}
103 # FILE auto-generated
106 INF_VERSION = ${module_inf_version}
107 BASE_NAME = ${module_name}
108 FILE_GUID = ${module_guid}
109 MODULE_TYPE = ${module_module_type}${BEGIN}
110 VERSION_STRING = ${module_version_string}${END}${BEGIN}
111 PCD_IS_DRIVER = ${pcd_is_driver_string}${END}${BEGIN}
112 UEFI_SPECIFICATION_VERSION = ${module_uefi_specification_version}${END}${BEGIN}
113 PI_SPECIFICATION_VERSION = ${module_pi_specification_version}${END}${BEGIN}
114 ENTRY_POINT = ${module_entry_point}${END}${BEGIN}
115 UNLOAD_IMAGE = ${module_unload_image}${END}${BEGIN}
116 CONSTRUCTOR = ${module_constructor}${END}${BEGIN}
117 DESTRUCTOR = ${module_destructor}${END}${BEGIN}
118 SHADOW = ${module_shadow}${END}${BEGIN}
119 PCI_VENDOR_ID = ${module_pci_vendor_id}${END}${BEGIN}
120 PCI_DEVICE_ID = ${module_pci_device_id}${END}${BEGIN}
121 PCI_CLASS_CODE = ${module_pci_class_code}${END}${BEGIN}
122 PCI_REVISION = ${module_pci_revision}${END}${BEGIN}
123 BUILD_NUMBER = ${module_build_number}${END}${BEGIN}
124 SPEC = ${module_spec}${END}${BEGIN}
125 UEFI_HII_RESOURCE_SECTION = ${module_uefi_hii_resource_section}${END}${BEGIN}
126 MODULE_UNI_FILE = ${module_uni_file}${END}
128 [Packages.${module_arch}]${BEGIN}
129 ${package_item}${END}
131 [Binaries.${module_arch}]${BEGIN}
134 [PatchPcd.${module_arch}]${BEGIN}
138 [Protocols.${module_arch}]${BEGIN}
142 [Ppis.${module_arch}]${BEGIN}
146 [Guids.${module_arch}]${BEGIN}
150 [PcdEx.${module_arch}]${BEGIN}
154 [LibraryClasses.${module_arch}]
155 ## @LIB_INSTANCES${BEGIN}
156 # ${libraryclasses_item}${END}
160 ${userextension_tianocore_item}
164 [BuildOptions.${module_arch}]
166 ## ${flags_item}${END}
168 ## Split command line option string to list
170 # subprocess.Popen needs the args to be a sequence. Otherwise there's problem
171 # in non-windows platform to launch command
173 def _SplitOption(OptionString
):
178 for Index
in range(0, len(OptionString
)):
179 CurrentChar
= OptionString
[Index
]
180 if CurrentChar
in ['"', "'"]:
181 if QuotationMark
== CurrentChar
:
183 elif QuotationMark
== "":
184 QuotationMark
= CurrentChar
189 if CurrentChar
in ["/", "-"] and LastChar
in [" ", "\t", "\r", "\n"]:
190 if Index
> OptionStart
:
191 OptionList
.append(OptionString
[OptionStart
:Index
- 1])
193 LastChar
= CurrentChar
194 OptionList
.append(OptionString
[OptionStart
:])
198 # Convert string to C format array
200 def _ConvertStringToByteArray(Value
):
201 Value
= Value
.strip()
205 if not Value
.endswith('}'):
207 Value
= Value
.replace(' ', '').replace('{', '').replace('}', '')
208 ValFields
= Value
.split(',')
210 for Index
in range(len(ValFields
)):
211 ValFields
[Index
] = str(int(ValFields
[Index
], 0))
214 Value
= '{' + ','.join(ValFields
) + '}'
218 if Value
.startswith('L"'):
219 if not Value
.endswith('"'):
223 elif not Value
.startswith('"') or not Value
.endswith('"'):
226 Value
= eval(Value
) # translate escape character
228 for Index
in range(0, len(Value
)):
230 NewValue
= NewValue
+ str(ord(Value
[Index
]) % 0x10000) + ','
232 NewValue
= NewValue
+ str(ord(Value
[Index
]) % 0x100) + ','
233 Value
= NewValue
+ '0}'
236 ## Base class for AutoGen
238 # This class just implements the cache mechanism of AutoGen objects.
240 class AutoGen(object):
241 # database to maintain the objects in each child class
242 __ObjectCache
= {} # (BuildTarget, ToolChain, ARCH, platform file): AutoGen object
246 # @param Class class object of real AutoGen class
247 # (WorkspaceAutoGen, ModuleAutoGen or PlatformAutoGen)
248 # @param Workspace Workspace directory or WorkspaceAutoGen object
249 # @param MetaFile The path of meta file
250 # @param Target Build target
251 # @param Toolchain Tool chain name
252 # @param Arch Target arch
253 # @param *args The specific class related parameters
254 # @param **kwargs The specific class related dict parameters
256 def __new__(cls
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
257 # check if the object has been created
258 Key
= (Target
, Toolchain
, Arch
, MetaFile
)
259 if Key
in cls
.__ObjectCache
:
260 # if it exists, just return it directly
261 return cls
.__ObjectCache
[Key
]
262 # it didnt exist. create it, cache it, then return it
263 RetVal
= cls
.__ObjectCache
[Key
] = super(AutoGen
, cls
).__new
__(cls
)
269 # The file path of platform file will be used to represent hash value of this object
271 # @retval int Hash value of the file path of platform file
274 return hash(self
.MetaFile
)
278 # The file path of platform file will be used to represent this object
280 # @retval string String of platform file path
283 return str(self
.MetaFile
)
286 def __eq__(self
, Other
):
287 return Other
and self
.MetaFile
== Other
289 ## Workspace AutoGen class
291 # This class is used mainly to control the whole platform build for different
292 # architecture. This class will generate top level makefile.
294 class WorkspaceAutoGen(AutoGen
):
295 # call super().__init__ then call the worker function with different parameter count
296 def __init__(self
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
297 if not hasattr(self
, "_Init"):
298 self
._InitWorker
(Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
)
301 ## Initialize WorkspaceAutoGen
303 # @param WorkspaceDir Root directory of workspace
304 # @param ActivePlatform Meta-file of active platform
305 # @param Target Build target
306 # @param Toolchain Tool chain name
307 # @param ArchList List of architecture of current build
308 # @param MetaFileDb Database containing meta-files
309 # @param BuildConfig Configuration of build
310 # @param ToolDefinition Tool chain definitions
311 # @param FlashDefinitionFile File of flash definition
312 # @param Fds FD list to be generated
313 # @param Fvs FV list to be generated
314 # @param Caps Capsule list to be generated
315 # @param SkuId SKU id from command line
317 def _InitWorker(self
, WorkspaceDir
, ActivePlatform
, Target
, Toolchain
, ArchList
, MetaFileDb
,
318 BuildConfig
, ToolDefinition
, FlashDefinitionFile
='', Fds
=None, Fvs
=None, Caps
=None, SkuId
='', UniFlag
=None,
319 Progress
=None, BuildModule
=None):
320 self
.BuildDatabase
= MetaFileDb
321 self
.MetaFile
= ActivePlatform
322 self
.WorkspaceDir
= WorkspaceDir
323 self
.Platform
= self
.BuildDatabase
[self
.MetaFile
, TAB_ARCH_COMMON
, Target
, Toolchain
]
324 GlobalData
.gActivePlatform
= self
.Platform
325 self
.BuildTarget
= Target
326 self
.ToolChain
= Toolchain
327 self
.ArchList
= ArchList
329 self
.UniFlag
= UniFlag
331 self
.TargetTxt
= BuildConfig
332 self
.ToolDef
= ToolDefinition
333 self
.FdfFile
= FlashDefinitionFile
334 self
.FdTargetList
= Fds
if Fds
else []
335 self
.FvTargetList
= Fvs
if Fvs
else []
336 self
.CapTargetList
= Caps
if Caps
else []
337 self
.AutoGenObjectList
= []
340 # there's many relative directory operations, so ...
341 os
.chdir(self
.WorkspaceDir
)
346 if not self
.ArchList
:
347 ArchList
= set(self
.Platform
.SupArchList
)
349 ArchList
= set(self
.ArchList
) & set(self
.Platform
.SupArchList
)
351 EdkLogger
.error("build", PARAMETER_INVALID
,
352 ExtraData
= "Invalid ARCH specified. [Valid ARCH: %s]" % (" ".join(self
.Platform
.SupArchList
)))
353 elif self
.ArchList
and len(ArchList
) != len(self
.ArchList
):
354 SkippedArchList
= set(self
.ArchList
).symmetric_difference(set(self
.Platform
.SupArchList
))
355 EdkLogger
.verbose("\nArch [%s] is ignored because the platform supports [%s] only!"
356 % (" ".join(SkippedArchList
), " ".join(self
.Platform
.SupArchList
)))
357 self
.ArchList
= tuple(ArchList
)
359 # Validate build target
360 if self
.BuildTarget
not in self
.Platform
.BuildTargets
:
361 EdkLogger
.error("build", PARAMETER_INVALID
,
362 ExtraData
="Build target [%s] is not supported by the platform. [Valid target: %s]"
363 % (self
.BuildTarget
, " ".join(self
.Platform
.BuildTargets
)))
366 # parse FDF file to get PCDs in it, if any
368 self
.FdfFile
= self
.Platform
.FlashDefinition
372 EdkLogger
.info('%-16s = %s' % ("Architecture(s)", ' '.join(self
.ArchList
)))
373 EdkLogger
.info('%-16s = %s' % ("Build target", self
.BuildTarget
))
374 EdkLogger
.info('%-16s = %s' % ("Toolchain", self
.ToolChain
))
376 EdkLogger
.info('\n%-24s = %s' % ("Active Platform", self
.Platform
))
378 EdkLogger
.info('%-24s = %s' % ("Active Module", BuildModule
))
381 EdkLogger
.info('%-24s = %s' % ("Flash Image Definition", self
.FdfFile
))
383 EdkLogger
.verbose("\nFLASH_DEFINITION = %s" % self
.FdfFile
)
386 Progress
.Start("\nProcessing meta-data")
390 # Mark now build in AutoGen Phase
392 GlobalData
.gAutoGenPhase
= True
393 Fdf
= FdfParser(self
.FdfFile
.Path
)
395 GlobalData
.gFdfParser
= Fdf
396 GlobalData
.gAutoGenPhase
= False
397 PcdSet
= Fdf
.Profile
.PcdDict
398 if Fdf
.CurrentFdName
and Fdf
.CurrentFdName
in Fdf
.Profile
.FdDict
:
399 FdDict
= Fdf
.Profile
.FdDict
[Fdf
.CurrentFdName
]
400 for FdRegion
in FdDict
.RegionList
:
401 if str(FdRegion
.RegionType
) is 'FILE' and self
.Platform
.VpdToolGuid
in str(FdRegion
.RegionDataList
):
402 if int(FdRegion
.Offset
) % 8 != 0:
403 EdkLogger
.error("build", FORMAT_INVALID
, 'The VPD Base Address %s must be 8-byte aligned.' % (FdRegion
.Offset
))
404 ModuleList
= Fdf
.Profile
.InfList
405 self
.FdfProfile
= Fdf
.Profile
406 for fvname
in self
.FvTargetList
:
407 if fvname
.upper() not in self
.FdfProfile
.FvDict
:
408 EdkLogger
.error("build", OPTION_VALUE_INVALID
,
409 "No such an FV in FDF file: %s" % fvname
)
411 # In DSC file may use FILE_GUID to override the module, then in the Platform.Modules use FILE_GUIDmodule.inf as key,
412 # but the path (self.MetaFile.Path) is the real path
413 for key
in self
.FdfProfile
.InfDict
:
415 MetaFile_cache
= defaultdict(set)
416 for Arch
in self
.ArchList
:
417 Current_Platform_cache
= self
.BuildDatabase
[self
.MetaFile
, Arch
, Target
, Toolchain
]
418 for Pkey
in Current_Platform_cache
.Modules
:
419 MetaFile_cache
[Arch
].add(Current_Platform_cache
.Modules
[Pkey
].MetaFile
)
420 for Inf
in self
.FdfProfile
.InfDict
[key
]:
421 ModuleFile
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, Arch
)
422 for Arch
in self
.ArchList
:
423 if ModuleFile
in MetaFile_cache
[Arch
]:
426 ModuleData
= self
.BuildDatabase
[ModuleFile
, Arch
, Target
, Toolchain
]
427 if not ModuleData
.IsBinaryModule
:
428 EdkLogger
.error('build', PARSER_ERROR
, "Module %s NOT found in DSC file; Is it really a binary module?" % ModuleFile
)
431 for Arch
in self
.ArchList
:
433 Platform
= self
.BuildDatabase
[self
.MetaFile
, Arch
, Target
, Toolchain
]
435 for Pkey
in Platform
.Modules
:
436 MetaFileList
.add(Platform
.Modules
[Pkey
].MetaFile
)
437 for Inf
in self
.FdfProfile
.InfDict
[key
]:
438 ModuleFile
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, Arch
)
439 if ModuleFile
in MetaFileList
:
441 ModuleData
= self
.BuildDatabase
[ModuleFile
, Arch
, Target
, Toolchain
]
442 if not ModuleData
.IsBinaryModule
:
443 EdkLogger
.error('build', PARSER_ERROR
, "Module %s NOT found in DSC file; Is it really a binary module?" % ModuleFile
)
448 self
.FdfProfile
= None
449 if self
.FdTargetList
:
450 EdkLogger
.info("No flash definition file found. FD [%s] will be ignored." % " ".join(self
.FdTargetList
))
451 self
.FdTargetList
= []
452 if self
.FvTargetList
:
453 EdkLogger
.info("No flash definition file found. FV [%s] will be ignored." % " ".join(self
.FvTargetList
))
454 self
.FvTargetList
= []
455 if self
.CapTargetList
:
456 EdkLogger
.info("No flash definition file found. Capsule [%s] will be ignored." % " ".join(self
.CapTargetList
))
457 self
.CapTargetList
= []
459 # apply SKU and inject PCDs from Flash Definition file
460 for Arch
in self
.ArchList
:
461 Platform
= self
.BuildDatabase
[self
.MetaFile
, Arch
, Target
, Toolchain
]
462 PlatformPcds
= Platform
.Pcds
463 self
._GuidDict
= Platform
._GuidDict
464 SourcePcdDict
= {TAB_PCDS_DYNAMIC_EX
:set(), TAB_PCDS_PATCHABLE_IN_MODULE
:set(),TAB_PCDS_DYNAMIC
:set(),TAB_PCDS_FIXED_AT_BUILD
:set()}
465 BinaryPcdDict
= {TAB_PCDS_DYNAMIC_EX
:set(), TAB_PCDS_PATCHABLE_IN_MODULE
:set()}
466 SourcePcdDict_Keys
= SourcePcdDict
.keys()
467 BinaryPcdDict_Keys
= BinaryPcdDict
.keys()
469 # generate the SourcePcdDict and BinaryPcdDict
470 PGen
= PlatformAutoGen(self
, self
.MetaFile
, Target
, Toolchain
, Arch
)
471 for BuildData
in list(PGen
.BuildDatabase
._CACHE
_.values()):
472 if BuildData
.Arch
!= Arch
:
474 if BuildData
.MetaFile
.Ext
== '.inf':
475 for key
in BuildData
.Pcds
:
476 if BuildData
.Pcds
[key
].Pending
:
477 if key
in Platform
.Pcds
:
478 PcdInPlatform
= Platform
.Pcds
[key
]
479 if PcdInPlatform
.Type
:
480 BuildData
.Pcds
[key
].Type
= PcdInPlatform
.Type
481 BuildData
.Pcds
[key
].Pending
= False
483 if BuildData
.MetaFile
in Platform
.Modules
:
484 PlatformModule
= Platform
.Modules
[str(BuildData
.MetaFile
)]
485 if key
in PlatformModule
.Pcds
:
486 PcdInPlatform
= PlatformModule
.Pcds
[key
]
487 if PcdInPlatform
.Type
:
488 BuildData
.Pcds
[key
].Type
= PcdInPlatform
.Type
489 BuildData
.Pcds
[key
].Pending
= False
491 #Pcd used in Library, Pcd Type from reference module if Pcd Type is Pending
492 if BuildData
.Pcds
[key
].Pending
:
493 MGen
= ModuleAutoGen(self
, BuildData
.MetaFile
, Target
, Toolchain
, Arch
, self
.MetaFile
)
494 if MGen
and MGen
.IsLibrary
:
495 if MGen
in PGen
.LibraryAutoGenList
:
496 ReferenceModules
= MGen
.ReferenceModules
497 for ReferenceModule
in ReferenceModules
:
498 if ReferenceModule
.MetaFile
in Platform
.Modules
:
499 RefPlatformModule
= Platform
.Modules
[str(ReferenceModule
.MetaFile
)]
500 if key
in RefPlatformModule
.Pcds
:
501 PcdInReferenceModule
= RefPlatformModule
.Pcds
[key
]
502 if PcdInReferenceModule
.Type
:
503 BuildData
.Pcds
[key
].Type
= PcdInReferenceModule
.Type
504 BuildData
.Pcds
[key
].Pending
= False
507 if TAB_PCDS_DYNAMIC_EX
in BuildData
.Pcds
[key
].Type
:
508 if BuildData
.IsBinaryModule
:
509 BinaryPcdDict
[TAB_PCDS_DYNAMIC_EX
].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
511 SourcePcdDict
[TAB_PCDS_DYNAMIC_EX
].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
513 elif TAB_PCDS_PATCHABLE_IN_MODULE
in BuildData
.Pcds
[key
].Type
:
514 if BuildData
.MetaFile
.Ext
== '.inf':
515 if BuildData
.IsBinaryModule
:
516 BinaryPcdDict
[TAB_PCDS_PATCHABLE_IN_MODULE
].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
518 SourcePcdDict
[TAB_PCDS_PATCHABLE_IN_MODULE
].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
520 elif TAB_PCDS_DYNAMIC
in BuildData
.Pcds
[key
].Type
:
521 SourcePcdDict
[TAB_PCDS_DYNAMIC
].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
522 elif TAB_PCDS_FIXED_AT_BUILD
in BuildData
.Pcds
[key
].Type
:
523 SourcePcdDict
[TAB_PCDS_FIXED_AT_BUILD
].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
527 # A PCD can only use one type for all source modules
529 for i
in SourcePcdDict_Keys
:
530 for j
in SourcePcdDict_Keys
:
532 Intersections
= SourcePcdDict
[i
].intersection(SourcePcdDict
[j
])
533 if len(Intersections
) > 0:
537 "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
),
538 ExtraData
='\n\t'.join(str(P
[1]+'.'+P
[0]) for P
in Intersections
)
542 # intersection the BinaryPCD for Mixed PCD
544 for i
in BinaryPcdDict_Keys
:
545 for j
in BinaryPcdDict_Keys
:
547 Intersections
= BinaryPcdDict
[i
].intersection(BinaryPcdDict
[j
])
548 for item
in Intersections
:
549 NewPcd1
= (item
[0] + '_' + i
, item
[1])
550 NewPcd2
= (item
[0] + '_' + j
, item
[1])
551 if item
not in GlobalData
.MixedPcd
:
552 GlobalData
.MixedPcd
[item
] = [NewPcd1
, NewPcd2
]
554 if NewPcd1
not in GlobalData
.MixedPcd
[item
]:
555 GlobalData
.MixedPcd
[item
].append(NewPcd1
)
556 if NewPcd2
not in GlobalData
.MixedPcd
[item
]:
557 GlobalData
.MixedPcd
[item
].append(NewPcd2
)
560 # intersection the SourcePCD and BinaryPCD for Mixed PCD
562 for i
in SourcePcdDict_Keys
:
563 for j
in BinaryPcdDict_Keys
:
565 Intersections
= SourcePcdDict
[i
].intersection(BinaryPcdDict
[j
])
566 for item
in Intersections
:
567 NewPcd1
= (item
[0] + '_' + i
, item
[1])
568 NewPcd2
= (item
[0] + '_' + j
, item
[1])
569 if item
not in GlobalData
.MixedPcd
:
570 GlobalData
.MixedPcd
[item
] = [NewPcd1
, NewPcd2
]
572 if NewPcd1
not in GlobalData
.MixedPcd
[item
]:
573 GlobalData
.MixedPcd
[item
].append(NewPcd1
)
574 if NewPcd2
not in GlobalData
.MixedPcd
[item
]:
575 GlobalData
.MixedPcd
[item
].append(NewPcd2
)
577 for BuildData
in list(PGen
.BuildDatabase
._CACHE
_.values()):
578 if BuildData
.Arch
!= Arch
:
580 for key
in BuildData
.Pcds
:
581 for SinglePcd
in GlobalData
.MixedPcd
:
582 if (BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
) == SinglePcd
:
583 for item
in GlobalData
.MixedPcd
[SinglePcd
]:
584 Pcd_Type
= item
[0].split('_')[-1]
585 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 \
586 (Pcd_Type
== TAB_PCDS_DYNAMIC
and BuildData
.Pcds
[key
].Type
in PCD_DYNAMIC_TYPE_SET
):
587 Value
= BuildData
.Pcds
[key
]
588 Value
.TokenCName
= BuildData
.Pcds
[key
].TokenCName
+ '_' + Pcd_Type
590 newkey
= (Value
.TokenCName
, key
[1])
592 newkey
= (Value
.TokenCName
, key
[1], key
[2])
593 del BuildData
.Pcds
[key
]
594 BuildData
.Pcds
[newkey
] = Value
598 # handle the mixed pcd in FDF file
600 if key
in GlobalData
.MixedPcd
:
603 for item
in GlobalData
.MixedPcd
[key
]:
606 #Collect package set information from INF of FDF
608 for Inf
in ModuleList
:
609 ModuleFile
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, Arch
)
610 if ModuleFile
in Platform
.Modules
:
612 ModuleData
= self
.BuildDatabase
[ModuleFile
, Arch
, Target
, Toolchain
]
613 PkgSet
.update(ModuleData
.Packages
)
614 Pkgs
= list(PkgSet
) + list(PGen
.PackageList
)
619 DecPcds
.add((Pcd
[0], Pcd
[1]))
620 DecPcdsKey
.add((Pcd
[0], Pcd
[1], Pcd
[2]))
622 Platform
.SkuName
= self
.SkuId
623 for Name
, Guid
,Fileds
in PcdSet
:
624 if (Name
, Guid
) not in DecPcds
:
628 "PCD (%s.%s) used in FDF is not declared in DEC files." % (Guid
, Name
),
629 File
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
, Fileds
][0],
630 Line
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
, Fileds
][1]
633 # Check whether Dynamic or DynamicEx PCD used in FDF file. If used, build break and give a error message.
634 if (Name
, Guid
, TAB_PCDS_FIXED_AT_BUILD
) in DecPcdsKey \
635 or (Name
, Guid
, TAB_PCDS_PATCHABLE_IN_MODULE
) in DecPcdsKey \
636 or (Name
, Guid
, TAB_PCDS_FEATURE_FLAG
) in DecPcdsKey
:
638 elif (Name
, Guid
, TAB_PCDS_DYNAMIC
) in DecPcdsKey
or (Name
, Guid
, TAB_PCDS_DYNAMIC_EX
) in DecPcdsKey
:
642 "Using Dynamic or DynamicEx type of PCD [%s.%s] in FDF file is not allowed." % (Guid
, Name
),
643 File
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
, Fileds
][0],
644 Line
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
, Fileds
][1]
647 Pa
= PlatformAutoGen(self
, self
.MetaFile
, Target
, Toolchain
, Arch
)
649 # Explicitly collect platform's dynamic PCDs
651 Pa
.CollectPlatformDynamicPcds()
652 Pa
.CollectFixedAtBuildPcds()
653 self
.AutoGenObjectList
.append(Pa
)
656 # Generate Package level hash value
658 GlobalData
.gPackageHash
= {}
659 if GlobalData
.gUseHashCache
:
661 self
._GenPkgLevelHash
(Pkg
)
664 # Check PCDs token value conflict in each DEC file.
666 self
._CheckAllPcdsTokenValueConflict
()
669 # Check PCD type and definition between DSC and DEC
671 self
._CheckPcdDefineAndType
()
674 # Create BuildOptions Macro & PCD metafile, also add the Active Platform and FDF file.
676 content
= 'gCommandLineDefines: '
677 content
+= str(GlobalData
.gCommandLineDefines
)
678 content
+= TAB_LINE_BREAK
679 content
+= 'BuildOptionPcd: '
680 content
+= str(GlobalData
.BuildOptionPcd
)
681 content
+= TAB_LINE_BREAK
682 content
+= 'Active Platform: '
683 content
+= str(self
.Platform
)
684 content
+= TAB_LINE_BREAK
686 content
+= 'Flash Image Definition: '
687 content
+= str(self
.FdfFile
)
688 content
+= TAB_LINE_BREAK
689 SaveFileOnChange(os
.path
.join(self
.BuildDir
, 'BuildOptions'), content
, False)
692 # Create PcdToken Number file for Dynamic/DynamicEx Pcd.
694 PcdTokenNumber
= 'PcdTokenNumber: '
695 if Pa
.PcdTokenNumber
:
696 if Pa
.DynamicPcdList
:
697 for Pcd
in Pa
.DynamicPcdList
:
698 PcdTokenNumber
+= TAB_LINE_BREAK
699 PcdTokenNumber
+= str((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
))
700 PcdTokenNumber
+= ' : '
701 PcdTokenNumber
+= str(Pa
.PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
])
702 SaveFileOnChange(os
.path
.join(self
.BuildDir
, 'PcdTokenNumber'), PcdTokenNumber
, False)
705 # Get set of workspace metafiles
707 AllWorkSpaceMetaFiles
= self
._GetMetaFiles
(Target
, Toolchain
, Arch
)
710 # Retrieve latest modified time of all metafiles
713 for f
in AllWorkSpaceMetaFiles
:
714 if os
.stat(f
)[8] > SrcTimeStamp
:
715 SrcTimeStamp
= os
.stat(f
)[8]
716 self
._SrcTimeStamp
= SrcTimeStamp
718 if GlobalData
.gUseHashCache
:
720 for files
in AllWorkSpaceMetaFiles
:
721 if files
.endswith('.dec'):
723 f
= open(files
, 'rb')
727 SaveFileOnChange(os
.path
.join(self
.BuildDir
, 'AutoGen.hash'), m
.hexdigest(), False)
728 GlobalData
.gPlatformHash
= m
.hexdigest()
731 # Write metafile list to build directory
733 AutoGenFilePath
= os
.path
.join(self
.BuildDir
, 'AutoGen')
734 if os
.path
.exists (AutoGenFilePath
):
735 os
.remove(AutoGenFilePath
)
736 if not os
.path
.exists(self
.BuildDir
):
737 os
.makedirs(self
.BuildDir
)
738 with
open(os
.path
.join(self
.BuildDir
, 'AutoGen'), 'w+') as file:
739 for f
in AllWorkSpaceMetaFiles
:
743 def _GenPkgLevelHash(self
, Pkg
):
744 if Pkg
.PackageName
in GlobalData
.gPackageHash
:
747 PkgDir
= os
.path
.join(self
.BuildDir
, Pkg
.Arch
, Pkg
.PackageName
)
748 CreateDirectory(PkgDir
)
749 HashFile
= os
.path
.join(PkgDir
, Pkg
.PackageName
+ '.hash')
751 # Get .dec file's hash value
752 f
= open(Pkg
.MetaFile
.Path
, 'rb')
756 # Get include files hash value
758 for inc
in sorted(Pkg
.Includes
, key
=lambda x
: str(x
)):
759 for Root
, Dirs
, Files
in os
.walk(str(inc
)):
760 for File
in sorted(Files
):
761 File_Path
= os
.path
.join(Root
, File
)
762 f
= open(File_Path
, 'rb')
766 SaveFileOnChange(HashFile
, m
.hexdigest(), False)
767 GlobalData
.gPackageHash
[Pkg
.PackageName
] = m
.hexdigest()
769 def _GetMetaFiles(self
, Target
, Toolchain
, Arch
):
770 AllWorkSpaceMetaFiles
= set()
775 AllWorkSpaceMetaFiles
.add (self
.FdfFile
.Path
)
776 for f
in GlobalData
.gFdfParser
.GetAllIncludedFile():
777 AllWorkSpaceMetaFiles
.add (f
.FileName
)
781 AllWorkSpaceMetaFiles
.add(self
.MetaFile
.Path
)
784 # add build_rule.txt & tools_def.txt
786 AllWorkSpaceMetaFiles
.add(os
.path
.join(GlobalData
.gConfDirectory
, gDefaultBuildRuleFile
))
787 AllWorkSpaceMetaFiles
.add(os
.path
.join(GlobalData
.gConfDirectory
, gDefaultToolsDefFile
))
789 # add BuildOption metafile
791 AllWorkSpaceMetaFiles
.add(os
.path
.join(self
.BuildDir
, 'BuildOptions'))
793 # add PcdToken Number file for Dynamic/DynamicEx Pcd
795 AllWorkSpaceMetaFiles
.add(os
.path
.join(self
.BuildDir
, 'PcdTokenNumber'))
797 for Pa
in self
.AutoGenObjectList
:
798 AllWorkSpaceMetaFiles
.add(Pa
.ToolDefinitionFile
)
800 for Arch
in self
.ArchList
:
804 for Package
in PlatformAutoGen(self
, self
.MetaFile
, Target
, Toolchain
, Arch
).PackageList
:
805 AllWorkSpaceMetaFiles
.add(Package
.MetaFile
.Path
)
810 for filePath
in self
.BuildDatabase
[self
.MetaFile
, Arch
, Target
, Toolchain
]._RawData
.IncludedFiles
:
811 AllWorkSpaceMetaFiles
.add(filePath
.Path
)
813 return AllWorkSpaceMetaFiles
815 def _CheckPcdDefineAndType(self
):
816 PcdTypeSet
= {TAB_PCDS_FIXED_AT_BUILD
,
817 TAB_PCDS_PATCHABLE_IN_MODULE
,
818 TAB_PCDS_FEATURE_FLAG
,
822 # This dict store PCDs which are not used by any modules with specified arches
823 UnusedPcd
= OrderedDict()
824 for Pa
in self
.AutoGenObjectList
:
825 # Key of DSC's Pcds dictionary is PcdCName, TokenSpaceGuid
826 for Pcd
in Pa
.Platform
.Pcds
:
827 PcdType
= Pa
.Platform
.Pcds
[Pcd
].Type
829 # If no PCD type, this PCD comes from FDF
833 # Try to remove Hii and Vpd suffix
834 if PcdType
.startswith(TAB_PCDS_DYNAMIC_EX
):
835 PcdType
= TAB_PCDS_DYNAMIC_EX
836 elif PcdType
.startswith(TAB_PCDS_DYNAMIC
):
837 PcdType
= TAB_PCDS_DYNAMIC
839 for Package
in Pa
.PackageList
:
840 # Key of DEC's Pcds dictionary is PcdCName, TokenSpaceGuid, PcdType
841 if (Pcd
[0], Pcd
[1], PcdType
) in Package
.Pcds
:
843 for Type
in PcdTypeSet
:
844 if (Pcd
[0], Pcd
[1], Type
) in Package
.Pcds
:
848 "Type [%s] of PCD [%s.%s] in DSC file doesn't match the type [%s] defined in DEC file." \
849 % (Pa
.Platform
.Pcds
[Pcd
].Type
, Pcd
[1], Pcd
[0], Type
),
854 UnusedPcd
.setdefault(Pcd
, []).append(Pa
.Arch
)
856 for Pcd
in UnusedPcd
:
859 "The PCD was not specified by any INF module in the platform for the given architecture.\n"
860 "\tPCD: [%s.%s]\n\tPlatform: [%s]\n\tArch: %s"
861 % (Pcd
[1], Pcd
[0], os
.path
.basename(str(self
.MetaFile
)), str(UnusedPcd
[Pcd
])),
866 return "%s [%s]" % (self
.MetaFile
, ", ".join(self
.ArchList
))
868 ## Return the directory to store FV files
871 return path
.join(self
.BuildDir
, TAB_FV_DIRECTORY
)
873 ## Return the directory to store all intermediate and final files built
876 return self
.AutoGenObjectList
[0].BuildDir
878 ## Return the build output directory platform specifies
881 return self
.Platform
.OutputDirectory
883 ## Return platform name
886 return self
.Platform
.PlatformName
888 ## Return meta-file GUID
891 return self
.Platform
.Guid
893 ## Return platform version
896 return self
.Platform
.Version
898 ## Return paths of tools
900 def ToolDefinition(self
):
901 return self
.AutoGenObjectList
[0].ToolDefinition
903 ## Return directory of platform makefile
905 # @retval string Makefile directory
908 def MakeFileDir(self
):
911 ## Return build command string
913 # @retval string Build command string
916 def BuildCommand(self
):
917 # BuildCommand should be all the same. So just get one from platform AutoGen
918 return self
.AutoGenObjectList
[0].BuildCommand
920 ## Check the PCDs token value conflict in each DEC file.
922 # Will cause build break and raise error message while two PCDs conflict.
926 def _CheckAllPcdsTokenValueConflict(self
):
927 for Pa
in self
.AutoGenObjectList
:
928 for Package
in Pa
.PackageList
:
929 PcdList
= list(Package
.Pcds
.values())
930 PcdList
.sort(key
=lambda x
: int(x
.TokenValue
, 0))
932 while (Count
< len(PcdList
) - 1) :
933 Item
= PcdList
[Count
]
934 ItemNext
= PcdList
[Count
+ 1]
936 # Make sure in the same token space the TokenValue should be unique
938 if (int(Item
.TokenValue
, 0) == int(ItemNext
.TokenValue
, 0)):
939 SameTokenValuePcdList
= []
940 SameTokenValuePcdList
.append(Item
)
941 SameTokenValuePcdList
.append(ItemNext
)
942 RemainPcdListLength
= len(PcdList
) - Count
- 2
943 for ValueSameCount
in range(RemainPcdListLength
):
944 if int(PcdList
[len(PcdList
) - RemainPcdListLength
+ ValueSameCount
].TokenValue
, 0) == int(Item
.TokenValue
, 0):
945 SameTokenValuePcdList
.append(PcdList
[len(PcdList
) - RemainPcdListLength
+ ValueSameCount
])
949 # Sort same token value PCD list with TokenGuid and TokenCName
951 SameTokenValuePcdList
.sort(key
=lambda x
: "%s.%s" % (x
.TokenSpaceGuidCName
, x
.TokenCName
))
952 SameTokenValuePcdListCount
= 0
953 while (SameTokenValuePcdListCount
< len(SameTokenValuePcdList
) - 1):
955 TemListItem
= SameTokenValuePcdList
[SameTokenValuePcdListCount
]
956 TemListItemNext
= SameTokenValuePcdList
[SameTokenValuePcdListCount
+ 1]
958 if (TemListItem
.TokenSpaceGuidCName
== TemListItemNext
.TokenSpaceGuidCName
) and (TemListItem
.TokenCName
!= TemListItemNext
.TokenCName
):
959 for PcdItem
in GlobalData
.MixedPcd
:
960 if (TemListItem
.TokenCName
, TemListItem
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
] or \
961 (TemListItemNext
.TokenCName
, TemListItemNext
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
967 "The TokenValue [%s] of PCD [%s.%s] is conflict with: [%s.%s] in %s"\
968 % (TemListItem
.TokenValue
, TemListItem
.TokenSpaceGuidCName
, TemListItem
.TokenCName
, TemListItemNext
.TokenSpaceGuidCName
, TemListItemNext
.TokenCName
, Package
),
971 SameTokenValuePcdListCount
+= 1
972 Count
+= SameTokenValuePcdListCount
975 PcdList
= list(Package
.Pcds
.values())
976 PcdList
.sort(key
=lambda x
: "%s.%s" % (x
.TokenSpaceGuidCName
, x
.TokenCName
))
978 while (Count
< len(PcdList
) - 1) :
979 Item
= PcdList
[Count
]
980 ItemNext
= PcdList
[Count
+ 1]
982 # Check PCDs with same TokenSpaceGuidCName.TokenCName have same token value as well.
984 if (Item
.TokenSpaceGuidCName
== ItemNext
.TokenSpaceGuidCName
) and (Item
.TokenCName
== ItemNext
.TokenCName
) and (int(Item
.TokenValue
, 0) != int(ItemNext
.TokenValue
, 0)):
988 "The TokenValue [%s] of PCD [%s.%s] in %s defined in two places should be same as well."\
989 % (Item
.TokenValue
, Item
.TokenSpaceGuidCName
, Item
.TokenCName
, Package
),
993 ## Generate fds command
995 def GenFdsCommand(self
):
996 return (GenMake
.TopLevelMakefile(self
)._TEMPLATE
_.Replace(GenMake
.TopLevelMakefile(self
)._TemplateDict
)).strip()
999 def GenFdsCommandDict(self
):
1001 LogLevel
= EdkLogger
.GetLevel()
1002 if LogLevel
== EdkLogger
.VERBOSE
:
1003 FdsCommandDict
["verbose"] = True
1004 elif LogLevel
<= EdkLogger
.DEBUG_9
:
1005 FdsCommandDict
["debug"] = LogLevel
- 1
1006 elif LogLevel
== EdkLogger
.QUIET
:
1007 FdsCommandDict
["quiet"] = True
1009 if GlobalData
.gEnableGenfdsMultiThread
:
1010 FdsCommandDict
["GenfdsMultiThread"] = True
1011 if GlobalData
.gIgnoreSource
:
1012 FdsCommandDict
["IgnoreSources"] = True
1014 FdsCommandDict
["OptionPcd"] = []
1015 for pcd
in GlobalData
.BuildOptionPcd
:
1017 pcdname
= '.'.join(pcd
[0:3])
1019 pcdname
= '.'.join(pcd
[0:2])
1020 if pcd
[3].startswith('{'):
1021 FdsCommandDict
["OptionPcd"].append(pcdname
+ '=' + 'H' + '"' + pcd
[3] + '"')
1023 FdsCommandDict
["OptionPcd"].append(pcdname
+ '=' + pcd
[3])
1026 # macros passed to GenFds
1028 MacroDict
.update(GlobalData
.gGlobalDefines
)
1029 MacroDict
.update(GlobalData
.gCommandLineDefines
)
1030 for MacroName
in MacroDict
:
1031 if MacroDict
[MacroName
] != "":
1032 MacroList
.append('"%s=%s"' % (MacroName
, MacroDict
[MacroName
].replace('\\', '\\\\')))
1034 MacroList
.append('"%s"' % MacroName
)
1035 FdsCommandDict
["macro"] = MacroList
1037 FdsCommandDict
["fdf_file"] = [self
.FdfFile
]
1038 FdsCommandDict
["build_target"] = self
.BuildTarget
1039 FdsCommandDict
["toolchain_tag"] = self
.ToolChain
1040 FdsCommandDict
["active_platform"] = str(self
)
1042 FdsCommandDict
["conf_directory"] = GlobalData
.gConfDirectory
1043 FdsCommandDict
["build_architecture_list"] = ','.join(self
.ArchList
)
1044 FdsCommandDict
["platform_build_directory"] = self
.BuildDir
1046 FdsCommandDict
["fd"] = self
.FdTargetList
1047 FdsCommandDict
["fv"] = self
.FvTargetList
1048 FdsCommandDict
["cap"] = self
.CapTargetList
1049 return FdsCommandDict
1051 ## Create makefile for the platform and modules in it
1053 # @param CreateDepsMakeFile Flag indicating if the makefile for
1054 # modules will be created as well
1056 def CreateMakeFile(self
, CreateDepsMakeFile
=False):
1057 if not CreateDepsMakeFile
:
1059 for Pa
in self
.AutoGenObjectList
:
1060 Pa
.CreateMakeFile(True)
1062 ## Create autogen code for platform and modules
1064 # Since there's no autogen code for platform, this method will do nothing
1065 # if CreateModuleCodeFile is set to False.
1067 # @param CreateDepsCodeFile Flag indicating if creating module's
1068 # autogen code file or not
1070 def CreateCodeFile(self
, CreateDepsCodeFile
=False):
1071 if not CreateDepsCodeFile
:
1073 for Pa
in self
.AutoGenObjectList
:
1074 Pa
.CreateCodeFile(True)
1076 ## Create AsBuilt INF file the platform
1078 def CreateAsBuiltInf(self
):
1082 ## AutoGen class for platform
1084 # PlatformAutoGen class will process the original information in platform
1085 # file in order to generate makefile for platform.
1087 class PlatformAutoGen(AutoGen
):
1088 # call super().__init__ then call the worker function with different parameter count
1089 def __init__(self
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
1090 if not hasattr(self
, "_Init"):
1091 self
._InitWorker
(Workspace
, MetaFile
, Target
, Toolchain
, Arch
)
1094 # Used to store all PCDs for both PEI and DXE phase, in order to generate
1095 # correct PCD database
1098 _NonDynaPcdList_
= []
1102 # The priority list while override build option
1104 PrioList
= {"0x11111" : 16, # TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE (Highest)
1105 "0x01111" : 15, # ******_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
1106 "0x10111" : 14, # TARGET_*********_ARCH_COMMANDTYPE_ATTRIBUTE
1107 "0x00111" : 13, # ******_*********_ARCH_COMMANDTYPE_ATTRIBUTE
1108 "0x11011" : 12, # TARGET_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
1109 "0x01011" : 11, # ******_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
1110 "0x10011" : 10, # TARGET_*********_****_COMMANDTYPE_ATTRIBUTE
1111 "0x00011" : 9, # ******_*********_****_COMMANDTYPE_ATTRIBUTE
1112 "0x11101" : 8, # TARGET_TOOLCHAIN_ARCH_***********_ATTRIBUTE
1113 "0x01101" : 7, # ******_TOOLCHAIN_ARCH_***********_ATTRIBUTE
1114 "0x10101" : 6, # TARGET_*********_ARCH_***********_ATTRIBUTE
1115 "0x00101" : 5, # ******_*********_ARCH_***********_ATTRIBUTE
1116 "0x11001" : 4, # TARGET_TOOLCHAIN_****_***********_ATTRIBUTE
1117 "0x01001" : 3, # ******_TOOLCHAIN_****_***********_ATTRIBUTE
1118 "0x10001" : 2, # TARGET_*********_****_***********_ATTRIBUTE
1119 "0x00001" : 1} # ******_*********_****_***********_ATTRIBUTE (Lowest)
1121 ## Initialize PlatformAutoGen
1124 # @param Workspace WorkspaceAutoGen object
1125 # @param PlatformFile Platform file (DSC file)
1126 # @param Target Build target (DEBUG, RELEASE)
1127 # @param Toolchain Name of tool chain
1128 # @param Arch arch of the platform supports
1130 def _InitWorker(self
, Workspace
, PlatformFile
, Target
, Toolchain
, Arch
):
1131 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "AutoGen platform [%s] [%s]" % (PlatformFile
, Arch
))
1132 GlobalData
.gProcessingFile
= "%s [%s, %s, %s]" % (PlatformFile
, Arch
, Toolchain
, Target
)
1134 self
.MetaFile
= PlatformFile
1135 self
.Workspace
= Workspace
1136 self
.WorkspaceDir
= Workspace
.WorkspaceDir
1137 self
.ToolChain
= Toolchain
1138 self
.BuildTarget
= Target
1140 self
.SourceDir
= PlatformFile
.SubDir
1141 self
.FdTargetList
= self
.Workspace
.FdTargetList
1142 self
.FvTargetList
= self
.Workspace
.FvTargetList
1143 # get the original module/package/platform objects
1144 self
.BuildDatabase
= Workspace
.BuildDatabase
1145 self
.DscBuildDataObj
= Workspace
.Platform
1147 # flag indicating if the makefile/C-code file has been created or not
1148 self
.IsMakeFileCreated
= False
1150 self
._DynamicPcdList
= None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
1151 self
._NonDynamicPcdList
= None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
1153 self
._AsBuildInfList
= []
1154 self
._AsBuildModuleList
= []
1156 self
.VariableInfo
= None
1158 if GlobalData
.gFdfParser
is not None:
1159 self
._AsBuildInfList
= GlobalData
.gFdfParser
.Profile
.InfList
1160 for Inf
in self
._AsBuildInfList
:
1161 InfClass
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, self
.Arch
)
1162 M
= self
.BuildDatabase
[InfClass
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1163 if not M
.IsBinaryModule
:
1165 self
._AsBuildModuleList
.append(InfClass
)
1166 # get library/modules for build
1167 self
.LibraryBuildDirectoryList
= []
1168 self
.ModuleBuildDirectoryList
= []
1172 ## hash() operator of PlatformAutoGen
1174 # The platform file path and arch string will be used to represent
1175 # hash value of this object
1177 # @retval int Hash value of the platform file path and arch
1179 @cached_class_function
1181 return hash((self
.MetaFile
, self
.Arch
))
1183 @cached_class_function
1185 return "%s [%s]" % (self
.MetaFile
, self
.Arch
)
1187 ## Create autogen code for platform and modules
1189 # Since there's no autogen code for platform, this method will do nothing
1190 # if CreateModuleCodeFile is set to False.
1192 # @param CreateModuleCodeFile Flag indicating if creating module's
1193 # autogen code file or not
1195 @cached_class_function
1196 def CreateCodeFile(self
, CreateModuleCodeFile
=False):
1197 # only module has code to be created, so do nothing if CreateModuleCodeFile is False
1198 if not CreateModuleCodeFile
:
1201 for Ma
in self
.ModuleAutoGenList
:
1202 Ma
.CreateCodeFile(True)
1204 ## Generate Fds Command
1206 def GenFdsCommand(self
):
1207 return self
.Workspace
.GenFdsCommand
1209 ## Create makefile for the platform and modules in it
1211 # @param CreateModuleMakeFile Flag indicating if the makefile for
1212 # modules will be created as well
1214 def CreateMakeFile(self
, CreateModuleMakeFile
=False, FfsCommand
= {}):
1215 if CreateModuleMakeFile
:
1216 for Ma
in self
._MaList
:
1217 key
= (Ma
.MetaFile
.File
, self
.Arch
)
1218 if key
in FfsCommand
:
1219 Ma
.CreateMakeFile(True, FfsCommand
[key
])
1221 Ma
.CreateMakeFile(True)
1223 # no need to create makefile for the platform more than once
1224 if self
.IsMakeFileCreated
:
1227 # create library/module build dirs for platform
1228 Makefile
= GenMake
.PlatformMakefile(self
)
1229 self
.LibraryBuildDirectoryList
= Makefile
.GetLibraryBuildDirectoryList()
1230 self
.ModuleBuildDirectoryList
= Makefile
.GetModuleBuildDirectoryList()
1232 self
.IsMakeFileCreated
= True
1235 def AllPcdList(self
):
1236 return self
.DynamicPcdList
+ self
.NonDynamicPcdList
1237 ## Deal with Shared FixedAtBuild Pcds
1239 def CollectFixedAtBuildPcds(self
):
1240 for LibAuto
in self
.LibraryAutoGenList
:
1241 FixedAtBuildPcds
= {}
1242 ShareFixedAtBuildPcdsSameValue
= {}
1243 for Module
in LibAuto
.ReferenceModules
:
1244 for Pcd
in set(Module
.FixedAtBuildPcds
+ LibAuto
.FixedAtBuildPcds
):
1245 DefaultValue
= Pcd
.DefaultValue
1246 # Cover the case: DSC component override the Pcd value and the Pcd only used in one Lib
1247 if Pcd
in Module
.LibraryPcdList
:
1248 Index
= Module
.LibraryPcdList
.index(Pcd
)
1249 DefaultValue
= Module
.LibraryPcdList
[Index
].DefaultValue
1250 key
= ".".join((Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
1251 if key
not in FixedAtBuildPcds
:
1252 ShareFixedAtBuildPcdsSameValue
[key
] = True
1253 FixedAtBuildPcds
[key
] = DefaultValue
1255 if FixedAtBuildPcds
[key
] != DefaultValue
:
1256 ShareFixedAtBuildPcdsSameValue
[key
] = False
1257 for Pcd
in LibAuto
.FixedAtBuildPcds
:
1258 key
= ".".join((Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
1259 if (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
) not in self
.NonDynamicPcdDict
:
1262 DscPcd
= self
.NonDynamicPcdDict
[(Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
)]
1263 if DscPcd
.Type
!= TAB_PCDS_FIXED_AT_BUILD
:
1265 if key
in ShareFixedAtBuildPcdsSameValue
and ShareFixedAtBuildPcdsSameValue
[key
]:
1266 LibAuto
.ConstPcd
[key
] = FixedAtBuildPcds
[key
]
1268 def CollectVariables(self
, DynamicPcdSet
):
1271 if self
.Workspace
.FdfFile
:
1272 FdDict
= self
.Workspace
.FdfProfile
.FdDict
[GlobalData
.gFdfParser
.CurrentFdName
]
1273 for FdRegion
in FdDict
.RegionList
:
1274 for item
in FdRegion
.RegionDataList
:
1275 if self
.Platform
.VpdToolGuid
.strip() and self
.Platform
.VpdToolGuid
in item
:
1276 VpdRegionSize
= FdRegion
.Size
1277 VpdRegionBase
= FdRegion
.Offset
1280 VariableInfo
= VariableMgr(self
.DscBuildDataObj
._GetDefaultStores
(), self
.DscBuildDataObj
.SkuIds
)
1281 VariableInfo
.SetVpdRegionMaxSize(VpdRegionSize
)
1282 VariableInfo
.SetVpdRegionOffset(VpdRegionBase
)
1284 for Pcd
in DynamicPcdSet
:
1285 pcdname
= ".".join((Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
1286 for SkuName
in Pcd
.SkuInfoList
:
1287 Sku
= Pcd
.SkuInfoList
[SkuName
]
1289 if SkuId
is None or SkuId
== '':
1291 if len(Sku
.VariableName
) > 0:
1292 if Sku
.VariableAttribute
and 'NV' not in Sku
.VariableAttribute
:
1294 VariableGuidStructure
= Sku
.VariableGuidValue
1295 VariableGuid
= GuidStructureStringToGuidString(VariableGuidStructure
)
1296 for StorageName
in Sku
.DefaultStoreDict
:
1297 VariableInfo
.append_variable(var_info(Index
, pcdname
, StorageName
, SkuName
, StringToArray(Sku
.VariableName
), VariableGuid
, Sku
.VariableOffset
, Sku
.VariableAttribute
, Sku
.HiiDefaultValue
, Sku
.DefaultStoreDict
[StorageName
] if Pcd
.DatumType
in TAB_PCD_NUMERIC_TYPES
else StringToArray(Sku
.DefaultStoreDict
[StorageName
]), Pcd
.DatumType
, Pcd
.CustomAttribute
['DscPosition'], Pcd
.CustomAttribute
.get('IsStru',False)))
1301 def UpdateNVStoreMaxSize(self
, OrgVpdFile
):
1302 if self
.VariableInfo
:
1303 VpdMapFilePath
= os
.path
.join(self
.BuildDir
, TAB_FV_DIRECTORY
, "%s.map" % self
.Platform
.VpdToolGuid
)
1304 PcdNvStoreDfBuffer
= [item
for item
in self
._DynamicPcdList
if item
.TokenCName
== "PcdNvStoreDefaultValueBuffer" and item
.TokenSpaceGuidCName
== "gEfiMdeModulePkgTokenSpaceGuid"]
1306 if PcdNvStoreDfBuffer
:
1307 if os
.path
.exists(VpdMapFilePath
):
1308 OrgVpdFile
.Read(VpdMapFilePath
)
1309 PcdItems
= OrgVpdFile
.GetOffset(PcdNvStoreDfBuffer
[0])
1310 NvStoreOffset
= list(PcdItems
.values())[0].strip() if PcdItems
else '0'
1312 EdkLogger
.error("build", FILE_READ_FAILURE
, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath
)
1314 NvStoreOffset
= int(NvStoreOffset
, 16) if NvStoreOffset
.upper().startswith("0X") else int(NvStoreOffset
)
1315 default_skuobj
= PcdNvStoreDfBuffer
[0].SkuInfoList
.get(TAB_DEFAULT
)
1316 maxsize
= self
.VariableInfo
.VpdRegionSize
- NvStoreOffset
if self
.VariableInfo
.VpdRegionSize
else len(default_skuobj
.DefaultValue
.split(","))
1317 var_data
= self
.VariableInfo
.PatchNVStoreDefaultMaxSize(maxsize
)
1319 if var_data
and default_skuobj
:
1320 default_skuobj
.DefaultValue
= var_data
1321 PcdNvStoreDfBuffer
[0].DefaultValue
= var_data
1322 PcdNvStoreDfBuffer
[0].SkuInfoList
.clear()
1323 PcdNvStoreDfBuffer
[0].SkuInfoList
[TAB_DEFAULT
] = default_skuobj
1324 PcdNvStoreDfBuffer
[0].MaxDatumSize
= str(len(default_skuobj
.DefaultValue
.split(",")))
1328 ## Collect dynamic PCDs
1330 # Gather dynamic PCDs list from each module and their settings from platform
1331 # This interface should be invoked explicitly when platform action is created.
1333 def CollectPlatformDynamicPcds(self
):
1334 for key
in self
.Platform
.Pcds
:
1335 for SinglePcd
in GlobalData
.MixedPcd
:
1336 if (self
.Platform
.Pcds
[key
].TokenCName
, self
.Platform
.Pcds
[key
].TokenSpaceGuidCName
) == SinglePcd
:
1337 for item
in GlobalData
.MixedPcd
[SinglePcd
]:
1338 Pcd_Type
= item
[0].split('_')[-1]
1339 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 \
1340 (Pcd_Type
== TAB_PCDS_DYNAMIC
and self
.Platform
.Pcds
[key
].Type
in PCD_DYNAMIC_TYPE_SET
):
1341 Value
= self
.Platform
.Pcds
[key
]
1342 Value
.TokenCName
= self
.Platform
.Pcds
[key
].TokenCName
+ '_' + Pcd_Type
1344 newkey
= (Value
.TokenCName
, key
[1])
1346 newkey
= (Value
.TokenCName
, key
[1], key
[2])
1347 del self
.Platform
.Pcds
[key
]
1348 self
.Platform
.Pcds
[newkey
] = Value
1352 # for gathering error information
1353 NoDatumTypePcdList
= set()
1355 for InfName
in self
._AsBuildInfList
:
1356 InfName
= mws
.join(self
.WorkspaceDir
, InfName
)
1357 FdfModuleList
.append(os
.path
.normpath(InfName
))
1358 for M
in self
._MaList
:
1359 # F is the Module for which M is the module autogen
1360 for PcdFromModule
in M
.ModulePcdList
+ M
.LibraryPcdList
:
1361 # make sure that the "VOID*" kind of datum has MaxDatumSize set
1362 if PcdFromModule
.DatumType
== TAB_VOID
and not PcdFromModule
.MaxDatumSize
:
1363 NoDatumTypePcdList
.add("%s.%s [%s]" % (PcdFromModule
.TokenSpaceGuidCName
, PcdFromModule
.TokenCName
, M
.MetaFile
))
1365 # Check the PCD from Binary INF or Source INF
1366 if M
.IsBinaryModule
== True:
1367 PcdFromModule
.IsFromBinaryInf
= True
1369 # Check the PCD from DSC or not
1370 PcdFromModule
.IsFromDsc
= (PcdFromModule
.TokenCName
, PcdFromModule
.TokenSpaceGuidCName
) in self
.Platform
.Pcds
1372 if PcdFromModule
.Type
in PCD_DYNAMIC_TYPE_SET
or PcdFromModule
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
1373 if M
.MetaFile
.Path
not in FdfModuleList
:
1374 # If one of the Source built modules listed in the DSC is not listed
1375 # in FDF modules, and the INF lists a PCD can only use the PcdsDynamic
1376 # access method (it is only listed in the DEC file that declares the
1377 # PCD as PcdsDynamic), then build tool will report warning message
1378 # notify the PI that they are attempting to build a module that must
1379 # be included in a flash image in order to be functional. These Dynamic
1380 # PCD will not be added into the Database unless it is used by other
1381 # modules that are included in the FDF file.
1382 if PcdFromModule
.Type
in PCD_DYNAMIC_TYPE_SET
and \
1383 PcdFromModule
.IsFromBinaryInf
== False:
1384 # Print warning message to let the developer make a determine.
1386 # If one of the Source built modules listed in the DSC is not listed in
1387 # FDF modules, and the INF lists a PCD can only use the PcdsDynamicEx
1388 # access method (it is only listed in the DEC file that declares the
1389 # PCD as PcdsDynamicEx), then DO NOT break the build; DO NOT add the
1390 # PCD to the Platform's PCD Database.
1391 if PcdFromModule
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
1394 # If a dynamic PCD used by a PEM module/PEI module & DXE module,
1395 # it should be stored in Pcd PEI database, If a dynamic only
1396 # used by DXE module, it should be stored in DXE PCD database.
1397 # The default Phase is DXE
1399 if M
.ModuleType
in SUP_MODULE_SET_PEI
:
1400 PcdFromModule
.Phase
= "PEI"
1401 if PcdFromModule
not in self
._DynaPcdList
_:
1402 self
._DynaPcdList
_.append(PcdFromModule
)
1403 elif PcdFromModule
.Phase
== 'PEI':
1404 # overwrite any the same PCD existing, if Phase is PEI
1405 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1406 self
._DynaPcdList
_[Index
] = PcdFromModule
1407 elif PcdFromModule
not in self
._NonDynaPcdList
_:
1408 self
._NonDynaPcdList
_.append(PcdFromModule
)
1409 elif PcdFromModule
in self
._NonDynaPcdList
_ and PcdFromModule
.IsFromBinaryInf
== True:
1410 Index
= self
._NonDynaPcdList
_.index(PcdFromModule
)
1411 if self
._NonDynaPcdList
_[Index
].IsFromBinaryInf
== False:
1412 #The PCD from Binary INF will override the same one from source INF
1413 self
._NonDynaPcdList
_.remove (self
._NonDynaPcdList
_[Index
])
1414 PcdFromModule
.Pending
= False
1415 self
._NonDynaPcdList
_.append (PcdFromModule
)
1416 DscModuleSet
= {os
.path
.normpath(ModuleInf
.Path
) for ModuleInf
in self
.Platform
.Modules
}
1417 # add the PCD from modules that listed in FDF but not in DSC to Database
1418 for InfName
in FdfModuleList
:
1419 if InfName
not in DscModuleSet
:
1420 InfClass
= PathClass(InfName
)
1421 M
= self
.BuildDatabase
[InfClass
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1422 # If a module INF in FDF but not in current arch's DSC module list, it must be module (either binary or source)
1423 # for different Arch. PCDs in source module for different Arch is already added before, so skip the source module here.
1424 # For binary module, if in current arch, we need to list the PCDs into database.
1425 if not M
.IsBinaryModule
:
1427 # Override the module PCD setting by platform setting
1428 ModulePcdList
= self
.ApplyPcdSetting(M
, M
.Pcds
)
1429 for PcdFromModule
in ModulePcdList
:
1430 PcdFromModule
.IsFromBinaryInf
= True
1431 PcdFromModule
.IsFromDsc
= False
1432 # Only allow the DynamicEx and Patchable PCD in AsBuild INF
1433 if PcdFromModule
.Type
not in PCD_DYNAMIC_EX_TYPE_SET
and PcdFromModule
.Type
not in TAB_PCDS_PATCHABLE_IN_MODULE
:
1434 EdkLogger
.error("build", AUTOGEN_ERROR
, "PCD setting error",
1436 ExtraData
="\n\tExisted %s PCD %s in:\n\t\t%s\n"
1437 % (PcdFromModule
.Type
, PcdFromModule
.TokenCName
, InfName
))
1438 # make sure that the "VOID*" kind of datum has MaxDatumSize set
1439 if PcdFromModule
.DatumType
== TAB_VOID
and not PcdFromModule
.MaxDatumSize
:
1440 NoDatumTypePcdList
.add("%s.%s [%s]" % (PcdFromModule
.TokenSpaceGuidCName
, PcdFromModule
.TokenCName
, InfName
))
1441 if M
.ModuleType
in SUP_MODULE_SET_PEI
:
1442 PcdFromModule
.Phase
= "PEI"
1443 if PcdFromModule
not in self
._DynaPcdList
_ and PcdFromModule
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
1444 self
._DynaPcdList
_.append(PcdFromModule
)
1445 elif PcdFromModule
not in self
._NonDynaPcdList
_ and PcdFromModule
.Type
in TAB_PCDS_PATCHABLE_IN_MODULE
:
1446 self
._NonDynaPcdList
_.append(PcdFromModule
)
1447 if PcdFromModule
in self
._DynaPcdList
_ and PcdFromModule
.Phase
== 'PEI' and PcdFromModule
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
1448 # Overwrite the phase of any the same PCD existing, if Phase is PEI.
1449 # It is to solve the case that a dynamic PCD used by a PEM module/PEI
1450 # module & DXE module at a same time.
1451 # Overwrite the type of the PCDs in source INF by the type of AsBuild
1452 # INF file as DynamicEx.
1453 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1454 self
._DynaPcdList
_[Index
].Phase
= PcdFromModule
.Phase
1455 self
._DynaPcdList
_[Index
].Type
= PcdFromModule
.Type
1456 for PcdFromModule
in self
._NonDynaPcdList
_:
1457 # If a PCD is not listed in the DSC file, but binary INF files used by
1458 # this platform all (that use this PCD) list the PCD in a [PatchPcds]
1459 # section, AND all source INF files used by this platform the build
1460 # that use the PCD list the PCD in either a [Pcds] or [PatchPcds]
1461 # section, then the tools must NOT add the PCD to the Platform's PCD
1462 # Database; the build must assign the access method for this PCD as
1463 # PcdsPatchableInModule.
1464 if PcdFromModule
not in self
._DynaPcdList
_:
1466 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1467 if PcdFromModule
.IsFromDsc
== False and \
1468 PcdFromModule
.Type
in TAB_PCDS_PATCHABLE_IN_MODULE
and \
1469 PcdFromModule
.IsFromBinaryInf
== True and \
1470 self
._DynaPcdList
_[Index
].IsFromBinaryInf
== False:
1471 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1472 self
._DynaPcdList
_.remove (self
._DynaPcdList
_[Index
])
1474 # print out error information and break the build, if error found
1475 if len(NoDatumTypePcdList
) > 0:
1476 NoDatumTypePcdListString
= "\n\t\t".join(NoDatumTypePcdList
)
1477 EdkLogger
.error("build", AUTOGEN_ERROR
, "PCD setting error",
1479 ExtraData
="\n\tPCD(s) without MaxDatumSize:\n\t\t%s\n"
1480 % NoDatumTypePcdListString
)
1481 self
._NonDynamicPcdList
= self
._NonDynaPcdList
_
1482 self
._DynamicPcdList
= self
._DynaPcdList
_
1484 # Sort dynamic PCD list to:
1485 # 1) If PCD's datum type is VOID* and value is unicode string which starts with L, the PCD item should
1486 # try to be put header of dynamicd List
1487 # 2) If PCD is HII type, the PCD item should be put after unicode type PCD
1489 # The reason of sorting is make sure the unicode string is in double-byte alignment in string table.
1491 UnicodePcdArray
= set()
1493 OtherPcdArray
= set()
1495 VpdFile
= VpdInfoFile
.VpdInfoFile()
1496 NeedProcessVpdMapFile
= False
1498 for pcd
in self
.Platform
.Pcds
:
1499 if pcd
not in self
._PlatformPcds
:
1500 self
._PlatformPcds
[pcd
] = self
.Platform
.Pcds
[pcd
]
1502 for item
in self
._PlatformPcds
:
1503 if self
._PlatformPcds
[item
].DatumType
and self
._PlatformPcds
[item
].DatumType
not in [TAB_UINT8
, TAB_UINT16
, TAB_UINT32
, TAB_UINT64
, TAB_VOID
, "BOOLEAN"]:
1504 self
._PlatformPcds
[item
].DatumType
= TAB_VOID
1506 if (self
.Workspace
.ArchList
[-1] == self
.Arch
):
1507 for Pcd
in self
._DynamicPcdList
:
1508 # just pick the a value to determine whether is unicode string type
1509 Sku
= Pcd
.SkuInfoList
.get(TAB_DEFAULT
)
1510 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1512 if Pcd
.DatumType
not in [TAB_UINT8
, TAB_UINT16
, TAB_UINT32
, TAB_UINT64
, TAB_VOID
, "BOOLEAN"]:
1513 Pcd
.DatumType
= TAB_VOID
1515 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
1516 # if found HII type PCD then insert to right of UnicodeIndex
1517 if Pcd
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
]:
1518 VpdPcdDict
[(Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
)] = Pcd
1520 #Collect DynamicHii PCD values and assign it to DynamicExVpd PCD gEfiMdeModulePkgTokenSpaceGuid.PcdNvStoreDefaultValueBuffer
1521 PcdNvStoreDfBuffer
= VpdPcdDict
.get(("PcdNvStoreDefaultValueBuffer", "gEfiMdeModulePkgTokenSpaceGuid"))
1522 if PcdNvStoreDfBuffer
:
1523 self
.VariableInfo
= self
.CollectVariables(self
._DynamicPcdList
)
1524 vardump
= self
.VariableInfo
.dump()
1527 #According to PCD_DATABASE_INIT in edk2\MdeModulePkg\Include\Guid\PcdDataBaseSignatureGuid.h,
1528 #the max size for string PCD should not exceed USHRT_MAX 65535(0xffff).
1529 #typedef UINT16 SIZE_INFO;
1530 #//SIZE_INFO SizeTable[];
1531 if len(vardump
.split(",")) > 0xffff:
1532 EdkLogger
.error("build", RESOURCE_OVERFLOW
, 'The current length of PCD %s value is %d, it exceeds to the max size of String PCD.' %(".".join([PcdNvStoreDfBuffer
.TokenSpaceGuidCName
,PcdNvStoreDfBuffer
.TokenCName
]) ,len(vardump
.split(","))))
1533 PcdNvStoreDfBuffer
.DefaultValue
= vardump
1534 for skuname
in PcdNvStoreDfBuffer
.SkuInfoList
:
1535 PcdNvStoreDfBuffer
.SkuInfoList
[skuname
].DefaultValue
= vardump
1536 PcdNvStoreDfBuffer
.MaxDatumSize
= str(len(vardump
.split(",")))
1538 #If the end user define [DefaultStores] and [XXX.Menufacturing] in DSC, but forget to configure PcdNvStoreDefaultValueBuffer to PcdsDynamicVpd
1539 if [Pcd
for Pcd
in self
._DynamicPcdList
if Pcd
.UserDefinedDefaultStoresFlag
]:
1540 EdkLogger
.warn("build", "PcdNvStoreDefaultValueBuffer should be defined as PcdsDynamicExVpd in dsc file since the DefaultStores is enabled for this platform.\n%s" %self
.Platform
.MetaFile
.Path
)
1541 PlatformPcds
= sorted(self
._PlatformPcds
.keys())
1543 # Add VPD type PCD into VpdFile and determine whether the VPD PCD need to be fixed up.
1546 for PcdKey
in PlatformPcds
:
1547 Pcd
= self
._PlatformPcds
[PcdKey
]
1548 if Pcd
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
] and \
1549 PcdKey
in VpdPcdDict
:
1550 Pcd
= VpdPcdDict
[PcdKey
]
1552 DefaultSku
= Pcd
.SkuInfoList
.get(TAB_DEFAULT
)
1554 PcdValue
= DefaultSku
.DefaultValue
1555 if PcdValue
not in SkuValueMap
:
1556 SkuValueMap
[PcdValue
] = []
1557 VpdFile
.Add(Pcd
, TAB_DEFAULT
, DefaultSku
.VpdOffset
)
1558 SkuValueMap
[PcdValue
].append(DefaultSku
)
1560 for (SkuName
, Sku
) in Pcd
.SkuInfoList
.items():
1561 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1562 PcdValue
= Sku
.DefaultValue
1564 PcdValue
= Pcd
.DefaultValue
1565 if Sku
.VpdOffset
!= TAB_STAR
:
1566 if PcdValue
.startswith("{"):
1568 elif PcdValue
.startswith("L"):
1573 VpdOffset
= int(Sku
.VpdOffset
)
1576 VpdOffset
= int(Sku
.VpdOffset
, 16)
1578 EdkLogger
.error("build", FORMAT_INVALID
, "Invalid offset value %s for PCD %s.%s." % (Sku
.VpdOffset
, Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
1579 if VpdOffset
% Alignment
!= 0:
1580 if PcdValue
.startswith("{"):
1581 EdkLogger
.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
), File
=self
.MetaFile
)
1583 EdkLogger
.error("build", FORMAT_INVALID
, 'The offset value of PCD %s.%s should be %s-byte aligned.' % (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
, Alignment
))
1584 if PcdValue
not in SkuValueMap
:
1585 SkuValueMap
[PcdValue
] = []
1586 VpdFile
.Add(Pcd
, SkuName
, Sku
.VpdOffset
)
1587 SkuValueMap
[PcdValue
].append(Sku
)
1588 # if the offset of a VPD is *, then it need to be fixed up by third party tool.
1589 if not NeedProcessVpdMapFile
and Sku
.VpdOffset
== TAB_STAR
:
1590 NeedProcessVpdMapFile
= True
1591 if self
.Platform
.VpdToolGuid
is None or self
.Platform
.VpdToolGuid
== '':
1592 EdkLogger
.error("Build", FILE_NOT_FOUND
, \
1593 "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.")
1595 VpdSkuMap
[PcdKey
] = SkuValueMap
1597 # Fix the PCDs define in VPD PCD section that never referenced by module.
1598 # An example is PCD for signature usage.
1600 for DscPcd
in PlatformPcds
:
1601 DscPcdEntry
= self
._PlatformPcds
[DscPcd
]
1602 if DscPcdEntry
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
]:
1603 if not (self
.Platform
.VpdToolGuid
is None or self
.Platform
.VpdToolGuid
== ''):
1605 for VpdPcd
in VpdFile
._VpdArray
:
1606 # This PCD has been referenced by module
1607 if (VpdPcd
.TokenSpaceGuidCName
== DscPcdEntry
.TokenSpaceGuidCName
) and \
1608 (VpdPcd
.TokenCName
== DscPcdEntry
.TokenCName
):
1611 # Not found, it should be signature
1613 # just pick the a value to determine whether is unicode string type
1615 SkuObjList
= list(DscPcdEntry
.SkuInfoList
.items())
1616 DefaultSku
= DscPcdEntry
.SkuInfoList
.get(TAB_DEFAULT
)
1618 defaultindex
= SkuObjList
.index((TAB_DEFAULT
, DefaultSku
))
1619 SkuObjList
[0], SkuObjList
[defaultindex
] = SkuObjList
[defaultindex
], SkuObjList
[0]
1620 for (SkuName
, Sku
) in SkuObjList
:
1621 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1623 # Need to iterate DEC pcd information to get the value & datumtype
1624 for eachDec
in self
.PackageList
:
1625 for DecPcd
in eachDec
.Pcds
:
1626 DecPcdEntry
= eachDec
.Pcds
[DecPcd
]
1627 if (DecPcdEntry
.TokenSpaceGuidCName
== DscPcdEntry
.TokenSpaceGuidCName
) and \
1628 (DecPcdEntry
.TokenCName
== DscPcdEntry
.TokenCName
):
1629 # Print warning message to let the developer make a determine.
1630 EdkLogger
.warn("build", "Unreferenced vpd pcd used!",
1631 File
=self
.MetaFile
, \
1632 ExtraData
= "PCD: %s.%s used in the DSC file %s is unreferenced." \
1633 %(DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
, self
.Platform
.MetaFile
.Path
))
1635 DscPcdEntry
.DatumType
= DecPcdEntry
.DatumType
1636 DscPcdEntry
.DefaultValue
= DecPcdEntry
.DefaultValue
1637 DscPcdEntry
.TokenValue
= DecPcdEntry
.TokenValue
1638 DscPcdEntry
.TokenSpaceGuidValue
= eachDec
.Guids
[DecPcdEntry
.TokenSpaceGuidCName
]
1639 # Only fix the value while no value provided in DSC file.
1640 if not Sku
.DefaultValue
:
1641 DscPcdEntry
.SkuInfoList
[list(DscPcdEntry
.SkuInfoList
.keys())[0]].DefaultValue
= DecPcdEntry
.DefaultValue
1643 if DscPcdEntry
not in self
._DynamicPcdList
:
1644 self
._DynamicPcdList
.append(DscPcdEntry
)
1645 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1646 PcdValue
= Sku
.DefaultValue
1648 PcdValue
= DscPcdEntry
.DefaultValue
1649 if Sku
.VpdOffset
!= TAB_STAR
:
1650 if PcdValue
.startswith("{"):
1652 elif PcdValue
.startswith("L"):
1657 VpdOffset
= int(Sku
.VpdOffset
)
1660 VpdOffset
= int(Sku
.VpdOffset
, 16)
1662 EdkLogger
.error("build", FORMAT_INVALID
, "Invalid offset value %s for PCD %s.%s." % (Sku
.VpdOffset
, DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
))
1663 if VpdOffset
% Alignment
!= 0:
1664 if PcdValue
.startswith("{"):
1665 EdkLogger
.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
), File
=self
.MetaFile
)
1667 EdkLogger
.error("build", FORMAT_INVALID
, 'The offset value of PCD %s.%s should be %s-byte aligned.' % (DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
, Alignment
))
1668 if PcdValue
not in SkuValueMap
:
1669 SkuValueMap
[PcdValue
] = []
1670 VpdFile
.Add(DscPcdEntry
, SkuName
, Sku
.VpdOffset
)
1671 SkuValueMap
[PcdValue
].append(Sku
)
1672 if not NeedProcessVpdMapFile
and Sku
.VpdOffset
== TAB_STAR
:
1673 NeedProcessVpdMapFile
= True
1674 if DscPcdEntry
.DatumType
== TAB_VOID
and PcdValue
.startswith("L"):
1675 UnicodePcdArray
.add(DscPcdEntry
)
1676 elif len(Sku
.VariableName
) > 0:
1677 HiiPcdArray
.add(DscPcdEntry
)
1679 OtherPcdArray
.add(DscPcdEntry
)
1681 # if the offset of a VPD is *, then it need to be fixed up by third party tool.
1682 VpdSkuMap
[DscPcd
] = SkuValueMap
1683 if (self
.Platform
.FlashDefinition
is None or self
.Platform
.FlashDefinition
== '') and \
1684 VpdFile
.GetCount() != 0:
1685 EdkLogger
.error("build", ATTRIBUTE_NOT_AVAILABLE
,
1686 "Fail to get FLASH_DEFINITION definition in DSC file %s which is required when DSC contains VPD PCD." % str(self
.Platform
.MetaFile
))
1688 if VpdFile
.GetCount() != 0:
1690 self
.FixVpdOffset(VpdFile
)
1692 self
.FixVpdOffset(self
.UpdateNVStoreMaxSize(VpdFile
))
1693 PcdNvStoreDfBuffer
= [item
for item
in self
._DynamicPcdList
if item
.TokenCName
== "PcdNvStoreDefaultValueBuffer" and item
.TokenSpaceGuidCName
== "gEfiMdeModulePkgTokenSpaceGuid"]
1694 if PcdNvStoreDfBuffer
:
1695 PcdName
,PcdGuid
= PcdNvStoreDfBuffer
[0].TokenCName
, PcdNvStoreDfBuffer
[0].TokenSpaceGuidCName
1696 if (PcdName
,PcdGuid
) in VpdSkuMap
:
1697 DefaultSku
= PcdNvStoreDfBuffer
[0].SkuInfoList
.get(TAB_DEFAULT
)
1698 VpdSkuMap
[(PcdName
,PcdGuid
)] = {DefaultSku
.DefaultValue
:[SkuObj
for SkuObj
in PcdNvStoreDfBuffer
[0].SkuInfoList
.values() ]}
1700 # Process VPD map file generated by third party BPDG tool
1701 if NeedProcessVpdMapFile
:
1702 VpdMapFilePath
= os
.path
.join(self
.BuildDir
, TAB_FV_DIRECTORY
, "%s.map" % self
.Platform
.VpdToolGuid
)
1703 if os
.path
.exists(VpdMapFilePath
):
1704 VpdFile
.Read(VpdMapFilePath
)
1706 # Fixup TAB_STAR offset
1707 for pcd
in VpdSkuMap
:
1708 vpdinfo
= VpdFile
.GetVpdInfo(pcd
)
1710 # just pick the a value to determine whether is unicode string type
1712 for pcdvalue
in VpdSkuMap
[pcd
]:
1713 for sku
in VpdSkuMap
[pcd
][pcdvalue
]:
1714 for item
in vpdinfo
:
1715 if item
[2] == pcdvalue
:
1716 sku
.VpdOffset
= item
[1]
1718 EdkLogger
.error("build", FILE_READ_FAILURE
, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath
)
1720 # Delete the DynamicPcdList At the last time enter into this function
1721 for Pcd
in self
._DynamicPcdList
:
1722 # just pick the a value to determine whether is unicode string type
1723 Sku
= Pcd
.SkuInfoList
.get(TAB_DEFAULT
)
1724 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1726 if Pcd
.DatumType
not in [TAB_UINT8
, TAB_UINT16
, TAB_UINT32
, TAB_UINT64
, TAB_VOID
, "BOOLEAN"]:
1727 Pcd
.DatumType
= TAB_VOID
1729 PcdValue
= Sku
.DefaultValue
1730 if Pcd
.DatumType
== TAB_VOID
and PcdValue
.startswith("L"):
1731 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
1732 UnicodePcdArray
.add(Pcd
)
1733 elif len(Sku
.VariableName
) > 0:
1734 # if found HII type PCD then insert to right of UnicodeIndex
1735 HiiPcdArray
.add(Pcd
)
1737 OtherPcdArray
.add(Pcd
)
1738 del self
._DynamicPcdList
[:]
1739 self
._DynamicPcdList
.extend(list(UnicodePcdArray
))
1740 self
._DynamicPcdList
.extend(list(HiiPcdArray
))
1741 self
._DynamicPcdList
.extend(list(OtherPcdArray
))
1742 allskuset
= [(SkuName
, Sku
.SkuId
) for pcd
in self
._DynamicPcdList
for (SkuName
, Sku
) in pcd
.SkuInfoList
.items()]
1743 for pcd
in self
._DynamicPcdList
:
1744 if len(pcd
.SkuInfoList
) == 1:
1745 for (SkuName
, SkuId
) in allskuset
:
1746 if isinstance(SkuId
, str) and eval(SkuId
) == 0 or SkuId
== 0:
1748 pcd
.SkuInfoList
[SkuName
] = copy
.deepcopy(pcd
.SkuInfoList
[TAB_DEFAULT
])
1749 pcd
.SkuInfoList
[SkuName
].SkuId
= SkuId
1750 pcd
.SkuInfoList
[SkuName
].SkuIdName
= SkuName
1752 def FixVpdOffset(self
, VpdFile
):
1753 FvPath
= os
.path
.join(self
.BuildDir
, TAB_FV_DIRECTORY
)
1754 if not os
.path
.exists(FvPath
):
1758 EdkLogger
.error("build", FILE_WRITE_FAILURE
, "Fail to create FV folder under %s" % self
.BuildDir
)
1760 VpdFilePath
= os
.path
.join(FvPath
, "%s.txt" % self
.Platform
.VpdToolGuid
)
1762 if VpdFile
.Write(VpdFilePath
):
1763 # retrieve BPDG tool's path from tool_def.txt according to VPD_TOOL_GUID defined in DSC file.
1765 for ToolDef
in self
.ToolDefinition
.values():
1766 if TAB_GUID
in ToolDef
and ToolDef
[TAB_GUID
] == self
.Platform
.VpdToolGuid
:
1767 if "PATH" not in ToolDef
:
1768 EdkLogger
.error("build", ATTRIBUTE_NOT_AVAILABLE
, "PATH attribute was not provided for BPDG guid tool %s in tools_def.txt" % self
.Platform
.VpdToolGuid
)
1769 BPDGToolName
= ToolDef
["PATH"]
1771 # Call third party GUID BPDG tool.
1772 if BPDGToolName
is not None:
1773 VpdInfoFile
.CallExtenalBPDGTool(BPDGToolName
, VpdFilePath
)
1775 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.")
1777 ## Return the platform build data object
1780 return self
.BuildDatabase
[self
.MetaFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1782 ## Return platform name
1785 return self
.Platform
.PlatformName
1787 ## Return the meta file GUID
1790 return self
.Platform
.Guid
1792 ## Return the platform version
1795 return self
.Platform
.Version
1797 ## Return the FDF file name
1800 if self
.Workspace
.FdfFile
:
1801 RetVal
= mws
.join(self
.WorkspaceDir
, self
.Workspace
.FdfFile
)
1806 ## Return the build output directory platform specifies
1808 def OutputDir(self
):
1809 return self
.Platform
.OutputDirectory
1811 ## Return the directory to store all intermediate and final files built
1814 if os
.path
.isabs(self
.OutputDir
):
1815 GlobalData
.gBuildDirectory
= RetVal
= path
.join(
1816 path
.abspath(self
.OutputDir
),
1817 self
.BuildTarget
+ "_" + self
.ToolChain
,
1820 GlobalData
.gBuildDirectory
= RetVal
= path
.join(
1823 self
.BuildTarget
+ "_" + self
.ToolChain
,
1827 ## Return directory of platform makefile
1829 # @retval string Makefile directory
1832 def MakeFileDir(self
):
1833 return path
.join(self
.BuildDir
, self
.Arch
)
1835 ## Return build command string
1837 # @retval string Build command string
1840 def BuildCommand(self
):
1842 if "MAKE" in self
.ToolDefinition
and "PATH" in self
.ToolDefinition
["MAKE"]:
1843 RetVal
+= _SplitOption(self
.ToolDefinition
["MAKE"]["PATH"])
1844 if "FLAGS" in self
.ToolDefinition
["MAKE"]:
1845 NewOption
= self
.ToolDefinition
["MAKE"]["FLAGS"].strip()
1847 RetVal
+= _SplitOption(NewOption
)
1848 if "MAKE" in self
.EdkIIBuildOption
:
1849 if "FLAGS" in self
.EdkIIBuildOption
["MAKE"]:
1850 Flags
= self
.EdkIIBuildOption
["MAKE"]["FLAGS"]
1851 if Flags
.startswith('='):
1852 RetVal
= [RetVal
[0]] + [Flags
[1:]]
1854 RetVal
.append(Flags
)
1857 ## Get tool chain definition
1859 # Get each tool definition for given tool chain from tools_def.txt and platform
1862 def ToolDefinition(self
):
1863 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDictionary
1864 if TAB_TOD_DEFINES_COMMAND_TYPE
not in self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
:
1865 EdkLogger
.error('build', RESOURCE_NOT_AVAILABLE
, "No tools found in configuration",
1866 ExtraData
="[%s]" % self
.MetaFile
)
1867 RetVal
= OrderedDict()
1869 for Def
in ToolDefinition
:
1870 Target
, Tag
, Arch
, Tool
, Attr
= Def
.split("_")
1871 if Target
!= self
.BuildTarget
or Tag
!= self
.ToolChain
or Arch
!= self
.Arch
:
1874 Value
= ToolDefinition
[Def
]
1875 # don't record the DLL
1877 DllPathList
.add(Value
)
1880 if Tool
not in RetVal
:
1881 RetVal
[Tool
] = OrderedDict()
1882 RetVal
[Tool
][Attr
] = Value
1885 if GlobalData
.gOptions
.SilentMode
and "MAKE" in RetVal
:
1886 if "FLAGS" not in RetVal
["MAKE"]:
1887 RetVal
["MAKE"]["FLAGS"] = ""
1888 RetVal
["MAKE"]["FLAGS"] += " -s"
1891 for Attr
in RetVal
[Tool
]:
1892 Value
= RetVal
[Tool
][Attr
]
1893 if Tool
in self
._BuildOptionWithToolDef
(RetVal
) and Attr
in self
._BuildOptionWithToolDef
(RetVal
)[Tool
]:
1894 # check if override is indicated
1895 if self
._BuildOptionWithToolDef
(RetVal
)[Tool
][Attr
].startswith('='):
1896 Value
= self
._BuildOptionWithToolDef
(RetVal
)[Tool
][Attr
][1:]
1899 Value
+= " " + self
._BuildOptionWithToolDef
(RetVal
)[Tool
][Attr
]
1901 Value
= self
._BuildOptionWithToolDef
(RetVal
)[Tool
][Attr
]
1904 # Don't put MAKE definition in the file
1906 ToolsDef
+= "%s = %s\n" % (Tool
, Value
)
1908 # Don't put MAKE definition in the file
1913 ToolsDef
+= "%s_%s = %s\n" % (Tool
, Attr
, Value
)
1915 tool_def_file
= os
.path
.join(self
.MakeFileDir
, "TOOLS_DEF." + self
.Arch
)
1916 SaveFileOnChange(tool_def_file
, ToolsDef
, False)
1917 for DllPath
in DllPathList
:
1918 os
.environ
["PATH"] = DllPath
+ os
.pathsep
+ os
.environ
["PATH"]
1919 os
.environ
["MAKE_FLAGS"] = MakeFlags
1923 ## Return the paths of tools
1925 def ToolDefinitionFile(self
):
1926 tool_def_file
= os
.path
.join(self
.MakeFileDir
, "TOOLS_DEF." + self
.Arch
)
1927 if not os
.path
.exists(tool_def_file
):
1929 return tool_def_file
1931 ## Retrieve the toolchain family of given toolchain tag. Default to 'MSFT'.
1933 def ToolChainFamily(self
):
1934 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
1935 if TAB_TOD_DEFINES_FAMILY
not in ToolDefinition \
1936 or self
.ToolChain
not in ToolDefinition
[TAB_TOD_DEFINES_FAMILY
] \
1937 or not ToolDefinition
[TAB_TOD_DEFINES_FAMILY
][self
.ToolChain
]:
1938 EdkLogger
.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
1940 RetVal
= TAB_COMPILER_MSFT
1942 RetVal
= ToolDefinition
[TAB_TOD_DEFINES_FAMILY
][self
.ToolChain
]
1946 def BuildRuleFamily(self
):
1947 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
1948 if TAB_TOD_DEFINES_BUILDRULEFAMILY
not in ToolDefinition \
1949 or self
.ToolChain
not in ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
] \
1950 or not ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
][self
.ToolChain
]:
1951 EdkLogger
.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
1953 return TAB_COMPILER_MSFT
1955 return ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
][self
.ToolChain
]
1957 ## Return the build options specific for all modules in this platform
1959 def BuildOption(self
):
1960 return self
._ExpandBuildOption
(self
.Platform
.BuildOptions
)
1962 def _BuildOptionWithToolDef(self
, ToolDef
):
1963 return self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, ToolDef
=ToolDef
)
1965 ## Return the build options specific for EDK modules in this platform
1967 def EdkBuildOption(self
):
1968 return self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, EDK_NAME
)
1970 ## Return the build options specific for EDKII modules in this platform
1972 def EdkIIBuildOption(self
):
1973 return self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, EDKII_NAME
)
1975 ## Parse build_rule.txt in Conf Directory.
1977 # @retval BuildRule object
1980 def BuildRule(self
):
1981 BuildRuleFile
= None
1982 if TAB_TAT_DEFINES_BUILD_RULE_CONF
in self
.Workspace
.TargetTxt
.TargetTxtDictionary
:
1983 BuildRuleFile
= self
.Workspace
.TargetTxt
.TargetTxtDictionary
[TAB_TAT_DEFINES_BUILD_RULE_CONF
]
1984 if not BuildRuleFile
:
1985 BuildRuleFile
= gDefaultBuildRuleFile
1986 RetVal
= BuildRule(BuildRuleFile
)
1987 if RetVal
._FileVersion
== "":
1988 RetVal
._FileVersion
= AutoGenReqBuildRuleVerNum
1990 if RetVal
._FileVersion
< AutoGenReqBuildRuleVerNum
:
1991 # If Build Rule's version is less than the version number required by the tools, halting the build.
1992 EdkLogger
.error("build", AUTOGEN_ERROR
,
1993 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])"\
1994 % (RetVal
._FileVersion
, AutoGenReqBuildRuleVerNum
))
1997 ## Summarize the packages used by modules in this platform
1999 def PackageList(self
):
2001 for La
in self
.LibraryAutoGenList
:
2002 RetVal
.update(La
.DependentPackageList
)
2003 for Ma
in self
.ModuleAutoGenList
:
2004 RetVal
.update(Ma
.DependentPackageList
)
2005 #Collect package set information from INF of FDF
2006 for ModuleFile
in self
._AsBuildModuleList
:
2007 if ModuleFile
in self
.Platform
.Modules
:
2009 ModuleData
= self
.BuildDatabase
[ModuleFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
2010 RetVal
.update(ModuleData
.Packages
)
2014 def NonDynamicPcdDict(self
):
2015 return {(Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
):Pcd
for Pcd
in self
.NonDynamicPcdList
}
2017 ## Get list of non-dynamic PCDs
2019 def NonDynamicPcdList(self
):
2020 if not self
._NonDynamicPcdList
:
2021 self
.CollectPlatformDynamicPcds()
2022 return self
._NonDynamicPcdList
2024 ## Get list of dynamic PCDs
2026 def DynamicPcdList(self
):
2027 if not self
._DynamicPcdList
:
2028 self
.CollectPlatformDynamicPcds()
2029 return self
._DynamicPcdList
2031 ## Generate Token Number for all PCD
2033 def PcdTokenNumber(self
):
2034 RetVal
= OrderedDict()
2037 # Make the Dynamic and DynamicEx PCD use within different TokenNumber area.
2041 # TokenNumber 0 ~ 10
2043 # TokeNumber 11 ~ 20
2045 for Pcd
in self
.DynamicPcdList
:
2046 if Pcd
.Phase
== "PEI" and Pcd
.Type
in PCD_DYNAMIC_TYPE_SET
:
2047 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
2048 RetVal
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2051 for Pcd
in self
.DynamicPcdList
:
2052 if Pcd
.Phase
== "PEI" and Pcd
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
2053 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
2054 RetVal
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2057 for Pcd
in self
.DynamicPcdList
:
2058 if Pcd
.Phase
== "DXE" and Pcd
.Type
in PCD_DYNAMIC_TYPE_SET
:
2059 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
2060 RetVal
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2063 for Pcd
in self
.DynamicPcdList
:
2064 if Pcd
.Phase
== "DXE" and Pcd
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
2065 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
2066 RetVal
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2069 for Pcd
in self
.NonDynamicPcdList
:
2070 RetVal
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2076 for ModuleFile
in self
.Platform
.Modules
:
2085 self
.Platform
.Modules
[ModuleFile
].M
= Ma
2086 return [x
.M
for x
in self
.Platform
.Modules
.values()]
2088 ## Summarize ModuleAutoGen objects of all modules to be built for this platform
2090 def ModuleAutoGenList(self
):
2092 for Ma
in self
._MaList
:
2093 if Ma
not in RetVal
:
2097 ## Summarize ModuleAutoGen objects of all libraries to be built for this platform
2099 def LibraryAutoGenList(self
):
2101 for Ma
in self
._MaList
:
2102 for La
in Ma
.LibraryAutoGenList
:
2103 if La
not in RetVal
:
2105 if Ma
not in La
.ReferenceModules
:
2106 La
.ReferenceModules
.append(Ma
)
2109 ## Test if a module is supported by the platform
2111 # An error will be raised directly if the module or its arch is not supported
2112 # by the platform or current configuration
2114 def ValidModule(self
, Module
):
2115 return Module
in self
.Platform
.Modules
or Module
in self
.Platform
.LibraryInstances \
2116 or Module
in self
._AsBuildModuleList
2118 ## Resolve the library classes in a module to library instances
2120 # This method will not only resolve library classes but also sort the library
2121 # instances according to the dependency-ship.
2123 # @param Module The module from which the library classes will be resolved
2125 # @retval library_list List of library instances sorted
2127 def ApplyLibraryInstance(self
, Module
):
2128 # Cover the case that the binary INF file is list in the FDF file but not DSC file, return empty list directly
2129 if str(Module
) not in self
.Platform
.Modules
:
2132 return GetModuleLibInstances(Module
,
2141 ## Override PCD setting (type, value, ...)
2143 # @param ToPcd The PCD to be overridden
2144 # @param FromPcd The PCD overriding from
2146 def _OverridePcd(self
, ToPcd
, FromPcd
, Module
="", Msg
="", Library
=""):
2148 # in case there's PCDs coming from FDF file, which have no type given.
2149 # at this point, ToPcd.Type has the type found from dependent
2152 TokenCName
= ToPcd
.TokenCName
2153 for PcdItem
in GlobalData
.MixedPcd
:
2154 if (ToPcd
.TokenCName
, ToPcd
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
2155 TokenCName
= PcdItem
[0]
2157 if FromPcd
is not None:
2158 if ToPcd
.Pending
and FromPcd
.Type
:
2159 ToPcd
.Type
= FromPcd
.Type
2160 elif ToPcd
.Type
and FromPcd
.Type\
2161 and ToPcd
.Type
!= FromPcd
.Type
and ToPcd
.Type
in FromPcd
.Type
:
2162 if ToPcd
.Type
.strip() == TAB_PCDS_DYNAMIC_EX
:
2163 ToPcd
.Type
= FromPcd
.Type
2164 elif ToPcd
.Type
and FromPcd
.Type \
2165 and ToPcd
.Type
!= FromPcd
.Type
:
2167 Module
= str(Module
) + " 's library file (" + str(Library
) + ")"
2168 EdkLogger
.error("build", OPTION_CONFLICT
, "Mismatched PCD type",
2169 ExtraData
="%s.%s is used as [%s] in module %s, but as [%s] in %s."\
2170 % (ToPcd
.TokenSpaceGuidCName
, TokenCName
,
2171 ToPcd
.Type
, Module
, FromPcd
.Type
, Msg
),
2174 if FromPcd
.MaxDatumSize
:
2175 ToPcd
.MaxDatumSize
= FromPcd
.MaxDatumSize
2176 ToPcd
.MaxSizeUserSet
= FromPcd
.MaxDatumSize
2177 if FromPcd
.DefaultValue
:
2178 ToPcd
.DefaultValue
= FromPcd
.DefaultValue
2179 if FromPcd
.TokenValue
:
2180 ToPcd
.TokenValue
= FromPcd
.TokenValue
2181 if FromPcd
.DatumType
:
2182 ToPcd
.DatumType
= FromPcd
.DatumType
2183 if FromPcd
.SkuInfoList
:
2184 ToPcd
.SkuInfoList
= FromPcd
.SkuInfoList
2185 if FromPcd
.UserDefinedDefaultStoresFlag
:
2186 ToPcd
.UserDefinedDefaultStoresFlag
= FromPcd
.UserDefinedDefaultStoresFlag
2187 # Add Flexible PCD format parse
2188 if ToPcd
.DefaultValue
:
2190 ToPcd
.DefaultValue
= ValueExpressionEx(ToPcd
.DefaultValue
, ToPcd
.DatumType
, self
.Workspace
._GuidDict
)(True)
2191 except BadExpression
as Value
:
2192 EdkLogger
.error('Parser', FORMAT_INVALID
, 'PCD [%s.%s] Value "%s", %s' %(ToPcd
.TokenSpaceGuidCName
, ToPcd
.TokenCName
, ToPcd
.DefaultValue
, Value
),
2195 # check the validation of datum
2196 IsValid
, Cause
= CheckPcdDatum(ToPcd
.DatumType
, ToPcd
.DefaultValue
)
2198 EdkLogger
.error('build', FORMAT_INVALID
, Cause
, File
=self
.MetaFile
,
2199 ExtraData
="%s.%s" % (ToPcd
.TokenSpaceGuidCName
, TokenCName
))
2200 ToPcd
.validateranges
= FromPcd
.validateranges
2201 ToPcd
.validlists
= FromPcd
.validlists
2202 ToPcd
.expressions
= FromPcd
.expressions
2203 ToPcd
.CustomAttribute
= FromPcd
.CustomAttribute
2205 if FromPcd
is not None and ToPcd
.DatumType
== TAB_VOID
and not ToPcd
.MaxDatumSize
:
2206 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "No MaxDatumSize specified for PCD %s.%s" \
2207 % (ToPcd
.TokenSpaceGuidCName
, TokenCName
))
2208 Value
= ToPcd
.DefaultValue
2210 ToPcd
.MaxDatumSize
= '1'
2211 elif Value
[0] == 'L':
2212 ToPcd
.MaxDatumSize
= str((len(Value
) - 2) * 2)
2213 elif Value
[0] == '{':
2214 ToPcd
.MaxDatumSize
= str(len(Value
.split(',')))
2216 ToPcd
.MaxDatumSize
= str(len(Value
) - 1)
2218 # apply default SKU for dynamic PCDS if specified one is not available
2219 if (ToPcd
.Type
in PCD_DYNAMIC_TYPE_SET
or ToPcd
.Type
in PCD_DYNAMIC_EX_TYPE_SET
) \
2220 and not ToPcd
.SkuInfoList
:
2221 if self
.Platform
.SkuName
in self
.Platform
.SkuIds
:
2222 SkuName
= self
.Platform
.SkuName
2224 SkuName
= TAB_DEFAULT
2225 ToPcd
.SkuInfoList
= {
2226 SkuName
: SkuInfoClass(SkuName
, self
.Platform
.SkuIds
[SkuName
][0], '', '', '', '', '', ToPcd
.DefaultValue
)
2229 ## Apply PCD setting defined platform to a module
2231 # @param Module The module from which the PCD setting will be overridden
2233 # @retval PCD_list The list PCDs with settings from platform
2235 def ApplyPcdSetting(self
, Module
, Pcds
, Library
=""):
2236 # for each PCD in module
2237 for Name
, Guid
in Pcds
:
2238 PcdInModule
= Pcds
[Name
, Guid
]
2239 # find out the PCD setting in platform
2240 if (Name
, Guid
) in self
.Platform
.Pcds
:
2241 PcdInPlatform
= self
.Platform
.Pcds
[Name
, Guid
]
2243 PcdInPlatform
= None
2244 # then override the settings if any
2245 self
._OverridePcd
(PcdInModule
, PcdInPlatform
, Module
, Msg
="DSC PCD sections", Library
=Library
)
2246 # resolve the VariableGuid value
2247 for SkuId
in PcdInModule
.SkuInfoList
:
2248 Sku
= PcdInModule
.SkuInfoList
[SkuId
]
2249 if Sku
.VariableGuid
== '': continue
2250 Sku
.VariableGuidValue
= GuidValue(Sku
.VariableGuid
, self
.PackageList
, self
.MetaFile
.Path
)
2251 if Sku
.VariableGuidValue
is None:
2252 PackageList
= "\n\t".join(str(P
) for P
in self
.PackageList
)
2255 RESOURCE_NOT_AVAILABLE
,
2256 "Value of GUID [%s] is not found in" % Sku
.VariableGuid
,
2257 ExtraData
=PackageList
+ "\n\t(used with %s.%s from module %s)" \
2258 % (Guid
, Name
, str(Module
)),
2262 # override PCD settings with module specific setting
2263 if Module
in self
.Platform
.Modules
:
2264 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
2265 for Key
in PlatformModule
.Pcds
:
2266 if GlobalData
.BuildOptionPcd
:
2267 for pcd
in GlobalData
.BuildOptionPcd
:
2268 (TokenSpaceGuidCName
, TokenCName
, FieldName
, pcdvalue
, _
) = pcd
2269 if (TokenCName
, TokenSpaceGuidCName
) == Key
and FieldName
=="":
2270 PlatformModule
.Pcds
[Key
].DefaultValue
= pcdvalue
2271 PlatformModule
.Pcds
[Key
].PcdValueFromComm
= pcdvalue
2277 elif Key
in GlobalData
.MixedPcd
:
2278 for PcdItem
in GlobalData
.MixedPcd
[Key
]:
2280 ToPcd
= Pcds
[PcdItem
]
2284 self
._OverridePcd
(ToPcd
, PlatformModule
.Pcds
[Key
], Module
, Msg
="DSC Components Module scoped PCD section", Library
=Library
)
2285 # use PCD value to calculate the MaxDatumSize when it is not specified
2286 for Name
, Guid
in Pcds
:
2287 Pcd
= Pcds
[Name
, Guid
]
2288 if Pcd
.DatumType
== TAB_VOID
and not Pcd
.MaxDatumSize
:
2289 Pcd
.MaxSizeUserSet
= None
2290 Value
= Pcd
.DefaultValue
2292 Pcd
.MaxDatumSize
= '1'
2293 elif Value
[0] == 'L':
2294 Pcd
.MaxDatumSize
= str((len(Value
) - 2) * 2)
2295 elif Value
[0] == '{':
2296 Pcd
.MaxDatumSize
= str(len(Value
.split(',')))
2298 Pcd
.MaxDatumSize
= str(len(Value
) - 1)
2299 return list(Pcds
.values())
2303 ## Calculate the priority value of the build option
2305 # @param Key Build option definition contain: TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
2307 # @retval Value Priority value based on the priority list.
2309 def CalculatePriorityValue(self
, Key
):
2310 Target
, ToolChain
, Arch
, CommandType
, Attr
= Key
.split('_')
2311 PriorityValue
= 0x11111
2312 if Target
== TAB_STAR
:
2313 PriorityValue
&= 0x01111
2314 if ToolChain
== TAB_STAR
:
2315 PriorityValue
&= 0x10111
2316 if Arch
== TAB_STAR
:
2317 PriorityValue
&= 0x11011
2318 if CommandType
== TAB_STAR
:
2319 PriorityValue
&= 0x11101
2320 if Attr
== TAB_STAR
:
2321 PriorityValue
&= 0x11110
2323 return self
.PrioList
["0x%0.5x" % PriorityValue
]
2326 ## Expand * in build option key
2328 # @param Options Options to be expanded
2329 # @param ToolDef Use specified ToolDef instead of full version.
2330 # This is needed during initialization to prevent
2331 # infinite recursion betweeh BuildOptions,
2332 # ToolDefinition, and this function.
2334 # @retval options Options expanded
2336 def _ExpandBuildOption(self
, Options
, ModuleStyle
=None, ToolDef
=None):
2338 ToolDef
= self
.ToolDefinition
2345 # Construct a list contain the build options which need override.
2349 # Key[0] -- tool family
2350 # Key[1] -- TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
2352 if (Key
[0] == self
.BuildRuleFamily
and
2353 (ModuleStyle
is None or len(Key
) < 3 or (len(Key
) > 2 and Key
[2] == ModuleStyle
))):
2354 Target
, ToolChain
, Arch
, CommandType
, Attr
= Key
[1].split('_')
2355 if (Target
== self
.BuildTarget
or Target
== TAB_STAR
) and\
2356 (ToolChain
== self
.ToolChain
or ToolChain
== TAB_STAR
) and\
2357 (Arch
== self
.Arch
or Arch
== TAB_STAR
) and\
2358 Options
[Key
].startswith("="):
2360 if OverrideList
.get(Key
[1]) is not None:
2361 OverrideList
.pop(Key
[1])
2362 OverrideList
[Key
[1]] = Options
[Key
]
2365 # Use the highest priority value.
2367 if (len(OverrideList
) >= 2):
2368 KeyList
= list(OverrideList
.keys())
2369 for Index
in range(len(KeyList
)):
2370 NowKey
= KeyList
[Index
]
2371 Target1
, ToolChain1
, Arch1
, CommandType1
, Attr1
= NowKey
.split("_")
2372 for Index1
in range(len(KeyList
) - Index
- 1):
2373 NextKey
= KeyList
[Index1
+ Index
+ 1]
2375 # Compare two Key, if one is included by another, choose the higher priority one
2377 Target2
, ToolChain2
, Arch2
, CommandType2
, Attr2
= NextKey
.split("_")
2378 if (Target1
== Target2
or Target1
== TAB_STAR
or Target2
== TAB_STAR
) and\
2379 (ToolChain1
== ToolChain2
or ToolChain1
== TAB_STAR
or ToolChain2
== TAB_STAR
) and\
2380 (Arch1
== Arch2
or Arch1
== TAB_STAR
or Arch2
== TAB_STAR
) and\
2381 (CommandType1
== CommandType2
or CommandType1
== TAB_STAR
or CommandType2
== TAB_STAR
) and\
2382 (Attr1
== Attr2
or Attr1
== TAB_STAR
or Attr2
== TAB_STAR
):
2384 if self
.CalculatePriorityValue(NowKey
) > self
.CalculatePriorityValue(NextKey
):
2385 if Options
.get((self
.BuildRuleFamily
, NextKey
)) is not None:
2386 Options
.pop((self
.BuildRuleFamily
, NextKey
))
2388 if Options
.get((self
.BuildRuleFamily
, NowKey
)) is not None:
2389 Options
.pop((self
.BuildRuleFamily
, NowKey
))
2392 if ModuleStyle
is not None and len (Key
) > 2:
2393 # Check Module style is EDK or EDKII.
2394 # Only append build option for the matched style module.
2395 if ModuleStyle
== EDK_NAME
and Key
[2] != EDK_NAME
:
2397 elif ModuleStyle
== EDKII_NAME
and Key
[2] != EDKII_NAME
:
2400 Target
, Tag
, Arch
, Tool
, Attr
= Key
[1].split("_")
2401 # if tool chain family doesn't match, skip it
2402 if Tool
in ToolDef
and Family
!= "":
2403 FamilyIsNull
= False
2404 if ToolDef
[Tool
].get(TAB_TOD_DEFINES_BUILDRULEFAMILY
, "") != "":
2405 if Family
!= ToolDef
[Tool
][TAB_TOD_DEFINES_BUILDRULEFAMILY
]:
2407 elif Family
!= ToolDef
[Tool
][TAB_TOD_DEFINES_FAMILY
]:
2410 # expand any wildcard
2411 if Target
== TAB_STAR
or Target
== self
.BuildTarget
:
2412 if Tag
== TAB_STAR
or Tag
== self
.ToolChain
:
2413 if Arch
== TAB_STAR
or Arch
== self
.Arch
:
2414 if Tool
not in BuildOptions
:
2415 BuildOptions
[Tool
] = {}
2416 if Attr
!= "FLAGS" or Attr
not in BuildOptions
[Tool
] or Options
[Key
].startswith('='):
2417 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2419 # append options for the same tool except PATH
2421 BuildOptions
[Tool
][Attr
] += " " + Options
[Key
]
2423 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2424 # Build Option Family has been checked, which need't to be checked again for family.
2425 if FamilyMatch
or FamilyIsNull
:
2429 if ModuleStyle
is not None and len (Key
) > 2:
2430 # Check Module style is EDK or EDKII.
2431 # Only append build option for the matched style module.
2432 if ModuleStyle
== EDK_NAME
and Key
[2] != EDK_NAME
:
2434 elif ModuleStyle
== EDKII_NAME
and Key
[2] != EDKII_NAME
:
2437 Target
, Tag
, Arch
, Tool
, Attr
= Key
[1].split("_")
2438 # if tool chain family doesn't match, skip it
2439 if Tool
not in ToolDef
or Family
== "":
2441 # option has been added before
2442 if Family
!= ToolDef
[Tool
][TAB_TOD_DEFINES_FAMILY
]:
2445 # expand any wildcard
2446 if Target
== TAB_STAR
or Target
== self
.BuildTarget
:
2447 if Tag
== TAB_STAR
or Tag
== self
.ToolChain
:
2448 if Arch
== TAB_STAR
or Arch
== self
.Arch
:
2449 if Tool
not in BuildOptions
:
2450 BuildOptions
[Tool
] = {}
2451 if Attr
!= "FLAGS" or Attr
not in BuildOptions
[Tool
] or Options
[Key
].startswith('='):
2452 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2454 # append options for the same tool except PATH
2456 BuildOptions
[Tool
][Attr
] += " " + Options
[Key
]
2458 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2461 ## Append build options in platform to a module
2463 # @param Module The module to which the build options will be appended
2465 # @retval options The options appended with build options in platform
2467 def ApplyBuildOption(self
, Module
):
2468 # Get the different options for the different style module
2469 PlatformOptions
= self
.EdkIIBuildOption
2470 ModuleTypeOptions
= self
.Platform
.GetBuildOptionsByModuleType(EDKII_NAME
, Module
.ModuleType
)
2471 ModuleTypeOptions
= self
._ExpandBuildOption
(ModuleTypeOptions
)
2472 ModuleOptions
= self
._ExpandBuildOption
(Module
.BuildOptions
)
2473 if Module
in self
.Platform
.Modules
:
2474 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
2475 PlatformModuleOptions
= self
._ExpandBuildOption
(PlatformModule
.BuildOptions
)
2477 PlatformModuleOptions
= {}
2479 BuildRuleOrder
= None
2480 for Options
in [self
.ToolDefinition
, ModuleOptions
, PlatformOptions
, ModuleTypeOptions
, PlatformModuleOptions
]:
2481 for Tool
in Options
:
2482 for Attr
in Options
[Tool
]:
2483 if Attr
== TAB_TOD_DEFINES_BUILDRULEORDER
:
2484 BuildRuleOrder
= Options
[Tool
][Attr
]
2486 AllTools
= set(list(ModuleOptions
.keys()) + list(PlatformOptions
.keys()) +
2487 list(PlatformModuleOptions
.keys()) + list(ModuleTypeOptions
.keys()) +
2488 list(self
.ToolDefinition
.keys()))
2489 BuildOptions
= defaultdict(lambda: defaultdict(str))
2490 for Tool
in AllTools
:
2491 for Options
in [self
.ToolDefinition
, ModuleOptions
, PlatformOptions
, ModuleTypeOptions
, PlatformModuleOptions
]:
2492 if Tool
not in Options
:
2494 for Attr
in Options
[Tool
]:
2496 # Do not generate it in Makefile
2498 if Attr
== TAB_TOD_DEFINES_BUILDRULEORDER
:
2500 Value
= Options
[Tool
][Attr
]
2501 # check if override is indicated
2502 if Value
.startswith('='):
2503 BuildOptions
[Tool
][Attr
] = mws
.handleWsMacro(Value
[1:])
2506 BuildOptions
[Tool
][Attr
] += " " + mws
.handleWsMacro(Value
)
2508 BuildOptions
[Tool
][Attr
] = mws
.handleWsMacro(Value
)
2510 return BuildOptions
, BuildRuleOrder
2513 # extend lists contained in a dictionary with lists stored in another dictionary
2514 # if CopyToDict is not derived from DefaultDict(list) then this may raise exception
2516 def ExtendCopyDictionaryLists(CopyToDict
, CopyFromDict
):
2517 for Key
in CopyFromDict
:
2518 CopyToDict
[Key
].extend(CopyFromDict
[Key
])
2520 # Create a directory specified by a set of path elements and return the full path
2521 def _MakeDir(PathList
):
2522 RetVal
= path
.join(*PathList
)
2523 CreateDirectory(RetVal
)
2526 ## ModuleAutoGen class
2528 # This class encapsules the AutoGen behaviors for the build tools. In addition to
2529 # the generation of AutoGen.h and AutoGen.c, it will generate *.depex file according
2530 # to the [depex] section in module's inf file.
2532 class ModuleAutoGen(AutoGen
):
2533 # call super().__init__ then call the worker function with different parameter count
2534 def __init__(self
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
2535 if not hasattr(self
, "_Init"):
2536 self
._InitWorker
(Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
)
2539 ## Cache the timestamps of metafiles of every module in a class attribute
2543 def __new__(cls
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
2544 # check if this module is employed by active platform
2545 if not PlatformAutoGen(Workspace
, args
[0], Target
, Toolchain
, Arch
).ValidModule(MetaFile
):
2546 EdkLogger
.verbose("Module [%s] for [%s] is not employed by active platform\n" \
2549 return super(ModuleAutoGen
, cls
).__new
__(cls
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
)
2551 ## Initialize ModuleAutoGen
2553 # @param Workspace EdkIIWorkspaceBuild object
2554 # @param ModuleFile The path of module file
2555 # @param Target Build target (DEBUG, RELEASE)
2556 # @param Toolchain Name of tool chain
2557 # @param Arch The arch the module supports
2558 # @param PlatformFile Platform meta-file
2560 def _InitWorker(self
, Workspace
, ModuleFile
, Target
, Toolchain
, Arch
, PlatformFile
):
2561 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "AutoGen module [%s] [%s]" % (ModuleFile
, Arch
))
2562 GlobalData
.gProcessingFile
= "%s [%s, %s, %s]" % (ModuleFile
, Arch
, Toolchain
, Target
)
2564 self
.Workspace
= Workspace
2565 self
.WorkspaceDir
= Workspace
.WorkspaceDir
2566 self
.MetaFile
= ModuleFile
2567 self
.PlatformInfo
= PlatformAutoGen(Workspace
, PlatformFile
, Target
, Toolchain
, Arch
)
2569 self
.SourceDir
= self
.MetaFile
.SubDir
2570 self
.SourceDir
= mws
.relpath(self
.SourceDir
, self
.WorkspaceDir
)
2572 self
.ToolChain
= Toolchain
2573 self
.BuildTarget
= Target
2575 self
.ToolChainFamily
= self
.PlatformInfo
.ToolChainFamily
2576 self
.BuildRuleFamily
= self
.PlatformInfo
.BuildRuleFamily
2578 self
.IsCodeFileCreated
= False
2579 self
.IsAsBuiltInfCreated
= False
2580 self
.DepexGenerated
= False
2582 self
.BuildDatabase
= self
.Workspace
.BuildDatabase
2583 self
.BuildRuleOrder
= None
2586 self
._PcdComments
= OrderedListDict()
2587 self
._GuidComments
= OrderedListDict()
2588 self
._ProtocolComments
= OrderedListDict()
2589 self
._PpiComments
= OrderedListDict()
2590 self
._BuildTargets
= None
2591 self
._IntroBuildTargetList
= None
2592 self
._FinalBuildTargetList
= None
2593 self
._FileTypes
= None
2595 self
.AutoGenDepSet
= set()
2596 self
.ReferenceModules
= []
2599 ## hash() operator of ModuleAutoGen
2601 # The module file path and arch string will be used to represent
2602 # hash value of this object
2604 # @retval int Hash value of the module file path and arch
2606 @cached_class_function
2608 return hash((self
.MetaFile
, self
.Arch
))
2611 return "%s [%s]" % (self
.MetaFile
, self
.Arch
)
2613 # Get FixedAtBuild Pcds of this Module
2615 def FixedAtBuildPcds(self
):
2617 for Pcd
in self
.ModulePcdList
:
2618 if Pcd
.Type
!= TAB_PCDS_FIXED_AT_BUILD
:
2620 if Pcd
not in RetVal
:
2625 def FixedVoidTypePcds(self
):
2627 for Pcd
in self
.FixedAtBuildPcds
:
2628 if Pcd
.DatumType
== TAB_VOID
:
2629 if '{}.{}'.format(Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) not in RetVal
:
2630 RetVal
['{}.{}'.format(Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
)] = Pcd
.DefaultValue
2634 def UniqueBaseName(self
):
2635 BaseName
= self
.Name
2636 for Module
in self
.PlatformInfo
.ModuleAutoGenList
:
2637 if Module
.MetaFile
== self
.MetaFile
:
2639 if Module
.Name
== self
.Name
:
2640 if uuid
.UUID(Module
.Guid
) == uuid
.UUID(self
.Guid
):
2641 EdkLogger
.error("build", FILE_DUPLICATED
, 'Modules have same BaseName and FILE_GUID:\n'
2642 ' %s\n %s' % (Module
.MetaFile
, self
.MetaFile
))
2643 BaseName
= '%s_%s' % (self
.Name
, self
.Guid
)
2646 # Macros could be used in build_rule.txt (also Makefile)
2649 return OrderedDict((
2650 ("WORKSPACE" ,self
.WorkspaceDir
),
2651 ("MODULE_NAME" ,self
.Name
),
2652 ("MODULE_NAME_GUID" ,self
.UniqueBaseName
),
2653 ("MODULE_GUID" ,self
.Guid
),
2654 ("MODULE_VERSION" ,self
.Version
),
2655 ("MODULE_TYPE" ,self
.ModuleType
),
2656 ("MODULE_FILE" ,str(self
.MetaFile
)),
2657 ("MODULE_FILE_BASE_NAME" ,self
.MetaFile
.BaseName
),
2658 ("MODULE_RELATIVE_DIR" ,self
.SourceDir
),
2659 ("MODULE_DIR" ,self
.SourceDir
),
2660 ("BASE_NAME" ,self
.Name
),
2661 ("ARCH" ,self
.Arch
),
2662 ("TOOLCHAIN" ,self
.ToolChain
),
2663 ("TOOLCHAIN_TAG" ,self
.ToolChain
),
2664 ("TOOL_CHAIN_TAG" ,self
.ToolChain
),
2665 ("TARGET" ,self
.BuildTarget
),
2666 ("BUILD_DIR" ,self
.PlatformInfo
.BuildDir
),
2667 ("BIN_DIR" ,os
.path
.join(self
.PlatformInfo
.BuildDir
, self
.Arch
)),
2668 ("LIB_DIR" ,os
.path
.join(self
.PlatformInfo
.BuildDir
, self
.Arch
)),
2669 ("MODULE_BUILD_DIR" ,self
.BuildDir
),
2670 ("OUTPUT_DIR" ,self
.OutputDir
),
2671 ("DEBUG_DIR" ,self
.DebugDir
),
2672 ("DEST_DIR_OUTPUT" ,self
.OutputDir
),
2673 ("DEST_DIR_DEBUG" ,self
.DebugDir
),
2674 ("PLATFORM_NAME" ,self
.PlatformInfo
.Name
),
2675 ("PLATFORM_GUID" ,self
.PlatformInfo
.Guid
),
2676 ("PLATFORM_VERSION" ,self
.PlatformInfo
.Version
),
2677 ("PLATFORM_RELATIVE_DIR" ,self
.PlatformInfo
.SourceDir
),
2678 ("PLATFORM_DIR" ,mws
.join(self
.WorkspaceDir
, self
.PlatformInfo
.SourceDir
)),
2679 ("PLATFORM_OUTPUT_DIR" ,self
.PlatformInfo
.OutputDir
),
2680 ("FFS_OUTPUT_DIR" ,self
.FfsOutputDir
)
2683 ## Return the module build data object
2686 return self
.BuildDatabase
[self
.MetaFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
2688 ## Return the module name
2691 return self
.Module
.BaseName
2693 ## Return the module DxsFile if exist
2696 return self
.Module
.DxsFile
2698 ## Return the module meta-file GUID
2702 # To build same module more than once, the module path with FILE_GUID overridden has
2703 # the file name FILE_GUIDmodule.inf, but the relative path (self.MetaFile.File) is the real path
2704 # in DSC. The overridden GUID can be retrieved from file name
2706 if os
.path
.basename(self
.MetaFile
.File
) != os
.path
.basename(self
.MetaFile
.Path
):
2708 # Length of GUID is 36
2710 return os
.path
.basename(self
.MetaFile
.Path
)[:36]
2711 return self
.Module
.Guid
2713 ## Return the module version
2716 return self
.Module
.Version
2718 ## Return the module type
2720 def ModuleType(self
):
2721 return self
.Module
.ModuleType
2723 ## Return the component type (for Edk.x style of module)
2725 def ComponentType(self
):
2726 return self
.Module
.ComponentType
2728 ## Return the build type
2730 def BuildType(self
):
2731 return self
.Module
.BuildType
2733 ## Return the PCD_IS_DRIVER setting
2735 def PcdIsDriver(self
):
2736 return self
.Module
.PcdIsDriver
2738 ## Return the autogen version, i.e. module meta-file version
2740 def AutoGenVersion(self
):
2741 return self
.Module
.AutoGenVersion
2743 ## Check if the module is library or not
2745 def IsLibrary(self
):
2746 return bool(self
.Module
.LibraryClass
)
2748 ## Check if the module is binary module or not
2750 def IsBinaryModule(self
):
2751 return self
.Module
.IsBinaryModule
2753 ## Return the directory to store intermediate files of the module
2757 self
.PlatformInfo
.BuildDir
,
2760 self
.MetaFile
.BaseName
2763 ## Return the directory to store the intermediate object files of the module
2765 def OutputDir(self
):
2766 return _MakeDir((self
.BuildDir
, "OUTPUT"))
2768 ## Return the directory path to store ffs file
2770 def FfsOutputDir(self
):
2771 if GlobalData
.gFdfParser
:
2772 return path
.join(self
.PlatformInfo
.BuildDir
, TAB_FV_DIRECTORY
, "Ffs", self
.Guid
+ self
.Name
)
2775 ## Return the directory to store auto-gened source files of the module
2778 return _MakeDir((self
.BuildDir
, "DEBUG"))
2780 ## Return the path of custom file
2782 def CustomMakefile(self
):
2784 for Type
in self
.Module
.CustomMakefile
:
2785 MakeType
= gMakeTypeMap
[Type
] if Type
in gMakeTypeMap
else 'nmake'
2786 File
= os
.path
.join(self
.SourceDir
, self
.Module
.CustomMakefile
[Type
])
2787 RetVal
[MakeType
] = File
2790 ## Return the directory of the makefile
2792 # @retval string The directory string of module's makefile
2795 def MakeFileDir(self
):
2796 return self
.BuildDir
2798 ## Return build command string
2800 # @retval string Build command string
2803 def BuildCommand(self
):
2804 return self
.PlatformInfo
.BuildCommand
2806 ## Get object list of all packages the module and its dependent libraries belong to
2808 # @retval list The list of package object
2811 def DerivedPackageList(self
):
2813 for M
in [self
.Module
] + self
.DependentLibraryList
:
2814 for Package
in M
.Packages
:
2815 if Package
in PackageList
:
2817 PackageList
.append(Package
)
2820 ## Get the depex string
2822 # @return : a string contain all depex expression.
2823 def _GetDepexExpresionString(self
):
2826 ## DPX_SOURCE IN Define section.
2827 if self
.Module
.DxsFile
:
2829 for M
in [self
.Module
] + self
.DependentLibraryList
:
2830 Filename
= M
.MetaFile
.Path
2831 InfObj
= InfSectionParser
.InfSectionParser(Filename
)
2832 DepexExpressionList
= InfObj
.GetDepexExpresionList()
2833 for DepexExpression
in DepexExpressionList
:
2834 for key
in DepexExpression
:
2835 Arch
, ModuleType
= key
2836 DepexExpr
= [x
for x
in DepexExpression
[key
] if not str(x
).startswith('#')]
2837 # the type of build module is USER_DEFINED.
2838 # All different DEPEX section tags would be copied into the As Built INF file
2839 # and there would be separate DEPEX section tags
2840 if self
.ModuleType
.upper() == SUP_MODULE_USER_DEFINED
:
2841 if (Arch
.upper() == self
.Arch
.upper()) and (ModuleType
.upper() != TAB_ARCH_COMMON
):
2842 DepexList
.append({(Arch
, ModuleType
): DepexExpr
})
2844 if Arch
.upper() == TAB_ARCH_COMMON
or \
2845 (Arch
.upper() == self
.Arch
.upper() and \
2846 ModuleType
.upper() in [TAB_ARCH_COMMON
, self
.ModuleType
.upper()]):
2847 DepexList
.append({(Arch
, ModuleType
): DepexExpr
})
2849 #the type of build module is USER_DEFINED.
2850 if self
.ModuleType
.upper() == SUP_MODULE_USER_DEFINED
:
2851 for Depex
in DepexList
:
2853 DepexStr
+= '[Depex.%s.%s]\n' % key
2854 DepexStr
+= '\n'.join('# '+ val
for val
in Depex
[key
])
2857 return '[Depex.%s]\n' % self
.Arch
2860 #the type of build module not is USER_DEFINED.
2862 for Depex
in DepexList
:
2867 for D
in Depex
.values():
2868 DepexStr
+= ' '.join(val
for val
in D
)
2869 Index
= DepexStr
.find('END')
2870 if Index
> -1 and Index
== len(DepexStr
) - 3:
2871 DepexStr
= DepexStr
[:-3]
2872 DepexStr
= DepexStr
.strip()
2875 DepexStr
= DepexStr
.lstrip('(').rstrip(')').strip()
2877 return '[Depex.%s]\n' % self
.Arch
2878 return '[Depex.%s]\n# ' % self
.Arch
+ DepexStr
2880 ## Merge dependency expression
2882 # @retval list The token list of the dependency expression after parsed
2885 def DepexList(self
):
2886 if self
.DxsFile
or self
.IsLibrary
or TAB_DEPENDENCY_EXPRESSION_FILE
in self
.FileTypes
:
2891 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expression
2893 for M
in [self
.Module
] + self
.DependentLibraryList
:
2895 for D
in M
.Depex
[self
.Arch
, self
.ModuleType
]:
2897 DepexList
.append('AND')
2898 DepexList
.append('(')
2899 #replace D with value if D is FixedAtBuild PCD
2903 NewList
.append(item
)
2905 FixedVoidTypePcds
= {}
2906 if item
in self
.FixedVoidTypePcds
:
2907 FixedVoidTypePcds
= self
.FixedVoidTypePcds
2908 elif M
in self
.PlatformInfo
.LibraryAutoGenList
:
2909 Index
= self
.PlatformInfo
.LibraryAutoGenList
.index(M
)
2910 FixedVoidTypePcds
= self
.PlatformInfo
.LibraryAutoGenList
[Index
].FixedVoidTypePcds
2911 if item
not in FixedVoidTypePcds
:
2912 EdkLogger
.error("build", FORMAT_INVALID
, "{} used in [Depex] section should be used as FixedAtBuild type and VOID* datum type in the module.".format(item
))
2914 Value
= FixedVoidTypePcds
[item
]
2915 if len(Value
.split(',')) != 16:
2916 EdkLogger
.error("build", FORMAT_INVALID
,
2917 "{} used in [Depex] section should be used as FixedAtBuild type and VOID* datum type and 16 bytes in the module.".format(item
))
2918 NewList
.append(Value
)
2919 DepexList
.extend(NewList
)
2920 if DepexList
[-1] == 'END': # no need of a END at this time
2922 DepexList
.append(')')
2925 EdkLogger
.verbose("DEPEX[%s] (+%s) = %s" % (self
.Name
, M
.BaseName
, DepexList
))
2926 if 'BEFORE' in DepexList
or 'AFTER' in DepexList
:
2928 if len(DepexList
) > 0:
2929 EdkLogger
.verbose('')
2930 return {self
.ModuleType
:DepexList
}
2932 ## Merge dependency expression
2934 # @retval list The token list of the dependency expression after parsed
2937 def DepexExpressionDict(self
):
2938 if self
.DxsFile
or self
.IsLibrary
or TAB_DEPENDENCY_EXPRESSION_FILE
in self
.FileTypes
:
2941 DepexExpressionString
= ''
2943 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
2945 for M
in [self
.Module
] + self
.DependentLibraryList
:
2947 for D
in M
.DepexExpression
[self
.Arch
, self
.ModuleType
]:
2948 if DepexExpressionString
!= '':
2949 DepexExpressionString
+= ' AND '
2950 DepexExpressionString
+= '('
2951 DepexExpressionString
+= D
2952 DepexExpressionString
= DepexExpressionString
.rstrip('END').strip()
2953 DepexExpressionString
+= ')'
2956 EdkLogger
.verbose("DEPEX[%s] (+%s) = %s" % (self
.Name
, M
.BaseName
, DepexExpressionString
))
2957 if 'BEFORE' in DepexExpressionString
or 'AFTER' in DepexExpressionString
:
2959 if len(DepexExpressionString
) > 0:
2960 EdkLogger
.verbose('')
2962 return {self
.ModuleType
:DepexExpressionString
}
2964 # Get the tiano core user extension, it is contain dependent library.
2965 # @retval: a list contain tiano core userextension.
2967 def _GetTianoCoreUserExtensionList(self
):
2968 TianoCoreUserExtentionList
= []
2969 for M
in [self
.Module
] + self
.DependentLibraryList
:
2970 Filename
= M
.MetaFile
.Path
2971 InfObj
= InfSectionParser
.InfSectionParser(Filename
)
2972 TianoCoreUserExtenList
= InfObj
.GetUserExtensionTianoCore()
2973 for TianoCoreUserExtent
in TianoCoreUserExtenList
:
2974 for Section
in TianoCoreUserExtent
:
2975 ItemList
= Section
.split(TAB_SPLIT
)
2977 if len(ItemList
) == 4:
2979 if Arch
.upper() == TAB_ARCH_COMMON
or Arch
.upper() == self
.Arch
.upper():
2981 TianoCoreList
.extend([TAB_SECTION_START
+ Section
+ TAB_SECTION_END
])
2982 TianoCoreList
.extend(TianoCoreUserExtent
[Section
][:])
2983 TianoCoreList
.append('\n')
2984 TianoCoreUserExtentionList
.append(TianoCoreList
)
2986 return TianoCoreUserExtentionList
2988 ## Return the list of specification version required for the module
2990 # @retval list The list of specification defined in module file
2993 def Specification(self
):
2994 return self
.Module
.Specification
2996 ## Tool option for the module build
2998 # @param PlatformInfo The object of PlatformBuildInfo
2999 # @retval dict The dict containing valid options
3002 def BuildOption(self
):
3003 RetVal
, self
.BuildRuleOrder
= self
.PlatformInfo
.ApplyBuildOption(self
.Module
)
3004 if self
.BuildRuleOrder
:
3005 self
.BuildRuleOrder
= ['.%s' % Ext
for Ext
in self
.BuildRuleOrder
.split()]
3008 ## Get include path list from tool option for the module build
3010 # @retval list The include path list
3013 def BuildOptionIncPathList(self
):
3015 # Regular expression for finding Include Directories, the difference between MSFT and INTEL/GCC/RVCT
3016 # is the former use /I , the Latter used -I to specify include directories
3018 if self
.PlatformInfo
.ToolChainFamily
in (TAB_COMPILER_MSFT
):
3019 BuildOptIncludeRegEx
= gBuildOptIncludePatternMsft
3020 elif self
.PlatformInfo
.ToolChainFamily
in ('INTEL', 'GCC', 'RVCT'):
3021 BuildOptIncludeRegEx
= gBuildOptIncludePatternOther
3024 # New ToolChainFamily, don't known whether there is option to specify include directories
3029 for Tool
in ('CC', 'PP', 'VFRPP', 'ASLPP', 'ASLCC', 'APP', 'ASM'):
3031 FlagOption
= self
.BuildOption
[Tool
]['FLAGS']
3035 if self
.ToolChainFamily
!= 'RVCT':
3036 IncPathList
= [NormPath(Path
, self
.Macros
) for Path
in BuildOptIncludeRegEx
.findall(FlagOption
)]
3039 # RVCT may specify a list of directory separated by commas
3042 for Path
in BuildOptIncludeRegEx
.findall(FlagOption
):
3043 PathList
= GetSplitList(Path
, TAB_COMMA_SPLIT
)
3044 IncPathList
.extend(NormPath(PathEntry
, self
.Macros
) for PathEntry
in PathList
)
3047 # EDK II modules must not reference header files outside of the packages they depend on or
3048 # within the module's directory tree. Report error if violation.
3050 if GlobalData
.gDisableIncludePathCheck
== False:
3051 for Path
in IncPathList
:
3052 if (Path
not in self
.IncludePathList
) and (CommonPath([Path
, self
.MetaFile
.Dir
]) != self
.MetaFile
.Dir
):
3053 ErrMsg
= "The include directory for the EDK II module in this line is invalid %s specified in %s FLAGS '%s'" % (Path
, Tool
, FlagOption
)
3054 EdkLogger
.error("build",
3057 File
=str(self
.MetaFile
))
3058 RetVal
+= IncPathList
3061 ## Return a list of files which can be built from source
3063 # What kind of files can be built is determined by build rules in
3064 # $(CONF_DIRECTORY)/build_rule.txt and toolchain family.
3067 def SourceFileList(self
):
3069 ToolChainTagSet
= {"", TAB_STAR
, self
.ToolChain
}
3070 ToolChainFamilySet
= {"", TAB_STAR
, self
.ToolChainFamily
, self
.BuildRuleFamily
}
3071 for F
in self
.Module
.Sources
:
3073 if F
.TagName
not in ToolChainTagSet
:
3074 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "The toolchain [%s] for processing file [%s] is found, "
3075 "but [%s] is currently used" % (F
.TagName
, str(F
), self
.ToolChain
))
3077 # match tool chain family or build rule family
3078 if F
.ToolChainFamily
not in ToolChainFamilySet
:
3081 "The file [%s] must be built by tools of [%s], " \
3082 "but current toolchain family is [%s], buildrule family is [%s]" \
3083 % (str(F
), F
.ToolChainFamily
, self
.ToolChainFamily
, self
.BuildRuleFamily
))
3086 # add the file path into search path list for file including
3087 if F
.Dir
not in self
.IncludePathList
:
3088 self
.IncludePathList
.insert(0, F
.Dir
)
3091 self
._MatchBuildRuleOrder
(RetVal
)
3094 self
._ApplyBuildRule
(F
, TAB_UNKNOWN_FILE
)
3097 def _MatchBuildRuleOrder(self
, FileList
):
3100 for SingleFile
in FileList
:
3101 if self
.BuildRuleOrder
and SingleFile
.Ext
in self
.BuildRuleOrder
and SingleFile
.Ext
in self
.BuildRules
:
3102 key
= SingleFile
.Path
.rsplit(SingleFile
.Ext
,1)[0]
3103 if key
in Order_Dict
:
3104 Order_Dict
[key
].append(SingleFile
.Ext
)
3106 Order_Dict
[key
] = [SingleFile
.Ext
]
3109 for F
in Order_Dict
:
3110 if len(Order_Dict
[F
]) > 1:
3111 Order_Dict
[F
].sort(key
=lambda i
: self
.BuildRuleOrder
.index(i
))
3112 for Ext
in Order_Dict
[F
][1:]:
3113 RemoveList
.append(F
+ Ext
)
3115 for item
in RemoveList
:
3116 FileList
.remove(item
)
3120 ## Return the list of unicode files
3122 def UnicodeFileList(self
):
3123 return self
.FileTypes
.get(TAB_UNICODE_FILE
,[])
3125 ## Return the list of vfr files
3127 def VfrFileList(self
):
3128 return self
.FileTypes
.get(TAB_VFR_FILE
, [])
3130 ## Return the list of Image Definition files
3132 def IdfFileList(self
):
3133 return self
.FileTypes
.get(TAB_IMAGE_FILE
,[])
3135 ## Return a list of files which can be built from binary
3137 # "Build" binary files are just to copy them to build directory.
3139 # @retval list The list of files which can be built later
3142 def BinaryFileList(self
):
3144 for F
in self
.Module
.Binaries
:
3145 if F
.Target
not in [TAB_ARCH_COMMON
, TAB_STAR
] and F
.Target
!= self
.BuildTarget
:
3148 self
._ApplyBuildRule
(F
, F
.Type
, BinaryFileList
=RetVal
)
3152 def BuildRules(self
):
3154 BuildRuleDatabase
= self
.PlatformInfo
.BuildRule
3155 for Type
in BuildRuleDatabase
.FileTypeList
:
3156 #first try getting build rule by BuildRuleFamily
3157 RuleObject
= BuildRuleDatabase
[Type
, self
.BuildType
, self
.Arch
, self
.BuildRuleFamily
]
3159 # build type is always module type, but ...
3160 if self
.ModuleType
!= self
.BuildType
:
3161 RuleObject
= BuildRuleDatabase
[Type
, self
.ModuleType
, self
.Arch
, self
.BuildRuleFamily
]
3162 #second try getting build rule by ToolChainFamily
3164 RuleObject
= BuildRuleDatabase
[Type
, self
.BuildType
, self
.Arch
, self
.ToolChainFamily
]
3166 # build type is always module type, but ...
3167 if self
.ModuleType
!= self
.BuildType
:
3168 RuleObject
= BuildRuleDatabase
[Type
, self
.ModuleType
, self
.Arch
, self
.ToolChainFamily
]
3171 RuleObject
= RuleObject
.Instantiate(self
.Macros
)
3172 RetVal
[Type
] = RuleObject
3173 for Ext
in RuleObject
.SourceFileExtList
:
3174 RetVal
[Ext
] = RuleObject
3177 def _ApplyBuildRule(self
, File
, FileType
, BinaryFileList
=None):
3178 if self
._BuildTargets
is None:
3179 self
._IntroBuildTargetList
= set()
3180 self
._FinalBuildTargetList
= set()
3181 self
._BuildTargets
= defaultdict(set)
3182 self
._FileTypes
= defaultdict(set)
3184 if not BinaryFileList
:
3185 BinaryFileList
= self
.BinaryFileList
3187 SubDirectory
= os
.path
.join(self
.OutputDir
, File
.SubDir
)
3188 if not os
.path
.exists(SubDirectory
):
3189 CreateDirectory(SubDirectory
)
3195 # Make sure to get build rule order value
3199 while Index
< len(SourceList
):
3200 Source
= SourceList
[Index
]
3204 CreateDirectory(Source
.Dir
)
3206 if File
.IsBinary
and File
== Source
and File
in BinaryFileList
:
3207 # Skip all files that are not binary libraries
3208 if not self
.IsLibrary
:
3210 RuleObject
= self
.BuildRules
[TAB_DEFAULT_BINARY_FILE
]
3211 elif FileType
in self
.BuildRules
:
3212 RuleObject
= self
.BuildRules
[FileType
]
3213 elif Source
.Ext
in self
.BuildRules
:
3214 RuleObject
= self
.BuildRules
[Source
.Ext
]
3216 # stop at no more rules
3218 self
._FinalBuildTargetList
.add(LastTarget
)
3221 FileType
= RuleObject
.SourceFileType
3222 self
._FileTypes
[FileType
].add(Source
)
3224 # stop at STATIC_LIBRARY for library
3225 if self
.IsLibrary
and FileType
== TAB_STATIC_LIBRARY
:
3227 self
._FinalBuildTargetList
.add(LastTarget
)
3230 Target
= RuleObject
.Apply(Source
, self
.BuildRuleOrder
)
3233 self
._FinalBuildTargetList
.add(LastTarget
)
3235 elif not Target
.Outputs
:
3236 # Only do build for target with outputs
3237 self
._FinalBuildTargetList
.add(Target
)
3239 self
._BuildTargets
[FileType
].add(Target
)
3241 if not Source
.IsBinary
and Source
== File
:
3242 self
._IntroBuildTargetList
.add(Target
)
3244 # to avoid cyclic rule
3245 if FileType
in RuleChain
:
3248 RuleChain
.add(FileType
)
3249 SourceList
.extend(Target
.Outputs
)
3251 FileType
= TAB_UNKNOWN_FILE
3255 if self
._BuildTargets
is None:
3256 self
._IntroBuildTargetList
= set()
3257 self
._FinalBuildTargetList
= set()
3258 self
._BuildTargets
= defaultdict(set)
3259 self
._FileTypes
= defaultdict(set)
3261 #TRICK: call SourceFileList property to apply build rule for source files
3264 #TRICK: call _GetBinaryFileList to apply build rule for binary files
3267 return self
._BuildTargets
3270 def IntroTargetList(self
):
3272 return self
._IntroBuildTargetList
3275 def CodaTargetList(self
):
3277 return self
._FinalBuildTargetList
3280 def FileTypes(self
):
3282 return self
._FileTypes
3284 ## Get the list of package object the module depends on
3286 # @retval list The package object list
3289 def DependentPackageList(self
):
3290 return self
.Module
.Packages
3292 ## Return the list of auto-generated code file
3294 # @retval list The list of auto-generated file
3297 def AutoGenFileList(self
):
3298 AutoGenUniIdf
= self
.BuildType
!= 'UEFI_HII'
3299 UniStringBinBuffer
= BytesIO()
3300 IdfGenBinBuffer
= BytesIO()
3302 AutoGenC
= TemplateString()
3303 AutoGenH
= TemplateString()
3304 StringH
= TemplateString()
3305 StringIdf
= TemplateString()
3306 GenC
.CreateCode(self
, AutoGenC
, AutoGenH
, StringH
, AutoGenUniIdf
, UniStringBinBuffer
, StringIdf
, AutoGenUniIdf
, IdfGenBinBuffer
)
3308 # AutoGen.c is generated if there are library classes in inf, or there are object files
3310 if str(AutoGenC
) != "" and (len(self
.Module
.LibraryClasses
) > 0
3311 or TAB_OBJECT_FILE
in self
.FileTypes
):
3312 AutoFile
= PathClass(gAutoGenCodeFileName
, self
.DebugDir
)
3313 RetVal
[AutoFile
] = str(AutoGenC
)
3314 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3315 if str(AutoGenH
) != "":
3316 AutoFile
= PathClass(gAutoGenHeaderFileName
, self
.DebugDir
)
3317 RetVal
[AutoFile
] = str(AutoGenH
)
3318 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3319 if str(StringH
) != "":
3320 AutoFile
= PathClass(gAutoGenStringFileName
% {"module_name":self
.Name
}, self
.DebugDir
)
3321 RetVal
[AutoFile
] = str(StringH
)
3322 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3323 if UniStringBinBuffer
is not None and UniStringBinBuffer
.getvalue() != b
"":
3324 AutoFile
= PathClass(gAutoGenStringFormFileName
% {"module_name":self
.Name
}, self
.OutputDir
)
3325 RetVal
[AutoFile
] = UniStringBinBuffer
.getvalue()
3326 AutoFile
.IsBinary
= True
3327 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3328 if UniStringBinBuffer
is not None:
3329 UniStringBinBuffer
.close()
3330 if str(StringIdf
) != "":
3331 AutoFile
= PathClass(gAutoGenImageDefFileName
% {"module_name":self
.Name
}, self
.DebugDir
)
3332 RetVal
[AutoFile
] = str(StringIdf
)
3333 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3334 if IdfGenBinBuffer
is not None and IdfGenBinBuffer
.getvalue() != b
"":
3335 AutoFile
= PathClass(gAutoGenIdfFileName
% {"module_name":self
.Name
}, self
.OutputDir
)
3336 RetVal
[AutoFile
] = IdfGenBinBuffer
.getvalue()
3337 AutoFile
.IsBinary
= True
3338 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3339 if IdfGenBinBuffer
is not None:
3340 IdfGenBinBuffer
.close()
3343 ## Return the list of library modules explicitly or implicitly used by this module
3345 def DependentLibraryList(self
):
3346 # only merge library classes and PCD for non-library module
3349 return self
.PlatformInfo
.ApplyLibraryInstance(self
.Module
)
3351 ## Get the list of PCDs from current module
3353 # @retval list The list of PCD
3356 def ModulePcdList(self
):
3357 # apply PCD settings from platform
3358 RetVal
= self
.PlatformInfo
.ApplyPcdSetting(self
.Module
, self
.Module
.Pcds
)
3359 ExtendCopyDictionaryLists(self
._PcdComments
, self
.Module
.PcdComments
)
3362 ## Get the list of PCDs from dependent libraries
3364 # @retval list The list of PCD
3367 def LibraryPcdList(self
):
3372 # get PCDs from dependent libraries
3373 for Library
in self
.DependentLibraryList
:
3374 PcdsInLibrary
= OrderedDict()
3375 ExtendCopyDictionaryLists(self
._PcdComments
, Library
.PcdComments
)
3376 for Key
in Library
.Pcds
:
3377 # skip duplicated PCDs
3378 if Key
in self
.Module
.Pcds
or Key
in Pcds
:
3381 PcdsInLibrary
[Key
] = copy
.copy(Library
.Pcds
[Key
])
3382 RetVal
.extend(self
.PlatformInfo
.ApplyPcdSetting(self
.Module
, PcdsInLibrary
, Library
=Library
))
3385 ## Get the GUID value mapping
3387 # @retval dict The mapping between GUID cname and its value
3391 RetVal
= OrderedDict(self
.Module
.Guids
)
3392 for Library
in self
.DependentLibraryList
:
3393 RetVal
.update(Library
.Guids
)
3394 ExtendCopyDictionaryLists(self
._GuidComments
, Library
.GuidComments
)
3395 ExtendCopyDictionaryLists(self
._GuidComments
, self
.Module
.GuidComments
)
3399 def GetGuidsUsedByPcd(self
):
3400 RetVal
= OrderedDict(self
.Module
.GetGuidsUsedByPcd())
3401 for Library
in self
.DependentLibraryList
:
3402 RetVal
.update(Library
.GetGuidsUsedByPcd())
3404 ## Get the protocol value mapping
3406 # @retval dict The mapping between protocol cname and its value
3409 def ProtocolList(self
):
3410 RetVal
= OrderedDict(self
.Module
.Protocols
)
3411 for Library
in self
.DependentLibraryList
:
3412 RetVal
.update(Library
.Protocols
)
3413 ExtendCopyDictionaryLists(self
._ProtocolComments
, Library
.ProtocolComments
)
3414 ExtendCopyDictionaryLists(self
._ProtocolComments
, self
.Module
.ProtocolComments
)
3417 ## Get the PPI value mapping
3419 # @retval dict The mapping between PPI cname and its value
3423 RetVal
= OrderedDict(self
.Module
.Ppis
)
3424 for Library
in self
.DependentLibraryList
:
3425 RetVal
.update(Library
.Ppis
)
3426 ExtendCopyDictionaryLists(self
._PpiComments
, Library
.PpiComments
)
3427 ExtendCopyDictionaryLists(self
._PpiComments
, self
.Module
.PpiComments
)
3430 ## Get the list of include search path
3432 # @retval list The list path
3435 def IncludePathList(self
):
3437 RetVal
.append(self
.MetaFile
.Dir
)
3438 RetVal
.append(self
.DebugDir
)
3440 for Package
in self
.Module
.Packages
:
3441 PackageDir
= mws
.join(self
.WorkspaceDir
, Package
.MetaFile
.Dir
)
3442 if PackageDir
not in RetVal
:
3443 RetVal
.append(PackageDir
)
3444 IncludesList
= Package
.Includes
3445 if Package
._PrivateIncludes
:
3446 if not self
.MetaFile
.OriginalPath
.Path
.startswith(PackageDir
):
3447 IncludesList
= list(set(Package
.Includes
).difference(set(Package
._PrivateIncludes
)))
3448 for Inc
in IncludesList
:
3449 if Inc
not in RetVal
:
3450 RetVal
.append(str(Inc
))
3454 def IncludePathLength(self
):
3455 return sum(len(inc
)+1 for inc
in self
.IncludePathList
)
3457 ## Get HII EX PCDs which maybe used by VFR
3459 # efivarstore used by VFR may relate with HII EX PCDs
3460 # Get the variable name and GUID from efivarstore and HII EX PCD
3461 # List the HII EX PCDs in As Built INF if both name and GUID match.
3463 # @retval list HII EX PCDs
3465 def _GetPcdsMaybeUsedByVfr(self
):
3466 if not self
.SourceFileList
:
3470 for SrcFile
in self
.SourceFileList
:
3471 if SrcFile
.Ext
.lower() != '.vfr':
3473 Vfri
= os
.path
.join(self
.OutputDir
, SrcFile
.BaseName
+ '.i')
3474 if not os
.path
.exists(Vfri
):
3476 VfriFile
= open(Vfri
, 'r')
3477 Content
= VfriFile
.read()
3479 Pos
= Content
.find('efivarstore')
3482 # Make sure 'efivarstore' is the start of efivarstore statement
3483 # In case of the value of 'name' (name = efivarstore) is equal to 'efivarstore'
3486 while Index
>= 0 and Content
[Index
] in ' \t\r\n':
3488 if Index
>= 0 and Content
[Index
] != ';':
3489 Pos
= Content
.find('efivarstore', Pos
+ len('efivarstore'))
3492 # 'efivarstore' must be followed by name and guid
3494 Name
= gEfiVarStoreNamePattern
.search(Content
, Pos
)
3497 Guid
= gEfiVarStoreGuidPattern
.search(Content
, Pos
)
3500 NameArray
= _ConvertStringToByteArray('L"' + Name
.group(1) + '"')
3501 NameGuids
.add((NameArray
, GuidStructureStringToGuidString(Guid
.group(1))))
3502 Pos
= Content
.find('efivarstore', Name
.end())
3506 for Pcd
in self
.PlatformInfo
.Platform
.Pcds
.values():
3507 if Pcd
.Type
!= TAB_PCDS_DYNAMIC_EX_HII
:
3509 for SkuInfo
in Pcd
.SkuInfoList
.values():
3510 Value
= GuidValue(SkuInfo
.VariableGuid
, self
.PlatformInfo
.PackageList
, self
.MetaFile
.Path
)
3513 Name
= _ConvertStringToByteArray(SkuInfo
.VariableName
)
3514 Guid
= GuidStructureStringToGuidString(Value
)
3515 if (Name
, Guid
) in NameGuids
and Pcd
not in HiiExPcds
:
3516 HiiExPcds
.append(Pcd
)
3521 def _GenOffsetBin(self
):
3523 for SourceFile
in self
.Module
.Sources
:
3524 if SourceFile
.Type
.upper() == ".VFR" :
3526 # search the .map file to find the offset of vfr binary in the PE32+/TE file.
3528 VfrUniBaseName
[SourceFile
.BaseName
] = (SourceFile
.BaseName
+ "Bin")
3529 elif SourceFile
.Type
.upper() == ".UNI" :
3531 # search the .map file to find the offset of Uni strings binary in the PE32+/TE file.
3533 VfrUniBaseName
["UniOffsetName"] = (self
.Name
+ "Strings")
3535 if not VfrUniBaseName
:
3537 MapFileName
= os
.path
.join(self
.OutputDir
, self
.Name
+ ".map")
3538 EfiFileName
= os
.path
.join(self
.OutputDir
, self
.Name
+ ".efi")
3539 VfrUniOffsetList
= GetVariableOffset(MapFileName
, EfiFileName
, list(VfrUniBaseName
.values()))
3540 if not VfrUniOffsetList
:
3543 OutputName
= '%sOffset.bin' % self
.Name
3544 UniVfrOffsetFileName
= os
.path
.join( self
.OutputDir
, OutputName
)
3547 fInputfile
= open(UniVfrOffsetFileName
, "wb+", 0)
3549 EdkLogger
.error("build", FILE_OPEN_FAILURE
, "File open failed for %s" % UniVfrOffsetFileName
, None)
3551 # Use a instance of BytesIO to cache data
3552 fStringIO
= BytesIO()
3554 for Item
in VfrUniOffsetList
:
3555 if (Item
[0].find("Strings") != -1):
3557 # UNI offset in image.
3559 # { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } }
3561 UniGuid
= b
'\xe0\xc5\x13\x89\xf63\x86M\x9b\xf1C\xef\x89\xfc\x06f'
3562 fStringIO
.write(UniGuid
)
3563 UniValue
= pack ('Q', int (Item
[1], 16))
3564 fStringIO
.write (UniValue
)
3567 # VFR binary offset in image.
3569 # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } };
3571 VfrGuid
= b
'\xb4|\xbc\xd0Gj_I\xaa\x11q\x07F\xda\x06\xa2'
3572 fStringIO
.write(VfrGuid
)
3573 VfrValue
= pack ('Q', int (Item
[1], 16))
3574 fStringIO
.write (VfrValue
)
3576 # write data into file.
3579 fInputfile
.write (fStringIO
.getvalue())
3581 EdkLogger
.error("build", FILE_WRITE_FAILURE
, "Write data to file %s failed, please check whether the "
3582 "file been locked or using by other applications." %UniVfrOffsetFileName
, None)
3589 def OutputFile(self
):
3591 OutputDir
= self
.OutputDir
.replace('\\', '/').strip('/')
3592 DebugDir
= self
.DebugDir
.replace('\\', '/').strip('/')
3593 for Item
in self
.CodaTargetList
:
3594 File
= Item
.Target
.Path
.replace('\\', '/').strip('/').replace(DebugDir
, '').replace(OutputDir
, '').strip('/')
3596 if self
.DepexGenerated
:
3597 retVal
.add(self
.Name
+ '.depex')
3599 Bin
= self
._GenOffsetBin
()
3603 for Root
, Dirs
, Files
in os
.walk(OutputDir
):
3605 if File
.lower().endswith('.pdb'):
3610 ## Create AsBuilt INF file the module
3612 def CreateAsBuiltInf(self
):
3614 if self
.IsAsBuiltInfCreated
:
3617 # Skip INF file generation for libraries
3621 # Skip the following code for modules with no source files
3622 if not self
.SourceFileList
:
3625 # Skip the following code for modules without any binary files
3626 if self
.BinaryFileList
:
3629 ### TODO: How to handles mixed source and binary modules
3631 # Find all DynamicEx and PatchableInModule PCDs used by this module and dependent libraries
3632 # Also find all packages that the DynamicEx PCDs depend on
3637 PcdTokenSpaceList
= []
3638 for Pcd
in self
.ModulePcdList
+ self
.LibraryPcdList
:
3639 if Pcd
.Type
== TAB_PCDS_PATCHABLE_IN_MODULE
:
3640 PatchablePcds
.append(Pcd
)
3641 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, TAB_PCDS_PATCHABLE_IN_MODULE
))
3642 elif Pcd
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
3645 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, TAB_PCDS_DYNAMIC_EX
))
3646 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, TAB_PCDS_DYNAMIC
))
3647 PcdTokenSpaceList
.append(Pcd
.TokenSpaceGuidCName
)
3648 GuidList
= OrderedDict(self
.GuidList
)
3649 for TokenSpace
in self
.GetGuidsUsedByPcd
:
3650 # If token space is not referred by patch PCD or Ex PCD, remove the GUID from GUID list
3651 # The GUIDs in GUIDs section should really be the GUIDs in source INF or referred by Ex an patch PCDs
3652 if TokenSpace
not in PcdTokenSpaceList
and TokenSpace
in GuidList
:
3653 GuidList
.pop(TokenSpace
)
3654 CheckList
= (GuidList
, self
.PpiList
, self
.ProtocolList
, PcdCheckList
)
3655 for Package
in self
.DerivedPackageList
:
3656 if Package
in Packages
:
3658 BeChecked
= (Package
.Guids
, Package
.Ppis
, Package
.Protocols
, Package
.Pcds
)
3660 for Index
in range(len(BeChecked
)):
3661 for Item
in CheckList
[Index
]:
3662 if Item
in BeChecked
[Index
]:
3663 Packages
.append(Package
)
3669 VfrPcds
= self
._GetPcdsMaybeUsedByVfr
()
3670 for Pkg
in self
.PlatformInfo
.PackageList
:
3673 for VfrPcd
in VfrPcds
:
3674 if ((VfrPcd
.TokenCName
, VfrPcd
.TokenSpaceGuidCName
, TAB_PCDS_DYNAMIC_EX
) in Pkg
.Pcds
or
3675 (VfrPcd
.TokenCName
, VfrPcd
.TokenSpaceGuidCName
, TAB_PCDS_DYNAMIC
) in Pkg
.Pcds
):
3676 Packages
.append(Pkg
)
3679 ModuleType
= SUP_MODULE_DXE_DRIVER
if self
.ModuleType
== SUP_MODULE_UEFI_DRIVER
and self
.DepexGenerated
else self
.ModuleType
3680 DriverType
= self
.PcdIsDriver
if self
.PcdIsDriver
else ''
3682 MDefs
= self
.Module
.Defines
3685 'module_name' : self
.Name
,
3686 'module_guid' : Guid
,
3687 'module_module_type' : ModuleType
,
3688 'module_version_string' : [MDefs
['VERSION_STRING']] if 'VERSION_STRING' in MDefs
else [],
3689 'pcd_is_driver_string' : [],
3690 'module_uefi_specification_version' : [],
3691 'module_pi_specification_version' : [],
3692 'module_entry_point' : self
.Module
.ModuleEntryPointList
,
3693 'module_unload_image' : self
.Module
.ModuleUnloadImageList
,
3694 'module_constructor' : self
.Module
.ConstructorList
,
3695 'module_destructor' : self
.Module
.DestructorList
,
3696 'module_shadow' : [MDefs
['SHADOW']] if 'SHADOW' in MDefs
else [],
3697 'module_pci_vendor_id' : [MDefs
['PCI_VENDOR_ID']] if 'PCI_VENDOR_ID' in MDefs
else [],
3698 'module_pci_device_id' : [MDefs
['PCI_DEVICE_ID']] if 'PCI_DEVICE_ID' in MDefs
else [],
3699 'module_pci_class_code' : [MDefs
['PCI_CLASS_CODE']] if 'PCI_CLASS_CODE' in MDefs
else [],
3700 'module_pci_revision' : [MDefs
['PCI_REVISION']] if 'PCI_REVISION' in MDefs
else [],
3701 'module_build_number' : [MDefs
['BUILD_NUMBER']] if 'BUILD_NUMBER' in MDefs
else [],
3702 'module_spec' : [MDefs
['SPEC']] if 'SPEC' in MDefs
else [],
3703 'module_uefi_hii_resource_section' : [MDefs
['UEFI_HII_RESOURCE_SECTION']] if 'UEFI_HII_RESOURCE_SECTION' in MDefs
else [],
3704 'module_uni_file' : [MDefs
['MODULE_UNI_FILE']] if 'MODULE_UNI_FILE' in MDefs
else [],
3705 'module_arch' : self
.Arch
,
3706 'package_item' : [Package
.MetaFile
.File
.replace('\\', '/') for Package
in Packages
],
3708 'patchablepcd_item' : [],
3710 'protocol_item' : [],
3714 'libraryclasses_item' : []
3717 if 'MODULE_UNI_FILE' in MDefs
:
3718 UNIFile
= os
.path
.join(self
.MetaFile
.Dir
, MDefs
['MODULE_UNI_FILE'])
3719 if os
.path
.isfile(UNIFile
):
3720 shutil
.copy2(UNIFile
, self
.OutputDir
)
3722 if self
.AutoGenVersion
> int(gInfSpecVersion
, 0):
3723 AsBuiltInfDict
['module_inf_version'] = '0x%08x' % self
.AutoGenVersion
3725 AsBuiltInfDict
['module_inf_version'] = gInfSpecVersion
3728 AsBuiltInfDict
['pcd_is_driver_string'].append(DriverType
)
3730 if 'UEFI_SPECIFICATION_VERSION' in self
.Specification
:
3731 AsBuiltInfDict
['module_uefi_specification_version'].append(self
.Specification
['UEFI_SPECIFICATION_VERSION'])
3732 if 'PI_SPECIFICATION_VERSION' in self
.Specification
:
3733 AsBuiltInfDict
['module_pi_specification_version'].append(self
.Specification
['PI_SPECIFICATION_VERSION'])
3735 OutputDir
= self
.OutputDir
.replace('\\', '/').strip('/')
3736 DebugDir
= self
.DebugDir
.replace('\\', '/').strip('/')
3737 for Item
in self
.CodaTargetList
:
3738 File
= Item
.Target
.Path
.replace('\\', '/').strip('/').replace(DebugDir
, '').replace(OutputDir
, '').strip('/')
3739 if os
.path
.isabs(File
):
3740 File
= File
.replace('\\', '/').strip('/').replace(OutputDir
, '').strip('/')
3741 if Item
.Target
.Ext
.lower() == '.aml':
3742 AsBuiltInfDict
['binary_item'].append('ASL|' + File
)
3743 elif Item
.Target
.Ext
.lower() == '.acpi':
3744 AsBuiltInfDict
['binary_item'].append('ACPI|' + File
)
3745 elif Item
.Target
.Ext
.lower() == '.efi':
3746 AsBuiltInfDict
['binary_item'].append('PE32|' + self
.Name
+ '.efi')
3748 AsBuiltInfDict
['binary_item'].append('BIN|' + File
)
3749 if not self
.DepexGenerated
:
3750 DepexFile
= os
.path
.join(self
.OutputDir
, self
.Name
+ '.depex')
3751 if os
.path
.exists(DepexFile
):
3752 self
.DepexGenerated
= True
3753 if self
.DepexGenerated
:
3754 if self
.ModuleType
in [SUP_MODULE_PEIM
]:
3755 AsBuiltInfDict
['binary_item'].append('PEI_DEPEX|' + self
.Name
+ '.depex')
3756 elif self
.ModuleType
in [SUP_MODULE_DXE_DRIVER
, SUP_MODULE_DXE_RUNTIME_DRIVER
, SUP_MODULE_DXE_SAL_DRIVER
, SUP_MODULE_UEFI_DRIVER
]:
3757 AsBuiltInfDict
['binary_item'].append('DXE_DEPEX|' + self
.Name
+ '.depex')
3758 elif self
.ModuleType
in [SUP_MODULE_DXE_SMM_DRIVER
]:
3759 AsBuiltInfDict
['binary_item'].append('SMM_DEPEX|' + self
.Name
+ '.depex')
3761 Bin
= self
._GenOffsetBin
()
3763 AsBuiltInfDict
['binary_item'].append('BIN|%s' % Bin
)
3765 for Root
, Dirs
, Files
in os
.walk(OutputDir
):
3767 if File
.lower().endswith('.pdb'):
3768 AsBuiltInfDict
['binary_item'].append('DISPOSABLE|' + File
)
3769 HeaderComments
= self
.Module
.HeaderComments
3771 for Index
in range(len(HeaderComments
)):
3772 if HeaderComments
[Index
].find('@BinaryHeader') != -1:
3773 HeaderComments
[Index
] = HeaderComments
[Index
].replace('@BinaryHeader', '@file')
3776 AsBuiltInfDict
['header_comments'] = '\n'.join(HeaderComments
[StartPos
:]).replace(':#', '://')
3777 AsBuiltInfDict
['tail_comments'] = '\n'.join(self
.Module
.TailComments
)
3780 (self
.ProtocolList
, self
._ProtocolComments
, 'protocol_item'),
3781 (self
.PpiList
, self
._PpiComments
, 'ppi_item'),
3782 (GuidList
, self
._GuidComments
, 'guid_item')
3784 for Item
in GenList
:
3785 for CName
in Item
[0]:
3786 Comments
= '\n '.join(Item
[1][CName
]) if CName
in Item
[1] else ''
3787 Entry
= Comments
+ '\n ' + CName
if Comments
else CName
3788 AsBuiltInfDict
[Item
[2]].append(Entry
)
3789 PatchList
= parsePcdInfoFromMapFile(
3790 os
.path
.join(self
.OutputDir
, self
.Name
+ '.map'),
3791 os
.path
.join(self
.OutputDir
, self
.Name
+ '.efi')
3794 for Pcd
in PatchablePcds
:
3795 TokenCName
= Pcd
.TokenCName
3796 for PcdItem
in GlobalData
.MixedPcd
:
3797 if (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
3798 TokenCName
= PcdItem
[0]
3800 for PatchPcd
in PatchList
:
3801 if TokenCName
== PatchPcd
[0]:
3806 if Pcd
.DatumType
== 'BOOLEAN':
3807 BoolValue
= Pcd
.DefaultValue
.upper()
3808 if BoolValue
== 'TRUE':
3809 Pcd
.DefaultValue
= '1'
3810 elif BoolValue
== 'FALSE':
3811 Pcd
.DefaultValue
= '0'
3813 if Pcd
.DatumType
in TAB_PCD_NUMERIC_TYPES
:
3814 HexFormat
= '0x%02x'
3815 if Pcd
.DatumType
== TAB_UINT16
:
3816 HexFormat
= '0x%04x'
3817 elif Pcd
.DatumType
== TAB_UINT32
:
3818 HexFormat
= '0x%08x'
3819 elif Pcd
.DatumType
== TAB_UINT64
:
3820 HexFormat
= '0x%016x'
3821 PcdValue
= HexFormat
% int(Pcd
.DefaultValue
, 0)
3823 if Pcd
.MaxDatumSize
is None or Pcd
.MaxDatumSize
== '':
3824 EdkLogger
.error("build", AUTOGEN_ERROR
,
3825 "Unknown [MaxDatumSize] of PCD [%s.%s]" % (Pcd
.TokenSpaceGuidCName
, TokenCName
)
3827 ArraySize
= int(Pcd
.MaxDatumSize
, 0)
3828 PcdValue
= Pcd
.DefaultValue
3829 if PcdValue
[0] != '{':
3831 if PcdValue
[0] == 'L':
3833 PcdValue
= PcdValue
.lstrip('L')
3834 PcdValue
= eval(PcdValue
)
3836 for Index
in range(0, len(PcdValue
)):
3838 CharVal
= ord(PcdValue
[Index
])
3839 NewValue
= NewValue
+ '0x%02x' % (CharVal
& 0x00FF) + ', ' \
3840 + '0x%02x' % (CharVal
>> 8) + ', '
3842 NewValue
= NewValue
+ '0x%02x' % (ord(PcdValue
[Index
]) % 0x100) + ', '
3845 Padding
= Padding
* 2
3846 ArraySize
= ArraySize
// 2
3847 if ArraySize
< (len(PcdValue
) + 1):
3848 if Pcd
.MaxSizeUserSet
:
3849 EdkLogger
.error("build", AUTOGEN_ERROR
,
3850 "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd
.TokenSpaceGuidCName
, TokenCName
)
3853 ArraySize
= len(PcdValue
) + 1
3854 if ArraySize
> len(PcdValue
) + 1:
3855 NewValue
= NewValue
+ Padding
* (ArraySize
- len(PcdValue
) - 1)
3856 PcdValue
= NewValue
+ Padding
.strip().rstrip(',') + '}'
3857 elif len(PcdValue
.split(',')) <= ArraySize
:
3858 PcdValue
= PcdValue
.rstrip('}') + ', 0x00' * (ArraySize
- len(PcdValue
.split(',')))
3861 if Pcd
.MaxSizeUserSet
:
3862 EdkLogger
.error("build", AUTOGEN_ERROR
,
3863 "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd
.TokenSpaceGuidCName
, TokenCName
)
3866 ArraySize
= len(PcdValue
) + 1
3867 PcdItem
= '%s.%s|%s|0x%X' % \
3868 (Pcd
.TokenSpaceGuidCName
, TokenCName
, PcdValue
, PatchPcd
[1])
3870 if (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) in self
._PcdComments
:
3871 PcdComments
= '\n '.join(self
._PcdComments
[Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
])
3873 PcdItem
= PcdComments
+ '\n ' + PcdItem
3874 AsBuiltInfDict
['patchablepcd_item'].append(PcdItem
)
3876 for Pcd
in Pcds
+ VfrPcds
:
3879 TokenCName
= Pcd
.TokenCName
3880 for PcdItem
in GlobalData
.MixedPcd
:
3881 if (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
3882 TokenCName
= PcdItem
[0]
3884 if Pcd
.Type
== TAB_PCDS_DYNAMIC_EX_HII
:
3885 for SkuName
in Pcd
.SkuInfoList
:
3886 SkuInfo
= Pcd
.SkuInfoList
[SkuName
]
3887 HiiInfo
= '## %s|%s|%s' % (SkuInfo
.VariableName
, SkuInfo
.VariableGuid
, SkuInfo
.VariableOffset
)
3889 if (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) in self
._PcdComments
:
3890 PcdCommentList
= self
._PcdComments
[Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
][:]
3894 for Index
, Comment
in enumerate(PcdCommentList
):
3895 for Usage
in UsageList
:
3896 if Comment
.find(Usage
) != -1:
3900 if UsageIndex
!= -1:
3901 PcdCommentList
[UsageIndex
] = '## %s %s %s' % (UsageStr
, HiiInfo
, PcdCommentList
[UsageIndex
].replace(UsageStr
, ''))
3903 PcdCommentList
.append('## UNDEFINED ' + HiiInfo
)
3904 PcdComments
= '\n '.join(PcdCommentList
)
3905 PcdEntry
= Pcd
.TokenSpaceGuidCName
+ '.' + TokenCName
3907 PcdEntry
= PcdComments
+ '\n ' + PcdEntry
3908 AsBuiltInfDict
['pcd_item'].append(PcdEntry
)
3909 for Item
in self
.BuildOption
:
3910 if 'FLAGS' in self
.BuildOption
[Item
]:
3911 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()))
3913 # Generated LibraryClasses section in comments.
3914 for Library
in self
.LibraryAutoGenList
:
3915 AsBuiltInfDict
['libraryclasses_item'].append(Library
.MetaFile
.File
.replace('\\', '/'))
3917 # Generated UserExtensions TianoCore section.
3918 # All tianocore user extensions are copied.
3920 for TianoCore
in self
._GetTianoCoreUserExtensionList
():
3921 UserExtStr
+= '\n'.join(TianoCore
)
3922 ExtensionFile
= os
.path
.join(self
.MetaFile
.Dir
, TianoCore
[1])
3923 if os
.path
.isfile(ExtensionFile
):
3924 shutil
.copy2(ExtensionFile
, self
.OutputDir
)
3925 AsBuiltInfDict
['userextension_tianocore_item'] = UserExtStr
3927 # Generated depex expression section in comments.
3928 DepexExpression
= self
._GetDepexExpresionString
()
3929 AsBuiltInfDict
['depexsection_item'] = DepexExpression
if DepexExpression
else ''
3931 AsBuiltInf
= TemplateString()
3932 AsBuiltInf
.Append(gAsBuiltInfHeaderString
.Replace(AsBuiltInfDict
))
3934 SaveFileOnChange(os
.path
.join(self
.OutputDir
, self
.Name
+ '.inf'), str(AsBuiltInf
), False)
3936 self
.IsAsBuiltInfCreated
= True
3938 def CopyModuleToCache(self
):
3939 FileDir
= path
.join(GlobalData
.gBinCacheDest
, self
.PlatformInfo
.OutputDir
, self
.BuildTarget
+ "_" + self
.ToolChain
, self
.Arch
, self
.SourceDir
, self
.MetaFile
.BaseName
)
3940 CreateDirectory (FileDir
)
3941 HashFile
= path
.join(self
.BuildDir
, self
.Name
+ '.hash')
3942 if os
.path
.exists(HashFile
):
3943 CopyFileOnChange(HashFile
, FileDir
)
3944 ModuleFile
= path
.join(self
.OutputDir
, self
.Name
+ '.inf')
3945 if os
.path
.exists(ModuleFile
):
3946 CopyFileOnChange(ModuleFile
, FileDir
)
3948 if not self
.OutputFile
:
3949 Ma
= self
.BuildDatabase
[self
.MetaFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
3950 self
.OutputFile
= Ma
.Binaries
3952 for File
in self
.OutputFile
:
3954 if not os
.path
.isabs(File
):
3955 File
= os
.path
.join(self
.OutputDir
, File
)
3956 if os
.path
.exists(File
):
3957 sub_dir
= os
.path
.relpath(File
, self
.OutputDir
)
3958 destination_file
= os
.path
.join(FileDir
, sub_dir
)
3959 destination_dir
= os
.path
.dirname(destination_file
)
3960 CreateDirectory(destination_dir
)
3961 CopyFileOnChange(File
, destination_dir
)
3963 def AttemptModuleCacheCopy(self
):
3964 # If library or Module is binary do not skip by hash
3965 if self
.IsBinaryModule
:
3967 # .inc is contains binary information so do not skip by hash as well
3968 for f_ext
in self
.SourceFileList
:
3969 if '.inc' in str(f_ext
):
3971 FileDir
= path
.join(GlobalData
.gBinCacheSource
, self
.PlatformInfo
.OutputDir
, self
.BuildTarget
+ "_" + self
.ToolChain
, self
.Arch
, self
.SourceDir
, self
.MetaFile
.BaseName
)
3972 HashFile
= path
.join(FileDir
, self
.Name
+ '.hash')
3973 if os
.path
.exists(HashFile
):
3974 f
= open(HashFile
, 'r')
3975 CacheHash
= f
.read()
3977 self
.GenModuleHash()
3978 if GlobalData
.gModuleHash
[self
.Arch
][self
.Name
]:
3979 if CacheHash
== GlobalData
.gModuleHash
[self
.Arch
][self
.Name
]:
3980 for root
, dir, files
in os
.walk(FileDir
):
3982 if self
.Name
+ '.hash' in f
:
3983 CopyFileOnChange(HashFile
, self
.BuildDir
)
3985 File
= path
.join(root
, f
)
3986 sub_dir
= os
.path
.relpath(File
, FileDir
)
3987 destination_file
= os
.path
.join(self
.OutputDir
, sub_dir
)
3988 destination_dir
= os
.path
.dirname(destination_file
)
3989 CreateDirectory(destination_dir
)
3990 CopyFileOnChange(File
, destination_dir
)
3991 if self
.Name
== "PcdPeim" or self
.Name
== "PcdDxe":
3992 CreatePcdDatabaseCode(self
, TemplateString(), TemplateString())
3996 ## Create makefile for the module and its dependent libraries
3998 # @param CreateLibraryMakeFile Flag indicating if or not the makefiles of
3999 # dependent libraries will be created
4001 @cached_class_function
4002 def CreateMakeFile(self
, CreateLibraryMakeFile
=True, GenFfsList
= []):
4003 # nest this function inside its only caller.
4004 def CreateTimeStamp():
4005 FileSet
= {self
.MetaFile
.Path
}
4007 for SourceFile
in self
.Module
.Sources
:
4008 FileSet
.add (SourceFile
.Path
)
4010 for Lib
in self
.DependentLibraryList
:
4011 FileSet
.add (Lib
.MetaFile
.Path
)
4013 for f
in self
.AutoGenDepSet
:
4014 FileSet
.add (f
.Path
)
4016 if os
.path
.exists (self
.TimeStampPath
):
4017 os
.remove (self
.TimeStampPath
)
4018 with
open(self
.TimeStampPath
, 'w+') as file:
4022 # Ignore generating makefile when it is a binary module
4023 if self
.IsBinaryModule
:
4026 self
.GenFfsList
= GenFfsList
4027 if not self
.IsLibrary
and CreateLibraryMakeFile
:
4028 for LibraryAutoGen
in self
.LibraryAutoGenList
:
4029 LibraryAutoGen
.CreateMakeFile()
4031 # Don't enable if hash feature enabled, CanSkip uses timestamps to determine build skipping
4032 if not GlobalData
.gUseHashCache
and self
.CanSkip():
4035 if len(self
.CustomMakefile
) == 0:
4036 Makefile
= GenMake
.ModuleMakefile(self
)
4038 Makefile
= GenMake
.CustomMakefile(self
)
4039 if Makefile
.Generate():
4040 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated makefile for module %s [%s]" %
4041 (self
.Name
, self
.Arch
))
4043 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Skipped the generation of makefile for module %s [%s]" %
4044 (self
.Name
, self
.Arch
))
4048 def CopyBinaryFiles(self
):
4049 for File
in self
.Module
.Binaries
:
4051 DstPath
= os
.path
.join(self
.OutputDir
, os
.path
.basename(SrcPath
))
4052 CopyLongFilePath(SrcPath
, DstPath
)
4053 ## Create autogen code for the module and its dependent libraries
4055 # @param CreateLibraryCodeFile Flag indicating if or not the code of
4056 # dependent libraries will be created
4058 def CreateCodeFile(self
, CreateLibraryCodeFile
=True):
4059 if self
.IsCodeFileCreated
:
4062 # Need to generate PcdDatabase even PcdDriver is binarymodule
4063 if self
.IsBinaryModule
and self
.PcdIsDriver
!= '':
4064 CreatePcdDatabaseCode(self
, TemplateString(), TemplateString())
4066 if self
.IsBinaryModule
:
4068 self
.CopyBinaryFiles()
4071 if not self
.IsLibrary
and CreateLibraryCodeFile
:
4072 for LibraryAutoGen
in self
.LibraryAutoGenList
:
4073 LibraryAutoGen
.CreateCodeFile()
4075 # Don't enable if hash feature enabled, CanSkip uses timestamps to determine build skipping
4076 if not GlobalData
.gUseHashCache
and self
.CanSkip():
4080 IgoredAutoGenList
= []
4082 for File
in self
.AutoGenFileList
:
4083 if GenC
.Generate(File
.Path
, self
.AutoGenFileList
[File
], File
.IsBinary
):
4084 AutoGenList
.append(str(File
))
4086 IgoredAutoGenList
.append(str(File
))
4089 for ModuleType
in self
.DepexList
:
4090 # Ignore empty [depex] section or [depex] section for SUP_MODULE_USER_DEFINED module
4091 if len(self
.DepexList
[ModuleType
]) == 0 or ModuleType
== SUP_MODULE_USER_DEFINED
:
4094 Dpx
= GenDepex
.DependencyExpression(self
.DepexList
[ModuleType
], ModuleType
, True)
4095 DpxFile
= gAutoGenDepexFileName
% {"module_name" : self
.Name
}
4097 if len(Dpx
.PostfixNotation
) != 0:
4098 self
.DepexGenerated
= True
4100 if Dpx
.Generate(path
.join(self
.OutputDir
, DpxFile
)):
4101 AutoGenList
.append(str(DpxFile
))
4103 IgoredAutoGenList
.append(str(DpxFile
))
4105 if IgoredAutoGenList
== []:
4106 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated [%s] files for module %s [%s]" %
4107 (" ".join(AutoGenList
), self
.Name
, self
.Arch
))
4108 elif AutoGenList
== []:
4109 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Skipped the generation of [%s] files for module %s [%s]" %
4110 (" ".join(IgoredAutoGenList
), self
.Name
, self
.Arch
))
4112 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated [%s] (skipped %s) files for module %s [%s]" %
4113 (" ".join(AutoGenList
), " ".join(IgoredAutoGenList
), self
.Name
, self
.Arch
))
4115 self
.IsCodeFileCreated
= True
4118 ## Summarize the ModuleAutoGen objects of all libraries used by this module
4120 def LibraryAutoGenList(self
):
4122 for Library
in self
.DependentLibraryList
:
4129 self
.PlatformInfo
.MetaFile
4131 if La
not in RetVal
:
4133 for Lib
in La
.CodaTargetList
:
4134 self
._ApplyBuildRule
(Lib
.Target
, TAB_UNKNOWN_FILE
)
4137 def GenModuleHash(self
):
4138 # Initialize a dictionary for each arch type
4139 if self
.Arch
not in GlobalData
.gModuleHash
:
4140 GlobalData
.gModuleHash
[self
.Arch
] = {}
4142 # Early exit if module or library has been hashed and is in memory
4143 if self
.Name
in GlobalData
.gModuleHash
[self
.Arch
]:
4144 return GlobalData
.gModuleHash
[self
.Arch
][self
.Name
].encode('utf-8')
4146 # Initialze hash object
4149 # Add Platform level hash
4150 m
.update(GlobalData
.gPlatformHash
.encode('utf-8'))
4152 # Add Package level hash
4153 if self
.DependentPackageList
:
4154 for Pkg
in sorted(self
.DependentPackageList
, key
=lambda x
: x
.PackageName
):
4155 if Pkg
.PackageName
in GlobalData
.gPackageHash
:
4156 m
.update(GlobalData
.gPackageHash
[Pkg
.PackageName
].encode('utf-8'))
4159 if self
.LibraryAutoGenList
:
4160 for Lib
in sorted(self
.LibraryAutoGenList
, key
=lambda x
: x
.Name
):
4161 if Lib
.Name
not in GlobalData
.gModuleHash
[self
.Arch
]:
4163 m
.update(GlobalData
.gModuleHash
[self
.Arch
][Lib
.Name
].encode('utf-8'))
4166 f
= open(str(self
.MetaFile
), 'rb')
4171 # Add Module's source files
4172 if self
.SourceFileList
:
4173 for File
in sorted(self
.SourceFileList
, key
=lambda x
: str(x
)):
4174 f
= open(str(File
), 'rb')
4179 GlobalData
.gModuleHash
[self
.Arch
][self
.Name
] = m
.hexdigest()
4181 return GlobalData
.gModuleHash
[self
.Arch
][self
.Name
].encode('utf-8')
4183 ## Decide whether we can skip the ModuleAutoGen process
4184 def CanSkipbyHash(self
):
4185 # Hashing feature is off
4186 if not GlobalData
.gUseHashCache
:
4189 # Initialize a dictionary for each arch type
4190 if self
.Arch
not in GlobalData
.gBuildHashSkipTracking
:
4191 GlobalData
.gBuildHashSkipTracking
[self
.Arch
] = dict()
4193 # If library or Module is binary do not skip by hash
4194 if self
.IsBinaryModule
:
4197 # .inc is contains binary information so do not skip by hash as well
4198 for f_ext
in self
.SourceFileList
:
4199 if '.inc' in str(f_ext
):
4202 # Use Cache, if exists and if Module has a copy in cache
4203 if GlobalData
.gBinCacheSource
and self
.AttemptModuleCacheCopy():
4206 # Early exit for libraries that haven't yet finished building
4207 HashFile
= path
.join(self
.BuildDir
, self
.Name
+ ".hash")
4208 if self
.IsLibrary
and not os
.path
.exists(HashFile
):
4211 # Return a Boolean based on if can skip by hash, either from memory or from IO.
4212 if self
.Name
not in GlobalData
.gBuildHashSkipTracking
[self
.Arch
]:
4213 # If hashes are the same, SaveFileOnChange() will return False.
4214 GlobalData
.gBuildHashSkipTracking
[self
.Arch
][self
.Name
] = not SaveFileOnChange(HashFile
, self
.GenModuleHash(), True)
4215 return GlobalData
.gBuildHashSkipTracking
[self
.Arch
][self
.Name
]
4217 return GlobalData
.gBuildHashSkipTracking
[self
.Arch
][self
.Name
]
4219 ## Decide whether we can skip the ModuleAutoGen process
4220 # If any source file is newer than the module than we cannot skip
4223 if self
.MakeFileDir
in GlobalData
.gSikpAutoGenCache
:
4225 if not os
.path
.exists(self
.TimeStampPath
):
4227 #last creation time of the module
4228 DstTimeStamp
= os
.stat(self
.TimeStampPath
)[8]
4230 SrcTimeStamp
= self
.Workspace
._SrcTimeStamp
4231 if SrcTimeStamp
> DstTimeStamp
:
4234 with
open(self
.TimeStampPath
,'r') as f
:
4236 source
= source
.rstrip('\n')
4237 if not os
.path
.exists(source
):
4239 if source
not in ModuleAutoGen
.TimeDict
:
4240 ModuleAutoGen
.TimeDict
[source
] = os
.stat(source
)[8]
4241 if ModuleAutoGen
.TimeDict
[source
] > DstTimeStamp
:
4243 GlobalData
.gSikpAutoGenCache
.add(self
.MakeFileDir
)
4247 def TimeStampPath(self
):
4248 return os
.path
.join(self
.MakeFileDir
, 'AutoGenTimeStamp')