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
)
1916 SaveFileOnChange(self
.ToolDefinitionFile
, 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 return os
.path
.join(self
.MakeFileDir
, "TOOLS_DEF." + self
.Arch
)
1928 ## Retrieve the toolchain family of given toolchain tag. Default to 'MSFT'.
1930 def ToolChainFamily(self
):
1931 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
1932 if TAB_TOD_DEFINES_FAMILY
not in ToolDefinition \
1933 or self
.ToolChain
not in ToolDefinition
[TAB_TOD_DEFINES_FAMILY
] \
1934 or not ToolDefinition
[TAB_TOD_DEFINES_FAMILY
][self
.ToolChain
]:
1935 EdkLogger
.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
1937 RetVal
= TAB_COMPILER_MSFT
1939 RetVal
= ToolDefinition
[TAB_TOD_DEFINES_FAMILY
][self
.ToolChain
]
1943 def BuildRuleFamily(self
):
1944 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
1945 if TAB_TOD_DEFINES_BUILDRULEFAMILY
not in ToolDefinition \
1946 or self
.ToolChain
not in ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
] \
1947 or not ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
][self
.ToolChain
]:
1948 EdkLogger
.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
1950 return TAB_COMPILER_MSFT
1952 return ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
][self
.ToolChain
]
1954 ## Return the build options specific for all modules in this platform
1956 def BuildOption(self
):
1957 return self
._ExpandBuildOption
(self
.Platform
.BuildOptions
)
1959 def _BuildOptionWithToolDef(self
, ToolDef
):
1960 return self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, ToolDef
=ToolDef
)
1962 ## Return the build options specific for EDK modules in this platform
1964 def EdkBuildOption(self
):
1965 return self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, EDK_NAME
)
1967 ## Return the build options specific for EDKII modules in this platform
1969 def EdkIIBuildOption(self
):
1970 return self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, EDKII_NAME
)
1972 ## Parse build_rule.txt in Conf Directory.
1974 # @retval BuildRule object
1977 def BuildRule(self
):
1978 BuildRuleFile
= None
1979 if TAB_TAT_DEFINES_BUILD_RULE_CONF
in self
.Workspace
.TargetTxt
.TargetTxtDictionary
:
1980 BuildRuleFile
= self
.Workspace
.TargetTxt
.TargetTxtDictionary
[TAB_TAT_DEFINES_BUILD_RULE_CONF
]
1981 if not BuildRuleFile
:
1982 BuildRuleFile
= gDefaultBuildRuleFile
1983 RetVal
= BuildRule(BuildRuleFile
)
1984 if RetVal
._FileVersion
== "":
1985 RetVal
._FileVersion
= AutoGenReqBuildRuleVerNum
1987 if RetVal
._FileVersion
< AutoGenReqBuildRuleVerNum
:
1988 # If Build Rule's version is less than the version number required by the tools, halting the build.
1989 EdkLogger
.error("build", AUTOGEN_ERROR
,
1990 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])"\
1991 % (RetVal
._FileVersion
, AutoGenReqBuildRuleVerNum
))
1994 ## Summarize the packages used by modules in this platform
1996 def PackageList(self
):
1998 for La
in self
.LibraryAutoGenList
:
1999 RetVal
.update(La
.DependentPackageList
)
2000 for Ma
in self
.ModuleAutoGenList
:
2001 RetVal
.update(Ma
.DependentPackageList
)
2002 #Collect package set information from INF of FDF
2003 for ModuleFile
in self
._AsBuildModuleList
:
2004 if ModuleFile
in self
.Platform
.Modules
:
2006 ModuleData
= self
.BuildDatabase
[ModuleFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
2007 RetVal
.update(ModuleData
.Packages
)
2011 def NonDynamicPcdDict(self
):
2012 return {(Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
):Pcd
for Pcd
in self
.NonDynamicPcdList
}
2014 ## Get list of non-dynamic PCDs
2016 def NonDynamicPcdList(self
):
2017 if not self
._NonDynamicPcdList
:
2018 self
.CollectPlatformDynamicPcds()
2019 return self
._NonDynamicPcdList
2021 ## Get list of dynamic PCDs
2023 def DynamicPcdList(self
):
2024 if not self
._DynamicPcdList
:
2025 self
.CollectPlatformDynamicPcds()
2026 return self
._DynamicPcdList
2028 ## Generate Token Number for all PCD
2030 def PcdTokenNumber(self
):
2031 RetVal
= OrderedDict()
2034 # Make the Dynamic and DynamicEx PCD use within different TokenNumber area.
2038 # TokenNumber 0 ~ 10
2040 # TokeNumber 11 ~ 20
2042 for Pcd
in self
.DynamicPcdList
:
2043 if Pcd
.Phase
== "PEI" and Pcd
.Type
in PCD_DYNAMIC_TYPE_SET
:
2044 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
2045 RetVal
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2048 for Pcd
in self
.DynamicPcdList
:
2049 if Pcd
.Phase
== "PEI" and Pcd
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
2050 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
2051 RetVal
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2054 for Pcd
in self
.DynamicPcdList
:
2055 if Pcd
.Phase
== "DXE" and Pcd
.Type
in PCD_DYNAMIC_TYPE_SET
:
2056 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
2057 RetVal
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2060 for Pcd
in self
.DynamicPcdList
:
2061 if Pcd
.Phase
== "DXE" and Pcd
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
2062 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
2063 RetVal
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2066 for Pcd
in self
.NonDynamicPcdList
:
2067 RetVal
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2073 for ModuleFile
in self
.Platform
.Modules
:
2082 self
.Platform
.Modules
[ModuleFile
].M
= Ma
2083 return [x
.M
for x
in self
.Platform
.Modules
.values()]
2085 ## Summarize ModuleAutoGen objects of all modules to be built for this platform
2087 def ModuleAutoGenList(self
):
2089 for Ma
in self
._MaList
:
2090 if Ma
not in RetVal
:
2094 ## Summarize ModuleAutoGen objects of all libraries to be built for this platform
2096 def LibraryAutoGenList(self
):
2098 for Ma
in self
._MaList
:
2099 for La
in Ma
.LibraryAutoGenList
:
2100 if La
not in RetVal
:
2102 if Ma
not in La
.ReferenceModules
:
2103 La
.ReferenceModules
.append(Ma
)
2106 ## Test if a module is supported by the platform
2108 # An error will be raised directly if the module or its arch is not supported
2109 # by the platform or current configuration
2111 def ValidModule(self
, Module
):
2112 return Module
in self
.Platform
.Modules
or Module
in self
.Platform
.LibraryInstances \
2113 or Module
in self
._AsBuildModuleList
2115 ## Resolve the library classes in a module to library instances
2117 # This method will not only resolve library classes but also sort the library
2118 # instances according to the dependency-ship.
2120 # @param Module The module from which the library classes will be resolved
2122 # @retval library_list List of library instances sorted
2124 def ApplyLibraryInstance(self
, Module
):
2125 # Cover the case that the binary INF file is list in the FDF file but not DSC file, return empty list directly
2126 if str(Module
) not in self
.Platform
.Modules
:
2129 return GetModuleLibInstances(Module
,
2138 ## Override PCD setting (type, value, ...)
2140 # @param ToPcd The PCD to be overridden
2141 # @param FromPcd The PCD overriding from
2143 def _OverridePcd(self
, ToPcd
, FromPcd
, Module
="", Msg
="", Library
=""):
2145 # in case there's PCDs coming from FDF file, which have no type given.
2146 # at this point, ToPcd.Type has the type found from dependent
2149 TokenCName
= ToPcd
.TokenCName
2150 for PcdItem
in GlobalData
.MixedPcd
:
2151 if (ToPcd
.TokenCName
, ToPcd
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
2152 TokenCName
= PcdItem
[0]
2154 if FromPcd
is not None:
2155 if ToPcd
.Pending
and FromPcd
.Type
:
2156 ToPcd
.Type
= FromPcd
.Type
2157 elif ToPcd
.Type
and FromPcd
.Type\
2158 and ToPcd
.Type
!= FromPcd
.Type
and ToPcd
.Type
in FromPcd
.Type
:
2159 if ToPcd
.Type
.strip() == TAB_PCDS_DYNAMIC_EX
:
2160 ToPcd
.Type
= FromPcd
.Type
2161 elif ToPcd
.Type
and FromPcd
.Type \
2162 and ToPcd
.Type
!= FromPcd
.Type
:
2164 Module
= str(Module
) + " 's library file (" + str(Library
) + ")"
2165 EdkLogger
.error("build", OPTION_CONFLICT
, "Mismatched PCD type",
2166 ExtraData
="%s.%s is used as [%s] in module %s, but as [%s] in %s."\
2167 % (ToPcd
.TokenSpaceGuidCName
, TokenCName
,
2168 ToPcd
.Type
, Module
, FromPcd
.Type
, Msg
),
2171 if FromPcd
.MaxDatumSize
:
2172 ToPcd
.MaxDatumSize
= FromPcd
.MaxDatumSize
2173 ToPcd
.MaxSizeUserSet
= FromPcd
.MaxDatumSize
2174 if FromPcd
.DefaultValue
:
2175 ToPcd
.DefaultValue
= FromPcd
.DefaultValue
2176 if FromPcd
.TokenValue
:
2177 ToPcd
.TokenValue
= FromPcd
.TokenValue
2178 if FromPcd
.DatumType
:
2179 ToPcd
.DatumType
= FromPcd
.DatumType
2180 if FromPcd
.SkuInfoList
:
2181 ToPcd
.SkuInfoList
= FromPcd
.SkuInfoList
2182 if FromPcd
.UserDefinedDefaultStoresFlag
:
2183 ToPcd
.UserDefinedDefaultStoresFlag
= FromPcd
.UserDefinedDefaultStoresFlag
2184 # Add Flexible PCD format parse
2185 if ToPcd
.DefaultValue
:
2187 ToPcd
.DefaultValue
= ValueExpressionEx(ToPcd
.DefaultValue
, ToPcd
.DatumType
, self
.Workspace
._GuidDict
)(True)
2188 except BadExpression
as Value
:
2189 EdkLogger
.error('Parser', FORMAT_INVALID
, 'PCD [%s.%s] Value "%s", %s' %(ToPcd
.TokenSpaceGuidCName
, ToPcd
.TokenCName
, ToPcd
.DefaultValue
, Value
),
2192 # check the validation of datum
2193 IsValid
, Cause
= CheckPcdDatum(ToPcd
.DatumType
, ToPcd
.DefaultValue
)
2195 EdkLogger
.error('build', FORMAT_INVALID
, Cause
, File
=self
.MetaFile
,
2196 ExtraData
="%s.%s" % (ToPcd
.TokenSpaceGuidCName
, TokenCName
))
2197 ToPcd
.validateranges
= FromPcd
.validateranges
2198 ToPcd
.validlists
= FromPcd
.validlists
2199 ToPcd
.expressions
= FromPcd
.expressions
2200 ToPcd
.CustomAttribute
= FromPcd
.CustomAttribute
2202 if FromPcd
is not None and ToPcd
.DatumType
== TAB_VOID
and not ToPcd
.MaxDatumSize
:
2203 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "No MaxDatumSize specified for PCD %s.%s" \
2204 % (ToPcd
.TokenSpaceGuidCName
, TokenCName
))
2205 Value
= ToPcd
.DefaultValue
2207 ToPcd
.MaxDatumSize
= '1'
2208 elif Value
[0] == 'L':
2209 ToPcd
.MaxDatumSize
= str((len(Value
) - 2) * 2)
2210 elif Value
[0] == '{':
2211 ToPcd
.MaxDatumSize
= str(len(Value
.split(',')))
2213 ToPcd
.MaxDatumSize
= str(len(Value
) - 1)
2215 # apply default SKU for dynamic PCDS if specified one is not available
2216 if (ToPcd
.Type
in PCD_DYNAMIC_TYPE_SET
or ToPcd
.Type
in PCD_DYNAMIC_EX_TYPE_SET
) \
2217 and not ToPcd
.SkuInfoList
:
2218 if self
.Platform
.SkuName
in self
.Platform
.SkuIds
:
2219 SkuName
= self
.Platform
.SkuName
2221 SkuName
= TAB_DEFAULT
2222 ToPcd
.SkuInfoList
= {
2223 SkuName
: SkuInfoClass(SkuName
, self
.Platform
.SkuIds
[SkuName
][0], '', '', '', '', '', ToPcd
.DefaultValue
)
2226 ## Apply PCD setting defined platform to a module
2228 # @param Module The module from which the PCD setting will be overridden
2230 # @retval PCD_list The list PCDs with settings from platform
2232 def ApplyPcdSetting(self
, Module
, Pcds
, Library
=""):
2233 # for each PCD in module
2234 for Name
, Guid
in Pcds
:
2235 PcdInModule
= Pcds
[Name
, Guid
]
2236 # find out the PCD setting in platform
2237 if (Name
, Guid
) in self
.Platform
.Pcds
:
2238 PcdInPlatform
= self
.Platform
.Pcds
[Name
, Guid
]
2240 PcdInPlatform
= None
2241 # then override the settings if any
2242 self
._OverridePcd
(PcdInModule
, PcdInPlatform
, Module
, Msg
="DSC PCD sections", Library
=Library
)
2243 # resolve the VariableGuid value
2244 for SkuId
in PcdInModule
.SkuInfoList
:
2245 Sku
= PcdInModule
.SkuInfoList
[SkuId
]
2246 if Sku
.VariableGuid
== '': continue
2247 Sku
.VariableGuidValue
= GuidValue(Sku
.VariableGuid
, self
.PackageList
, self
.MetaFile
.Path
)
2248 if Sku
.VariableGuidValue
is None:
2249 PackageList
= "\n\t".join(str(P
) for P
in self
.PackageList
)
2252 RESOURCE_NOT_AVAILABLE
,
2253 "Value of GUID [%s] is not found in" % Sku
.VariableGuid
,
2254 ExtraData
=PackageList
+ "\n\t(used with %s.%s from module %s)" \
2255 % (Guid
, Name
, str(Module
)),
2259 # override PCD settings with module specific setting
2260 if Module
in self
.Platform
.Modules
:
2261 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
2262 for Key
in PlatformModule
.Pcds
:
2263 if GlobalData
.BuildOptionPcd
:
2264 for pcd
in GlobalData
.BuildOptionPcd
:
2265 (TokenSpaceGuidCName
, TokenCName
, FieldName
, pcdvalue
, _
) = pcd
2266 if (TokenCName
, TokenSpaceGuidCName
) == Key
and FieldName
=="":
2267 PlatformModule
.Pcds
[Key
].DefaultValue
= pcdvalue
2268 PlatformModule
.Pcds
[Key
].PcdValueFromComm
= pcdvalue
2274 elif Key
in GlobalData
.MixedPcd
:
2275 for PcdItem
in GlobalData
.MixedPcd
[Key
]:
2277 ToPcd
= Pcds
[PcdItem
]
2281 self
._OverridePcd
(ToPcd
, PlatformModule
.Pcds
[Key
], Module
, Msg
="DSC Components Module scoped PCD section", Library
=Library
)
2282 # use PCD value to calculate the MaxDatumSize when it is not specified
2283 for Name
, Guid
in Pcds
:
2284 Pcd
= Pcds
[Name
, Guid
]
2285 if Pcd
.DatumType
== TAB_VOID
and not Pcd
.MaxDatumSize
:
2286 Pcd
.MaxSizeUserSet
= None
2287 Value
= Pcd
.DefaultValue
2289 Pcd
.MaxDatumSize
= '1'
2290 elif Value
[0] == 'L':
2291 Pcd
.MaxDatumSize
= str((len(Value
) - 2) * 2)
2292 elif Value
[0] == '{':
2293 Pcd
.MaxDatumSize
= str(len(Value
.split(',')))
2295 Pcd
.MaxDatumSize
= str(len(Value
) - 1)
2296 return list(Pcds
.values())
2300 ## Calculate the priority value of the build option
2302 # @param Key Build option definition contain: TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
2304 # @retval Value Priority value based on the priority list.
2306 def CalculatePriorityValue(self
, Key
):
2307 Target
, ToolChain
, Arch
, CommandType
, Attr
= Key
.split('_')
2308 PriorityValue
= 0x11111
2309 if Target
== TAB_STAR
:
2310 PriorityValue
&= 0x01111
2311 if ToolChain
== TAB_STAR
:
2312 PriorityValue
&= 0x10111
2313 if Arch
== TAB_STAR
:
2314 PriorityValue
&= 0x11011
2315 if CommandType
== TAB_STAR
:
2316 PriorityValue
&= 0x11101
2317 if Attr
== TAB_STAR
:
2318 PriorityValue
&= 0x11110
2320 return self
.PrioList
["0x%0.5x" % PriorityValue
]
2323 ## Expand * in build option key
2325 # @param Options Options to be expanded
2326 # @param ToolDef Use specified ToolDef instead of full version.
2327 # This is needed during initialization to prevent
2328 # infinite recursion betweeh BuildOptions,
2329 # ToolDefinition, and this function.
2331 # @retval options Options expanded
2333 def _ExpandBuildOption(self
, Options
, ModuleStyle
=None, ToolDef
=None):
2335 ToolDef
= self
.ToolDefinition
2342 # Construct a list contain the build options which need override.
2346 # Key[0] -- tool family
2347 # Key[1] -- TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
2349 if (Key
[0] == self
.BuildRuleFamily
and
2350 (ModuleStyle
is None or len(Key
) < 3 or (len(Key
) > 2 and Key
[2] == ModuleStyle
))):
2351 Target
, ToolChain
, Arch
, CommandType
, Attr
= Key
[1].split('_')
2352 if (Target
== self
.BuildTarget
or Target
== TAB_STAR
) and\
2353 (ToolChain
== self
.ToolChain
or ToolChain
== TAB_STAR
) and\
2354 (Arch
== self
.Arch
or Arch
== TAB_STAR
) and\
2355 Options
[Key
].startswith("="):
2357 if OverrideList
.get(Key
[1]) is not None:
2358 OverrideList
.pop(Key
[1])
2359 OverrideList
[Key
[1]] = Options
[Key
]
2362 # Use the highest priority value.
2364 if (len(OverrideList
) >= 2):
2365 KeyList
= list(OverrideList
.keys())
2366 for Index
in range(len(KeyList
)):
2367 NowKey
= KeyList
[Index
]
2368 Target1
, ToolChain1
, Arch1
, CommandType1
, Attr1
= NowKey
.split("_")
2369 for Index1
in range(len(KeyList
) - Index
- 1):
2370 NextKey
= KeyList
[Index1
+ Index
+ 1]
2372 # Compare two Key, if one is included by another, choose the higher priority one
2374 Target2
, ToolChain2
, Arch2
, CommandType2
, Attr2
= NextKey
.split("_")
2375 if (Target1
== Target2
or Target1
== TAB_STAR
or Target2
== TAB_STAR
) and\
2376 (ToolChain1
== ToolChain2
or ToolChain1
== TAB_STAR
or ToolChain2
== TAB_STAR
) and\
2377 (Arch1
== Arch2
or Arch1
== TAB_STAR
or Arch2
== TAB_STAR
) and\
2378 (CommandType1
== CommandType2
or CommandType1
== TAB_STAR
or CommandType2
== TAB_STAR
) and\
2379 (Attr1
== Attr2
or Attr1
== TAB_STAR
or Attr2
== TAB_STAR
):
2381 if self
.CalculatePriorityValue(NowKey
) > self
.CalculatePriorityValue(NextKey
):
2382 if Options
.get((self
.BuildRuleFamily
, NextKey
)) is not None:
2383 Options
.pop((self
.BuildRuleFamily
, NextKey
))
2385 if Options
.get((self
.BuildRuleFamily
, NowKey
)) is not None:
2386 Options
.pop((self
.BuildRuleFamily
, NowKey
))
2389 if ModuleStyle
is not None and len (Key
) > 2:
2390 # Check Module style is EDK or EDKII.
2391 # Only append build option for the matched style module.
2392 if ModuleStyle
== EDK_NAME
and Key
[2] != EDK_NAME
:
2394 elif ModuleStyle
== EDKII_NAME
and Key
[2] != EDKII_NAME
:
2397 Target
, Tag
, Arch
, Tool
, Attr
= Key
[1].split("_")
2398 # if tool chain family doesn't match, skip it
2399 if Tool
in ToolDef
and Family
!= "":
2400 FamilyIsNull
= False
2401 if ToolDef
[Tool
].get(TAB_TOD_DEFINES_BUILDRULEFAMILY
, "") != "":
2402 if Family
!= ToolDef
[Tool
][TAB_TOD_DEFINES_BUILDRULEFAMILY
]:
2404 elif Family
!= ToolDef
[Tool
][TAB_TOD_DEFINES_FAMILY
]:
2407 # expand any wildcard
2408 if Target
== TAB_STAR
or Target
== self
.BuildTarget
:
2409 if Tag
== TAB_STAR
or Tag
== self
.ToolChain
:
2410 if Arch
== TAB_STAR
or Arch
== self
.Arch
:
2411 if Tool
not in BuildOptions
:
2412 BuildOptions
[Tool
] = {}
2413 if Attr
!= "FLAGS" or Attr
not in BuildOptions
[Tool
] or Options
[Key
].startswith('='):
2414 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2416 # append options for the same tool except PATH
2418 BuildOptions
[Tool
][Attr
] += " " + Options
[Key
]
2420 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2421 # Build Option Family has been checked, which need't to be checked again for family.
2422 if FamilyMatch
or FamilyIsNull
:
2426 if ModuleStyle
is not None and len (Key
) > 2:
2427 # Check Module style is EDK or EDKII.
2428 # Only append build option for the matched style module.
2429 if ModuleStyle
== EDK_NAME
and Key
[2] != EDK_NAME
:
2431 elif ModuleStyle
== EDKII_NAME
and Key
[2] != EDKII_NAME
:
2434 Target
, Tag
, Arch
, Tool
, Attr
= Key
[1].split("_")
2435 # if tool chain family doesn't match, skip it
2436 if Tool
not in ToolDef
or Family
== "":
2438 # option has been added before
2439 if Family
!= ToolDef
[Tool
][TAB_TOD_DEFINES_FAMILY
]:
2442 # expand any wildcard
2443 if Target
== TAB_STAR
or Target
== self
.BuildTarget
:
2444 if Tag
== TAB_STAR
or Tag
== self
.ToolChain
:
2445 if Arch
== TAB_STAR
or Arch
== self
.Arch
:
2446 if Tool
not in BuildOptions
:
2447 BuildOptions
[Tool
] = {}
2448 if Attr
!= "FLAGS" or Attr
not in BuildOptions
[Tool
] or Options
[Key
].startswith('='):
2449 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2451 # append options for the same tool except PATH
2453 BuildOptions
[Tool
][Attr
] += " " + Options
[Key
]
2455 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2458 ## Append build options in platform to a module
2460 # @param Module The module to which the build options will be appended
2462 # @retval options The options appended with build options in platform
2464 def ApplyBuildOption(self
, Module
):
2465 # Get the different options for the different style module
2466 PlatformOptions
= self
.EdkIIBuildOption
2467 ModuleTypeOptions
= self
.Platform
.GetBuildOptionsByModuleType(EDKII_NAME
, Module
.ModuleType
)
2468 ModuleTypeOptions
= self
._ExpandBuildOption
(ModuleTypeOptions
)
2469 ModuleOptions
= self
._ExpandBuildOption
(Module
.BuildOptions
)
2470 if Module
in self
.Platform
.Modules
:
2471 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
2472 PlatformModuleOptions
= self
._ExpandBuildOption
(PlatformModule
.BuildOptions
)
2474 PlatformModuleOptions
= {}
2476 BuildRuleOrder
= None
2477 for Options
in [self
.ToolDefinition
, ModuleOptions
, PlatformOptions
, ModuleTypeOptions
, PlatformModuleOptions
]:
2478 for Tool
in Options
:
2479 for Attr
in Options
[Tool
]:
2480 if Attr
== TAB_TOD_DEFINES_BUILDRULEORDER
:
2481 BuildRuleOrder
= Options
[Tool
][Attr
]
2483 AllTools
= set(list(ModuleOptions
.keys()) + list(PlatformOptions
.keys()) +
2484 list(PlatformModuleOptions
.keys()) + list(ModuleTypeOptions
.keys()) +
2485 list(self
.ToolDefinition
.keys()))
2486 BuildOptions
= defaultdict(lambda: defaultdict(str))
2487 for Tool
in AllTools
:
2488 for Options
in [self
.ToolDefinition
, ModuleOptions
, PlatformOptions
, ModuleTypeOptions
, PlatformModuleOptions
]:
2489 if Tool
not in Options
:
2491 for Attr
in Options
[Tool
]:
2493 # Do not generate it in Makefile
2495 if Attr
== TAB_TOD_DEFINES_BUILDRULEORDER
:
2497 Value
= Options
[Tool
][Attr
]
2498 # check if override is indicated
2499 if Value
.startswith('='):
2500 BuildOptions
[Tool
][Attr
] = mws
.handleWsMacro(Value
[1:])
2503 BuildOptions
[Tool
][Attr
] += " " + mws
.handleWsMacro(Value
)
2505 BuildOptions
[Tool
][Attr
] = mws
.handleWsMacro(Value
)
2507 return BuildOptions
, BuildRuleOrder
2510 # extend lists contained in a dictionary with lists stored in another dictionary
2511 # if CopyToDict is not derived from DefaultDict(list) then this may raise exception
2513 def ExtendCopyDictionaryLists(CopyToDict
, CopyFromDict
):
2514 for Key
in CopyFromDict
:
2515 CopyToDict
[Key
].extend(CopyFromDict
[Key
])
2517 # Create a directory specified by a set of path elements and return the full path
2518 def _MakeDir(PathList
):
2519 RetVal
= path
.join(*PathList
)
2520 CreateDirectory(RetVal
)
2523 ## ModuleAutoGen class
2525 # This class encapsules the AutoGen behaviors for the build tools. In addition to
2526 # the generation of AutoGen.h and AutoGen.c, it will generate *.depex file according
2527 # to the [depex] section in module's inf file.
2529 class ModuleAutoGen(AutoGen
):
2530 # call super().__init__ then call the worker function with different parameter count
2531 def __init__(self
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
2532 if not hasattr(self
, "_Init"):
2533 self
._InitWorker
(Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
)
2536 ## Cache the timestamps of metafiles of every module in a class attribute
2540 def __new__(cls
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
2541 # check if this module is employed by active platform
2542 if not PlatformAutoGen(Workspace
, args
[0], Target
, Toolchain
, Arch
).ValidModule(MetaFile
):
2543 EdkLogger
.verbose("Module [%s] for [%s] is not employed by active platform\n" \
2546 return super(ModuleAutoGen
, cls
).__new
__(cls
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
)
2548 ## Initialize ModuleAutoGen
2550 # @param Workspace EdkIIWorkspaceBuild object
2551 # @param ModuleFile The path of module file
2552 # @param Target Build target (DEBUG, RELEASE)
2553 # @param Toolchain Name of tool chain
2554 # @param Arch The arch the module supports
2555 # @param PlatformFile Platform meta-file
2557 def _InitWorker(self
, Workspace
, ModuleFile
, Target
, Toolchain
, Arch
, PlatformFile
):
2558 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "AutoGen module [%s] [%s]" % (ModuleFile
, Arch
))
2559 GlobalData
.gProcessingFile
= "%s [%s, %s, %s]" % (ModuleFile
, Arch
, Toolchain
, Target
)
2561 self
.Workspace
= Workspace
2562 self
.WorkspaceDir
= Workspace
.WorkspaceDir
2563 self
.MetaFile
= ModuleFile
2564 self
.PlatformInfo
= PlatformAutoGen(Workspace
, PlatformFile
, Target
, Toolchain
, Arch
)
2566 self
.SourceDir
= self
.MetaFile
.SubDir
2567 self
.SourceDir
= mws
.relpath(self
.SourceDir
, self
.WorkspaceDir
)
2569 self
.ToolChain
= Toolchain
2570 self
.BuildTarget
= Target
2572 self
.ToolChainFamily
= self
.PlatformInfo
.ToolChainFamily
2573 self
.BuildRuleFamily
= self
.PlatformInfo
.BuildRuleFamily
2575 self
.IsCodeFileCreated
= False
2576 self
.IsAsBuiltInfCreated
= False
2577 self
.DepexGenerated
= False
2579 self
.BuildDatabase
= self
.Workspace
.BuildDatabase
2580 self
.BuildRuleOrder
= None
2583 self
._PcdComments
= OrderedListDict()
2584 self
._GuidComments
= OrderedListDict()
2585 self
._ProtocolComments
= OrderedListDict()
2586 self
._PpiComments
= OrderedListDict()
2587 self
._BuildTargets
= None
2588 self
._IntroBuildTargetList
= None
2589 self
._FinalBuildTargetList
= None
2590 self
._FileTypes
= None
2592 self
.AutoGenDepSet
= set()
2593 self
.ReferenceModules
= []
2596 ## hash() operator of ModuleAutoGen
2598 # The module file path and arch string will be used to represent
2599 # hash value of this object
2601 # @retval int Hash value of the module file path and arch
2603 @cached_class_function
2605 return hash((self
.MetaFile
, self
.Arch
))
2608 return "%s [%s]" % (self
.MetaFile
, self
.Arch
)
2610 # Get FixedAtBuild Pcds of this Module
2612 def FixedAtBuildPcds(self
):
2614 for Pcd
in self
.ModulePcdList
:
2615 if Pcd
.Type
!= TAB_PCDS_FIXED_AT_BUILD
:
2617 if Pcd
not in RetVal
:
2622 def FixedVoidTypePcds(self
):
2624 for Pcd
in self
.FixedAtBuildPcds
:
2625 if Pcd
.DatumType
== TAB_VOID
:
2626 if '{}.{}'.format(Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) not in RetVal
:
2627 RetVal
['{}.{}'.format(Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
)] = Pcd
.DefaultValue
2631 def UniqueBaseName(self
):
2632 BaseName
= self
.Name
2633 for Module
in self
.PlatformInfo
.ModuleAutoGenList
:
2634 if Module
.MetaFile
== self
.MetaFile
:
2636 if Module
.Name
== self
.Name
:
2637 if uuid
.UUID(Module
.Guid
) == uuid
.UUID(self
.Guid
):
2638 EdkLogger
.error("build", FILE_DUPLICATED
, 'Modules have same BaseName and FILE_GUID:\n'
2639 ' %s\n %s' % (Module
.MetaFile
, self
.MetaFile
))
2640 BaseName
= '%s_%s' % (self
.Name
, self
.Guid
)
2643 # Macros could be used in build_rule.txt (also Makefile)
2646 return OrderedDict((
2647 ("WORKSPACE" ,self
.WorkspaceDir
),
2648 ("MODULE_NAME" ,self
.Name
),
2649 ("MODULE_NAME_GUID" ,self
.UniqueBaseName
),
2650 ("MODULE_GUID" ,self
.Guid
),
2651 ("MODULE_VERSION" ,self
.Version
),
2652 ("MODULE_TYPE" ,self
.ModuleType
),
2653 ("MODULE_FILE" ,str(self
.MetaFile
)),
2654 ("MODULE_FILE_BASE_NAME" ,self
.MetaFile
.BaseName
),
2655 ("MODULE_RELATIVE_DIR" ,self
.SourceDir
),
2656 ("MODULE_DIR" ,self
.SourceDir
),
2657 ("BASE_NAME" ,self
.Name
),
2658 ("ARCH" ,self
.Arch
),
2659 ("TOOLCHAIN" ,self
.ToolChain
),
2660 ("TOOLCHAIN_TAG" ,self
.ToolChain
),
2661 ("TOOL_CHAIN_TAG" ,self
.ToolChain
),
2662 ("TARGET" ,self
.BuildTarget
),
2663 ("BUILD_DIR" ,self
.PlatformInfo
.BuildDir
),
2664 ("BIN_DIR" ,os
.path
.join(self
.PlatformInfo
.BuildDir
, self
.Arch
)),
2665 ("LIB_DIR" ,os
.path
.join(self
.PlatformInfo
.BuildDir
, self
.Arch
)),
2666 ("MODULE_BUILD_DIR" ,self
.BuildDir
),
2667 ("OUTPUT_DIR" ,self
.OutputDir
),
2668 ("DEBUG_DIR" ,self
.DebugDir
),
2669 ("DEST_DIR_OUTPUT" ,self
.OutputDir
),
2670 ("DEST_DIR_DEBUG" ,self
.DebugDir
),
2671 ("PLATFORM_NAME" ,self
.PlatformInfo
.Name
),
2672 ("PLATFORM_GUID" ,self
.PlatformInfo
.Guid
),
2673 ("PLATFORM_VERSION" ,self
.PlatformInfo
.Version
),
2674 ("PLATFORM_RELATIVE_DIR" ,self
.PlatformInfo
.SourceDir
),
2675 ("PLATFORM_DIR" ,mws
.join(self
.WorkspaceDir
, self
.PlatformInfo
.SourceDir
)),
2676 ("PLATFORM_OUTPUT_DIR" ,self
.PlatformInfo
.OutputDir
),
2677 ("FFS_OUTPUT_DIR" ,self
.FfsOutputDir
)
2680 ## Return the module build data object
2683 return self
.BuildDatabase
[self
.MetaFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
2685 ## Return the module name
2688 return self
.Module
.BaseName
2690 ## Return the module DxsFile if exist
2693 return self
.Module
.DxsFile
2695 ## Return the module meta-file GUID
2699 # To build same module more than once, the module path with FILE_GUID overridden has
2700 # the file name FILE_GUIDmodule.inf, but the relative path (self.MetaFile.File) is the real path
2701 # in DSC. The overridden GUID can be retrieved from file name
2703 if os
.path
.basename(self
.MetaFile
.File
) != os
.path
.basename(self
.MetaFile
.Path
):
2705 # Length of GUID is 36
2707 return os
.path
.basename(self
.MetaFile
.Path
)[:36]
2708 return self
.Module
.Guid
2710 ## Return the module version
2713 return self
.Module
.Version
2715 ## Return the module type
2717 def ModuleType(self
):
2718 return self
.Module
.ModuleType
2720 ## Return the component type (for Edk.x style of module)
2722 def ComponentType(self
):
2723 return self
.Module
.ComponentType
2725 ## Return the build type
2727 def BuildType(self
):
2728 return self
.Module
.BuildType
2730 ## Return the PCD_IS_DRIVER setting
2732 def PcdIsDriver(self
):
2733 return self
.Module
.PcdIsDriver
2735 ## Return the autogen version, i.e. module meta-file version
2737 def AutoGenVersion(self
):
2738 return self
.Module
.AutoGenVersion
2740 ## Check if the module is library or not
2742 def IsLibrary(self
):
2743 return bool(self
.Module
.LibraryClass
)
2745 ## Check if the module is binary module or not
2747 def IsBinaryModule(self
):
2748 return self
.Module
.IsBinaryModule
2750 ## Return the directory to store intermediate files of the module
2754 self
.PlatformInfo
.BuildDir
,
2757 self
.MetaFile
.BaseName
2760 ## Return the directory to store the intermediate object files of the module
2762 def OutputDir(self
):
2763 return _MakeDir((self
.BuildDir
, "OUTPUT"))
2765 ## Return the directory path to store ffs file
2767 def FfsOutputDir(self
):
2768 if GlobalData
.gFdfParser
:
2769 return path
.join(self
.PlatformInfo
.BuildDir
, TAB_FV_DIRECTORY
, "Ffs", self
.Guid
+ self
.Name
)
2772 ## Return the directory to store auto-gened source files of the module
2775 return _MakeDir((self
.BuildDir
, "DEBUG"))
2777 ## Return the path of custom file
2779 def CustomMakefile(self
):
2781 for Type
in self
.Module
.CustomMakefile
:
2782 MakeType
= gMakeTypeMap
[Type
] if Type
in gMakeTypeMap
else 'nmake'
2783 File
= os
.path
.join(self
.SourceDir
, self
.Module
.CustomMakefile
[Type
])
2784 RetVal
[MakeType
] = File
2787 ## Return the directory of the makefile
2789 # @retval string The directory string of module's makefile
2792 def MakeFileDir(self
):
2793 return self
.BuildDir
2795 ## Return build command string
2797 # @retval string Build command string
2800 def BuildCommand(self
):
2801 return self
.PlatformInfo
.BuildCommand
2803 ## Get object list of all packages the module and its dependent libraries belong to
2805 # @retval list The list of package object
2808 def DerivedPackageList(self
):
2810 for M
in [self
.Module
] + self
.DependentLibraryList
:
2811 for Package
in M
.Packages
:
2812 if Package
in PackageList
:
2814 PackageList
.append(Package
)
2817 ## Get the depex string
2819 # @return : a string contain all depex expression.
2820 def _GetDepexExpresionString(self
):
2823 ## DPX_SOURCE IN Define section.
2824 if self
.Module
.DxsFile
:
2826 for M
in [self
.Module
] + self
.DependentLibraryList
:
2827 Filename
= M
.MetaFile
.Path
2828 InfObj
= InfSectionParser
.InfSectionParser(Filename
)
2829 DepexExpressionList
= InfObj
.GetDepexExpresionList()
2830 for DepexExpression
in DepexExpressionList
:
2831 for key
in DepexExpression
:
2832 Arch
, ModuleType
= key
2833 DepexExpr
= [x
for x
in DepexExpression
[key
] if not str(x
).startswith('#')]
2834 # the type of build module is USER_DEFINED.
2835 # All different DEPEX section tags would be copied into the As Built INF file
2836 # and there would be separate DEPEX section tags
2837 if self
.ModuleType
.upper() == SUP_MODULE_USER_DEFINED
:
2838 if (Arch
.upper() == self
.Arch
.upper()) and (ModuleType
.upper() != TAB_ARCH_COMMON
):
2839 DepexList
.append({(Arch
, ModuleType
): DepexExpr
})
2841 if Arch
.upper() == TAB_ARCH_COMMON
or \
2842 (Arch
.upper() == self
.Arch
.upper() and \
2843 ModuleType
.upper() in [TAB_ARCH_COMMON
, self
.ModuleType
.upper()]):
2844 DepexList
.append({(Arch
, ModuleType
): DepexExpr
})
2846 #the type of build module is USER_DEFINED.
2847 if self
.ModuleType
.upper() == SUP_MODULE_USER_DEFINED
:
2848 for Depex
in DepexList
:
2850 DepexStr
+= '[Depex.%s.%s]\n' % key
2851 DepexStr
+= '\n'.join('# '+ val
for val
in Depex
[key
])
2854 return '[Depex.%s]\n' % self
.Arch
2857 #the type of build module not is USER_DEFINED.
2859 for Depex
in DepexList
:
2864 for D
in Depex
.values():
2865 DepexStr
+= ' '.join(val
for val
in D
)
2866 Index
= DepexStr
.find('END')
2867 if Index
> -1 and Index
== len(DepexStr
) - 3:
2868 DepexStr
= DepexStr
[:-3]
2869 DepexStr
= DepexStr
.strip()
2872 DepexStr
= DepexStr
.lstrip('(').rstrip(')').strip()
2874 return '[Depex.%s]\n' % self
.Arch
2875 return '[Depex.%s]\n# ' % self
.Arch
+ DepexStr
2877 ## Merge dependency expression
2879 # @retval list The token list of the dependency expression after parsed
2882 def DepexList(self
):
2883 if self
.DxsFile
or self
.IsLibrary
or TAB_DEPENDENCY_EXPRESSION_FILE
in self
.FileTypes
:
2888 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expression
2890 for M
in [self
.Module
] + self
.DependentLibraryList
:
2892 for D
in M
.Depex
[self
.Arch
, self
.ModuleType
]:
2894 DepexList
.append('AND')
2895 DepexList
.append('(')
2896 #replace D with value if D is FixedAtBuild PCD
2900 NewList
.append(item
)
2902 FixedVoidTypePcds
= {}
2903 if item
in self
.FixedVoidTypePcds
:
2904 FixedVoidTypePcds
= self
.FixedVoidTypePcds
2905 elif M
in self
.PlatformInfo
.LibraryAutoGenList
:
2906 Index
= self
.PlatformInfo
.LibraryAutoGenList
.index(M
)
2907 FixedVoidTypePcds
= self
.PlatformInfo
.LibraryAutoGenList
[Index
].FixedVoidTypePcds
2908 if item
not in FixedVoidTypePcds
:
2909 EdkLogger
.error("build", FORMAT_INVALID
, "{} used in [Depex] section should be used as FixedAtBuild type and VOID* datum type in the module.".format(item
))
2911 Value
= FixedVoidTypePcds
[item
]
2912 if len(Value
.split(',')) != 16:
2913 EdkLogger
.error("build", FORMAT_INVALID
,
2914 "{} used in [Depex] section should be used as FixedAtBuild type and VOID* datum type and 16 bytes in the module.".format(item
))
2915 NewList
.append(Value
)
2916 DepexList
.extend(NewList
)
2917 if DepexList
[-1] == 'END': # no need of a END at this time
2919 DepexList
.append(')')
2922 EdkLogger
.verbose("DEPEX[%s] (+%s) = %s" % (self
.Name
, M
.BaseName
, DepexList
))
2923 if 'BEFORE' in DepexList
or 'AFTER' in DepexList
:
2925 if len(DepexList
) > 0:
2926 EdkLogger
.verbose('')
2927 return {self
.ModuleType
:DepexList
}
2929 ## Merge dependency expression
2931 # @retval list The token list of the dependency expression after parsed
2934 def DepexExpressionDict(self
):
2935 if self
.DxsFile
or self
.IsLibrary
or TAB_DEPENDENCY_EXPRESSION_FILE
in self
.FileTypes
:
2938 DepexExpressionString
= ''
2940 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
2942 for M
in [self
.Module
] + self
.DependentLibraryList
:
2944 for D
in M
.DepexExpression
[self
.Arch
, self
.ModuleType
]:
2945 if DepexExpressionString
!= '':
2946 DepexExpressionString
+= ' AND '
2947 DepexExpressionString
+= '('
2948 DepexExpressionString
+= D
2949 DepexExpressionString
= DepexExpressionString
.rstrip('END').strip()
2950 DepexExpressionString
+= ')'
2953 EdkLogger
.verbose("DEPEX[%s] (+%s) = %s" % (self
.Name
, M
.BaseName
, DepexExpressionString
))
2954 if 'BEFORE' in DepexExpressionString
or 'AFTER' in DepexExpressionString
:
2956 if len(DepexExpressionString
) > 0:
2957 EdkLogger
.verbose('')
2959 return {self
.ModuleType
:DepexExpressionString
}
2961 # Get the tiano core user extension, it is contain dependent library.
2962 # @retval: a list contain tiano core userextension.
2964 def _GetTianoCoreUserExtensionList(self
):
2965 TianoCoreUserExtentionList
= []
2966 for M
in [self
.Module
] + self
.DependentLibraryList
:
2967 Filename
= M
.MetaFile
.Path
2968 InfObj
= InfSectionParser
.InfSectionParser(Filename
)
2969 TianoCoreUserExtenList
= InfObj
.GetUserExtensionTianoCore()
2970 for TianoCoreUserExtent
in TianoCoreUserExtenList
:
2971 for Section
in TianoCoreUserExtent
:
2972 ItemList
= Section
.split(TAB_SPLIT
)
2974 if len(ItemList
) == 4:
2976 if Arch
.upper() == TAB_ARCH_COMMON
or Arch
.upper() == self
.Arch
.upper():
2978 TianoCoreList
.extend([TAB_SECTION_START
+ Section
+ TAB_SECTION_END
])
2979 TianoCoreList
.extend(TianoCoreUserExtent
[Section
][:])
2980 TianoCoreList
.append('\n')
2981 TianoCoreUserExtentionList
.append(TianoCoreList
)
2983 return TianoCoreUserExtentionList
2985 ## Return the list of specification version required for the module
2987 # @retval list The list of specification defined in module file
2990 def Specification(self
):
2991 return self
.Module
.Specification
2993 ## Tool option for the module build
2995 # @param PlatformInfo The object of PlatformBuildInfo
2996 # @retval dict The dict containing valid options
2999 def BuildOption(self
):
3000 RetVal
, self
.BuildRuleOrder
= self
.PlatformInfo
.ApplyBuildOption(self
.Module
)
3001 if self
.BuildRuleOrder
:
3002 self
.BuildRuleOrder
= ['.%s' % Ext
for Ext
in self
.BuildRuleOrder
.split()]
3005 ## Get include path list from tool option for the module build
3007 # @retval list The include path list
3010 def BuildOptionIncPathList(self
):
3012 # Regular expression for finding Include Directories, the difference between MSFT and INTEL/GCC/RVCT
3013 # is the former use /I , the Latter used -I to specify include directories
3015 if self
.PlatformInfo
.ToolChainFamily
in (TAB_COMPILER_MSFT
):
3016 BuildOptIncludeRegEx
= gBuildOptIncludePatternMsft
3017 elif self
.PlatformInfo
.ToolChainFamily
in ('INTEL', 'GCC', 'RVCT'):
3018 BuildOptIncludeRegEx
= gBuildOptIncludePatternOther
3021 # New ToolChainFamily, don't known whether there is option to specify include directories
3026 for Tool
in ('CC', 'PP', 'VFRPP', 'ASLPP', 'ASLCC', 'APP', 'ASM'):
3028 FlagOption
= self
.BuildOption
[Tool
]['FLAGS']
3032 if self
.ToolChainFamily
!= 'RVCT':
3033 IncPathList
= [NormPath(Path
, self
.Macros
) for Path
in BuildOptIncludeRegEx
.findall(FlagOption
)]
3036 # RVCT may specify a list of directory separated by commas
3039 for Path
in BuildOptIncludeRegEx
.findall(FlagOption
):
3040 PathList
= GetSplitList(Path
, TAB_COMMA_SPLIT
)
3041 IncPathList
.extend(NormPath(PathEntry
, self
.Macros
) for PathEntry
in PathList
)
3044 # EDK II modules must not reference header files outside of the packages they depend on or
3045 # within the module's directory tree. Report error if violation.
3047 if GlobalData
.gDisableIncludePathCheck
== False:
3048 for Path
in IncPathList
:
3049 if (Path
not in self
.IncludePathList
) and (CommonPath([Path
, self
.MetaFile
.Dir
]) != self
.MetaFile
.Dir
):
3050 ErrMsg
= "The include directory for the EDK II module in this line is invalid %s specified in %s FLAGS '%s'" % (Path
, Tool
, FlagOption
)
3051 EdkLogger
.error("build",
3054 File
=str(self
.MetaFile
))
3055 RetVal
+= IncPathList
3058 ## Return a list of files which can be built from source
3060 # What kind of files can be built is determined by build rules in
3061 # $(CONF_DIRECTORY)/build_rule.txt and toolchain family.
3064 def SourceFileList(self
):
3066 ToolChainTagSet
= {"", TAB_STAR
, self
.ToolChain
}
3067 ToolChainFamilySet
= {"", TAB_STAR
, self
.ToolChainFamily
, self
.BuildRuleFamily
}
3068 for F
in self
.Module
.Sources
:
3070 if F
.TagName
not in ToolChainTagSet
:
3071 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "The toolchain [%s] for processing file [%s] is found, "
3072 "but [%s] is currently used" % (F
.TagName
, str(F
), self
.ToolChain
))
3074 # match tool chain family or build rule family
3075 if F
.ToolChainFamily
not in ToolChainFamilySet
:
3078 "The file [%s] must be built by tools of [%s], " \
3079 "but current toolchain family is [%s], buildrule family is [%s]" \
3080 % (str(F
), F
.ToolChainFamily
, self
.ToolChainFamily
, self
.BuildRuleFamily
))
3083 # add the file path into search path list for file including
3084 if F
.Dir
not in self
.IncludePathList
:
3085 self
.IncludePathList
.insert(0, F
.Dir
)
3088 self
._MatchBuildRuleOrder
(RetVal
)
3091 self
._ApplyBuildRule
(F
, TAB_UNKNOWN_FILE
)
3094 def _MatchBuildRuleOrder(self
, FileList
):
3097 for SingleFile
in FileList
:
3098 if self
.BuildRuleOrder
and SingleFile
.Ext
in self
.BuildRuleOrder
and SingleFile
.Ext
in self
.BuildRules
:
3099 key
= SingleFile
.Path
.rsplit(SingleFile
.Ext
,1)[0]
3100 if key
in Order_Dict
:
3101 Order_Dict
[key
].append(SingleFile
.Ext
)
3103 Order_Dict
[key
] = [SingleFile
.Ext
]
3106 for F
in Order_Dict
:
3107 if len(Order_Dict
[F
]) > 1:
3108 Order_Dict
[F
].sort(key
=lambda i
: self
.BuildRuleOrder
.index(i
))
3109 for Ext
in Order_Dict
[F
][1:]:
3110 RemoveList
.append(F
+ Ext
)
3112 for item
in RemoveList
:
3113 FileList
.remove(item
)
3117 ## Return the list of unicode files
3119 def UnicodeFileList(self
):
3120 return self
.FileTypes
.get(TAB_UNICODE_FILE
,[])
3122 ## Return the list of vfr files
3124 def VfrFileList(self
):
3125 return self
.FileTypes
.get(TAB_VFR_FILE
, [])
3127 ## Return the list of Image Definition files
3129 def IdfFileList(self
):
3130 return self
.FileTypes
.get(TAB_IMAGE_FILE
,[])
3132 ## Return a list of files which can be built from binary
3134 # "Build" binary files are just to copy them to build directory.
3136 # @retval list The list of files which can be built later
3139 def BinaryFileList(self
):
3141 for F
in self
.Module
.Binaries
:
3142 if F
.Target
not in [TAB_ARCH_COMMON
, TAB_STAR
] and F
.Target
!= self
.BuildTarget
:
3145 self
._ApplyBuildRule
(F
, F
.Type
, BinaryFileList
=RetVal
)
3149 def BuildRules(self
):
3151 BuildRuleDatabase
= self
.PlatformInfo
.BuildRule
3152 for Type
in BuildRuleDatabase
.FileTypeList
:
3153 #first try getting build rule by BuildRuleFamily
3154 RuleObject
= BuildRuleDatabase
[Type
, self
.BuildType
, self
.Arch
, self
.BuildRuleFamily
]
3156 # build type is always module type, but ...
3157 if self
.ModuleType
!= self
.BuildType
:
3158 RuleObject
= BuildRuleDatabase
[Type
, self
.ModuleType
, self
.Arch
, self
.BuildRuleFamily
]
3159 #second try getting build rule by ToolChainFamily
3161 RuleObject
= BuildRuleDatabase
[Type
, self
.BuildType
, self
.Arch
, self
.ToolChainFamily
]
3163 # build type is always module type, but ...
3164 if self
.ModuleType
!= self
.BuildType
:
3165 RuleObject
= BuildRuleDatabase
[Type
, self
.ModuleType
, self
.Arch
, self
.ToolChainFamily
]
3168 RuleObject
= RuleObject
.Instantiate(self
.Macros
)
3169 RetVal
[Type
] = RuleObject
3170 for Ext
in RuleObject
.SourceFileExtList
:
3171 RetVal
[Ext
] = RuleObject
3174 def _ApplyBuildRule(self
, File
, FileType
, BinaryFileList
=None):
3175 if self
._BuildTargets
is None:
3176 self
._IntroBuildTargetList
= set()
3177 self
._FinalBuildTargetList
= set()
3178 self
._BuildTargets
= defaultdict(set)
3179 self
._FileTypes
= defaultdict(set)
3181 if not BinaryFileList
:
3182 BinaryFileList
= self
.BinaryFileList
3184 SubDirectory
= os
.path
.join(self
.OutputDir
, File
.SubDir
)
3185 if not os
.path
.exists(SubDirectory
):
3186 CreateDirectory(SubDirectory
)
3192 # Make sure to get build rule order value
3196 while Index
< len(SourceList
):
3197 Source
= SourceList
[Index
]
3201 CreateDirectory(Source
.Dir
)
3203 if File
.IsBinary
and File
== Source
and File
in BinaryFileList
:
3204 # Skip all files that are not binary libraries
3205 if not self
.IsLibrary
:
3207 RuleObject
= self
.BuildRules
[TAB_DEFAULT_BINARY_FILE
]
3208 elif FileType
in self
.BuildRules
:
3209 RuleObject
= self
.BuildRules
[FileType
]
3210 elif Source
.Ext
in self
.BuildRules
:
3211 RuleObject
= self
.BuildRules
[Source
.Ext
]
3213 # stop at no more rules
3215 self
._FinalBuildTargetList
.add(LastTarget
)
3218 FileType
= RuleObject
.SourceFileType
3219 self
._FileTypes
[FileType
].add(Source
)
3221 # stop at STATIC_LIBRARY for library
3222 if self
.IsLibrary
and FileType
== TAB_STATIC_LIBRARY
:
3224 self
._FinalBuildTargetList
.add(LastTarget
)
3227 Target
= RuleObject
.Apply(Source
, self
.BuildRuleOrder
)
3230 self
._FinalBuildTargetList
.add(LastTarget
)
3232 elif not Target
.Outputs
:
3233 # Only do build for target with outputs
3234 self
._FinalBuildTargetList
.add(Target
)
3236 self
._BuildTargets
[FileType
].add(Target
)
3238 if not Source
.IsBinary
and Source
== File
:
3239 self
._IntroBuildTargetList
.add(Target
)
3241 # to avoid cyclic rule
3242 if FileType
in RuleChain
:
3245 RuleChain
.add(FileType
)
3246 SourceList
.extend(Target
.Outputs
)
3248 FileType
= TAB_UNKNOWN_FILE
3252 if self
._BuildTargets
is None:
3253 self
._IntroBuildTargetList
= set()
3254 self
._FinalBuildTargetList
= set()
3255 self
._BuildTargets
= defaultdict(set)
3256 self
._FileTypes
= defaultdict(set)
3258 #TRICK: call SourceFileList property to apply build rule for source files
3261 #TRICK: call _GetBinaryFileList to apply build rule for binary files
3264 return self
._BuildTargets
3267 def IntroTargetList(self
):
3269 return self
._IntroBuildTargetList
3272 def CodaTargetList(self
):
3274 return self
._FinalBuildTargetList
3277 def FileTypes(self
):
3279 return self
._FileTypes
3281 ## Get the list of package object the module depends on
3283 # @retval list The package object list
3286 def DependentPackageList(self
):
3287 return self
.Module
.Packages
3289 ## Return the list of auto-generated code file
3291 # @retval list The list of auto-generated file
3294 def AutoGenFileList(self
):
3295 AutoGenUniIdf
= self
.BuildType
!= 'UEFI_HII'
3296 UniStringBinBuffer
= BytesIO()
3297 IdfGenBinBuffer
= BytesIO()
3299 AutoGenC
= TemplateString()
3300 AutoGenH
= TemplateString()
3301 StringH
= TemplateString()
3302 StringIdf
= TemplateString()
3303 GenC
.CreateCode(self
, AutoGenC
, AutoGenH
, StringH
, AutoGenUniIdf
, UniStringBinBuffer
, StringIdf
, AutoGenUniIdf
, IdfGenBinBuffer
)
3305 # AutoGen.c is generated if there are library classes in inf, or there are object files
3307 if str(AutoGenC
) != "" and (len(self
.Module
.LibraryClasses
) > 0
3308 or TAB_OBJECT_FILE
in self
.FileTypes
):
3309 AutoFile
= PathClass(gAutoGenCodeFileName
, self
.DebugDir
)
3310 RetVal
[AutoFile
] = str(AutoGenC
)
3311 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3312 if str(AutoGenH
) != "":
3313 AutoFile
= PathClass(gAutoGenHeaderFileName
, self
.DebugDir
)
3314 RetVal
[AutoFile
] = str(AutoGenH
)
3315 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3316 if str(StringH
) != "":
3317 AutoFile
= PathClass(gAutoGenStringFileName
% {"module_name":self
.Name
}, self
.DebugDir
)
3318 RetVal
[AutoFile
] = str(StringH
)
3319 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3320 if UniStringBinBuffer
is not None and UniStringBinBuffer
.getvalue() != b
"":
3321 AutoFile
= PathClass(gAutoGenStringFormFileName
% {"module_name":self
.Name
}, self
.OutputDir
)
3322 RetVal
[AutoFile
] = UniStringBinBuffer
.getvalue()
3323 AutoFile
.IsBinary
= True
3324 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3325 if UniStringBinBuffer
is not None:
3326 UniStringBinBuffer
.close()
3327 if str(StringIdf
) != "":
3328 AutoFile
= PathClass(gAutoGenImageDefFileName
% {"module_name":self
.Name
}, self
.DebugDir
)
3329 RetVal
[AutoFile
] = str(StringIdf
)
3330 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3331 if IdfGenBinBuffer
is not None and IdfGenBinBuffer
.getvalue() != b
"":
3332 AutoFile
= PathClass(gAutoGenIdfFileName
% {"module_name":self
.Name
}, self
.OutputDir
)
3333 RetVal
[AutoFile
] = IdfGenBinBuffer
.getvalue()
3334 AutoFile
.IsBinary
= True
3335 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3336 if IdfGenBinBuffer
is not None:
3337 IdfGenBinBuffer
.close()
3340 ## Return the list of library modules explicitly or implicitly used by this module
3342 def DependentLibraryList(self
):
3343 # only merge library classes and PCD for non-library module
3346 return self
.PlatformInfo
.ApplyLibraryInstance(self
.Module
)
3348 ## Get the list of PCDs from current module
3350 # @retval list The list of PCD
3353 def ModulePcdList(self
):
3354 # apply PCD settings from platform
3355 RetVal
= self
.PlatformInfo
.ApplyPcdSetting(self
.Module
, self
.Module
.Pcds
)
3356 ExtendCopyDictionaryLists(self
._PcdComments
, self
.Module
.PcdComments
)
3359 ## Get the list of PCDs from dependent libraries
3361 # @retval list The list of PCD
3364 def LibraryPcdList(self
):
3369 # get PCDs from dependent libraries
3370 for Library
in self
.DependentLibraryList
:
3371 PcdsInLibrary
= OrderedDict()
3372 ExtendCopyDictionaryLists(self
._PcdComments
, Library
.PcdComments
)
3373 for Key
in Library
.Pcds
:
3374 # skip duplicated PCDs
3375 if Key
in self
.Module
.Pcds
or Key
in Pcds
:
3378 PcdsInLibrary
[Key
] = copy
.copy(Library
.Pcds
[Key
])
3379 RetVal
.extend(self
.PlatformInfo
.ApplyPcdSetting(self
.Module
, PcdsInLibrary
, Library
=Library
))
3382 ## Get the GUID value mapping
3384 # @retval dict The mapping between GUID cname and its value
3388 RetVal
= OrderedDict(self
.Module
.Guids
)
3389 for Library
in self
.DependentLibraryList
:
3390 RetVal
.update(Library
.Guids
)
3391 ExtendCopyDictionaryLists(self
._GuidComments
, Library
.GuidComments
)
3392 ExtendCopyDictionaryLists(self
._GuidComments
, self
.Module
.GuidComments
)
3396 def GetGuidsUsedByPcd(self
):
3397 RetVal
= OrderedDict(self
.Module
.GetGuidsUsedByPcd())
3398 for Library
in self
.DependentLibraryList
:
3399 RetVal
.update(Library
.GetGuidsUsedByPcd())
3401 ## Get the protocol value mapping
3403 # @retval dict The mapping between protocol cname and its value
3406 def ProtocolList(self
):
3407 RetVal
= OrderedDict(self
.Module
.Protocols
)
3408 for Library
in self
.DependentLibraryList
:
3409 RetVal
.update(Library
.Protocols
)
3410 ExtendCopyDictionaryLists(self
._ProtocolComments
, Library
.ProtocolComments
)
3411 ExtendCopyDictionaryLists(self
._ProtocolComments
, self
.Module
.ProtocolComments
)
3414 ## Get the PPI value mapping
3416 # @retval dict The mapping between PPI cname and its value
3420 RetVal
= OrderedDict(self
.Module
.Ppis
)
3421 for Library
in self
.DependentLibraryList
:
3422 RetVal
.update(Library
.Ppis
)
3423 ExtendCopyDictionaryLists(self
._PpiComments
, Library
.PpiComments
)
3424 ExtendCopyDictionaryLists(self
._PpiComments
, self
.Module
.PpiComments
)
3427 ## Get the list of include search path
3429 # @retval list The list path
3432 def IncludePathList(self
):
3434 RetVal
.append(self
.MetaFile
.Dir
)
3435 RetVal
.append(self
.DebugDir
)
3437 for Package
in self
.Module
.Packages
:
3438 PackageDir
= mws
.join(self
.WorkspaceDir
, Package
.MetaFile
.Dir
)
3439 if PackageDir
not in RetVal
:
3440 RetVal
.append(PackageDir
)
3441 IncludesList
= Package
.Includes
3442 if Package
._PrivateIncludes
:
3443 if not self
.MetaFile
.OriginalPath
.Path
.startswith(PackageDir
):
3444 IncludesList
= list(set(Package
.Includes
).difference(set(Package
._PrivateIncludes
)))
3445 for Inc
in IncludesList
:
3446 if Inc
not in RetVal
:
3447 RetVal
.append(str(Inc
))
3451 def IncludePathLength(self
):
3452 return sum(len(inc
)+1 for inc
in self
.IncludePathList
)
3454 ## Get HII EX PCDs which maybe used by VFR
3456 # efivarstore used by VFR may relate with HII EX PCDs
3457 # Get the variable name and GUID from efivarstore and HII EX PCD
3458 # List the HII EX PCDs in As Built INF if both name and GUID match.
3460 # @retval list HII EX PCDs
3462 def _GetPcdsMaybeUsedByVfr(self
):
3463 if not self
.SourceFileList
:
3467 for SrcFile
in self
.SourceFileList
:
3468 if SrcFile
.Ext
.lower() != '.vfr':
3470 Vfri
= os
.path
.join(self
.OutputDir
, SrcFile
.BaseName
+ '.i')
3471 if not os
.path
.exists(Vfri
):
3473 VfriFile
= open(Vfri
, 'r')
3474 Content
= VfriFile
.read()
3476 Pos
= Content
.find('efivarstore')
3479 # Make sure 'efivarstore' is the start of efivarstore statement
3480 # In case of the value of 'name' (name = efivarstore) is equal to 'efivarstore'
3483 while Index
>= 0 and Content
[Index
] in ' \t\r\n':
3485 if Index
>= 0 and Content
[Index
] != ';':
3486 Pos
= Content
.find('efivarstore', Pos
+ len('efivarstore'))
3489 # 'efivarstore' must be followed by name and guid
3491 Name
= gEfiVarStoreNamePattern
.search(Content
, Pos
)
3494 Guid
= gEfiVarStoreGuidPattern
.search(Content
, Pos
)
3497 NameArray
= _ConvertStringToByteArray('L"' + Name
.group(1) + '"')
3498 NameGuids
.add((NameArray
, GuidStructureStringToGuidString(Guid
.group(1))))
3499 Pos
= Content
.find('efivarstore', Name
.end())
3503 for Pcd
in self
.PlatformInfo
.Platform
.Pcds
.values():
3504 if Pcd
.Type
!= TAB_PCDS_DYNAMIC_EX_HII
:
3506 for SkuInfo
in Pcd
.SkuInfoList
.values():
3507 Value
= GuidValue(SkuInfo
.VariableGuid
, self
.PlatformInfo
.PackageList
, self
.MetaFile
.Path
)
3510 Name
= _ConvertStringToByteArray(SkuInfo
.VariableName
)
3511 Guid
= GuidStructureStringToGuidString(Value
)
3512 if (Name
, Guid
) in NameGuids
and Pcd
not in HiiExPcds
:
3513 HiiExPcds
.append(Pcd
)
3518 def _GenOffsetBin(self
):
3520 for SourceFile
in self
.Module
.Sources
:
3521 if SourceFile
.Type
.upper() == ".VFR" :
3523 # search the .map file to find the offset of vfr binary in the PE32+/TE file.
3525 VfrUniBaseName
[SourceFile
.BaseName
] = (SourceFile
.BaseName
+ "Bin")
3526 elif SourceFile
.Type
.upper() == ".UNI" :
3528 # search the .map file to find the offset of Uni strings binary in the PE32+/TE file.
3530 VfrUniBaseName
["UniOffsetName"] = (self
.Name
+ "Strings")
3532 if not VfrUniBaseName
:
3534 MapFileName
= os
.path
.join(self
.OutputDir
, self
.Name
+ ".map")
3535 EfiFileName
= os
.path
.join(self
.OutputDir
, self
.Name
+ ".efi")
3536 VfrUniOffsetList
= GetVariableOffset(MapFileName
, EfiFileName
, list(VfrUniBaseName
.values()))
3537 if not VfrUniOffsetList
:
3540 OutputName
= '%sOffset.bin' % self
.Name
3541 UniVfrOffsetFileName
= os
.path
.join( self
.OutputDir
, OutputName
)
3544 fInputfile
= open(UniVfrOffsetFileName
, "wb+", 0)
3546 EdkLogger
.error("build", FILE_OPEN_FAILURE
, "File open failed for %s" % UniVfrOffsetFileName
, None)
3548 # Use a instance of BytesIO to cache data
3549 fStringIO
= BytesIO()
3551 for Item
in VfrUniOffsetList
:
3552 if (Item
[0].find("Strings") != -1):
3554 # UNI offset in image.
3556 # { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } }
3558 UniGuid
= b
'\xe0\xc5\x13\x89\xf63\x86M\x9b\xf1C\xef\x89\xfc\x06f'
3559 fStringIO
.write(UniGuid
)
3560 UniValue
= pack ('Q', int (Item
[1], 16))
3561 fStringIO
.write (UniValue
)
3564 # VFR binary offset in image.
3566 # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } };
3568 VfrGuid
= b
'\xb4|\xbc\xd0Gj_I\xaa\x11q\x07F\xda\x06\xa2'
3569 fStringIO
.write(VfrGuid
)
3570 VfrValue
= pack ('Q', int (Item
[1], 16))
3571 fStringIO
.write (VfrValue
)
3573 # write data into file.
3576 fInputfile
.write (fStringIO
.getvalue())
3578 EdkLogger
.error("build", FILE_WRITE_FAILURE
, "Write data to file %s failed, please check whether the "
3579 "file been locked or using by other applications." %UniVfrOffsetFileName
, None)
3586 def OutputFile(self
):
3588 OutputDir
= self
.OutputDir
.replace('\\', '/').strip('/')
3589 DebugDir
= self
.DebugDir
.replace('\\', '/').strip('/')
3590 for Item
in self
.CodaTargetList
:
3591 File
= Item
.Target
.Path
.replace('\\', '/').strip('/').replace(DebugDir
, '').replace(OutputDir
, '').strip('/')
3593 if self
.DepexGenerated
:
3594 retVal
.add(self
.Name
+ '.depex')
3596 Bin
= self
._GenOffsetBin
()
3600 for Root
, Dirs
, Files
in os
.walk(OutputDir
):
3602 if File
.lower().endswith('.pdb'):
3607 ## Create AsBuilt INF file the module
3609 def CreateAsBuiltInf(self
):
3611 if self
.IsAsBuiltInfCreated
:
3614 # Skip INF file generation for libraries
3618 # Skip the following code for modules with no source files
3619 if not self
.SourceFileList
:
3622 # Skip the following code for modules without any binary files
3623 if self
.BinaryFileList
:
3626 ### TODO: How to handles mixed source and binary modules
3628 # Find all DynamicEx and PatchableInModule PCDs used by this module and dependent libraries
3629 # Also find all packages that the DynamicEx PCDs depend on
3634 PcdTokenSpaceList
= []
3635 for Pcd
in self
.ModulePcdList
+ self
.LibraryPcdList
:
3636 if Pcd
.Type
== TAB_PCDS_PATCHABLE_IN_MODULE
:
3637 PatchablePcds
.append(Pcd
)
3638 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, TAB_PCDS_PATCHABLE_IN_MODULE
))
3639 elif Pcd
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
3642 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, TAB_PCDS_DYNAMIC_EX
))
3643 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, TAB_PCDS_DYNAMIC
))
3644 PcdTokenSpaceList
.append(Pcd
.TokenSpaceGuidCName
)
3645 GuidList
= OrderedDict(self
.GuidList
)
3646 for TokenSpace
in self
.GetGuidsUsedByPcd
:
3647 # If token space is not referred by patch PCD or Ex PCD, remove the GUID from GUID list
3648 # The GUIDs in GUIDs section should really be the GUIDs in source INF or referred by Ex an patch PCDs
3649 if TokenSpace
not in PcdTokenSpaceList
and TokenSpace
in GuidList
:
3650 GuidList
.pop(TokenSpace
)
3651 CheckList
= (GuidList
, self
.PpiList
, self
.ProtocolList
, PcdCheckList
)
3652 for Package
in self
.DerivedPackageList
:
3653 if Package
in Packages
:
3655 BeChecked
= (Package
.Guids
, Package
.Ppis
, Package
.Protocols
, Package
.Pcds
)
3657 for Index
in range(len(BeChecked
)):
3658 for Item
in CheckList
[Index
]:
3659 if Item
in BeChecked
[Index
]:
3660 Packages
.append(Package
)
3666 VfrPcds
= self
._GetPcdsMaybeUsedByVfr
()
3667 for Pkg
in self
.PlatformInfo
.PackageList
:
3670 for VfrPcd
in VfrPcds
:
3671 if ((VfrPcd
.TokenCName
, VfrPcd
.TokenSpaceGuidCName
, TAB_PCDS_DYNAMIC_EX
) in Pkg
.Pcds
or
3672 (VfrPcd
.TokenCName
, VfrPcd
.TokenSpaceGuidCName
, TAB_PCDS_DYNAMIC
) in Pkg
.Pcds
):
3673 Packages
.append(Pkg
)
3676 ModuleType
= SUP_MODULE_DXE_DRIVER
if self
.ModuleType
== SUP_MODULE_UEFI_DRIVER
and self
.DepexGenerated
else self
.ModuleType
3677 DriverType
= self
.PcdIsDriver
if self
.PcdIsDriver
else ''
3679 MDefs
= self
.Module
.Defines
3682 'module_name' : self
.Name
,
3683 'module_guid' : Guid
,
3684 'module_module_type' : ModuleType
,
3685 'module_version_string' : [MDefs
['VERSION_STRING']] if 'VERSION_STRING' in MDefs
else [],
3686 'pcd_is_driver_string' : [],
3687 'module_uefi_specification_version' : [],
3688 'module_pi_specification_version' : [],
3689 'module_entry_point' : self
.Module
.ModuleEntryPointList
,
3690 'module_unload_image' : self
.Module
.ModuleUnloadImageList
,
3691 'module_constructor' : self
.Module
.ConstructorList
,
3692 'module_destructor' : self
.Module
.DestructorList
,
3693 'module_shadow' : [MDefs
['SHADOW']] if 'SHADOW' in MDefs
else [],
3694 'module_pci_vendor_id' : [MDefs
['PCI_VENDOR_ID']] if 'PCI_VENDOR_ID' in MDefs
else [],
3695 'module_pci_device_id' : [MDefs
['PCI_DEVICE_ID']] if 'PCI_DEVICE_ID' in MDefs
else [],
3696 'module_pci_class_code' : [MDefs
['PCI_CLASS_CODE']] if 'PCI_CLASS_CODE' in MDefs
else [],
3697 'module_pci_revision' : [MDefs
['PCI_REVISION']] if 'PCI_REVISION' in MDefs
else [],
3698 'module_build_number' : [MDefs
['BUILD_NUMBER']] if 'BUILD_NUMBER' in MDefs
else [],
3699 'module_spec' : [MDefs
['SPEC']] if 'SPEC' in MDefs
else [],
3700 'module_uefi_hii_resource_section' : [MDefs
['UEFI_HII_RESOURCE_SECTION']] if 'UEFI_HII_RESOURCE_SECTION' in MDefs
else [],
3701 'module_uni_file' : [MDefs
['MODULE_UNI_FILE']] if 'MODULE_UNI_FILE' in MDefs
else [],
3702 'module_arch' : self
.Arch
,
3703 'package_item' : [Package
.MetaFile
.File
.replace('\\', '/') for Package
in Packages
],
3705 'patchablepcd_item' : [],
3707 'protocol_item' : [],
3711 'libraryclasses_item' : []
3714 if 'MODULE_UNI_FILE' in MDefs
:
3715 UNIFile
= os
.path
.join(self
.MetaFile
.Dir
, MDefs
['MODULE_UNI_FILE'])
3716 if os
.path
.isfile(UNIFile
):
3717 shutil
.copy2(UNIFile
, self
.OutputDir
)
3719 if self
.AutoGenVersion
> int(gInfSpecVersion
, 0):
3720 AsBuiltInfDict
['module_inf_version'] = '0x%08x' % self
.AutoGenVersion
3722 AsBuiltInfDict
['module_inf_version'] = gInfSpecVersion
3725 AsBuiltInfDict
['pcd_is_driver_string'].append(DriverType
)
3727 if 'UEFI_SPECIFICATION_VERSION' in self
.Specification
:
3728 AsBuiltInfDict
['module_uefi_specification_version'].append(self
.Specification
['UEFI_SPECIFICATION_VERSION'])
3729 if 'PI_SPECIFICATION_VERSION' in self
.Specification
:
3730 AsBuiltInfDict
['module_pi_specification_version'].append(self
.Specification
['PI_SPECIFICATION_VERSION'])
3732 OutputDir
= self
.OutputDir
.replace('\\', '/').strip('/')
3733 DebugDir
= self
.DebugDir
.replace('\\', '/').strip('/')
3734 for Item
in self
.CodaTargetList
:
3735 File
= Item
.Target
.Path
.replace('\\', '/').strip('/').replace(DebugDir
, '').replace(OutputDir
, '').strip('/')
3736 if os
.path
.isabs(File
):
3737 File
= File
.replace('\\', '/').strip('/').replace(OutputDir
, '').strip('/')
3738 if Item
.Target
.Ext
.lower() == '.aml':
3739 AsBuiltInfDict
['binary_item'].append('ASL|' + File
)
3740 elif Item
.Target
.Ext
.lower() == '.acpi':
3741 AsBuiltInfDict
['binary_item'].append('ACPI|' + File
)
3742 elif Item
.Target
.Ext
.lower() == '.efi':
3743 AsBuiltInfDict
['binary_item'].append('PE32|' + self
.Name
+ '.efi')
3745 AsBuiltInfDict
['binary_item'].append('BIN|' + File
)
3746 if not self
.DepexGenerated
:
3747 DepexFile
= os
.path
.join(self
.OutputDir
, self
.Name
+ '.depex')
3748 if os
.path
.exists(DepexFile
):
3749 self
.DepexGenerated
= True
3750 if self
.DepexGenerated
:
3751 if self
.ModuleType
in [SUP_MODULE_PEIM
]:
3752 AsBuiltInfDict
['binary_item'].append('PEI_DEPEX|' + self
.Name
+ '.depex')
3753 elif self
.ModuleType
in [SUP_MODULE_DXE_DRIVER
, SUP_MODULE_DXE_RUNTIME_DRIVER
, SUP_MODULE_DXE_SAL_DRIVER
, SUP_MODULE_UEFI_DRIVER
]:
3754 AsBuiltInfDict
['binary_item'].append('DXE_DEPEX|' + self
.Name
+ '.depex')
3755 elif self
.ModuleType
in [SUP_MODULE_DXE_SMM_DRIVER
]:
3756 AsBuiltInfDict
['binary_item'].append('SMM_DEPEX|' + self
.Name
+ '.depex')
3758 Bin
= self
._GenOffsetBin
()
3760 AsBuiltInfDict
['binary_item'].append('BIN|%s' % Bin
)
3762 for Root
, Dirs
, Files
in os
.walk(OutputDir
):
3764 if File
.lower().endswith('.pdb'):
3765 AsBuiltInfDict
['binary_item'].append('DISPOSABLE|' + File
)
3766 HeaderComments
= self
.Module
.HeaderComments
3768 for Index
in range(len(HeaderComments
)):
3769 if HeaderComments
[Index
].find('@BinaryHeader') != -1:
3770 HeaderComments
[Index
] = HeaderComments
[Index
].replace('@BinaryHeader', '@file')
3773 AsBuiltInfDict
['header_comments'] = '\n'.join(HeaderComments
[StartPos
:]).replace(':#', '://')
3774 AsBuiltInfDict
['tail_comments'] = '\n'.join(self
.Module
.TailComments
)
3777 (self
.ProtocolList
, self
._ProtocolComments
, 'protocol_item'),
3778 (self
.PpiList
, self
._PpiComments
, 'ppi_item'),
3779 (GuidList
, self
._GuidComments
, 'guid_item')
3781 for Item
in GenList
:
3782 for CName
in Item
[0]:
3783 Comments
= '\n '.join(Item
[1][CName
]) if CName
in Item
[1] else ''
3784 Entry
= Comments
+ '\n ' + CName
if Comments
else CName
3785 AsBuiltInfDict
[Item
[2]].append(Entry
)
3786 PatchList
= parsePcdInfoFromMapFile(
3787 os
.path
.join(self
.OutputDir
, self
.Name
+ '.map'),
3788 os
.path
.join(self
.OutputDir
, self
.Name
+ '.efi')
3791 for Pcd
in PatchablePcds
:
3792 TokenCName
= Pcd
.TokenCName
3793 for PcdItem
in GlobalData
.MixedPcd
:
3794 if (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
3795 TokenCName
= PcdItem
[0]
3797 for PatchPcd
in PatchList
:
3798 if TokenCName
== PatchPcd
[0]:
3803 if Pcd
.DatumType
== 'BOOLEAN':
3804 BoolValue
= Pcd
.DefaultValue
.upper()
3805 if BoolValue
== 'TRUE':
3806 Pcd
.DefaultValue
= '1'
3807 elif BoolValue
== 'FALSE':
3808 Pcd
.DefaultValue
= '0'
3810 if Pcd
.DatumType
in TAB_PCD_NUMERIC_TYPES
:
3811 HexFormat
= '0x%02x'
3812 if Pcd
.DatumType
== TAB_UINT16
:
3813 HexFormat
= '0x%04x'
3814 elif Pcd
.DatumType
== TAB_UINT32
:
3815 HexFormat
= '0x%08x'
3816 elif Pcd
.DatumType
== TAB_UINT64
:
3817 HexFormat
= '0x%016x'
3818 PcdValue
= HexFormat
% int(Pcd
.DefaultValue
, 0)
3820 if Pcd
.MaxDatumSize
is None or Pcd
.MaxDatumSize
== '':
3821 EdkLogger
.error("build", AUTOGEN_ERROR
,
3822 "Unknown [MaxDatumSize] of PCD [%s.%s]" % (Pcd
.TokenSpaceGuidCName
, TokenCName
)
3824 ArraySize
= int(Pcd
.MaxDatumSize
, 0)
3825 PcdValue
= Pcd
.DefaultValue
3826 if PcdValue
[0] != '{':
3828 if PcdValue
[0] == 'L':
3830 PcdValue
= PcdValue
.lstrip('L')
3831 PcdValue
= eval(PcdValue
)
3833 for Index
in range(0, len(PcdValue
)):
3835 CharVal
= ord(PcdValue
[Index
])
3836 NewValue
= NewValue
+ '0x%02x' % (CharVal
& 0x00FF) + ', ' \
3837 + '0x%02x' % (CharVal
>> 8) + ', '
3839 NewValue
= NewValue
+ '0x%02x' % (ord(PcdValue
[Index
]) % 0x100) + ', '
3842 Padding
= Padding
* 2
3843 ArraySize
= ArraySize
// 2
3844 if ArraySize
< (len(PcdValue
) + 1):
3845 if Pcd
.MaxSizeUserSet
:
3846 EdkLogger
.error("build", AUTOGEN_ERROR
,
3847 "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd
.TokenSpaceGuidCName
, TokenCName
)
3850 ArraySize
= len(PcdValue
) + 1
3851 if ArraySize
> len(PcdValue
) + 1:
3852 NewValue
= NewValue
+ Padding
* (ArraySize
- len(PcdValue
) - 1)
3853 PcdValue
= NewValue
+ Padding
.strip().rstrip(',') + '}'
3854 elif len(PcdValue
.split(',')) <= ArraySize
:
3855 PcdValue
= PcdValue
.rstrip('}') + ', 0x00' * (ArraySize
- len(PcdValue
.split(',')))
3858 if Pcd
.MaxSizeUserSet
:
3859 EdkLogger
.error("build", AUTOGEN_ERROR
,
3860 "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd
.TokenSpaceGuidCName
, TokenCName
)
3863 ArraySize
= len(PcdValue
) + 1
3864 PcdItem
= '%s.%s|%s|0x%X' % \
3865 (Pcd
.TokenSpaceGuidCName
, TokenCName
, PcdValue
, PatchPcd
[1])
3867 if (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) in self
._PcdComments
:
3868 PcdComments
= '\n '.join(self
._PcdComments
[Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
])
3870 PcdItem
= PcdComments
+ '\n ' + PcdItem
3871 AsBuiltInfDict
['patchablepcd_item'].append(PcdItem
)
3873 for Pcd
in Pcds
+ VfrPcds
:
3876 TokenCName
= Pcd
.TokenCName
3877 for PcdItem
in GlobalData
.MixedPcd
:
3878 if (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
3879 TokenCName
= PcdItem
[0]
3881 if Pcd
.Type
== TAB_PCDS_DYNAMIC_EX_HII
:
3882 for SkuName
in Pcd
.SkuInfoList
:
3883 SkuInfo
= Pcd
.SkuInfoList
[SkuName
]
3884 HiiInfo
= '## %s|%s|%s' % (SkuInfo
.VariableName
, SkuInfo
.VariableGuid
, SkuInfo
.VariableOffset
)
3886 if (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) in self
._PcdComments
:
3887 PcdCommentList
= self
._PcdComments
[Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
][:]
3891 for Index
, Comment
in enumerate(PcdCommentList
):
3892 for Usage
in UsageList
:
3893 if Comment
.find(Usage
) != -1:
3897 if UsageIndex
!= -1:
3898 PcdCommentList
[UsageIndex
] = '## %s %s %s' % (UsageStr
, HiiInfo
, PcdCommentList
[UsageIndex
].replace(UsageStr
, ''))
3900 PcdCommentList
.append('## UNDEFINED ' + HiiInfo
)
3901 PcdComments
= '\n '.join(PcdCommentList
)
3902 PcdEntry
= Pcd
.TokenSpaceGuidCName
+ '.' + TokenCName
3904 PcdEntry
= PcdComments
+ '\n ' + PcdEntry
3905 AsBuiltInfDict
['pcd_item'].append(PcdEntry
)
3906 for Item
in self
.BuildOption
:
3907 if 'FLAGS' in self
.BuildOption
[Item
]:
3908 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()))
3910 # Generated LibraryClasses section in comments.
3911 for Library
in self
.LibraryAutoGenList
:
3912 AsBuiltInfDict
['libraryclasses_item'].append(Library
.MetaFile
.File
.replace('\\', '/'))
3914 # Generated UserExtensions TianoCore section.
3915 # All tianocore user extensions are copied.
3917 for TianoCore
in self
._GetTianoCoreUserExtensionList
():
3918 UserExtStr
+= '\n'.join(TianoCore
)
3919 ExtensionFile
= os
.path
.join(self
.MetaFile
.Dir
, TianoCore
[1])
3920 if os
.path
.isfile(ExtensionFile
):
3921 shutil
.copy2(ExtensionFile
, self
.OutputDir
)
3922 AsBuiltInfDict
['userextension_tianocore_item'] = UserExtStr
3924 # Generated depex expression section in comments.
3925 DepexExpression
= self
._GetDepexExpresionString
()
3926 AsBuiltInfDict
['depexsection_item'] = DepexExpression
if DepexExpression
else ''
3928 AsBuiltInf
= TemplateString()
3929 AsBuiltInf
.Append(gAsBuiltInfHeaderString
.Replace(AsBuiltInfDict
))
3931 SaveFileOnChange(os
.path
.join(self
.OutputDir
, self
.Name
+ '.inf'), str(AsBuiltInf
), False)
3933 self
.IsAsBuiltInfCreated
= True
3935 def CopyModuleToCache(self
):
3936 FileDir
= path
.join(GlobalData
.gBinCacheDest
, self
.PlatformInfo
.OutputDir
, self
.BuildTarget
+ "_" + self
.ToolChain
, self
.Arch
, self
.SourceDir
, self
.MetaFile
.BaseName
)
3937 CreateDirectory (FileDir
)
3938 HashFile
= path
.join(self
.BuildDir
, self
.Name
+ '.hash')
3939 if os
.path
.exists(HashFile
):
3940 CopyFileOnChange(HashFile
, FileDir
)
3941 ModuleFile
= path
.join(self
.OutputDir
, self
.Name
+ '.inf')
3942 if os
.path
.exists(ModuleFile
):
3943 CopyFileOnChange(ModuleFile
, FileDir
)
3945 if not self
.OutputFile
:
3946 Ma
= self
.BuildDatabase
[self
.MetaFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
3947 self
.OutputFile
= Ma
.Binaries
3949 for File
in self
.OutputFile
:
3951 if not os
.path
.isabs(File
):
3952 File
= os
.path
.join(self
.OutputDir
, File
)
3953 if os
.path
.exists(File
):
3954 sub_dir
= os
.path
.relpath(File
, self
.OutputDir
)
3955 destination_file
= os
.path
.join(FileDir
, sub_dir
)
3956 destination_dir
= os
.path
.dirname(destination_file
)
3957 CreateDirectory(destination_dir
)
3958 CopyFileOnChange(File
, destination_dir
)
3960 def AttemptModuleCacheCopy(self
):
3961 # If library or Module is binary do not skip by hash
3962 if self
.IsBinaryModule
:
3964 # .inc is contains binary information so do not skip by hash as well
3965 for f_ext
in self
.SourceFileList
:
3966 if '.inc' in str(f_ext
):
3968 FileDir
= path
.join(GlobalData
.gBinCacheSource
, self
.PlatformInfo
.OutputDir
, self
.BuildTarget
+ "_" + self
.ToolChain
, self
.Arch
, self
.SourceDir
, self
.MetaFile
.BaseName
)
3969 HashFile
= path
.join(FileDir
, self
.Name
+ '.hash')
3970 if os
.path
.exists(HashFile
):
3971 f
= open(HashFile
, 'r')
3972 CacheHash
= f
.read()
3974 self
.GenModuleHash()
3975 if GlobalData
.gModuleHash
[self
.Arch
][self
.Name
]:
3976 if CacheHash
== GlobalData
.gModuleHash
[self
.Arch
][self
.Name
]:
3977 for root
, dir, files
in os
.walk(FileDir
):
3979 if self
.Name
+ '.hash' in f
:
3980 CopyFileOnChange(HashFile
, self
.BuildDir
)
3982 File
= path
.join(root
, f
)
3983 sub_dir
= os
.path
.relpath(File
, FileDir
)
3984 destination_file
= os
.path
.join(self
.OutputDir
, sub_dir
)
3985 destination_dir
= os
.path
.dirname(destination_file
)
3986 CreateDirectory(destination_dir
)
3987 CopyFileOnChange(File
, destination_dir
)
3988 if self
.Name
== "PcdPeim" or self
.Name
== "PcdDxe":
3989 CreatePcdDatabaseCode(self
, TemplateString(), TemplateString())
3993 ## Create makefile for the module and its dependent libraries
3995 # @param CreateLibraryMakeFile Flag indicating if or not the makefiles of
3996 # dependent libraries will be created
3998 @cached_class_function
3999 def CreateMakeFile(self
, CreateLibraryMakeFile
=True, GenFfsList
= []):
4000 # nest this function inside its only caller.
4001 def CreateTimeStamp():
4002 FileSet
= {self
.MetaFile
.Path
}
4004 for SourceFile
in self
.Module
.Sources
:
4005 FileSet
.add (SourceFile
.Path
)
4007 for Lib
in self
.DependentLibraryList
:
4008 FileSet
.add (Lib
.MetaFile
.Path
)
4010 for f
in self
.AutoGenDepSet
:
4011 FileSet
.add (f
.Path
)
4013 if os
.path
.exists (self
.TimeStampPath
):
4014 os
.remove (self
.TimeStampPath
)
4015 with
open(self
.TimeStampPath
, 'w+') as file:
4019 # Ignore generating makefile when it is a binary module
4020 if self
.IsBinaryModule
:
4023 self
.GenFfsList
= GenFfsList
4024 if not self
.IsLibrary
and CreateLibraryMakeFile
:
4025 for LibraryAutoGen
in self
.LibraryAutoGenList
:
4026 LibraryAutoGen
.CreateMakeFile()
4028 # Don't enable if hash feature enabled, CanSkip uses timestamps to determine build skipping
4029 if not GlobalData
.gUseHashCache
and self
.CanSkip():
4032 if len(self
.CustomMakefile
) == 0:
4033 Makefile
= GenMake
.ModuleMakefile(self
)
4035 Makefile
= GenMake
.CustomMakefile(self
)
4036 if Makefile
.Generate():
4037 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated makefile for module %s [%s]" %
4038 (self
.Name
, self
.Arch
))
4040 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Skipped the generation of makefile for module %s [%s]" %
4041 (self
.Name
, self
.Arch
))
4045 def CopyBinaryFiles(self
):
4046 for File
in self
.Module
.Binaries
:
4048 DstPath
= os
.path
.join(self
.OutputDir
, os
.path
.basename(SrcPath
))
4049 CopyLongFilePath(SrcPath
, DstPath
)
4050 ## Create autogen code for the module and its dependent libraries
4052 # @param CreateLibraryCodeFile Flag indicating if or not the code of
4053 # dependent libraries will be created
4055 def CreateCodeFile(self
, CreateLibraryCodeFile
=True):
4056 if self
.IsCodeFileCreated
:
4059 # Need to generate PcdDatabase even PcdDriver is binarymodule
4060 if self
.IsBinaryModule
and self
.PcdIsDriver
!= '':
4061 CreatePcdDatabaseCode(self
, TemplateString(), TemplateString())
4063 if self
.IsBinaryModule
:
4065 self
.CopyBinaryFiles()
4068 if not self
.IsLibrary
and CreateLibraryCodeFile
:
4069 for LibraryAutoGen
in self
.LibraryAutoGenList
:
4070 LibraryAutoGen
.CreateCodeFile()
4072 # Don't enable if hash feature enabled, CanSkip uses timestamps to determine build skipping
4073 if not GlobalData
.gUseHashCache
and self
.CanSkip():
4077 IgoredAutoGenList
= []
4079 for File
in self
.AutoGenFileList
:
4080 if GenC
.Generate(File
.Path
, self
.AutoGenFileList
[File
], File
.IsBinary
):
4081 AutoGenList
.append(str(File
))
4083 IgoredAutoGenList
.append(str(File
))
4086 for ModuleType
in self
.DepexList
:
4087 # Ignore empty [depex] section or [depex] section for SUP_MODULE_USER_DEFINED module
4088 if len(self
.DepexList
[ModuleType
]) == 0 or ModuleType
== SUP_MODULE_USER_DEFINED
:
4091 Dpx
= GenDepex
.DependencyExpression(self
.DepexList
[ModuleType
], ModuleType
, True)
4092 DpxFile
= gAutoGenDepexFileName
% {"module_name" : self
.Name
}
4094 if len(Dpx
.PostfixNotation
) != 0:
4095 self
.DepexGenerated
= True
4097 if Dpx
.Generate(path
.join(self
.OutputDir
, DpxFile
)):
4098 AutoGenList
.append(str(DpxFile
))
4100 IgoredAutoGenList
.append(str(DpxFile
))
4102 if IgoredAutoGenList
== []:
4103 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated [%s] files for module %s [%s]" %
4104 (" ".join(AutoGenList
), self
.Name
, self
.Arch
))
4105 elif AutoGenList
== []:
4106 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Skipped the generation of [%s] files for module %s [%s]" %
4107 (" ".join(IgoredAutoGenList
), self
.Name
, self
.Arch
))
4109 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated [%s] (skipped %s) files for module %s [%s]" %
4110 (" ".join(AutoGenList
), " ".join(IgoredAutoGenList
), self
.Name
, self
.Arch
))
4112 self
.IsCodeFileCreated
= True
4115 ## Summarize the ModuleAutoGen objects of all libraries used by this module
4117 def LibraryAutoGenList(self
):
4119 for Library
in self
.DependentLibraryList
:
4126 self
.PlatformInfo
.MetaFile
4128 if La
not in RetVal
:
4130 for Lib
in La
.CodaTargetList
:
4131 self
._ApplyBuildRule
(Lib
.Target
, TAB_UNKNOWN_FILE
)
4134 def GenModuleHash(self
):
4135 # Initialize a dictionary for each arch type
4136 if self
.Arch
not in GlobalData
.gModuleHash
:
4137 GlobalData
.gModuleHash
[self
.Arch
] = {}
4139 # Early exit if module or library has been hashed and is in memory
4140 if self
.Name
in GlobalData
.gModuleHash
[self
.Arch
]:
4141 return GlobalData
.gModuleHash
[self
.Arch
][self
.Name
].encode('utf-8')
4143 # Initialze hash object
4146 # Add Platform level hash
4147 m
.update(GlobalData
.gPlatformHash
.encode('utf-8'))
4149 # Add Package level hash
4150 if self
.DependentPackageList
:
4151 for Pkg
in sorted(self
.DependentPackageList
, key
=lambda x
: x
.PackageName
):
4152 if Pkg
.PackageName
in GlobalData
.gPackageHash
:
4153 m
.update(GlobalData
.gPackageHash
[Pkg
.PackageName
].encode('utf-8'))
4156 if self
.LibraryAutoGenList
:
4157 for Lib
in sorted(self
.LibraryAutoGenList
, key
=lambda x
: x
.Name
):
4158 if Lib
.Name
not in GlobalData
.gModuleHash
[self
.Arch
]:
4160 m
.update(GlobalData
.gModuleHash
[self
.Arch
][Lib
.Name
].encode('utf-8'))
4163 f
= open(str(self
.MetaFile
), 'rb')
4168 # Add Module's source files
4169 if self
.SourceFileList
:
4170 for File
in sorted(self
.SourceFileList
, key
=lambda x
: str(x
)):
4171 f
= open(str(File
), 'rb')
4176 GlobalData
.gModuleHash
[self
.Arch
][self
.Name
] = m
.hexdigest()
4178 return GlobalData
.gModuleHash
[self
.Arch
][self
.Name
].encode('utf-8')
4180 ## Decide whether we can skip the ModuleAutoGen process
4181 def CanSkipbyHash(self
):
4182 # Hashing feature is off
4183 if not GlobalData
.gUseHashCache
:
4186 # Initialize a dictionary for each arch type
4187 if self
.Arch
not in GlobalData
.gBuildHashSkipTracking
:
4188 GlobalData
.gBuildHashSkipTracking
[self
.Arch
] = dict()
4190 # If library or Module is binary do not skip by hash
4191 if self
.IsBinaryModule
:
4194 # .inc is contains binary information so do not skip by hash as well
4195 for f_ext
in self
.SourceFileList
:
4196 if '.inc' in str(f_ext
):
4199 # Use Cache, if exists and if Module has a copy in cache
4200 if GlobalData
.gBinCacheSource
and self
.AttemptModuleCacheCopy():
4203 # Early exit for libraries that haven't yet finished building
4204 HashFile
= path
.join(self
.BuildDir
, self
.Name
+ ".hash")
4205 if self
.IsLibrary
and not os
.path
.exists(HashFile
):
4208 # Return a Boolean based on if can skip by hash, either from memory or from IO.
4209 if self
.Name
not in GlobalData
.gBuildHashSkipTracking
[self
.Arch
]:
4210 # If hashes are the same, SaveFileOnChange() will return False.
4211 GlobalData
.gBuildHashSkipTracking
[self
.Arch
][self
.Name
] = not SaveFileOnChange(HashFile
, self
.GenModuleHash(), True)
4212 return GlobalData
.gBuildHashSkipTracking
[self
.Arch
][self
.Name
]
4214 return GlobalData
.gBuildHashSkipTracking
[self
.Arch
][self
.Name
]
4216 ## Decide whether we can skip the ModuleAutoGen process
4217 # If any source file is newer than the module than we cannot skip
4220 if self
.MakeFileDir
in GlobalData
.gSikpAutoGenCache
:
4222 if not os
.path
.exists(self
.TimeStampPath
):
4224 #last creation time of the module
4225 DstTimeStamp
= os
.stat(self
.TimeStampPath
)[8]
4227 SrcTimeStamp
= self
.Workspace
._SrcTimeStamp
4228 if SrcTimeStamp
> DstTimeStamp
:
4231 with
open(self
.TimeStampPath
,'r') as f
:
4233 source
= source
.rstrip('\n')
4234 if not os
.path
.exists(source
):
4236 if source
not in ModuleAutoGen
.TimeDict
:
4237 ModuleAutoGen
.TimeDict
[source
] = os
.stat(source
)[8]
4238 if ModuleAutoGen
.TimeDict
[source
] > DstTimeStamp
:
4240 GlobalData
.gSikpAutoGenCache
.add(self
.MakeFileDir
)
4244 def TimeStampPath(self
):
4245 return os
.path
.join(self
.MakeFileDir
, 'AutoGenTimeStamp')