2 # Generate AutoGen.h, AutoGen.c and *.depex files
4 # Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
5 # Copyright (c) 2018, Hewlett Packard Enterprise Development, L.P.<BR>
7 # This program and the accompanying materials
8 # are licensed and made available under the terms and conditions of the BSD License
9 # which accompanies this distribution. The full text of the license may be found at
10 # http://opensource.org/licenses/bsd-license.php
12 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 import Common
.LongFilePathOs
as os
20 import os
.path
as path
27 from StringIO
import StringIO
29 from StrGather
import *
30 from BuildEngine
import BuildRule
32 from Common
.LongFilePathSupport
import CopyLongFilePath
33 from Common
.BuildToolError
import *
34 from Common
.DataType
import *
35 from Common
.Misc
import *
36 from Common
.StringUtils
import *
37 import Common
.GlobalData
as GlobalData
38 from GenFds
.FdfParser
import *
39 from CommonDataClass
.CommonClass
import SkuInfoClass
40 from Workspace
.BuildClassObject
import *
41 from GenPatchPcdTable
.GenPatchPcdTable
import parsePcdInfoFromMapFile
42 import Common
.VpdInfoFile
as VpdInfoFile
43 from GenPcdDb
import CreatePcdDatabaseCode
44 from Workspace
.MetaFileCommentParser
import UsageList
45 from Workspace
.WorkspaceCommon
import GetModuleLibInstances
46 from Common
.MultipleWorkspace
import MultipleWorkspace
as mws
47 import InfSectionParser
50 from GenVar
import VariableMgr
,var_info
51 from collections
import OrderedDict
52 from collections
import defaultdict
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
= {"MSFT":"nmake", "GCC":"gmake"}
81 ## Build rule configuration file
82 gDefaultBuildRuleFile
= 'build_rule.txt'
84 ## Tools definition configuration file
85 gDefaultToolsDefFile
= 'tools_def.txt'
87 ## Build rule default version
88 AutoGenReqBuildRuleVerNum
= "0.1"
90 ## default file name for AutoGen
91 gAutoGenCodeFileName
= "AutoGen.c"
92 gAutoGenHeaderFileName
= "AutoGen.h"
93 gAutoGenStringFileName
= "%(module_name)sStrDefs.h"
94 gAutoGenStringFormFileName
= "%(module_name)sStrDefs.hpk"
95 gAutoGenDepexFileName
= "%(module_name)s.depex"
96 gAutoGenImageDefFileName
= "%(module_name)sImgDefs.h"
97 gAutoGenIdfFileName
= "%(module_name)sIdf.hpk"
98 gInfSpecVersion
= "0x00010017"
101 # Template string to generic AsBuilt INF
103 gAsBuiltInfHeaderString
= TemplateString("""${header_comments}
106 # FILE auto-generated
109 INF_VERSION = ${module_inf_version}
110 BASE_NAME = ${module_name}
111 FILE_GUID = ${module_guid}
112 MODULE_TYPE = ${module_module_type}${BEGIN}
113 VERSION_STRING = ${module_version_string}${END}${BEGIN}
114 PCD_IS_DRIVER = ${pcd_is_driver_string}${END}${BEGIN}
115 UEFI_SPECIFICATION_VERSION = ${module_uefi_specification_version}${END}${BEGIN}
116 PI_SPECIFICATION_VERSION = ${module_pi_specification_version}${END}${BEGIN}
117 ENTRY_POINT = ${module_entry_point}${END}${BEGIN}
118 UNLOAD_IMAGE = ${module_unload_image}${END}${BEGIN}
119 CONSTRUCTOR = ${module_constructor}${END}${BEGIN}
120 DESTRUCTOR = ${module_destructor}${END}${BEGIN}
121 SHADOW = ${module_shadow}${END}${BEGIN}
122 PCI_VENDOR_ID = ${module_pci_vendor_id}${END}${BEGIN}
123 PCI_DEVICE_ID = ${module_pci_device_id}${END}${BEGIN}
124 PCI_CLASS_CODE = ${module_pci_class_code}${END}${BEGIN}
125 PCI_REVISION = ${module_pci_revision}${END}${BEGIN}
126 BUILD_NUMBER = ${module_build_number}${END}${BEGIN}
127 SPEC = ${module_spec}${END}${BEGIN}
128 UEFI_HII_RESOURCE_SECTION = ${module_uefi_hii_resource_section}${END}${BEGIN}
129 MODULE_UNI_FILE = ${module_uni_file}${END}
131 [Packages.${module_arch}]${BEGIN}
132 ${package_item}${END}
134 [Binaries.${module_arch}]${BEGIN}
137 [PatchPcd.${module_arch}]${BEGIN}
141 [Protocols.${module_arch}]${BEGIN}
145 [Ppis.${module_arch}]${BEGIN}
149 [Guids.${module_arch}]${BEGIN}
153 [PcdEx.${module_arch}]${BEGIN}
157 [LibraryClasses.${module_arch}]
158 ## @LIB_INSTANCES${BEGIN}
159 # ${libraryclasses_item}${END}
163 ${userextension_tianocore_item}
167 [BuildOptions.${module_arch}]
169 ## ${flags_item}${END}
172 ## Base class for AutoGen
174 # This class just implements the cache mechanism of AutoGen objects.
176 class AutoGen(object):
177 # database to maintain the objects in each child class
178 __ObjectCache
= {} # (BuildTarget, ToolChain, ARCH, platform file): AutoGen object
182 # @param Class class object of real AutoGen class
183 # (WorkspaceAutoGen, ModuleAutoGen or PlatformAutoGen)
184 # @param Workspace Workspace directory or WorkspaceAutoGen object
185 # @param MetaFile The path of meta file
186 # @param Target Build target
187 # @param Toolchain Tool chain name
188 # @param Arch Target arch
189 # @param *args The specific class related parameters
190 # @param **kwargs The specific class related dict parameters
192 def __new__(cls
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
193 # check if the object has been created
194 Key
= (Target
, Toolchain
, Arch
, MetaFile
)
196 # if it exists, just return it directly
197 return cls
.__ObjectCache
[Key
]
199 # it didnt exist. create it, cache it, then return it
200 cls
.__ObjectCache
[Key
] = super(AutoGen
, cls
).__new
__(cls
)
201 return cls
.__ObjectCache
[Key
]
203 def __init__ (self
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
204 super(AutoGen
, self
).__init
__(self
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
)
208 # The file path of platform file will be used to represent hash value of this object
210 # @retval int Hash value of the file path of platform file
213 return hash(self
.MetaFile
)
217 # The file path of platform file will be used to represent this object
219 # @retval string String of platform file path
222 return str(self
.MetaFile
)
225 def __eq__(self
, Other
):
226 return Other
and self
.MetaFile
== Other
228 ## Workspace AutoGen class
230 # This class is used mainly to control the whole platform build for different
231 # architecture. This class will generate top level makefile.
233 class WorkspaceAutoGen(AutoGen
):
234 # call super().__init__ then call the worker function with different parameter count
235 def __init__(self
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
239 super(WorkspaceAutoGen
, self
).__init
__(Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
)
240 self
._InitWorker
(Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
)
243 ## Initialize WorkspaceAutoGen
245 # @param WorkspaceDir Root directory of workspace
246 # @param ActivePlatform Meta-file of active platform
247 # @param Target Build target
248 # @param Toolchain Tool chain name
249 # @param ArchList List of architecture of current build
250 # @param MetaFileDb Database containing meta-files
251 # @param BuildConfig Configuration of build
252 # @param ToolDefinition Tool chain definitions
253 # @param FlashDefinitionFile File of flash definition
254 # @param Fds FD list to be generated
255 # @param Fvs FV list to be generated
256 # @param Caps Capsule list to be generated
257 # @param SkuId SKU id from command line
259 def _InitWorker(self
, WorkspaceDir
, ActivePlatform
, Target
, Toolchain
, ArchList
, MetaFileDb
,
260 BuildConfig
, ToolDefinition
, FlashDefinitionFile
='', Fds
=None, Fvs
=None, Caps
=None, SkuId
='', UniFlag
=None,
261 Progress
=None, BuildModule
=None):
262 self
.BuildDatabase
= MetaFileDb
263 self
.MetaFile
= ActivePlatform
264 self
.WorkspaceDir
= WorkspaceDir
265 self
.Platform
= self
.BuildDatabase
[self
.MetaFile
, TAB_ARCH_COMMON
, Target
, Toolchain
]
266 GlobalData
.gActivePlatform
= self
.Platform
267 self
.BuildTarget
= Target
268 self
.ToolChain
= Toolchain
269 self
.ArchList
= ArchList
271 self
.UniFlag
= UniFlag
273 self
.TargetTxt
= BuildConfig
274 self
.ToolDef
= ToolDefinition
275 self
.FdfFile
= FlashDefinitionFile
276 self
.FdTargetList
= Fds
if Fds
else []
277 self
.FvTargetList
= Fvs
if Fvs
else []
278 self
.CapTargetList
= Caps
if Caps
else []
279 self
.AutoGenObjectList
= []
280 self
._BuildDir
= None
282 self
._MakeFileDir
= None
283 self
._BuildCommand
= None
286 # there's many relative directory operations, so ...
287 os
.chdir(self
.WorkspaceDir
)
292 if not self
.ArchList
:
293 ArchList
= set(self
.Platform
.SupArchList
)
295 ArchList
= set(self
.ArchList
) & set(self
.Platform
.SupArchList
)
297 EdkLogger
.error("build", PARAMETER_INVALID
,
298 ExtraData
= "Invalid ARCH specified. [Valid ARCH: %s]" % (" ".join(self
.Platform
.SupArchList
)))
299 elif self
.ArchList
and len(ArchList
) != len(self
.ArchList
):
300 SkippedArchList
= set(self
.ArchList
).symmetric_difference(set(self
.Platform
.SupArchList
))
301 EdkLogger
.verbose("\nArch [%s] is ignored because the platform supports [%s] only!"
302 % (" ".join(SkippedArchList
), " ".join(self
.Platform
.SupArchList
)))
303 self
.ArchList
= tuple(ArchList
)
305 # Validate build target
306 if self
.BuildTarget
not in self
.Platform
.BuildTargets
:
307 EdkLogger
.error("build", PARAMETER_INVALID
,
308 ExtraData
="Build target [%s] is not supported by the platform. [Valid target: %s]"
309 % (self
.BuildTarget
, " ".join(self
.Platform
.BuildTargets
)))
312 # parse FDF file to get PCDs in it, if any
314 self
.FdfFile
= self
.Platform
.FlashDefinition
318 EdkLogger
.info('%-16s = %s' % ("Architecture(s)", ' '.join(self
.ArchList
)))
319 EdkLogger
.info('%-16s = %s' % ("Build target", self
.BuildTarget
))
320 EdkLogger
.info('%-16s = %s' % ("Toolchain", self
.ToolChain
))
322 EdkLogger
.info('\n%-24s = %s' % ("Active Platform", self
.Platform
))
324 EdkLogger
.info('%-24s = %s' % ("Active Module", BuildModule
))
327 EdkLogger
.info('%-24s = %s' % ("Flash Image Definition", self
.FdfFile
))
329 EdkLogger
.verbose("\nFLASH_DEFINITION = %s" % self
.FdfFile
)
332 Progress
.Start("\nProcessing meta-data")
336 # Mark now build in AutoGen Phase
338 GlobalData
.gAutoGenPhase
= True
339 Fdf
= FdfParser(self
.FdfFile
.Path
)
341 GlobalData
.gFdfParser
= Fdf
342 GlobalData
.gAutoGenPhase
= False
343 PcdSet
= Fdf
.Profile
.PcdDict
344 if Fdf
.CurrentFdName
and Fdf
.CurrentFdName
in Fdf
.Profile
.FdDict
:
345 FdDict
= Fdf
.Profile
.FdDict
[Fdf
.CurrentFdName
]
346 for FdRegion
in FdDict
.RegionList
:
347 if str(FdRegion
.RegionType
) is 'FILE' and self
.Platform
.VpdToolGuid
in str(FdRegion
.RegionDataList
):
348 if int(FdRegion
.Offset
) % 8 != 0:
349 EdkLogger
.error("build", FORMAT_INVALID
, 'The VPD Base Address %s must be 8-byte aligned.' % (FdRegion
.Offset
))
350 ModuleList
= Fdf
.Profile
.InfList
351 self
.FdfProfile
= Fdf
.Profile
352 for fvname
in self
.FvTargetList
:
353 if fvname
.upper() not in self
.FdfProfile
.FvDict
:
354 EdkLogger
.error("build", OPTION_VALUE_INVALID
,
355 "No such an FV in FDF file: %s" % fvname
)
357 # In DSC file may use FILE_GUID to override the module, then in the Platform.Modules use FILE_GUIDmodule.inf as key,
358 # but the path (self.MetaFile.Path) is the real path
359 for key
in self
.FdfProfile
.InfDict
:
361 MetaFile_cache
= defaultdict(set)
362 for Arch
in self
.ArchList
:
363 Current_Platform_cache
= self
.BuildDatabase
[self
.MetaFile
, Arch
, Target
, Toolchain
]
364 for Pkey
in Current_Platform_cache
.Modules
:
365 MetaFile_cache
[Arch
].add(Current_Platform_cache
.Modules
[Pkey
].MetaFile
)
366 for Inf
in self
.FdfProfile
.InfDict
[key
]:
367 ModuleFile
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, Arch
)
368 for Arch
in self
.ArchList
:
369 if ModuleFile
in MetaFile_cache
[Arch
]:
372 ModuleData
= self
.BuildDatabase
[ModuleFile
, Arch
, Target
, Toolchain
]
373 if not ModuleData
.IsBinaryModule
:
374 EdkLogger
.error('build', PARSER_ERROR
, "Module %s NOT found in DSC file; Is it really a binary module?" % ModuleFile
)
377 for Arch
in self
.ArchList
:
379 Platform
= self
.BuildDatabase
[self
.MetaFile
, Arch
, Target
, Toolchain
]
381 for Pkey
in Platform
.Modules
:
382 MetaFileList
.add(Platform
.Modules
[Pkey
].MetaFile
)
383 for Inf
in self
.FdfProfile
.InfDict
[key
]:
384 ModuleFile
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, Arch
)
385 if ModuleFile
in MetaFileList
:
387 ModuleData
= self
.BuildDatabase
[ModuleFile
, Arch
, Target
, Toolchain
]
388 if not ModuleData
.IsBinaryModule
:
389 EdkLogger
.error('build', PARSER_ERROR
, "Module %s NOT found in DSC file; Is it really a binary module?" % ModuleFile
)
394 self
.FdfProfile
= None
395 if self
.FdTargetList
:
396 EdkLogger
.info("No flash definition file found. FD [%s] will be ignored." % " ".join(self
.FdTargetList
))
397 self
.FdTargetList
= []
398 if self
.FvTargetList
:
399 EdkLogger
.info("No flash definition file found. FV [%s] will be ignored." % " ".join(self
.FvTargetList
))
400 self
.FvTargetList
= []
401 if self
.CapTargetList
:
402 EdkLogger
.info("No flash definition file found. Capsule [%s] will be ignored." % " ".join(self
.CapTargetList
))
403 self
.CapTargetList
= []
405 # apply SKU and inject PCDs from Flash Definition file
406 for Arch
in self
.ArchList
:
407 Platform
= self
.BuildDatabase
[self
.MetaFile
, Arch
, Target
, Toolchain
]
408 PlatformPcds
= Platform
.Pcds
409 self
._GuidDict
= Platform
._GuidDict
410 SourcePcdDict
= {TAB_PCDS_DYNAMIC_EX
:set(), TAB_PCDS_PATCHABLE_IN_MODULE
:set(),TAB_PCDS_DYNAMIC
:set(),TAB_PCDS_FIXED_AT_BUILD
:set()}
411 BinaryPcdDict
= {TAB_PCDS_DYNAMIC_EX
:set(), TAB_PCDS_PATCHABLE_IN_MODULE
:set()}
412 SourcePcdDict_Keys
= SourcePcdDict
.keys()
413 BinaryPcdDict_Keys
= BinaryPcdDict
.keys()
415 # generate the SourcePcdDict and BinaryPcdDict
416 PGen
= PlatformAutoGen(self
, self
.MetaFile
, Target
, Toolchain
, Arch
)
417 for BuildData
in PGen
.BuildDatabase
._CACHE
_.values():
418 if BuildData
.Arch
!= Arch
:
420 if BuildData
.MetaFile
.Ext
== '.inf':
421 for key
in BuildData
.Pcds
:
422 if BuildData
.Pcds
[key
].Pending
:
423 if key
in Platform
.Pcds
:
424 PcdInPlatform
= Platform
.Pcds
[key
]
425 if PcdInPlatform
.Type
:
426 BuildData
.Pcds
[key
].Type
= PcdInPlatform
.Type
427 BuildData
.Pcds
[key
].Pending
= False
429 if BuildData
.MetaFile
in Platform
.Modules
:
430 PlatformModule
= Platform
.Modules
[str(BuildData
.MetaFile
)]
431 if key
in PlatformModule
.Pcds
:
432 PcdInPlatform
= PlatformModule
.Pcds
[key
]
433 if PcdInPlatform
.Type
:
434 BuildData
.Pcds
[key
].Type
= PcdInPlatform
.Type
435 BuildData
.Pcds
[key
].Pending
= False
437 #Pcd used in Library, Pcd Type from reference module if Pcd Type is Pending
438 if BuildData
.Pcds
[key
].Pending
:
439 MGen
= ModuleAutoGen(self
, BuildData
.MetaFile
, Target
, Toolchain
, Arch
, self
.MetaFile
)
440 if MGen
and MGen
.IsLibrary
:
441 if MGen
in PGen
.LibraryAutoGenList
:
442 ReferenceModules
= MGen
._ReferenceModules
443 for ReferenceModule
in ReferenceModules
:
444 if ReferenceModule
.MetaFile
in Platform
.Modules
:
445 RefPlatformModule
= Platform
.Modules
[str(ReferenceModule
.MetaFile
)]
446 if key
in RefPlatformModule
.Pcds
:
447 PcdInReferenceModule
= RefPlatformModule
.Pcds
[key
]
448 if PcdInReferenceModule
.Type
:
449 BuildData
.Pcds
[key
].Type
= PcdInReferenceModule
.Type
450 BuildData
.Pcds
[key
].Pending
= False
453 if TAB_PCDS_DYNAMIC_EX
in BuildData
.Pcds
[key
].Type
:
454 if BuildData
.IsBinaryModule
:
455 BinaryPcdDict
[TAB_PCDS_DYNAMIC_EX
].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
457 SourcePcdDict
[TAB_PCDS_DYNAMIC_EX
].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
459 elif TAB_PCDS_PATCHABLE_IN_MODULE
in BuildData
.Pcds
[key
].Type
:
460 if BuildData
.MetaFile
.Ext
== '.inf':
461 if BuildData
.IsBinaryModule
:
462 BinaryPcdDict
[TAB_PCDS_PATCHABLE_IN_MODULE
].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
464 SourcePcdDict
[TAB_PCDS_PATCHABLE_IN_MODULE
].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
466 elif TAB_PCDS_DYNAMIC
in BuildData
.Pcds
[key
].Type
:
467 SourcePcdDict
[TAB_PCDS_DYNAMIC
].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
468 elif TAB_PCDS_FIXED_AT_BUILD
in BuildData
.Pcds
[key
].Type
:
469 SourcePcdDict
[TAB_PCDS_FIXED_AT_BUILD
].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
473 # A PCD can only use one type for all source modules
475 for i
in SourcePcdDict_Keys
:
476 for j
in SourcePcdDict_Keys
:
478 Intersections
= SourcePcdDict
[i
].intersection(SourcePcdDict
[j
])
479 if len(Intersections
) > 0:
483 "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
),
484 ExtraData
="%s" % '\n\t'.join(str(P
[1]+'.'+P
[0]) for P
in Intersections
)
488 # intersection the BinaryPCD for Mixed PCD
490 for i
in BinaryPcdDict_Keys
:
491 for j
in BinaryPcdDict_Keys
:
493 Intersections
= BinaryPcdDict
[i
].intersection(BinaryPcdDict
[j
])
494 for item
in Intersections
:
495 NewPcd1
= (item
[0] + '_' + i
, item
[1])
496 NewPcd2
= (item
[0] + '_' + j
, item
[1])
497 if item
not in GlobalData
.MixedPcd
:
498 GlobalData
.MixedPcd
[item
] = [NewPcd1
, NewPcd2
]
500 if NewPcd1
not in GlobalData
.MixedPcd
[item
]:
501 GlobalData
.MixedPcd
[item
].append(NewPcd1
)
502 if NewPcd2
not in GlobalData
.MixedPcd
[item
]:
503 GlobalData
.MixedPcd
[item
].append(NewPcd2
)
506 # intersection the SourcePCD and BinaryPCD for Mixed PCD
508 for i
in SourcePcdDict_Keys
:
509 for j
in BinaryPcdDict_Keys
:
511 Intersections
= SourcePcdDict
[i
].intersection(BinaryPcdDict
[j
])
512 for item
in Intersections
:
513 NewPcd1
= (item
[0] + '_' + i
, item
[1])
514 NewPcd2
= (item
[0] + '_' + j
, item
[1])
515 if item
not in GlobalData
.MixedPcd
:
516 GlobalData
.MixedPcd
[item
] = [NewPcd1
, NewPcd2
]
518 if NewPcd1
not in GlobalData
.MixedPcd
[item
]:
519 GlobalData
.MixedPcd
[item
].append(NewPcd1
)
520 if NewPcd2
not in GlobalData
.MixedPcd
[item
]:
521 GlobalData
.MixedPcd
[item
].append(NewPcd2
)
523 for BuildData
in PGen
.BuildDatabase
._CACHE
_.values():
524 if BuildData
.Arch
!= Arch
:
526 for key
in BuildData
.Pcds
:
527 for SinglePcd
in GlobalData
.MixedPcd
:
528 if (BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
) == SinglePcd
:
529 for item
in GlobalData
.MixedPcd
[SinglePcd
]:
530 Pcd_Type
= item
[0].split('_')[-1]
531 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 \
532 (Pcd_Type
== TAB_PCDS_DYNAMIC
and BuildData
.Pcds
[key
].Type
in PCD_DYNAMIC_TYPE_SET
):
533 Value
= BuildData
.Pcds
[key
]
534 Value
.TokenCName
= BuildData
.Pcds
[key
].TokenCName
+ '_' + Pcd_Type
536 newkey
= (Value
.TokenCName
, key
[1])
538 newkey
= (Value
.TokenCName
, key
[1], key
[2])
539 del BuildData
.Pcds
[key
]
540 BuildData
.Pcds
[newkey
] = Value
544 # handle the mixed pcd in FDF file
546 if key
in GlobalData
.MixedPcd
:
549 for item
in GlobalData
.MixedPcd
[key
]:
552 #Collect package set information from INF of FDF
554 for Inf
in ModuleList
:
555 ModuleFile
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, Arch
)
556 if ModuleFile
in Platform
.Modules
:
558 ModuleData
= self
.BuildDatabase
[ModuleFile
, Arch
, Target
, Toolchain
]
559 PkgSet
.update(ModuleData
.Packages
)
560 Pkgs
= list(PkgSet
) + list(PGen
.PackageList
)
565 DecPcds
.add((Pcd
[0], Pcd
[1]))
566 DecPcdsKey
.add((Pcd
[0], Pcd
[1], Pcd
[2]))
568 Platform
.SkuName
= self
.SkuId
569 for Name
, Guid
in PcdSet
:
570 if (Name
, Guid
) not in DecPcds
:
574 "PCD (%s.%s) used in FDF is not declared in DEC files." % (Guid
, Name
),
575 File
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
][0],
576 Line
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
][1]
579 # Check whether Dynamic or DynamicEx PCD used in FDF file. If used, build break and give a error message.
580 if (Name
, Guid
, TAB_PCDS_FIXED_AT_BUILD
) in DecPcdsKey \
581 or (Name
, Guid
, TAB_PCDS_PATCHABLE_IN_MODULE
) in DecPcdsKey \
582 or (Name
, Guid
, TAB_PCDS_FEATURE_FLAG
) in DecPcdsKey
:
583 Platform
.AddPcd(Name
, Guid
, PcdSet
[Name
, Guid
])
585 elif (Name
, Guid
, TAB_PCDS_DYNAMIC
) in DecPcdsKey
or (Name
, Guid
, TAB_PCDS_DYNAMIC_EX
) in DecPcdsKey
:
589 "Using Dynamic or DynamicEx type of PCD [%s.%s] in FDF file is not allowed." % (Guid
, Name
),
590 File
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
][0],
591 Line
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
][1]
594 Pa
= PlatformAutoGen(self
, self
.MetaFile
, Target
, Toolchain
, Arch
)
596 # Explicitly collect platform's dynamic PCDs
598 Pa
.CollectPlatformDynamicPcds()
599 Pa
.CollectFixedAtBuildPcds()
600 self
.AutoGenObjectList
.append(Pa
)
603 # Generate Package level hash value
605 GlobalData
.gPackageHash
[Arch
] = {}
606 if GlobalData
.gUseHashCache
:
608 self
._GenPkgLevelHash
(Pkg
)
611 # Check PCDs token value conflict in each DEC file.
613 self
._CheckAllPcdsTokenValueConflict
()
616 # Check PCD type and definition between DSC and DEC
618 self
._CheckPcdDefineAndType
()
621 # self._CheckDuplicateInFV(Fdf)
624 # Create BuildOptions Macro & PCD metafile, also add the Active Platform and FDF file.
626 content
= 'gCommandLineDefines: '
627 content
+= str(GlobalData
.gCommandLineDefines
)
628 content
+= os
.linesep
629 content
+= 'BuildOptionPcd: '
630 content
+= str(GlobalData
.BuildOptionPcd
)
631 content
+= os
.linesep
632 content
+= 'Active Platform: '
633 content
+= str(self
.Platform
)
634 content
+= os
.linesep
636 content
+= 'Flash Image Definition: '
637 content
+= str(self
.FdfFile
)
638 content
+= os
.linesep
639 SaveFileOnChange(os
.path
.join(self
.BuildDir
, 'BuildOptions'), content
, False)
642 # Create PcdToken Number file for Dynamic/DynamicEx Pcd.
644 PcdTokenNumber
= 'PcdTokenNumber: '
645 if Pa
.PcdTokenNumber
:
646 if Pa
.DynamicPcdList
:
647 for Pcd
in Pa
.DynamicPcdList
:
648 PcdTokenNumber
+= os
.linesep
649 PcdTokenNumber
+= str((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
))
650 PcdTokenNumber
+= ' : '
651 PcdTokenNumber
+= str(Pa
.PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
])
652 SaveFileOnChange(os
.path
.join(self
.BuildDir
, 'PcdTokenNumber'), PcdTokenNumber
, False)
655 # Get set of workspace metafiles
657 AllWorkSpaceMetaFiles
= self
._GetMetaFiles
(Target
, Toolchain
, Arch
)
660 # Retrieve latest modified time of all metafiles
663 for f
in AllWorkSpaceMetaFiles
:
664 if os
.stat(f
)[8] > SrcTimeStamp
:
665 SrcTimeStamp
= os
.stat(f
)[8]
666 self
._SrcTimeStamp
= SrcTimeStamp
668 if GlobalData
.gUseHashCache
:
670 for files
in AllWorkSpaceMetaFiles
:
671 if files
.endswith('.dec'):
677 SaveFileOnChange(os
.path
.join(self
.BuildDir
, 'AutoGen.hash'), m
.hexdigest(), True)
678 GlobalData
.gPlatformHash
= m
.hexdigest()
681 # Write metafile list to build directory
683 AutoGenFilePath
= os
.path
.join(self
.BuildDir
, 'AutoGen')
684 if os
.path
.exists (AutoGenFilePath
):
685 os
.remove(AutoGenFilePath
)
686 if not os
.path
.exists(self
.BuildDir
):
687 os
.makedirs(self
.BuildDir
)
688 with
open(os
.path
.join(self
.BuildDir
, 'AutoGen'), 'w+') as file:
689 for f
in AllWorkSpaceMetaFiles
:
693 def _GenPkgLevelHash(self
, Pkg
):
694 if Pkg
.PackageName
in GlobalData
.gPackageHash
[Pkg
.Arch
]:
697 PkgDir
= os
.path
.join(self
.BuildDir
, Pkg
.Arch
, Pkg
.PackageName
)
698 CreateDirectory(PkgDir
)
699 HashFile
= os
.path
.join(PkgDir
, Pkg
.PackageName
+ '.hash')
701 # Get .dec file's hash value
702 f
= open(Pkg
.MetaFile
.Path
, 'r')
706 # Get include files hash value
708 for inc
in sorted(Pkg
.Includes
, key
=lambda x
: str(x
)):
709 for Root
, Dirs
, Files
in os
.walk(str(inc
)):
710 for File
in sorted(Files
):
711 File_Path
= os
.path
.join(Root
, File
)
712 f
= open(File_Path
, 'r')
716 SaveFileOnChange(HashFile
, m
.hexdigest(), True)
717 GlobalData
.gPackageHash
[Pkg
.Arch
][Pkg
.PackageName
] = m
.hexdigest()
719 def _GetMetaFiles(self
, Target
, Toolchain
, Arch
):
720 AllWorkSpaceMetaFiles
= set()
725 AllWorkSpaceMetaFiles
.add (self
.FdfFile
.Path
)
727 FdfFiles
= GlobalData
.gFdfParser
.GetAllIncludedFile()
729 AllWorkSpaceMetaFiles
.add (f
.FileName
)
733 AllWorkSpaceMetaFiles
.add(self
.MetaFile
.Path
)
736 # add build_rule.txt & tools_def.txt
738 AllWorkSpaceMetaFiles
.add(os
.path
.join(GlobalData
.gConfDirectory
, gDefaultBuildRuleFile
))
739 AllWorkSpaceMetaFiles
.add(os
.path
.join(GlobalData
.gConfDirectory
, gDefaultToolsDefFile
))
741 # add BuildOption metafile
743 AllWorkSpaceMetaFiles
.add(os
.path
.join(self
.BuildDir
, 'BuildOptions'))
745 # add PcdToken Number file for Dynamic/DynamicEx Pcd
747 AllWorkSpaceMetaFiles
.add(os
.path
.join(self
.BuildDir
, 'PcdTokenNumber'))
749 for Arch
in self
.ArchList
:
750 Platform
= self
.BuildDatabase
[self
.MetaFile
, Arch
, Target
, Toolchain
]
751 PGen
= PlatformAutoGen(self
, self
.MetaFile
, Target
, Toolchain
, Arch
)
756 for Package
in PGen
.PackageList
:
757 AllWorkSpaceMetaFiles
.add(Package
.MetaFile
.Path
)
762 for filePath
in Platform
._RawData
.IncludedFiles
:
763 AllWorkSpaceMetaFiles
.add(filePath
.Path
)
765 return AllWorkSpaceMetaFiles
767 ## _CheckDuplicateInFV() method
769 # Check whether there is duplicate modules/files exist in FV section.
770 # The check base on the file GUID;
772 def _CheckDuplicateInFV(self
, Fdf
):
773 for Fv
in Fdf
.Profile
.FvDict
:
775 for FfsFile
in Fdf
.Profile
.FvDict
[Fv
].FfsList
:
776 if FfsFile
.InfFileName
and FfsFile
.NameGuid
is None:
781 for Pa
in self
.AutoGenObjectList
:
784 for Module
in Pa
.ModuleAutoGenList
:
785 if path
.normpath(Module
.MetaFile
.File
) == path
.normpath(FfsFile
.InfFileName
):
787 if Module
.Guid
.upper() not in _GuidDict
:
788 _GuidDict
[Module
.Guid
.upper()] = FfsFile
791 EdkLogger
.error("build",
793 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile
.CurrentLineNum
,
794 FfsFile
.CurrentLineContent
,
795 _GuidDict
[Module
.Guid
.upper()].CurrentLineNum
,
796 _GuidDict
[Module
.Guid
.upper()].CurrentLineContent
,
797 Module
.Guid
.upper()),
798 ExtraData
=self
.FdfFile
)
800 # Some INF files not have entity in DSC file.
803 if FfsFile
.InfFileName
.find('$') == -1:
804 InfPath
= NormPath(FfsFile
.InfFileName
)
805 if not os
.path
.exists(InfPath
):
806 EdkLogger
.error('build', GENFDS_ERROR
, "Non-existant Module %s !" % (FfsFile
.InfFileName
))
808 PathClassObj
= PathClass(FfsFile
.InfFileName
, self
.WorkspaceDir
)
810 # Here we just need to get FILE_GUID from INF file, use 'COMMON' as ARCH attribute. and use
811 # BuildObject from one of AutoGenObjectList is enough.
813 InfObj
= self
.AutoGenObjectList
[0].BuildDatabase
.WorkspaceDb
.BuildObject
[PathClassObj
, TAB_ARCH_COMMON
, self
.BuildTarget
, self
.ToolChain
]
814 if InfObj
.Guid
.upper() not in _GuidDict
:
815 _GuidDict
[InfObj
.Guid
.upper()] = FfsFile
817 EdkLogger
.error("build",
819 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile
.CurrentLineNum
,
820 FfsFile
.CurrentLineContent
,
821 _GuidDict
[InfObj
.Guid
.upper()].CurrentLineNum
,
822 _GuidDict
[InfObj
.Guid
.upper()].CurrentLineContent
,
823 InfObj
.Guid
.upper()),
824 ExtraData
=self
.FdfFile
)
827 if FfsFile
.NameGuid
is not None:
829 # If the NameGuid reference a PCD name.
830 # The style must match: PCD(xxxx.yyy)
832 if gPCDAsGuidPattern
.match(FfsFile
.NameGuid
):
834 # Replace the PCD value.
836 _PcdName
= FfsFile
.NameGuid
.lstrip("PCD(").rstrip(")")
838 for Pa
in self
.AutoGenObjectList
:
840 for PcdItem
in Pa
.AllPcdList
:
841 if (PcdItem
.TokenSpaceGuidCName
+ "." + PcdItem
.TokenCName
) == _PcdName
:
843 # First convert from CFormatGuid to GUID string
845 _PcdGuidString
= GuidStructureStringToGuidString(PcdItem
.DefaultValue
)
847 if not _PcdGuidString
:
849 # Then try Byte array.
851 _PcdGuidString
= GuidStructureByteArrayToGuidString(PcdItem
.DefaultValue
)
853 if not _PcdGuidString
:
855 # Not Byte array or CFormat GUID, raise error.
857 EdkLogger
.error("build",
859 "The format of PCD value is incorrect. PCD: %s , Value: %s\n" % (_PcdName
, PcdItem
.DefaultValue
),
860 ExtraData
=self
.FdfFile
)
862 if _PcdGuidString
.upper() not in _GuidDict
:
863 _GuidDict
[_PcdGuidString
.upper()] = FfsFile
867 EdkLogger
.error("build",
869 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile
.CurrentLineNum
,
870 FfsFile
.CurrentLineContent
,
871 _GuidDict
[_PcdGuidString
.upper()].CurrentLineNum
,
872 _GuidDict
[_PcdGuidString
.upper()].CurrentLineContent
,
873 FfsFile
.NameGuid
.upper()),
874 ExtraData
=self
.FdfFile
)
876 if FfsFile
.NameGuid
.upper() not in _GuidDict
:
877 _GuidDict
[FfsFile
.NameGuid
.upper()] = FfsFile
880 # Two raw file GUID conflict.
882 EdkLogger
.error("build",
884 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile
.CurrentLineNum
,
885 FfsFile
.CurrentLineContent
,
886 _GuidDict
[FfsFile
.NameGuid
.upper()].CurrentLineNum
,
887 _GuidDict
[FfsFile
.NameGuid
.upper()].CurrentLineContent
,
888 FfsFile
.NameGuid
.upper()),
889 ExtraData
=self
.FdfFile
)
892 def _CheckPcdDefineAndType(self
):
894 TAB_PCDS_FIXED_AT_BUILD
, TAB_PCDS_PATCHABLE_IN_MODULE
, TAB_PCDS_FEATURE_FLAG
,
895 TAB_PCDS_DYNAMIC
, #TAB_PCDS_DYNAMIC_HII, TAB_PCDS_DYNAMIC_VPD,
896 TAB_PCDS_DYNAMIC_EX
, # TAB_PCDS_DYNAMIC_EX_HII, TAB_PCDS_DYNAMIC_EX_VPD
899 # This dict store PCDs which are not used by any modules with specified arches
900 UnusedPcd
= OrderedDict()
901 for Pa
in self
.AutoGenObjectList
:
902 # Key of DSC's Pcds dictionary is PcdCName, TokenSpaceGuid
903 for Pcd
in Pa
.Platform
.Pcds
:
904 PcdType
= Pa
.Platform
.Pcds
[Pcd
].Type
906 # If no PCD type, this PCD comes from FDF
910 # Try to remove Hii and Vpd suffix
911 if PcdType
.startswith(TAB_PCDS_DYNAMIC_EX
):
912 PcdType
= TAB_PCDS_DYNAMIC_EX
913 elif PcdType
.startswith(TAB_PCDS_DYNAMIC
):
914 PcdType
= TAB_PCDS_DYNAMIC
916 for Package
in Pa
.PackageList
:
917 # Key of DEC's Pcds dictionary is PcdCName, TokenSpaceGuid, PcdType
918 if (Pcd
[0], Pcd
[1], PcdType
) in Package
.Pcds
:
920 for Type
in PcdTypeList
:
921 if (Pcd
[0], Pcd
[1], Type
) in Package
.Pcds
:
925 "Type [%s] of PCD [%s.%s] in DSC file doesn't match the type [%s] defined in DEC file." \
926 % (Pa
.Platform
.Pcds
[Pcd
].Type
, Pcd
[1], Pcd
[0], Type
),
931 UnusedPcd
.setdefault(Pcd
, []).append(Pa
.Arch
)
933 for Pcd
in UnusedPcd
:
936 "The PCD was not specified by any INF module in the platform for the given architecture.\n"
937 "\tPCD: [%s.%s]\n\tPlatform: [%s]\n\tArch: %s"
938 % (Pcd
[1], Pcd
[0], os
.path
.basename(str(self
.MetaFile
)), str(UnusedPcd
[Pcd
])),
943 return "%s [%s]" % (self
.MetaFile
, ", ".join(self
.ArchList
))
945 ## Return the directory to store FV files
947 if self
._FvDir
is None:
948 self
._FvDir
= path
.join(self
.BuildDir
, TAB_FV_DIRECTORY
)
951 ## Return the directory to store all intermediate and final files built
952 def _GetBuildDir(self
):
953 if self
._BuildDir
is None:
954 return self
.AutoGenObjectList
[0].BuildDir
956 ## Return the build output directory platform specifies
957 def _GetOutputDir(self
):
958 return self
.Platform
.OutputDirectory
960 ## Return platform name
962 return self
.Platform
.PlatformName
964 ## Return meta-file GUID
966 return self
.Platform
.Guid
968 ## Return platform version
969 def _GetVersion(self
):
970 return self
.Platform
.Version
972 ## Return paths of tools
973 def _GetToolDefinition(self
):
974 return self
.AutoGenObjectList
[0].ToolDefinition
976 ## Return directory of platform makefile
978 # @retval string Makefile directory
980 def _GetMakeFileDir(self
):
981 if self
._MakeFileDir
is None:
982 self
._MakeFileDir
= self
.BuildDir
983 return self
._MakeFileDir
985 ## Return build command string
987 # @retval string Build command string
989 def _GetBuildCommand(self
):
990 if self
._BuildCommand
is None:
991 # BuildCommand should be all the same. So just get one from platform AutoGen
992 self
._BuildCommand
= self
.AutoGenObjectList
[0].BuildCommand
993 return self
._BuildCommand
995 ## Check the PCDs token value conflict in each DEC file.
997 # Will cause build break and raise error message while two PCDs conflict.
1001 def _CheckAllPcdsTokenValueConflict(self
):
1002 for Pa
in self
.AutoGenObjectList
:
1003 for Package
in Pa
.PackageList
:
1004 PcdList
= Package
.Pcds
.values()
1005 PcdList
.sort(lambda x
, y
: cmp(int(x
.TokenValue
, 0), int(y
.TokenValue
, 0)))
1007 while (Count
< len(PcdList
) - 1) :
1008 Item
= PcdList
[Count
]
1009 ItemNext
= PcdList
[Count
+ 1]
1011 # Make sure in the same token space the TokenValue should be unique
1013 if (int(Item
.TokenValue
, 0) == int(ItemNext
.TokenValue
, 0)):
1014 SameTokenValuePcdList
= []
1015 SameTokenValuePcdList
.append(Item
)
1016 SameTokenValuePcdList
.append(ItemNext
)
1017 RemainPcdListLength
= len(PcdList
) - Count
- 2
1018 for ValueSameCount
in range(RemainPcdListLength
):
1019 if int(PcdList
[len(PcdList
) - RemainPcdListLength
+ ValueSameCount
].TokenValue
, 0) == int(Item
.TokenValue
, 0):
1020 SameTokenValuePcdList
.append(PcdList
[len(PcdList
) - RemainPcdListLength
+ ValueSameCount
])
1024 # Sort same token value PCD list with TokenGuid and TokenCName
1026 SameTokenValuePcdList
.sort(lambda x
, y
: cmp("%s.%s" % (x
.TokenSpaceGuidCName
, x
.TokenCName
), "%s.%s" % (y
.TokenSpaceGuidCName
, y
.TokenCName
)))
1027 SameTokenValuePcdListCount
= 0
1028 while (SameTokenValuePcdListCount
< len(SameTokenValuePcdList
) - 1):
1030 TemListItem
= SameTokenValuePcdList
[SameTokenValuePcdListCount
]
1031 TemListItemNext
= SameTokenValuePcdList
[SameTokenValuePcdListCount
+ 1]
1033 if (TemListItem
.TokenSpaceGuidCName
== TemListItemNext
.TokenSpaceGuidCName
) and (TemListItem
.TokenCName
!= TemListItemNext
.TokenCName
):
1034 for PcdItem
in GlobalData
.MixedPcd
:
1035 if (TemListItem
.TokenCName
, TemListItem
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
] or \
1036 (TemListItemNext
.TokenCName
, TemListItemNext
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
1042 "The TokenValue [%s] of PCD [%s.%s] is conflict with: [%s.%s] in %s"\
1043 % (TemListItem
.TokenValue
, TemListItem
.TokenSpaceGuidCName
, TemListItem
.TokenCName
, TemListItemNext
.TokenSpaceGuidCName
, TemListItemNext
.TokenCName
, Package
),
1046 SameTokenValuePcdListCount
+= 1
1047 Count
+= SameTokenValuePcdListCount
1050 PcdList
= Package
.Pcds
.values()
1051 PcdList
.sort(lambda x
, y
: cmp("%s.%s" % (x
.TokenSpaceGuidCName
, x
.TokenCName
), "%s.%s" % (y
.TokenSpaceGuidCName
, y
.TokenCName
)))
1053 while (Count
< len(PcdList
) - 1) :
1054 Item
= PcdList
[Count
]
1055 ItemNext
= PcdList
[Count
+ 1]
1057 # Check PCDs with same TokenSpaceGuidCName.TokenCName have same token value as well.
1059 if (Item
.TokenSpaceGuidCName
== ItemNext
.TokenSpaceGuidCName
) and (Item
.TokenCName
== ItemNext
.TokenCName
) and (int(Item
.TokenValue
, 0) != int(ItemNext
.TokenValue
, 0)):
1063 "The TokenValue [%s] of PCD [%s.%s] in %s defined in two places should be same as well."\
1064 % (Item
.TokenValue
, Item
.TokenSpaceGuidCName
, Item
.TokenCName
, Package
),
1068 ## Generate fds command
1069 def _GenFdsCommand(self
):
1070 return (GenMake
.TopLevelMakefile(self
)._TEMPLATE
_.Replace(GenMake
.TopLevelMakefile(self
)._TemplateDict
)).strip()
1072 ## Create makefile for the platform and modules in it
1074 # @param CreateDepsMakeFile Flag indicating if the makefile for
1075 # modules will be created as well
1077 def CreateMakeFile(self
, CreateDepsMakeFile
=False):
1078 if CreateDepsMakeFile
:
1079 for Pa
in self
.AutoGenObjectList
:
1080 Pa
.CreateMakeFile(CreateDepsMakeFile
)
1082 ## Create autogen code for platform and modules
1084 # Since there's no autogen code for platform, this method will do nothing
1085 # if CreateModuleCodeFile is set to False.
1087 # @param CreateDepsCodeFile Flag indicating if creating module's
1088 # autogen code file or not
1090 def CreateCodeFile(self
, CreateDepsCodeFile
=False):
1091 if not CreateDepsCodeFile
:
1093 for Pa
in self
.AutoGenObjectList
:
1094 Pa
.CreateCodeFile(CreateDepsCodeFile
)
1096 ## Create AsBuilt INF file the platform
1098 def CreateAsBuiltInf(self
):
1101 Name
= property(_GetName
)
1102 Guid
= property(_GetGuid
)
1103 Version
= property(_GetVersion
)
1104 OutputDir
= property(_GetOutputDir
)
1106 ToolDefinition
= property(_GetToolDefinition
) # toolcode : tool path
1108 BuildDir
= property(_GetBuildDir
)
1109 FvDir
= property(_GetFvDir
)
1110 MakeFileDir
= property(_GetMakeFileDir
)
1111 BuildCommand
= property(_GetBuildCommand
)
1112 GenFdsCommand
= property(_GenFdsCommand
)
1114 ## AutoGen class for platform
1116 # PlatformAutoGen class will process the original information in platform
1117 # file in order to generate makefile for platform.
1119 class PlatformAutoGen(AutoGen
):
1120 # call super().__init__ then call the worker function with different parameter count
1121 def __init__(self
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
1125 super(PlatformAutoGen
, self
).__init
__(self
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
)
1126 self
._InitWorker
(Workspace
, MetaFile
, Target
, Toolchain
, Arch
)
1129 # Used to store all PCDs for both PEI and DXE phase, in order to generate
1130 # correct PCD database
1133 _NonDynaPcdList_
= []
1137 # The priority list while override build option
1139 PrioList
= {"0x11111" : 16, # TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE (Highest)
1140 "0x01111" : 15, # ******_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
1141 "0x10111" : 14, # TARGET_*********_ARCH_COMMANDTYPE_ATTRIBUTE
1142 "0x00111" : 13, # ******_*********_ARCH_COMMANDTYPE_ATTRIBUTE
1143 "0x11011" : 12, # TARGET_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
1144 "0x01011" : 11, # ******_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
1145 "0x10011" : 10, # TARGET_*********_****_COMMANDTYPE_ATTRIBUTE
1146 "0x00011" : 9, # ******_*********_****_COMMANDTYPE_ATTRIBUTE
1147 "0x11101" : 8, # TARGET_TOOLCHAIN_ARCH_***********_ATTRIBUTE
1148 "0x01101" : 7, # ******_TOOLCHAIN_ARCH_***********_ATTRIBUTE
1149 "0x10101" : 6, # TARGET_*********_ARCH_***********_ATTRIBUTE
1150 "0x00101" : 5, # ******_*********_ARCH_***********_ATTRIBUTE
1151 "0x11001" : 4, # TARGET_TOOLCHAIN_****_***********_ATTRIBUTE
1152 "0x01001" : 3, # ******_TOOLCHAIN_****_***********_ATTRIBUTE
1153 "0x10001" : 2, # TARGET_*********_****_***********_ATTRIBUTE
1154 "0x00001" : 1} # ******_*********_****_***********_ATTRIBUTE (Lowest)
1156 ## Initialize PlatformAutoGen
1159 # @param Workspace WorkspaceAutoGen object
1160 # @param PlatformFile Platform file (DSC file)
1161 # @param Target Build target (DEBUG, RELEASE)
1162 # @param Toolchain Name of tool chain
1163 # @param Arch arch of the platform supports
1165 def _InitWorker(self
, Workspace
, PlatformFile
, Target
, Toolchain
, Arch
):
1166 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "AutoGen platform [%s] [%s]" % (PlatformFile
, Arch
))
1167 GlobalData
.gProcessingFile
= "%s [%s, %s, %s]" % (PlatformFile
, Arch
, Toolchain
, Target
)
1169 self
.MetaFile
= PlatformFile
1170 self
.Workspace
= Workspace
1171 self
.WorkspaceDir
= Workspace
.WorkspaceDir
1172 self
.ToolChain
= Toolchain
1173 self
.BuildTarget
= Target
1175 self
.SourceDir
= PlatformFile
.SubDir
1176 self
.SourceOverrideDir
= None
1177 self
.FdTargetList
= self
.Workspace
.FdTargetList
1178 self
.FvTargetList
= self
.Workspace
.FvTargetList
1179 self
.AllPcdList
= []
1180 # get the original module/package/platform objects
1181 self
.BuildDatabase
= Workspace
.BuildDatabase
1182 self
.DscBuildDataObj
= Workspace
.Platform
1183 self
._GuidDict
= Workspace
._GuidDict
1185 # flag indicating if the makefile/C-code file has been created or not
1186 self
.IsMakeFileCreated
= False
1187 self
.IsCodeFileCreated
= False
1189 self
._Platform
= None
1192 self
._Version
= None
1194 self
._BuildRule
= None
1195 self
._SourceDir
= None
1196 self
._BuildDir
= None
1197 self
._OutputDir
= None
1199 self
._MakeFileDir
= None
1200 self
._FdfFile
= None
1202 self
._PcdTokenNumber
= None # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber
1203 self
._DynamicPcdList
= None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
1204 self
._NonDynamicPcdList
= None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
1205 self
._NonDynamicPcdDict
= {}
1207 self
._ToolDefinitions
= None
1208 self
._ToolDefFile
= None # toolcode : tool path
1209 self
._ToolChainFamily
= None
1210 self
._BuildRuleFamily
= None
1211 self
._BuildOption
= None # toolcode : option
1212 self
._EdkBuildOption
= None # edktoolcode : option
1213 self
._EdkIIBuildOption
= None # edkiitoolcode : option
1214 self
._PackageList
= None
1215 self
._ModuleAutoGenList
= None
1216 self
._LibraryAutoGenList
= None
1217 self
._BuildCommand
= None
1218 self
._AsBuildInfList
= []
1219 self
._AsBuildModuleList
= []
1221 self
.VariableInfo
= None
1223 if GlobalData
.gFdfParser
is not None:
1224 self
._AsBuildInfList
= GlobalData
.gFdfParser
.Profile
.InfList
1225 for Inf
in self
._AsBuildInfList
:
1226 InfClass
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, self
.Arch
)
1227 M
= self
.BuildDatabase
[InfClass
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1228 if not M
.IsSupportedArch
:
1230 self
._AsBuildModuleList
.append(InfClass
)
1231 # get library/modules for build
1232 self
.LibraryBuildDirectoryList
= []
1233 self
.ModuleBuildDirectoryList
= []
1238 return "%s [%s]" % (self
.MetaFile
, self
.Arch
)
1240 ## Create autogen code for platform and modules
1242 # Since there's no autogen code for platform, this method will do nothing
1243 # if CreateModuleCodeFile is set to False.
1245 # @param CreateModuleCodeFile Flag indicating if creating module's
1246 # autogen code file or not
1248 def CreateCodeFile(self
, CreateModuleCodeFile
=False):
1249 # only module has code to be greated, so do nothing if CreateModuleCodeFile is False
1250 if self
.IsCodeFileCreated
or not CreateModuleCodeFile
:
1253 for Ma
in self
.ModuleAutoGenList
:
1254 Ma
.CreateCodeFile(True)
1256 # don't do this twice
1257 self
.IsCodeFileCreated
= True
1259 ## Generate Fds Command
1260 def _GenFdsCommand(self
):
1261 return self
.Workspace
.GenFdsCommand
1263 ## Create makefile for the platform and mdoules in it
1265 # @param CreateModuleMakeFile Flag indicating if the makefile for
1266 # modules will be created as well
1268 def CreateMakeFile(self
, CreateModuleMakeFile
=False, FfsCommand
= {}):
1269 if CreateModuleMakeFile
:
1270 for ModuleFile
in self
.Platform
.Modules
:
1271 Ma
= ModuleAutoGen(self
.Workspace
, ModuleFile
, self
.BuildTarget
,
1272 self
.ToolChain
, self
.Arch
, self
.MetaFile
)
1273 if (ModuleFile
.File
, self
.Arch
) in FfsCommand
:
1274 Ma
.CreateMakeFile(True, FfsCommand
[ModuleFile
.File
, self
.Arch
])
1276 Ma
.CreateMakeFile(True)
1277 #Ma.CreateAsBuiltInf()
1279 # no need to create makefile for the platform more than once
1280 if self
.IsMakeFileCreated
:
1283 # create library/module build dirs for platform
1284 Makefile
= GenMake
.PlatformMakefile(self
)
1285 self
.LibraryBuildDirectoryList
= Makefile
.GetLibraryBuildDirectoryList()
1286 self
.ModuleBuildDirectoryList
= Makefile
.GetModuleBuildDirectoryList()
1288 self
.IsMakeFileCreated
= True
1290 ## Deal with Shared FixedAtBuild Pcds
1292 def CollectFixedAtBuildPcds(self
):
1293 for LibAuto
in self
.LibraryAutoGenList
:
1294 FixedAtBuildPcds
= {}
1295 ShareFixedAtBuildPcdsSameValue
= {}
1296 for Module
in LibAuto
._ReferenceModules
:
1297 for Pcd
in Module
.FixedAtBuildPcds
+ LibAuto
.FixedAtBuildPcds
:
1298 key
= ".".join((Pcd
.TokenSpaceGuidCName
,Pcd
.TokenCName
))
1299 if key
not in FixedAtBuildPcds
:
1300 ShareFixedAtBuildPcdsSameValue
[key
] = True
1301 FixedAtBuildPcds
[key
] = Pcd
.DefaultValue
1303 if FixedAtBuildPcds
[key
] != Pcd
.DefaultValue
:
1304 ShareFixedAtBuildPcdsSameValue
[key
] = False
1305 for Pcd
in LibAuto
.FixedAtBuildPcds
:
1306 key
= ".".join((Pcd
.TokenSpaceGuidCName
,Pcd
.TokenCName
))
1307 if (Pcd
.TokenCName
,Pcd
.TokenSpaceGuidCName
) not in self
.NonDynamicPcdDict
:
1310 DscPcd
= self
.NonDynamicPcdDict
[(Pcd
.TokenCName
,Pcd
.TokenSpaceGuidCName
)]
1311 if DscPcd
.Type
!= TAB_PCDS_FIXED_AT_BUILD
:
1313 if key
in ShareFixedAtBuildPcdsSameValue
and ShareFixedAtBuildPcdsSameValue
[key
]:
1314 LibAuto
.ConstPcd
[key
] = FixedAtBuildPcds
[key
]
1316 def CollectVariables(self
, DynamicPcdSet
):
1320 if self
.Workspace
.FdfFile
:
1321 FdDict
= self
.Workspace
.FdfProfile
.FdDict
[GlobalData
.gFdfParser
.CurrentFdName
]
1322 for FdRegion
in FdDict
.RegionList
:
1323 for item
in FdRegion
.RegionDataList
:
1324 if self
.Platform
.VpdToolGuid
.strip() and self
.Platform
.VpdToolGuid
in item
:
1325 VpdRegionSize
= FdRegion
.Size
1326 VpdRegionBase
= FdRegion
.Offset
1330 VariableInfo
= VariableMgr(self
.DscBuildDataObj
._GetDefaultStores
(),self
.DscBuildDataObj
._GetSkuIds
())
1331 VariableInfo
.SetVpdRegionMaxSize(VpdRegionSize
)
1332 VariableInfo
.SetVpdRegionOffset(VpdRegionBase
)
1334 for Pcd
in DynamicPcdSet
:
1335 pcdname
= ".".join((Pcd
.TokenSpaceGuidCName
,Pcd
.TokenCName
))
1336 for SkuName
in Pcd
.SkuInfoList
:
1337 Sku
= Pcd
.SkuInfoList
[SkuName
]
1339 if SkuId
is None or SkuId
== '':
1341 if len(Sku
.VariableName
) > 0:
1342 VariableGuidStructure
= Sku
.VariableGuidValue
1343 VariableGuid
= GuidStructureStringToGuidString(VariableGuidStructure
)
1344 for StorageName
in Sku
.DefaultStoreDict
:
1345 VariableInfo
.append_variable(var_info(Index
,pcdname
,StorageName
,SkuName
, StringToArray(Sku
.VariableName
),VariableGuid
, Sku
.VariableOffset
, Sku
.VariableAttribute
, Sku
.HiiDefaultValue
,Sku
.DefaultStoreDict
[StorageName
],Pcd
.DatumType
))
1349 def UpdateNVStoreMaxSize(self
,OrgVpdFile
):
1350 if self
.VariableInfo
:
1351 VpdMapFilePath
= os
.path
.join(self
.BuildDir
, TAB_FV_DIRECTORY
, "%s.map" % self
.Platform
.VpdToolGuid
)
1352 PcdNvStoreDfBuffer
= [item
for item
in self
._DynamicPcdList
if item
.TokenCName
== "PcdNvStoreDefaultValueBuffer" and item
.TokenSpaceGuidCName
== "gEfiMdeModulePkgTokenSpaceGuid"]
1354 if PcdNvStoreDfBuffer
:
1355 if os
.path
.exists(VpdMapFilePath
):
1356 OrgVpdFile
.Read(VpdMapFilePath
)
1357 PcdItems
= OrgVpdFile
.GetOffset(PcdNvStoreDfBuffer
[0])
1358 NvStoreOffset
= PcdItems
.values()[0].strip() if PcdItems
else '0'
1360 EdkLogger
.error("build", FILE_READ_FAILURE
, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath
)
1362 NvStoreOffset
= int(NvStoreOffset
,16) if NvStoreOffset
.upper().startswith("0X") else int(NvStoreOffset
)
1363 default_skuobj
= PcdNvStoreDfBuffer
[0].SkuInfoList
.get(TAB_DEFAULT
)
1364 maxsize
= self
.VariableInfo
.VpdRegionSize
- NvStoreOffset
if self
.VariableInfo
.VpdRegionSize
else len(default_skuobj
.DefaultValue
.split(","))
1365 var_data
= self
.VariableInfo
.PatchNVStoreDefaultMaxSize(maxsize
)
1367 if var_data
and default_skuobj
:
1368 default_skuobj
.DefaultValue
= var_data
1369 PcdNvStoreDfBuffer
[0].DefaultValue
= var_data
1370 PcdNvStoreDfBuffer
[0].SkuInfoList
.clear()
1371 PcdNvStoreDfBuffer
[0].SkuInfoList
[TAB_DEFAULT
] = default_skuobj
1372 PcdNvStoreDfBuffer
[0].MaxDatumSize
= str(len(default_skuobj
.DefaultValue
.split(",")))
1376 ## Collect dynamic PCDs
1378 # Gather dynamic PCDs list from each module and their settings from platform
1379 # This interface should be invoked explicitly when platform action is created.
1381 def CollectPlatformDynamicPcds(self
):
1383 for key
in self
.Platform
.Pcds
:
1384 for SinglePcd
in GlobalData
.MixedPcd
:
1385 if (self
.Platform
.Pcds
[key
].TokenCName
, self
.Platform
.Pcds
[key
].TokenSpaceGuidCName
) == SinglePcd
:
1386 for item
in GlobalData
.MixedPcd
[SinglePcd
]:
1387 Pcd_Type
= item
[0].split('_')[-1]
1388 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 \
1389 (Pcd_Type
== TAB_PCDS_DYNAMIC
and self
.Platform
.Pcds
[key
].Type
in PCD_DYNAMIC_TYPE_SET
):
1390 Value
= self
.Platform
.Pcds
[key
]
1391 Value
.TokenCName
= self
.Platform
.Pcds
[key
].TokenCName
+ '_' + Pcd_Type
1393 newkey
= (Value
.TokenCName
, key
[1])
1395 newkey
= (Value
.TokenCName
, key
[1], key
[2])
1396 del self
.Platform
.Pcds
[key
]
1397 self
.Platform
.Pcds
[newkey
] = Value
1405 # for gathering error information
1406 NoDatumTypePcdList
= set()
1408 for InfName
in self
._AsBuildInfList
:
1409 InfName
= mws
.join(self
.WorkspaceDir
, InfName
)
1410 FdfModuleList
.append(os
.path
.normpath(InfName
))
1411 for F
in self
.Platform
.Modules
.keys():
1412 M
= ModuleAutoGen(self
.Workspace
, F
, self
.BuildTarget
, self
.ToolChain
, self
.Arch
, self
.MetaFile
)
1413 #GuidValue.update(M.Guids)
1415 self
.Platform
.Modules
[F
].M
= M
1417 for PcdFromModule
in M
.ModulePcdList
+ M
.LibraryPcdList
:
1418 # make sure that the "VOID*" kind of datum has MaxDatumSize set
1419 if PcdFromModule
.DatumType
== TAB_VOID
and not PcdFromModule
.MaxDatumSize
:
1420 NoDatumTypePcdList
.add("%s.%s [%s]" % (PcdFromModule
.TokenSpaceGuidCName
, PcdFromModule
.TokenCName
, F
))
1422 # Check the PCD from Binary INF or Source INF
1423 if M
.IsBinaryModule
== True:
1424 PcdFromModule
.IsFromBinaryInf
= True
1426 # Check the PCD from DSC or not
1427 PcdFromModule
.IsFromDsc
= (PcdFromModule
.TokenCName
, PcdFromModule
.TokenSpaceGuidCName
) in self
.Platform
.Pcds
1429 if PcdFromModule
.Type
in PCD_DYNAMIC_TYPE_SET
or PcdFromModule
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
1430 if F
.Path
not in FdfModuleList
:
1431 # If one of the Source built modules listed in the DSC is not listed
1432 # in FDF modules, and the INF lists a PCD can only use the PcdsDynamic
1433 # access method (it is only listed in the DEC file that declares the
1434 # PCD as PcdsDynamic), then build tool will report warning message
1435 # notify the PI that they are attempting to build a module that must
1436 # be included in a flash image in order to be functional. These Dynamic
1437 # PCD will not be added into the Database unless it is used by other
1438 # modules that are included in the FDF file.
1439 if PcdFromModule
.Type
in PCD_DYNAMIC_TYPE_SET
and \
1440 PcdFromModule
.IsFromBinaryInf
== False:
1441 # Print warning message to let the developer make a determine.
1443 # If one of the Source built modules listed in the DSC is not listed in
1444 # FDF modules, and the INF lists a PCD can only use the PcdsDynamicEx
1445 # access method (it is only listed in the DEC file that declares the
1446 # PCD as PcdsDynamicEx), then DO NOT break the build; DO NOT add the
1447 # PCD to the Platform's PCD Database.
1448 if PcdFromModule
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
1451 # If a dynamic PCD used by a PEM module/PEI module & DXE module,
1452 # it should be stored in Pcd PEI database, If a dynamic only
1453 # used by DXE module, it should be stored in DXE PCD database.
1454 # The default Phase is DXE
1456 if M
.ModuleType
in SUP_MODULE_SET_PEI
:
1457 PcdFromModule
.Phase
= "PEI"
1458 if PcdFromModule
not in self
._DynaPcdList
_:
1459 self
._DynaPcdList
_.append(PcdFromModule
)
1460 elif PcdFromModule
.Phase
== 'PEI':
1461 # overwrite any the same PCD existing, if Phase is PEI
1462 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1463 self
._DynaPcdList
_[Index
] = PcdFromModule
1464 elif PcdFromModule
not in self
._NonDynaPcdList
_:
1465 self
._NonDynaPcdList
_.append(PcdFromModule
)
1466 elif PcdFromModule
in self
._NonDynaPcdList
_ and PcdFromModule
.IsFromBinaryInf
== True:
1467 Index
= self
._NonDynaPcdList
_.index(PcdFromModule
)
1468 if self
._NonDynaPcdList
_[Index
].IsFromBinaryInf
== False:
1469 #The PCD from Binary INF will override the same one from source INF
1470 self
._NonDynaPcdList
_.remove (self
._NonDynaPcdList
_[Index
])
1471 PcdFromModule
.Pending
= False
1472 self
._NonDynaPcdList
_.append (PcdFromModule
)
1473 DscModuleSet
= {os
.path
.normpath(ModuleInf
.Path
) for ModuleInf
in self
.Platform
.Modules
}
1474 # add the PCD from modules that listed in FDF but not in DSC to Database
1475 for InfName
in FdfModuleList
:
1476 if InfName
not in DscModuleSet
:
1477 InfClass
= PathClass(InfName
)
1478 M
= self
.BuildDatabase
[InfClass
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1479 # If a module INF in FDF but not in current arch's DSC module list, it must be module (either binary or source)
1480 # for different Arch. PCDs in source module for different Arch is already added before, so skip the source module here.
1481 # For binary module, if in current arch, we need to list the PCDs into database.
1482 if not M
.IsSupportedArch
:
1484 # Override the module PCD setting by platform setting
1485 ModulePcdList
= self
.ApplyPcdSetting(M
, M
.Pcds
)
1486 for PcdFromModule
in ModulePcdList
:
1487 PcdFromModule
.IsFromBinaryInf
= True
1488 PcdFromModule
.IsFromDsc
= False
1489 # Only allow the DynamicEx and Patchable PCD in AsBuild INF
1490 if PcdFromModule
.Type
not in PCD_DYNAMIC_EX_TYPE_SET
and PcdFromModule
.Type
not in TAB_PCDS_PATCHABLE_IN_MODULE
:
1491 EdkLogger
.error("build", AUTOGEN_ERROR
, "PCD setting error",
1493 ExtraData
="\n\tExisted %s PCD %s in:\n\t\t%s\n"
1494 % (PcdFromModule
.Type
, PcdFromModule
.TokenCName
, InfName
))
1495 # make sure that the "VOID*" kind of datum has MaxDatumSize set
1496 if PcdFromModule
.DatumType
== TAB_VOID
and not PcdFromModule
.MaxDatumSize
:
1497 NoDatumTypePcdList
.add("%s.%s [%s]" % (PcdFromModule
.TokenSpaceGuidCName
, PcdFromModule
.TokenCName
, InfName
))
1498 if M
.ModuleType
in SUP_MODULE_SET_PEI
:
1499 PcdFromModule
.Phase
= "PEI"
1500 if PcdFromModule
not in self
._DynaPcdList
_ and PcdFromModule
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
1501 self
._DynaPcdList
_.append(PcdFromModule
)
1502 elif PcdFromModule
not in self
._NonDynaPcdList
_ and PcdFromModule
.Type
in TAB_PCDS_PATCHABLE_IN_MODULE
:
1503 self
._NonDynaPcdList
_.append(PcdFromModule
)
1504 if PcdFromModule
in self
._DynaPcdList
_ and PcdFromModule
.Phase
== 'PEI' and PcdFromModule
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
1505 # Overwrite the phase of any the same PCD existing, if Phase is PEI.
1506 # It is to solve the case that a dynamic PCD used by a PEM module/PEI
1507 # module & DXE module at a same time.
1508 # Overwrite the type of the PCDs in source INF by the type of AsBuild
1509 # INF file as DynamicEx.
1510 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1511 self
._DynaPcdList
_[Index
].Phase
= PcdFromModule
.Phase
1512 self
._DynaPcdList
_[Index
].Type
= PcdFromModule
.Type
1513 for PcdFromModule
in self
._NonDynaPcdList
_:
1514 # If a PCD is not listed in the DSC file, but binary INF files used by
1515 # this platform all (that use this PCD) list the PCD in a [PatchPcds]
1516 # section, AND all source INF files used by this platform the build
1517 # that use the PCD list the PCD in either a [Pcds] or [PatchPcds]
1518 # section, then the tools must NOT add the PCD to the Platform's PCD
1519 # Database; the build must assign the access method for this PCD as
1520 # PcdsPatchableInModule.
1521 if PcdFromModule
not in self
._DynaPcdList
_:
1523 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1524 if PcdFromModule
.IsFromDsc
== False and \
1525 PcdFromModule
.Type
in TAB_PCDS_PATCHABLE_IN_MODULE
and \
1526 PcdFromModule
.IsFromBinaryInf
== True and \
1527 self
._DynaPcdList
_[Index
].IsFromBinaryInf
== False:
1528 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1529 self
._DynaPcdList
_.remove (self
._DynaPcdList
_[Index
])
1531 # print out error information and break the build, if error found
1532 if len(NoDatumTypePcdList
) > 0:
1533 NoDatumTypePcdListString
= "\n\t\t".join(NoDatumTypePcdList
)
1534 EdkLogger
.error("build", AUTOGEN_ERROR
, "PCD setting error",
1536 ExtraData
="\n\tPCD(s) without MaxDatumSize:\n\t\t%s\n"
1537 % NoDatumTypePcdListString
)
1538 self
._NonDynamicPcdList
= self
._NonDynaPcdList
_
1539 self
._DynamicPcdList
= self
._DynaPcdList
_
1541 # Sort dynamic PCD list to:
1542 # 1) If PCD's datum type is VOID* and value is unicode string which starts with L, the PCD item should
1543 # try to be put header of dynamicd List
1544 # 2) If PCD is HII type, the PCD item should be put after unicode type PCD
1546 # The reason of sorting is make sure the unicode string is in double-byte alignment in string table.
1548 UnicodePcdArray
= set()
1550 OtherPcdArray
= set()
1552 VpdFile
= VpdInfoFile
.VpdInfoFile()
1553 NeedProcessVpdMapFile
= False
1555 for pcd
in self
.Platform
.Pcds
:
1556 if pcd
not in self
._PlatformPcds
:
1557 self
._PlatformPcds
[pcd
] = self
.Platform
.Pcds
[pcd
]
1559 for item
in self
._PlatformPcds
:
1560 if self
._PlatformPcds
[item
].DatumType
and self
._PlatformPcds
[item
].DatumType
not in [TAB_UINT8
, TAB_UINT16
, TAB_UINT32
, TAB_UINT64
, TAB_VOID
, "BOOLEAN"]:
1561 self
._PlatformPcds
[item
].DatumType
= TAB_VOID
1563 if (self
.Workspace
.ArchList
[-1] == self
.Arch
):
1564 for Pcd
in self
._DynamicPcdList
:
1565 # just pick the a value to determine whether is unicode string type
1566 Sku
= Pcd
.SkuInfoList
.values()[0]
1567 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1569 if Pcd
.DatumType
not in [TAB_UINT8
, TAB_UINT16
, TAB_UINT32
, TAB_UINT64
, TAB_VOID
, "BOOLEAN"]:
1570 Pcd
.DatumType
= TAB_VOID
1572 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
1573 # if found HII type PCD then insert to right of UnicodeIndex
1574 if Pcd
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
]:
1575 VpdPcdDict
[(Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
)] = Pcd
1577 #Collect DynamicHii PCD values and assign it to DynamicExVpd PCD gEfiMdeModulePkgTokenSpaceGuid.PcdNvStoreDefaultValueBuffer
1578 PcdNvStoreDfBuffer
= VpdPcdDict
.get(("PcdNvStoreDefaultValueBuffer","gEfiMdeModulePkgTokenSpaceGuid"))
1579 if PcdNvStoreDfBuffer
:
1580 self
.VariableInfo
= self
.CollectVariables(self
._DynamicPcdList
)
1581 vardump
= self
.VariableInfo
.dump()
1583 PcdNvStoreDfBuffer
.DefaultValue
= vardump
1584 for skuname
in PcdNvStoreDfBuffer
.SkuInfoList
:
1585 PcdNvStoreDfBuffer
.SkuInfoList
[skuname
].DefaultValue
= vardump
1586 PcdNvStoreDfBuffer
.MaxDatumSize
= str(len(vardump
.split(",")))
1588 PlatformPcds
= self
._PlatformPcds
.keys()
1591 # Add VPD type PCD into VpdFile and determine whether the VPD PCD need to be fixed up.
1594 for PcdKey
in PlatformPcds
:
1595 Pcd
= self
._PlatformPcds
[PcdKey
]
1596 if Pcd
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
] and \
1597 PcdKey
in VpdPcdDict
:
1598 Pcd
= VpdPcdDict
[PcdKey
]
1600 DefaultSku
= Pcd
.SkuInfoList
.get(TAB_DEFAULT
)
1602 PcdValue
= DefaultSku
.DefaultValue
1603 if PcdValue
not in SkuValueMap
:
1604 SkuValueMap
[PcdValue
] = []
1605 VpdFile
.Add(Pcd
, TAB_DEFAULT
,DefaultSku
.VpdOffset
)
1606 SkuValueMap
[PcdValue
].append(DefaultSku
)
1608 for (SkuName
,Sku
) in Pcd
.SkuInfoList
.items():
1609 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1610 PcdValue
= Sku
.DefaultValue
1612 PcdValue
= Pcd
.DefaultValue
1613 if Sku
.VpdOffset
!= '*':
1614 if PcdValue
.startswith("{"):
1616 elif PcdValue
.startswith("L"):
1621 VpdOffset
= int(Sku
.VpdOffset
)
1624 VpdOffset
= int(Sku
.VpdOffset
, 16)
1626 EdkLogger
.error("build", FORMAT_INVALID
, "Invalid offset value %s for PCD %s.%s." % (Sku
.VpdOffset
, Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
1627 if VpdOffset
% Alignment
!= 0:
1628 if PcdValue
.startswith("{"):
1629 EdkLogger
.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
), File
=self
.MetaFile
)
1631 EdkLogger
.error("build", FORMAT_INVALID
, 'The offset value of PCD %s.%s should be %s-byte aligned.' % (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
, Alignment
))
1632 if PcdValue
not in SkuValueMap
:
1633 SkuValueMap
[PcdValue
] = []
1634 VpdFile
.Add(Pcd
, SkuName
,Sku
.VpdOffset
)
1635 SkuValueMap
[PcdValue
].append(Sku
)
1636 # if the offset of a VPD is *, then it need to be fixed up by third party tool.
1637 if not NeedProcessVpdMapFile
and Sku
.VpdOffset
== "*":
1638 NeedProcessVpdMapFile
= True
1639 if self
.Platform
.VpdToolGuid
is None or self
.Platform
.VpdToolGuid
== '':
1640 EdkLogger
.error("Build", FILE_NOT_FOUND
, \
1641 "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.")
1643 VpdSkuMap
[PcdKey
] = SkuValueMap
1645 # Fix the PCDs define in VPD PCD section that never referenced by module.
1646 # An example is PCD for signature usage.
1648 for DscPcd
in PlatformPcds
:
1649 DscPcdEntry
= self
._PlatformPcds
[DscPcd
]
1650 if DscPcdEntry
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
]:
1651 if not (self
.Platform
.VpdToolGuid
is None or self
.Platform
.VpdToolGuid
== ''):
1653 for VpdPcd
in VpdFile
._VpdArray
:
1654 # This PCD has been referenced by module
1655 if (VpdPcd
.TokenSpaceGuidCName
== DscPcdEntry
.TokenSpaceGuidCName
) and \
1656 (VpdPcd
.TokenCName
== DscPcdEntry
.TokenCName
):
1659 # Not found, it should be signature
1661 # just pick the a value to determine whether is unicode string type
1663 SkuObjList
= DscPcdEntry
.SkuInfoList
.items()
1664 DefaultSku
= DscPcdEntry
.SkuInfoList
.get(TAB_DEFAULT
)
1666 defaultindex
= SkuObjList
.index((TAB_DEFAULT
,DefaultSku
))
1667 SkuObjList
[0],SkuObjList
[defaultindex
] = SkuObjList
[defaultindex
],SkuObjList
[0]
1668 for (SkuName
,Sku
) in SkuObjList
:
1669 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1671 # Need to iterate DEC pcd information to get the value & datumtype
1672 for eachDec
in self
.PackageList
:
1673 for DecPcd
in eachDec
.Pcds
:
1674 DecPcdEntry
= eachDec
.Pcds
[DecPcd
]
1675 if (DecPcdEntry
.TokenSpaceGuidCName
== DscPcdEntry
.TokenSpaceGuidCName
) and \
1676 (DecPcdEntry
.TokenCName
== DscPcdEntry
.TokenCName
):
1677 # Print warning message to let the developer make a determine.
1678 EdkLogger
.warn("build", "Unreferenced vpd pcd used!",
1679 File
=self
.MetaFile
, \
1680 ExtraData
= "PCD: %s.%s used in the DSC file %s is unreferenced." \
1681 %(DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
, self
.Platform
.MetaFile
.Path
))
1683 DscPcdEntry
.DatumType
= DecPcdEntry
.DatumType
1684 DscPcdEntry
.DefaultValue
= DecPcdEntry
.DefaultValue
1685 DscPcdEntry
.TokenValue
= DecPcdEntry
.TokenValue
1686 DscPcdEntry
.TokenSpaceGuidValue
= eachDec
.Guids
[DecPcdEntry
.TokenSpaceGuidCName
]
1687 # Only fix the value while no value provided in DSC file.
1688 if not Sku
.DefaultValue
:
1689 DscPcdEntry
.SkuInfoList
[DscPcdEntry
.SkuInfoList
.keys()[0]].DefaultValue
= DecPcdEntry
.DefaultValue
1691 if DscPcdEntry
not in self
._DynamicPcdList
:
1692 self
._DynamicPcdList
.append(DscPcdEntry
)
1693 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1694 PcdValue
= Sku
.DefaultValue
1696 PcdValue
= DscPcdEntry
.DefaultValue
1697 if Sku
.VpdOffset
!= '*':
1698 if PcdValue
.startswith("{"):
1700 elif PcdValue
.startswith("L"):
1705 VpdOffset
= int(Sku
.VpdOffset
)
1708 VpdOffset
= int(Sku
.VpdOffset
, 16)
1710 EdkLogger
.error("build", FORMAT_INVALID
, "Invalid offset value %s for PCD %s.%s." % (Sku
.VpdOffset
, DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
))
1711 if VpdOffset
% Alignment
!= 0:
1712 if PcdValue
.startswith("{"):
1713 EdkLogger
.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
), File
=self
.MetaFile
)
1715 EdkLogger
.error("build", FORMAT_INVALID
, 'The offset value of PCD %s.%s should be %s-byte aligned.' % (DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
, Alignment
))
1716 if PcdValue
not in SkuValueMap
:
1717 SkuValueMap
[PcdValue
] = []
1718 VpdFile
.Add(DscPcdEntry
, SkuName
,Sku
.VpdOffset
)
1719 SkuValueMap
[PcdValue
].append(Sku
)
1720 if not NeedProcessVpdMapFile
and Sku
.VpdOffset
== "*":
1721 NeedProcessVpdMapFile
= True
1722 if DscPcdEntry
.DatumType
== TAB_VOID
and PcdValue
.startswith("L"):
1723 UnicodePcdArray
.add(DscPcdEntry
)
1724 elif len(Sku
.VariableName
) > 0:
1725 HiiPcdArray
.add(DscPcdEntry
)
1727 OtherPcdArray
.add(DscPcdEntry
)
1729 # if the offset of a VPD is *, then it need to be fixed up by third party tool.
1730 VpdSkuMap
[DscPcd
] = SkuValueMap
1731 if (self
.Platform
.FlashDefinition
is None or self
.Platform
.FlashDefinition
== '') and \
1732 VpdFile
.GetCount() != 0:
1733 EdkLogger
.error("build", ATTRIBUTE_NOT_AVAILABLE
,
1734 "Fail to get FLASH_DEFINITION definition in DSC file %s which is required when DSC contains VPD PCD." % str(self
.Platform
.MetaFile
))
1736 if VpdFile
.GetCount() != 0:
1738 self
.FixVpdOffset(VpdFile
)
1740 self
.FixVpdOffset(self
.UpdateNVStoreMaxSize(VpdFile
))
1742 # Process VPD map file generated by third party BPDG tool
1743 if NeedProcessVpdMapFile
:
1744 VpdMapFilePath
= os
.path
.join(self
.BuildDir
, TAB_FV_DIRECTORY
, "%s.map" % self
.Platform
.VpdToolGuid
)
1745 if os
.path
.exists(VpdMapFilePath
):
1746 VpdFile
.Read(VpdMapFilePath
)
1749 for pcd
in VpdSkuMap
:
1750 vpdinfo
= VpdFile
.GetVpdInfo(pcd
)
1752 # just pick the a value to determine whether is unicode string type
1754 for pcdvalue
in VpdSkuMap
[pcd
]:
1755 for sku
in VpdSkuMap
[pcd
][pcdvalue
]:
1756 for item
in vpdinfo
:
1757 if item
[2] == pcdvalue
:
1758 sku
.VpdOffset
= item
[1]
1760 EdkLogger
.error("build", FILE_READ_FAILURE
, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath
)
1762 # Delete the DynamicPcdList At the last time enter into this function
1763 for Pcd
in self
._DynamicPcdList
:
1764 # just pick the a value to determine whether is unicode string type
1765 Sku
= Pcd
.SkuInfoList
.values()[0]
1766 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1768 if Pcd
.DatumType
not in [TAB_UINT8
, TAB_UINT16
, TAB_UINT32
, TAB_UINT64
, TAB_VOID
, "BOOLEAN"]:
1769 Pcd
.DatumType
= TAB_VOID
1771 PcdValue
= Sku
.DefaultValue
1772 if Pcd
.DatumType
== TAB_VOID
and PcdValue
.startswith("L"):
1773 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
1774 UnicodePcdArray
.add(Pcd
)
1775 elif len(Sku
.VariableName
) > 0:
1776 # if found HII type PCD then insert to right of UnicodeIndex
1777 HiiPcdArray
.add(Pcd
)
1779 OtherPcdArray
.add(Pcd
)
1780 del self
._DynamicPcdList
[:]
1781 self
._DynamicPcdList
.extend(list(UnicodePcdArray
))
1782 self
._DynamicPcdList
.extend(list(HiiPcdArray
))
1783 self
._DynamicPcdList
.extend(list(OtherPcdArray
))
1784 allskuset
= [(SkuName
,Sku
.SkuId
) for pcd
in self
._DynamicPcdList
for (SkuName
,Sku
) in pcd
.SkuInfoList
.items()]
1785 for pcd
in self
._DynamicPcdList
:
1786 if len(pcd
.SkuInfoList
) == 1:
1787 for (SkuName
,SkuId
) in allskuset
:
1788 if type(SkuId
) in (str,unicode) and eval(SkuId
) == 0 or SkuId
== 0:
1790 pcd
.SkuInfoList
[SkuName
] = copy
.deepcopy(pcd
.SkuInfoList
[TAB_DEFAULT
])
1791 pcd
.SkuInfoList
[SkuName
].SkuId
= SkuId
1792 self
.AllPcdList
= self
._NonDynamicPcdList
+ self
._DynamicPcdList
1794 def FixVpdOffset(self
,VpdFile
):
1795 FvPath
= os
.path
.join(self
.BuildDir
, TAB_FV_DIRECTORY
)
1796 if not os
.path
.exists(FvPath
):
1800 EdkLogger
.error("build", FILE_WRITE_FAILURE
, "Fail to create FV folder under %s" % self
.BuildDir
)
1802 VpdFilePath
= os
.path
.join(FvPath
, "%s.txt" % self
.Platform
.VpdToolGuid
)
1804 if VpdFile
.Write(VpdFilePath
):
1805 # retrieve BPDG tool's path from tool_def.txt according to VPD_TOOL_GUID defined in DSC file.
1807 for ToolDef
in self
.ToolDefinition
.values():
1808 if ToolDef
.has_key(TAB_GUID
) and ToolDef
[TAB_GUID
] == self
.Platform
.VpdToolGuid
:
1809 if not ToolDef
.has_key("PATH"):
1810 EdkLogger
.error("build", ATTRIBUTE_NOT_AVAILABLE
, "PATH attribute was not provided for BPDG guid tool %s in tools_def.txt" % self
.Platform
.VpdToolGuid
)
1811 BPDGToolName
= ToolDef
["PATH"]
1813 # Call third party GUID BPDG tool.
1814 if BPDGToolName
is not None:
1815 VpdInfoFile
.CallExtenalBPDGTool(BPDGToolName
, VpdFilePath
)
1817 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.")
1819 ## Return the platform build data object
1820 def _GetPlatform(self
):
1821 if self
._Platform
is None:
1822 self
._Platform
= self
.BuildDatabase
[self
.MetaFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1823 return self
._Platform
1825 ## Return platform name
1827 return self
.Platform
.PlatformName
1829 ## Return the meta file GUID
1831 return self
.Platform
.Guid
1833 ## Return the platform version
1834 def _GetVersion(self
):
1835 return self
.Platform
.Version
1837 ## Return the FDF file name
1838 def _GetFdfFile(self
):
1839 if self
._FdfFile
is None:
1840 if self
.Workspace
.FdfFile
!= "":
1841 self
._FdfFile
= mws
.join(self
.WorkspaceDir
, self
.Workspace
.FdfFile
)
1844 return self
._FdfFile
1846 ## Return the build output directory platform specifies
1847 def _GetOutputDir(self
):
1848 return self
.Platform
.OutputDirectory
1850 ## Return the directory to store all intermediate and final files built
1851 def _GetBuildDir(self
):
1852 if self
._BuildDir
is None:
1853 if os
.path
.isabs(self
.OutputDir
):
1854 self
._BuildDir
= path
.join(
1855 path
.abspath(self
.OutputDir
),
1856 self
.BuildTarget
+ "_" + self
.ToolChain
,
1859 self
._BuildDir
= path
.join(
1862 self
.BuildTarget
+ "_" + self
.ToolChain
,
1864 GlobalData
.gBuildDirectory
= self
._BuildDir
1865 return self
._BuildDir
1867 ## Return directory of platform makefile
1869 # @retval string Makefile directory
1871 def _GetMakeFileDir(self
):
1872 if self
._MakeFileDir
is None:
1873 self
._MakeFileDir
= path
.join(self
.BuildDir
, self
.Arch
)
1874 return self
._MakeFileDir
1876 ## Return build command string
1878 # @retval string Build command string
1880 def _GetBuildCommand(self
):
1881 if self
._BuildCommand
is None:
1882 self
._BuildCommand
= []
1883 if "MAKE" in self
.ToolDefinition
and "PATH" in self
.ToolDefinition
["MAKE"]:
1884 self
._BuildCommand
+= SplitOption(self
.ToolDefinition
["MAKE"]["PATH"])
1885 if "FLAGS" in self
.ToolDefinition
["MAKE"]:
1886 NewOption
= self
.ToolDefinition
["MAKE"]["FLAGS"].strip()
1888 self
._BuildCommand
+= SplitOption(NewOption
)
1889 if "MAKE" in self
.EdkIIBuildOption
:
1890 if "FLAGS" in self
.EdkIIBuildOption
["MAKE"]:
1891 Flags
= self
.EdkIIBuildOption
["MAKE"]["FLAGS"]
1892 if Flags
.startswith('='):
1893 self
._BuildCommand
= [self
._BuildCommand
[0]] + [Flags
[1:]]
1895 self
._BuildCommand
+= [Flags
]
1896 return self
._BuildCommand
1898 ## Get tool chain definition
1900 # Get each tool defition for given tool chain from tools_def.txt and platform
1902 def _GetToolDefinition(self
):
1903 if self
._ToolDefinitions
is None:
1904 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDictionary
1905 if TAB_TOD_DEFINES_COMMAND_TYPE
not in self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
:
1906 EdkLogger
.error('build', RESOURCE_NOT_AVAILABLE
, "No tools found in configuration",
1907 ExtraData
="[%s]" % self
.MetaFile
)
1908 self
._ToolDefinitions
= {}
1910 for Def
in ToolDefinition
:
1911 Target
, Tag
, Arch
, Tool
, Attr
= Def
.split("_")
1912 if Target
!= self
.BuildTarget
or Tag
!= self
.ToolChain
or Arch
!= self
.Arch
:
1915 Value
= ToolDefinition
[Def
]
1916 # don't record the DLL
1918 DllPathList
.add(Value
)
1921 if Tool
not in self
._ToolDefinitions
:
1922 self
._ToolDefinitions
[Tool
] = {}
1923 self
._ToolDefinitions
[Tool
][Attr
] = Value
1926 if GlobalData
.gOptions
.SilentMode
and "MAKE" in self
._ToolDefinitions
:
1927 if "FLAGS" not in self
._ToolDefinitions
["MAKE"]:
1928 self
._ToolDefinitions
["MAKE"]["FLAGS"] = ""
1929 self
._ToolDefinitions
["MAKE"]["FLAGS"] += " -s"
1931 for Tool
in self
._ToolDefinitions
:
1932 for Attr
in self
._ToolDefinitions
[Tool
]:
1933 Value
= self
._ToolDefinitions
[Tool
][Attr
]
1934 if Tool
in self
.BuildOption
and Attr
in self
.BuildOption
[Tool
]:
1935 # check if override is indicated
1936 if self
.BuildOption
[Tool
][Attr
].startswith('='):
1937 Value
= self
.BuildOption
[Tool
][Attr
][1:]
1940 Value
+= " " + self
.BuildOption
[Tool
][Attr
]
1942 Value
= self
.BuildOption
[Tool
][Attr
]
1945 # Don't put MAKE definition in the file
1947 ToolsDef
+= "%s = %s\n" % (Tool
, Value
)
1949 # Don't put MAKE definition in the file
1954 ToolsDef
+= "%s_%s = %s\n" % (Tool
, Attr
, Value
)
1957 SaveFileOnChange(self
.ToolDefinitionFile
, ToolsDef
)
1958 for DllPath
in DllPathList
:
1959 os
.environ
["PATH"] = DllPath
+ os
.pathsep
+ os
.environ
["PATH"]
1960 os
.environ
["MAKE_FLAGS"] = MakeFlags
1962 return self
._ToolDefinitions
1964 ## Return the paths of tools
1965 def _GetToolDefFile(self
):
1966 if self
._ToolDefFile
is None:
1967 self
._ToolDefFile
= os
.path
.join(self
.MakeFileDir
, "TOOLS_DEF." + self
.Arch
)
1968 return self
._ToolDefFile
1970 ## Retrieve the toolchain family of given toolchain tag. Default to 'MSFT'.
1971 def _GetToolChainFamily(self
):
1972 if self
._ToolChainFamily
is None:
1973 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
1974 if TAB_TOD_DEFINES_FAMILY
not in ToolDefinition \
1975 or self
.ToolChain
not in ToolDefinition
[TAB_TOD_DEFINES_FAMILY
] \
1976 or not ToolDefinition
[TAB_TOD_DEFINES_FAMILY
][self
.ToolChain
]:
1977 EdkLogger
.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
1979 self
._ToolChainFamily
= "MSFT"
1981 self
._ToolChainFamily
= ToolDefinition
[TAB_TOD_DEFINES_FAMILY
][self
.ToolChain
]
1982 return self
._ToolChainFamily
1984 def _GetBuildRuleFamily(self
):
1985 if self
._BuildRuleFamily
is None:
1986 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
1987 if TAB_TOD_DEFINES_BUILDRULEFAMILY
not in ToolDefinition \
1988 or self
.ToolChain
not in ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
] \
1989 or not ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
][self
.ToolChain
]:
1990 EdkLogger
.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
1992 self
._BuildRuleFamily
= "MSFT"
1994 self
._BuildRuleFamily
= ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
][self
.ToolChain
]
1995 return self
._BuildRuleFamily
1997 ## Return the build options specific for all modules in this platform
1998 def _GetBuildOptions(self
):
1999 if self
._BuildOption
is None:
2000 self
._BuildOption
= self
._ExpandBuildOption
(self
.Platform
.BuildOptions
)
2001 return self
._BuildOption
2003 ## Return the build options specific for EDK modules in this platform
2004 def _GetEdkBuildOptions(self
):
2005 if self
._EdkBuildOption
is None:
2006 self
._EdkBuildOption
= self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, EDK_NAME
)
2007 return self
._EdkBuildOption
2009 ## Return the build options specific for EDKII modules in this platform
2010 def _GetEdkIIBuildOptions(self
):
2011 if self
._EdkIIBuildOption
is None:
2012 self
._EdkIIBuildOption
= self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, EDKII_NAME
)
2013 return self
._EdkIIBuildOption
2015 ## Parse build_rule.txt in Conf Directory.
2017 # @retval BuildRule object
2019 def _GetBuildRule(self
):
2020 if self
._BuildRule
is None:
2021 BuildRuleFile
= None
2022 if TAB_TAT_DEFINES_BUILD_RULE_CONF
in self
.Workspace
.TargetTxt
.TargetTxtDictionary
:
2023 BuildRuleFile
= self
.Workspace
.TargetTxt
.TargetTxtDictionary
[TAB_TAT_DEFINES_BUILD_RULE_CONF
]
2024 if not BuildRuleFile
:
2025 BuildRuleFile
= gDefaultBuildRuleFile
2026 self
._BuildRule
= BuildRule(BuildRuleFile
)
2027 if self
._BuildRule
._FileVersion
== "":
2028 self
._BuildRule
._FileVersion
= AutoGenReqBuildRuleVerNum
2030 if self
._BuildRule
._FileVersion
< AutoGenReqBuildRuleVerNum
:
2031 # If Build Rule's version is less than the version number required by the tools, halting the build.
2032 EdkLogger
.error("build", AUTOGEN_ERROR
,
2033 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])"\
2034 % (self
._BuildRule
._FileVersion
, AutoGenReqBuildRuleVerNum
))
2036 return self
._BuildRule
2038 ## Summarize the packages used by modules in this platform
2039 def _GetPackageList(self
):
2040 if self
._PackageList
is None:
2041 self
._PackageList
= set()
2042 for La
in self
.LibraryAutoGenList
:
2043 self
._PackageList
.update(La
.DependentPackageList
)
2044 for Ma
in self
.ModuleAutoGenList
:
2045 self
._PackageList
.update(Ma
.DependentPackageList
)
2046 #Collect package set information from INF of FDF
2048 for ModuleFile
in self
._AsBuildModuleList
:
2049 if ModuleFile
in self
.Platform
.Modules
:
2051 ModuleData
= self
.BuildDatabase
[ModuleFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
2052 PkgSet
.update(ModuleData
.Packages
)
2053 self
._PackageList
= list(self
._PackageList
) + list (PkgSet
)
2054 return self
._PackageList
2056 def _GetNonDynamicPcdDict(self
):
2057 if self
._NonDynamicPcdDict
:
2058 return self
._NonDynamicPcdDict
2059 for Pcd
in self
.NonDynamicPcdList
:
2060 self
._NonDynamicPcdDict
[(Pcd
.TokenCName
,Pcd
.TokenSpaceGuidCName
)] = Pcd
2061 return self
._NonDynamicPcdDict
2063 ## Get list of non-dynamic PCDs
2064 def _GetNonDynamicPcdList(self
):
2065 if self
._NonDynamicPcdList
is None:
2066 self
.CollectPlatformDynamicPcds()
2067 return self
._NonDynamicPcdList
2069 ## Get list of dynamic PCDs
2070 def _GetDynamicPcdList(self
):
2071 if self
._DynamicPcdList
is None:
2072 self
.CollectPlatformDynamicPcds()
2073 return self
._DynamicPcdList
2075 ## Generate Token Number for all PCD
2076 def _GetPcdTokenNumbers(self
):
2077 if self
._PcdTokenNumber
is None:
2078 self
._PcdTokenNumber
= OrderedDict()
2081 # Make the Dynamic and DynamicEx PCD use within different TokenNumber area.
2085 # TokenNumber 0 ~ 10
2087 # TokeNumber 11 ~ 20
2089 for Pcd
in self
.DynamicPcdList
:
2090 if Pcd
.Phase
== "PEI":
2091 if Pcd
.Type
in PCD_DYNAMIC_TYPE_SET
:
2092 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
2093 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2096 for Pcd
in self
.DynamicPcdList
:
2097 if Pcd
.Phase
== "PEI":
2098 if Pcd
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
2099 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
2100 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2103 for Pcd
in self
.DynamicPcdList
:
2104 if Pcd
.Phase
== "DXE":
2105 if Pcd
.Type
in PCD_DYNAMIC_TYPE_SET
:
2106 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
2107 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2110 for Pcd
in self
.DynamicPcdList
:
2111 if Pcd
.Phase
== "DXE":
2112 if Pcd
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
2113 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
2114 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2117 for Pcd
in self
.NonDynamicPcdList
:
2118 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2120 return self
._PcdTokenNumber
2122 ## Summarize ModuleAutoGen objects of all modules/libraries to be built for this platform
2123 def _GetAutoGenObjectList(self
):
2124 self
._ModuleAutoGenList
= []
2125 self
._LibraryAutoGenList
= []
2126 for ModuleFile
in self
.Platform
.Modules
:
2135 if Ma
not in self
._ModuleAutoGenList
:
2136 self
._ModuleAutoGenList
.append(Ma
)
2137 for La
in Ma
.LibraryAutoGenList
:
2138 if La
not in self
._LibraryAutoGenList
:
2139 self
._LibraryAutoGenList
.append(La
)
2140 if Ma
not in La
._ReferenceModules
:
2141 La
._ReferenceModules
.append(Ma
)
2143 ## Summarize ModuleAutoGen objects of all modules to be built for this platform
2144 def _GetModuleAutoGenList(self
):
2145 if self
._ModuleAutoGenList
is None:
2146 self
._GetAutoGenObjectList
()
2147 return self
._ModuleAutoGenList
2149 ## Summarize ModuleAutoGen objects of all libraries to be built for this platform
2150 def _GetLibraryAutoGenList(self
):
2151 if self
._LibraryAutoGenList
is None:
2152 self
._GetAutoGenObjectList
()
2153 return self
._LibraryAutoGenList
2155 ## Test if a module is supported by the platform
2157 # An error will be raised directly if the module or its arch is not supported
2158 # by the platform or current configuration
2160 def ValidModule(self
, Module
):
2161 return Module
in self
.Platform
.Modules
or Module
in self
.Platform
.LibraryInstances \
2162 or Module
in self
._AsBuildModuleList
2164 ## Resolve the library classes in a module to library instances
2166 # This method will not only resolve library classes but also sort the library
2167 # instances according to the dependency-ship.
2169 # @param Module The module from which the library classes will be resolved
2171 # @retval library_list List of library instances sorted
2173 def ApplyLibraryInstance(self
, Module
):
2174 # Cover the case that the binary INF file is list in the FDF file but not DSC file, return empty list directly
2175 if str(Module
) not in self
.Platform
.Modules
:
2178 return GetModuleLibInstances(Module
,
2187 ## Override PCD setting (type, value, ...)
2189 # @param ToPcd The PCD to be overrided
2190 # @param FromPcd The PCD overrideing from
2192 def _OverridePcd(self
, ToPcd
, FromPcd
, Module
="", Msg
="", Library
=""):
2194 # in case there's PCDs coming from FDF file, which have no type given.
2195 # at this point, ToPcd.Type has the type found from dependent
2198 TokenCName
= ToPcd
.TokenCName
2199 for PcdItem
in GlobalData
.MixedPcd
:
2200 if (ToPcd
.TokenCName
, ToPcd
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
2201 TokenCName
= PcdItem
[0]
2203 if FromPcd
is not None:
2204 if ToPcd
.Pending
and FromPcd
.Type
:
2205 ToPcd
.Type
= FromPcd
.Type
2206 elif (ToPcd
.Type
) and (FromPcd
.Type
)\
2207 and (ToPcd
.Type
!= FromPcd
.Type
) and (ToPcd
.Type
in FromPcd
.Type
):
2208 if ToPcd
.Type
.strip() == TAB_PCDS_DYNAMIC_EX
:
2209 ToPcd
.Type
= FromPcd
.Type
2210 elif ToPcd
.Type
and FromPcd
.Type \
2211 and ToPcd
.Type
!= FromPcd
.Type
:
2213 Module
= str(Module
) + " 's library file (" + str(Library
) + ")"
2214 EdkLogger
.error("build", OPTION_CONFLICT
, "Mismatched PCD type",
2215 ExtraData
="%s.%s is used as [%s] in module %s, but as [%s] in %s."\
2216 % (ToPcd
.TokenSpaceGuidCName
, TokenCName
,
2217 ToPcd
.Type
, Module
, FromPcd
.Type
, Msg
),
2220 if FromPcd
.MaxDatumSize
:
2221 ToPcd
.MaxDatumSize
= FromPcd
.MaxDatumSize
2222 ToPcd
.MaxSizeUserSet
= FromPcd
.MaxDatumSize
2223 if FromPcd
.DefaultValue
:
2224 ToPcd
.DefaultValue
= FromPcd
.DefaultValue
2225 if FromPcd
.TokenValue
:
2226 ToPcd
.TokenValue
= FromPcd
.TokenValue
2227 if FromPcd
.DatumType
:
2228 ToPcd
.DatumType
= FromPcd
.DatumType
2229 if FromPcd
.SkuInfoList
:
2230 ToPcd
.SkuInfoList
= FromPcd
.SkuInfoList
2231 # Add Flexible PCD format parse
2232 if ToPcd
.DefaultValue
:
2234 ToPcd
.DefaultValue
= ValueExpressionEx(ToPcd
.DefaultValue
, ToPcd
.DatumType
, self
._GuidDict
)(True)
2235 except BadExpression
, Value
:
2236 EdkLogger
.error('Parser', FORMAT_INVALID
, 'PCD [%s.%s] Value "%s", %s' %(ToPcd
.TokenSpaceGuidCName
, ToPcd
.TokenCName
, ToPcd
.DefaultValue
, Value
),
2239 # check the validation of datum
2240 IsValid
, Cause
= CheckPcdDatum(ToPcd
.DatumType
, ToPcd
.DefaultValue
)
2242 EdkLogger
.error('build', FORMAT_INVALID
, Cause
, File
=self
.MetaFile
,
2243 ExtraData
="%s.%s" % (ToPcd
.TokenSpaceGuidCName
, TokenCName
))
2244 ToPcd
.validateranges
= FromPcd
.validateranges
2245 ToPcd
.validlists
= FromPcd
.validlists
2246 ToPcd
.expressions
= FromPcd
.expressions
2248 if FromPcd
is not None and ToPcd
.DatumType
== TAB_VOID
and not ToPcd
.MaxDatumSize
:
2249 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "No MaxDatumSize specified for PCD %s.%s" \
2250 % (ToPcd
.TokenSpaceGuidCName
, TokenCName
))
2251 Value
= ToPcd
.DefaultValue
2253 ToPcd
.MaxDatumSize
= '1'
2254 elif Value
[0] == 'L':
2255 ToPcd
.MaxDatumSize
= str((len(Value
) - 2) * 2)
2256 elif Value
[0] == '{':
2257 ToPcd
.MaxDatumSize
= str(len(Value
.split(',')))
2259 ToPcd
.MaxDatumSize
= str(len(Value
) - 1)
2261 # apply default SKU for dynamic PCDS if specified one is not available
2262 if (ToPcd
.Type
in PCD_DYNAMIC_TYPE_SET
or ToPcd
.Type
in PCD_DYNAMIC_EX_TYPE_SET
) \
2263 and not ToPcd
.SkuInfoList
:
2264 if self
.Platform
.SkuName
in self
.Platform
.SkuIds
:
2265 SkuName
= self
.Platform
.SkuName
2267 SkuName
= TAB_DEFAULT
2268 ToPcd
.SkuInfoList
= {
2269 SkuName
: SkuInfoClass(SkuName
, self
.Platform
.SkuIds
[SkuName
][0], '', '', '', '', '', ToPcd
.DefaultValue
)
2272 ## Apply PCD setting defined platform to a module
2274 # @param Module The module from which the PCD setting will be overrided
2276 # @retval PCD_list The list PCDs with settings from platform
2278 def ApplyPcdSetting(self
, Module
, Pcds
, Library
=""):
2279 # for each PCD in module
2280 for Name
, Guid
in Pcds
:
2281 PcdInModule
= Pcds
[Name
, Guid
]
2282 # find out the PCD setting in platform
2283 if (Name
, Guid
) in self
.Platform
.Pcds
:
2284 PcdInPlatform
= self
.Platform
.Pcds
[Name
, Guid
]
2286 PcdInPlatform
= None
2287 # then override the settings if any
2288 self
._OverridePcd
(PcdInModule
, PcdInPlatform
, Module
, Msg
="DSC PCD sections", Library
=Library
)
2289 # resolve the VariableGuid value
2290 for SkuId
in PcdInModule
.SkuInfoList
:
2291 Sku
= PcdInModule
.SkuInfoList
[SkuId
]
2292 if Sku
.VariableGuid
== '': continue
2293 Sku
.VariableGuidValue
= GuidValue(Sku
.VariableGuid
, self
.PackageList
, self
.MetaFile
.Path
)
2294 if Sku
.VariableGuidValue
is None:
2295 PackageList
= "\n\t".join(str(P
) for P
in self
.PackageList
)
2298 RESOURCE_NOT_AVAILABLE
,
2299 "Value of GUID [%s] is not found in" % Sku
.VariableGuid
,
2300 ExtraData
=PackageList
+ "\n\t(used with %s.%s from module %s)" \
2301 % (Guid
, Name
, str(Module
)),
2305 # override PCD settings with module specific setting
2306 if Module
in self
.Platform
.Modules
:
2307 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
2308 for Key
in PlatformModule
.Pcds
:
2313 elif Key
in GlobalData
.MixedPcd
:
2314 for PcdItem
in GlobalData
.MixedPcd
[Key
]:
2316 ToPcd
= Pcds
[PcdItem
]
2320 self
._OverridePcd
(ToPcd
, PlatformModule
.Pcds
[Key
], Module
, Msg
="DSC Components Module scoped PCD section", Library
=Library
)
2321 # use PCD value to calculate the MaxDatumSize when it is not specified
2322 for Name
, Guid
in Pcds
:
2323 Pcd
= Pcds
[Name
, Guid
]
2324 if Pcd
.DatumType
== TAB_VOID
and not Pcd
.MaxDatumSize
:
2325 Pcd
.MaxSizeUserSet
= None
2326 Value
= Pcd
.DefaultValue
2328 Pcd
.MaxDatumSize
= '1'
2329 elif Value
[0] == 'L':
2330 Pcd
.MaxDatumSize
= str((len(Value
) - 2) * 2)
2331 elif Value
[0] == '{':
2332 Pcd
.MaxDatumSize
= str(len(Value
.split(',')))
2334 Pcd
.MaxDatumSize
= str(len(Value
) - 1)
2335 return Pcds
.values()
2337 ## Resolve library names to library modules
2339 # (for Edk.x modules)
2341 # @param Module The module from which the library names will be resolved
2343 # @retval library_list The list of library modules
2345 def ResolveLibraryReference(self
, Module
):
2346 EdkLogger
.verbose("")
2347 EdkLogger
.verbose("Library instances of module [%s] [%s]:" % (str(Module
), self
.Arch
))
2348 LibraryConsumerList
= [Module
]
2350 # "CompilerStub" is a must for Edk modules
2351 if Module
.Libraries
:
2352 Module
.Libraries
.append("CompilerStub")
2354 while len(LibraryConsumerList
) > 0:
2355 M
= LibraryConsumerList
.pop()
2356 for LibraryName
in M
.Libraries
:
2357 Library
= self
.Platform
.LibraryClasses
[LibraryName
, ':dummy:']
2359 for Key
in self
.Platform
.LibraryClasses
.data
:
2360 if LibraryName
.upper() == Key
.upper():
2361 Library
= self
.Platform
.LibraryClasses
[Key
, ':dummy:']
2364 EdkLogger
.warn("build", "Library [%s] is not found" % LibraryName
, File
=str(M
),
2365 ExtraData
="\t%s [%s]" % (str(Module
), self
.Arch
))
2368 if Library
not in LibraryList
:
2369 LibraryList
.append(Library
)
2370 LibraryConsumerList
.append(Library
)
2371 EdkLogger
.verbose("\t" + LibraryName
+ " : " + str(Library
) + ' ' + str(type(Library
)))
2374 ## Calculate the priority value of the build option
2376 # @param Key Build option definition contain: TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
2378 # @retval Value Priority value based on the priority list.
2380 def CalculatePriorityValue(self
, Key
):
2381 Target
, ToolChain
, Arch
, CommandType
, Attr
= Key
.split('_')
2382 PriorityValue
= 0x11111
2384 PriorityValue
&= 0x01111
2385 if ToolChain
== "*":
2386 PriorityValue
&= 0x10111
2388 PriorityValue
&= 0x11011
2389 if CommandType
== "*":
2390 PriorityValue
&= 0x11101
2392 PriorityValue
&= 0x11110
2394 return self
.PrioList
["0x%0.5x" % PriorityValue
]
2397 ## Expand * in build option key
2399 # @param Options Options to be expanded
2401 # @retval options Options expanded
2403 def _ExpandBuildOption(self
, Options
, ModuleStyle
=None):
2410 # Construct a list contain the build options which need override.
2414 # Key[0] -- tool family
2415 # Key[1] -- TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
2417 if (Key
[0] == self
.BuildRuleFamily
and
2418 (ModuleStyle
is None or len(Key
) < 3 or (len(Key
) > 2 and Key
[2] == ModuleStyle
))):
2419 Target
, ToolChain
, Arch
, CommandType
, Attr
= Key
[1].split('_')
2420 if Target
== self
.BuildTarget
or Target
== "*":
2421 if ToolChain
== self
.ToolChain
or ToolChain
== "*":
2422 if Arch
== self
.Arch
or Arch
== "*":
2423 if Options
[Key
].startswith("="):
2424 if OverrideList
.get(Key
[1]) is not None:
2425 OverrideList
.pop(Key
[1])
2426 OverrideList
[Key
[1]] = Options
[Key
]
2429 # Use the highest priority value.
2431 if (len(OverrideList
) >= 2):
2432 KeyList
= OverrideList
.keys()
2433 for Index
in range(len(KeyList
)):
2434 NowKey
= KeyList
[Index
]
2435 Target1
, ToolChain1
, Arch1
, CommandType1
, Attr1
= NowKey
.split("_")
2436 for Index1
in range(len(KeyList
) - Index
- 1):
2437 NextKey
= KeyList
[Index1
+ Index
+ 1]
2439 # Compare two Key, if one is included by another, choose the higher priority one
2441 Target2
, ToolChain2
, Arch2
, CommandType2
, Attr2
= NextKey
.split("_")
2442 if Target1
== Target2
or Target1
== "*" or Target2
== "*":
2443 if ToolChain1
== ToolChain2
or ToolChain1
== "*" or ToolChain2
== "*":
2444 if Arch1
== Arch2
or Arch1
== "*" or Arch2
== "*":
2445 if CommandType1
== CommandType2
or CommandType1
== "*" or CommandType2
== "*":
2446 if Attr1
== Attr2
or Attr1
== "*" or Attr2
== "*":
2447 if self
.CalculatePriorityValue(NowKey
) > self
.CalculatePriorityValue(NextKey
):
2448 if Options
.get((self
.BuildRuleFamily
, NextKey
)) is not None:
2449 Options
.pop((self
.BuildRuleFamily
, NextKey
))
2451 if Options
.get((self
.BuildRuleFamily
, NowKey
)) is not None:
2452 Options
.pop((self
.BuildRuleFamily
, NowKey
))
2455 if ModuleStyle
is not None and len (Key
) > 2:
2456 # Check Module style is EDK or EDKII.
2457 # Only append build option for the matched style module.
2458 if ModuleStyle
== EDK_NAME
and Key
[2] != EDK_NAME
:
2460 elif ModuleStyle
== EDKII_NAME
and Key
[2] != EDKII_NAME
:
2463 Target
, Tag
, Arch
, Tool
, Attr
= Key
[1].split("_")
2464 # if tool chain family doesn't match, skip it
2465 if Tool
in self
.ToolDefinition
and Family
!= "":
2466 FamilyIsNull
= False
2467 if self
.ToolDefinition
[Tool
].get(TAB_TOD_DEFINES_BUILDRULEFAMILY
, "") != "":
2468 if Family
!= self
.ToolDefinition
[Tool
][TAB_TOD_DEFINES_BUILDRULEFAMILY
]:
2470 elif Family
!= self
.ToolDefinition
[Tool
][TAB_TOD_DEFINES_FAMILY
]:
2473 # expand any wildcard
2474 if Target
== "*" or Target
== self
.BuildTarget
:
2475 if Tag
== "*" or Tag
== self
.ToolChain
:
2476 if Arch
== "*" or Arch
== self
.Arch
:
2477 if Tool
not in BuildOptions
:
2478 BuildOptions
[Tool
] = {}
2479 if Attr
!= "FLAGS" or Attr
not in BuildOptions
[Tool
] or Options
[Key
].startswith('='):
2480 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2482 # append options for the same tool except PATH
2484 BuildOptions
[Tool
][Attr
] += " " + Options
[Key
]
2486 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2487 # Build Option Family has been checked, which need't to be checked again for family.
2488 if FamilyMatch
or FamilyIsNull
:
2492 if ModuleStyle
is not None and len (Key
) > 2:
2493 # Check Module style is EDK or EDKII.
2494 # Only append build option for the matched style module.
2495 if ModuleStyle
== EDK_NAME
and Key
[2] != EDK_NAME
:
2497 elif ModuleStyle
== EDKII_NAME
and Key
[2] != EDKII_NAME
:
2500 Target
, Tag
, Arch
, Tool
, Attr
= Key
[1].split("_")
2501 # if tool chain family doesn't match, skip it
2502 if Tool
not in self
.ToolDefinition
or Family
== "":
2504 # option has been added before
2505 if Family
!= self
.ToolDefinition
[Tool
][TAB_TOD_DEFINES_FAMILY
]:
2508 # expand any wildcard
2509 if Target
== "*" or Target
== self
.BuildTarget
:
2510 if Tag
== "*" or Tag
== self
.ToolChain
:
2511 if Arch
== "*" or Arch
== self
.Arch
:
2512 if Tool
not in BuildOptions
:
2513 BuildOptions
[Tool
] = {}
2514 if Attr
!= "FLAGS" or Attr
not in BuildOptions
[Tool
] or Options
[Key
].startswith('='):
2515 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2517 # append options for the same tool except PATH
2519 BuildOptions
[Tool
][Attr
] += " " + Options
[Key
]
2521 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2524 ## Append build options in platform to a module
2526 # @param Module The module to which the build options will be appened
2528 # @retval options The options appended with build options in platform
2530 def ApplyBuildOption(self
, Module
):
2531 # Get the different options for the different style module
2532 if Module
.AutoGenVersion
< 0x00010005:
2533 PlatformOptions
= self
.EdkBuildOption
2534 ModuleTypeOptions
= self
.Platform
.GetBuildOptionsByModuleType(EDK_NAME
, Module
.ModuleType
)
2536 PlatformOptions
= self
.EdkIIBuildOption
2537 ModuleTypeOptions
= self
.Platform
.GetBuildOptionsByModuleType(EDKII_NAME
, Module
.ModuleType
)
2538 ModuleTypeOptions
= self
._ExpandBuildOption
(ModuleTypeOptions
)
2539 ModuleOptions
= self
._ExpandBuildOption
(Module
.BuildOptions
)
2540 if Module
in self
.Platform
.Modules
:
2541 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
2542 PlatformModuleOptions
= self
._ExpandBuildOption
(PlatformModule
.BuildOptions
)
2544 PlatformModuleOptions
= {}
2546 BuildRuleOrder
= None
2547 for Options
in [self
.ToolDefinition
, ModuleOptions
, PlatformOptions
, ModuleTypeOptions
, PlatformModuleOptions
]:
2548 for Tool
in Options
:
2549 for Attr
in Options
[Tool
]:
2550 if Attr
== TAB_TOD_DEFINES_BUILDRULEORDER
:
2551 BuildRuleOrder
= Options
[Tool
][Attr
]
2553 AllTools
= set(ModuleOptions
.keys() + PlatformOptions
.keys() +
2554 PlatformModuleOptions
.keys() + ModuleTypeOptions
.keys() +
2555 self
.ToolDefinition
.keys())
2556 BuildOptions
= defaultdict(lambda: defaultdict(str))
2557 for Tool
in AllTools
:
2558 for Options
in [self
.ToolDefinition
, ModuleOptions
, PlatformOptions
, ModuleTypeOptions
, PlatformModuleOptions
]:
2559 if Tool
not in Options
:
2561 for Attr
in Options
[Tool
]:
2563 # Do not generate it in Makefile
2565 if Attr
== TAB_TOD_DEFINES_BUILDRULEORDER
:
2567 Value
= Options
[Tool
][Attr
]
2568 # check if override is indicated
2569 if Value
.startswith('='):
2570 BuildOptions
[Tool
][Attr
] = mws
.handleWsMacro(Value
[1:])
2573 BuildOptions
[Tool
][Attr
] += " " + mws
.handleWsMacro(Value
)
2575 BuildOptions
[Tool
][Attr
] = mws
.handleWsMacro(Value
)
2577 if Module
.AutoGenVersion
< 0x00010005 and self
.Workspace
.UniFlag
is not None:
2579 # Override UNI flag only for EDK module.
2581 BuildOptions
['BUILD']['FLAGS'] = self
.Workspace
.UniFlag
2582 return BuildOptions
, BuildRuleOrder
2584 Platform
= property(_GetPlatform
)
2585 Name
= property(_GetName
)
2586 Guid
= property(_GetGuid
)
2587 Version
= property(_GetVersion
)
2589 OutputDir
= property(_GetOutputDir
)
2590 BuildDir
= property(_GetBuildDir
)
2591 MakeFileDir
= property(_GetMakeFileDir
)
2592 FdfFile
= property(_GetFdfFile
)
2594 PcdTokenNumber
= property(_GetPcdTokenNumbers
) # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber
2595 DynamicPcdList
= property(_GetDynamicPcdList
) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
2596 NonDynamicPcdList
= property(_GetNonDynamicPcdList
) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
2597 NonDynamicPcdDict
= property(_GetNonDynamicPcdDict
)
2598 PackageList
= property(_GetPackageList
)
2600 ToolDefinition
= property(_GetToolDefinition
) # toolcode : tool path
2601 ToolDefinitionFile
= property(_GetToolDefFile
) # toolcode : lib path
2602 ToolChainFamily
= property(_GetToolChainFamily
)
2603 BuildRuleFamily
= property(_GetBuildRuleFamily
)
2604 BuildOption
= property(_GetBuildOptions
) # toolcode : option
2605 EdkBuildOption
= property(_GetEdkBuildOptions
) # edktoolcode : option
2606 EdkIIBuildOption
= property(_GetEdkIIBuildOptions
) # edkiitoolcode : option
2608 BuildCommand
= property(_GetBuildCommand
)
2609 BuildRule
= property(_GetBuildRule
)
2610 ModuleAutoGenList
= property(_GetModuleAutoGenList
)
2611 LibraryAutoGenList
= property(_GetLibraryAutoGenList
)
2612 GenFdsCommand
= property(_GenFdsCommand
)
2614 ## ModuleAutoGen class
2616 # This class encapsules the AutoGen behaviors for the build tools. In addition to
2617 # the generation of AutoGen.h and AutoGen.c, it will generate *.depex file according
2618 # to the [depex] section in module's inf file.
2620 class ModuleAutoGen(AutoGen
):
2621 # call super().__init__ then call the worker function with different parameter count
2622 def __init__(self
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
2626 super(ModuleAutoGen
, self
).__init
__(Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
)
2627 self
._InitWorker
(Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
)
2630 ## Cache the timestamps of metafiles of every module in a class variable
2634 def __new__(cls
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
2635 obj
= super(ModuleAutoGen
, cls
).__new
__(cls
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
)
2636 # check if this module is employed by active platform
2637 if not PlatformAutoGen(Workspace
, args
[0], Target
, Toolchain
, Arch
).ValidModule(MetaFile
):
2638 EdkLogger
.verbose("Module [%s] for [%s] is not employed by active platform\n" \
2643 ## Initialize ModuleAutoGen
2645 # @param Workspace EdkIIWorkspaceBuild object
2646 # @param ModuleFile The path of module file
2647 # @param Target Build target (DEBUG, RELEASE)
2648 # @param Toolchain Name of tool chain
2649 # @param Arch The arch the module supports
2650 # @param PlatformFile Platform meta-file
2652 def _InitWorker(self
, Workspace
, ModuleFile
, Target
, Toolchain
, Arch
, PlatformFile
):
2653 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "AutoGen module [%s] [%s]" % (ModuleFile
, Arch
))
2654 GlobalData
.gProcessingFile
= "%s [%s, %s, %s]" % (ModuleFile
, Arch
, Toolchain
, Target
)
2656 self
.Workspace
= Workspace
2657 self
.WorkspaceDir
= Workspace
.WorkspaceDir
2658 self
._GuidDict
= Workspace
._GuidDict
2659 self
.MetaFile
= ModuleFile
2660 self
.PlatformInfo
= PlatformAutoGen(Workspace
, PlatformFile
, Target
, Toolchain
, Arch
)
2662 self
.SourceDir
= self
.MetaFile
.SubDir
2663 self
.SourceDir
= mws
.relpath(self
.SourceDir
, self
.WorkspaceDir
)
2665 self
.SourceOverrideDir
= None
2666 # use overrided path defined in DSC file
2667 if self
.MetaFile
.Key
in GlobalData
.gOverrideDir
:
2668 self
.SourceOverrideDir
= GlobalData
.gOverrideDir
[self
.MetaFile
.Key
]
2670 self
.ToolChain
= Toolchain
2671 self
.BuildTarget
= Target
2673 self
.ToolChainFamily
= self
.PlatformInfo
.ToolChainFamily
2674 self
.BuildRuleFamily
= self
.PlatformInfo
.BuildRuleFamily
2676 self
.IsMakeFileCreated
= False
2677 self
.IsCodeFileCreated
= False
2678 self
.IsAsBuiltInfCreated
= False
2679 self
.DepexGenerated
= False
2681 self
.BuildDatabase
= self
.Workspace
.BuildDatabase
2682 self
.BuildRuleOrder
= None
2688 self
._Version
= None
2689 self
._ModuleType
= None
2690 self
._ComponentType
= None
2691 self
._PcdIsDriver
= None
2692 self
._AutoGenVersion
= None
2693 self
._LibraryFlag
= None
2694 self
._CustomMakefile
= None
2697 self
._BuildDir
= None
2698 self
._OutputDir
= None
2699 self
._FfsOutputDir
= None
2700 self
._DebugDir
= None
2701 self
._MakeFileDir
= None
2703 self
._IncludePathList
= None
2704 self
._IncludePathLength
= 0
2705 self
._AutoGenFileList
= None
2706 self
._UnicodeFileList
= None
2707 self
._VfrFileList
= None
2708 self
._IdfFileList
= None
2709 self
._SourceFileList
= None
2710 self
._ObjectFileList
= None
2711 self
._BinaryFileList
= None
2713 self
._DependentPackageList
= None
2714 self
._DependentLibraryList
= None
2715 self
._LibraryAutoGenList
= None
2716 self
._DerivedPackageList
= None
2717 self
._ModulePcdList
= None
2718 self
._LibraryPcdList
= None
2719 self
._PcdComments
= OrderedDict()
2720 self
._GuidList
= None
2721 self
._GuidsUsedByPcd
= None
2722 self
._GuidComments
= OrderedDict()
2723 self
._ProtocolList
= None
2724 self
._ProtocolComments
= OrderedDict()
2725 self
._PpiList
= None
2726 self
._PpiComments
= OrderedDict()
2727 self
._DepexList
= None
2728 self
._DepexExpressionList
= None
2729 self
._BuildOption
= None
2730 self
._BuildOptionIncPathList
= None
2731 self
._BuildTargets
= None
2732 self
._IntroBuildTargetList
= None
2733 self
._FinalBuildTargetList
= None
2734 self
._FileTypes
= None
2735 self
._BuildRules
= None
2737 self
._TimeStampPath
= None
2739 self
.AutoGenDepSet
= set()
2742 ## The Modules referenced to this Library
2743 # Only Library has this attribute
2744 self
._ReferenceModules
= []
2746 ## Store the FixedAtBuild Pcds
2748 self
._FixedAtBuildPcds
= []
2753 return "%s [%s]" % (self
.MetaFile
, self
.Arch
)
2755 # Get FixedAtBuild Pcds of this Module
2756 def _GetFixedAtBuildPcds(self
):
2757 if self
._FixedAtBuildPcds
:
2758 return self
._FixedAtBuildPcds
2759 for Pcd
in self
.ModulePcdList
:
2760 if Pcd
.Type
!= TAB_PCDS_FIXED_AT_BUILD
:
2762 if Pcd
not in self
._FixedAtBuildPcds
:
2763 self
._FixedAtBuildPcds
.append(Pcd
)
2765 return self
._FixedAtBuildPcds
2767 def _GetUniqueBaseName(self
):
2768 BaseName
= self
.Name
2769 for Module
in self
.PlatformInfo
.ModuleAutoGenList
:
2770 if Module
.MetaFile
== self
.MetaFile
:
2772 if Module
.Name
== self
.Name
:
2773 if uuid
.UUID(Module
.Guid
) == uuid
.UUID(self
.Guid
):
2774 EdkLogger
.error("build", FILE_DUPLICATED
, 'Modules have same BaseName and FILE_GUID:\n'
2775 ' %s\n %s' % (Module
.MetaFile
, self
.MetaFile
))
2776 BaseName
= '%s_%s' % (self
.Name
, self
.Guid
)
2779 # Macros could be used in build_rule.txt (also Makefile)
2780 def _GetMacros(self
):
2781 if self
._Macro
is None:
2782 self
._Macro
= OrderedDict()
2783 self
._Macro
["WORKSPACE" ] = self
.WorkspaceDir
2784 self
._Macro
["MODULE_NAME" ] = self
.Name
2785 self
._Macro
["MODULE_NAME_GUID" ] = self
._GetUniqueBaseName
()
2786 self
._Macro
["MODULE_GUID" ] = self
.Guid
2787 self
._Macro
["MODULE_VERSION" ] = self
.Version
2788 self
._Macro
["MODULE_TYPE" ] = self
.ModuleType
2789 self
._Macro
["MODULE_FILE" ] = str(self
.MetaFile
)
2790 self
._Macro
["MODULE_FILE_BASE_NAME" ] = self
.MetaFile
.BaseName
2791 self
._Macro
["MODULE_RELATIVE_DIR" ] = self
.SourceDir
2792 self
._Macro
["MODULE_DIR" ] = self
.SourceDir
2794 self
._Macro
["BASE_NAME" ] = self
.Name
2796 self
._Macro
["ARCH" ] = self
.Arch
2797 self
._Macro
["TOOLCHAIN" ] = self
.ToolChain
2798 self
._Macro
["TOOLCHAIN_TAG" ] = self
.ToolChain
2799 self
._Macro
["TOOL_CHAIN_TAG" ] = self
.ToolChain
2800 self
._Macro
["TARGET" ] = self
.BuildTarget
2802 self
._Macro
["BUILD_DIR" ] = self
.PlatformInfo
.BuildDir
2803 self
._Macro
["BIN_DIR" ] = os
.path
.join(self
.PlatformInfo
.BuildDir
, self
.Arch
)
2804 self
._Macro
["LIB_DIR" ] = os
.path
.join(self
.PlatformInfo
.BuildDir
, self
.Arch
)
2805 self
._Macro
["MODULE_BUILD_DIR" ] = self
.BuildDir
2806 self
._Macro
["OUTPUT_DIR" ] = self
.OutputDir
2807 self
._Macro
["DEBUG_DIR" ] = self
.DebugDir
2808 self
._Macro
["DEST_DIR_OUTPUT" ] = self
.OutputDir
2809 self
._Macro
["DEST_DIR_DEBUG" ] = self
.DebugDir
2810 self
._Macro
["PLATFORM_NAME" ] = self
.PlatformInfo
.Name
2811 self
._Macro
["PLATFORM_GUID" ] = self
.PlatformInfo
.Guid
2812 self
._Macro
["PLATFORM_VERSION" ] = self
.PlatformInfo
.Version
2813 self
._Macro
["PLATFORM_RELATIVE_DIR" ] = self
.PlatformInfo
.SourceDir
2814 self
._Macro
["PLATFORM_DIR" ] = mws
.join(self
.WorkspaceDir
, self
.PlatformInfo
.SourceDir
)
2815 self
._Macro
["PLATFORM_OUTPUT_DIR" ] = self
.PlatformInfo
.OutputDir
2816 self
._Macro
["FFS_OUTPUT_DIR" ] = self
.FfsOutputDir
2819 ## Return the module build data object
2820 def _GetModule(self
):
2821 if self
._Module
is None:
2822 self
._Module
= self
.Workspace
.BuildDatabase
[self
.MetaFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
2825 ## Return the module name
2826 def _GetBaseName(self
):
2827 return self
.Module
.BaseName
2829 ## Return the module DxsFile if exist
2830 def _GetDxsFile(self
):
2831 return self
.Module
.DxsFile
2833 ## Return the module SourceOverridePath
2834 def _GetSourceOverridePath(self
):
2835 return self
.Module
.SourceOverridePath
2837 ## Return the module meta-file GUID
2840 # To build same module more than once, the module path with FILE_GUID overridden has
2841 # the file name FILE_GUIDmodule.inf, but the relative path (self.MetaFile.File) is the realy path
2842 # in DSC. The overridden GUID can be retrieved from file name
2844 if os
.path
.basename(self
.MetaFile
.File
) != os
.path
.basename(self
.MetaFile
.Path
):
2846 # Length of GUID is 36
2848 return os
.path
.basename(self
.MetaFile
.Path
)[:36]
2849 return self
.Module
.Guid
2851 ## Return the module version
2852 def _GetVersion(self
):
2853 return self
.Module
.Version
2855 ## Return the module type
2856 def _GetModuleType(self
):
2857 return self
.Module
.ModuleType
2859 ## Return the component type (for Edk.x style of module)
2860 def _GetComponentType(self
):
2861 return self
.Module
.ComponentType
2863 ## Return the build type
2864 def _GetBuildType(self
):
2865 return self
.Module
.BuildType
2867 ## Return the PCD_IS_DRIVER setting
2868 def _GetPcdIsDriver(self
):
2869 return self
.Module
.PcdIsDriver
2871 ## Return the autogen version, i.e. module meta-file version
2872 def _GetAutoGenVersion(self
):
2873 return self
.Module
.AutoGenVersion
2875 ## Check if the module is library or not
2876 def _IsLibrary(self
):
2877 if self
._LibraryFlag
is None:
2878 if self
.Module
.LibraryClass
is not None and self
.Module
.LibraryClass
!= []:
2879 self
._LibraryFlag
= True
2881 self
._LibraryFlag
= False
2882 return self
._LibraryFlag
2884 ## Check if the module is binary module or not
2885 def _IsBinaryModule(self
):
2886 return self
.Module
.IsBinaryModule
2888 ## Return the directory to store intermediate files of the module
2889 def _GetBuildDir(self
):
2890 if self
._BuildDir
is None:
2891 self
._BuildDir
= path
.join(
2892 self
.PlatformInfo
.BuildDir
,
2895 self
.MetaFile
.BaseName
2897 CreateDirectory(self
._BuildDir
)
2898 return self
._BuildDir
2900 ## Return the directory to store the intermediate object files of the mdoule
2901 def _GetOutputDir(self
):
2902 if self
._OutputDir
is None:
2903 self
._OutputDir
= path
.join(self
.BuildDir
, "OUTPUT")
2904 CreateDirectory(self
._OutputDir
)
2905 return self
._OutputDir
2907 ## Return the directory to store ffs file
2908 def _GetFfsOutputDir(self
):
2909 if self
._FfsOutputDir
is None:
2910 if GlobalData
.gFdfParser
is not None:
2911 self
._FfsOutputDir
= path
.join(self
.PlatformInfo
.BuildDir
, TAB_FV_DIRECTORY
, "Ffs", self
.Guid
+ self
.Name
)
2913 self
._FfsOutputDir
= ''
2914 return self
._FfsOutputDir
2916 ## Return the directory to store auto-gened source files of the mdoule
2917 def _GetDebugDir(self
):
2918 if self
._DebugDir
is None:
2919 self
._DebugDir
= path
.join(self
.BuildDir
, "DEBUG")
2920 CreateDirectory(self
._DebugDir
)
2921 return self
._DebugDir
2923 ## Return the path of custom file
2924 def _GetCustomMakefile(self
):
2925 if self
._CustomMakefile
is None:
2926 self
._CustomMakefile
= {}
2927 for Type
in self
.Module
.CustomMakefile
:
2928 if Type
in gMakeTypeMap
:
2929 MakeType
= gMakeTypeMap
[Type
]
2932 if self
.SourceOverrideDir
is not None:
2933 File
= os
.path
.join(self
.SourceOverrideDir
, self
.Module
.CustomMakefile
[Type
])
2934 if not os
.path
.exists(File
):
2935 File
= os
.path
.join(self
.SourceDir
, self
.Module
.CustomMakefile
[Type
])
2937 File
= os
.path
.join(self
.SourceDir
, self
.Module
.CustomMakefile
[Type
])
2938 self
._CustomMakefile
[MakeType
] = File
2939 return self
._CustomMakefile
2941 ## Return the directory of the makefile
2943 # @retval string The directory string of module's makefile
2945 def _GetMakeFileDir(self
):
2946 return self
.BuildDir
2948 ## Return build command string
2950 # @retval string Build command string
2952 def _GetBuildCommand(self
):
2953 return self
.PlatformInfo
.BuildCommand
2955 ## Get object list of all packages the module and its dependent libraries belong to
2957 # @retval list The list of package object
2959 def _GetDerivedPackageList(self
):
2961 for M
in [self
.Module
] + self
.DependentLibraryList
:
2962 for Package
in M
.Packages
:
2963 if Package
in PackageList
:
2965 PackageList
.append(Package
)
2968 ## Get the depex string
2970 # @return : a string contain all depex expresion.
2971 def _GetDepexExpresionString(self
):
2974 ## DPX_SOURCE IN Define section.
2975 if self
.Module
.DxsFile
:
2977 for M
in [self
.Module
] + self
.DependentLibraryList
:
2978 Filename
= M
.MetaFile
.Path
2979 InfObj
= InfSectionParser
.InfSectionParser(Filename
)
2980 DepexExpresionList
= InfObj
.GetDepexExpresionList()
2981 for DepexExpresion
in DepexExpresionList
:
2982 for key
in DepexExpresion
:
2983 Arch
, ModuleType
= key
2984 DepexExpr
= [x
for x
in DepexExpresion
[key
] if not str(x
).startswith('#')]
2985 # the type of build module is USER_DEFINED.
2986 # All different DEPEX section tags would be copied into the As Built INF file
2987 # and there would be separate DEPEX section tags
2988 if self
.ModuleType
.upper() == SUP_MODULE_USER_DEFINED
:
2989 if (Arch
.upper() == self
.Arch
.upper()) and (ModuleType
.upper() != TAB_ARCH_COMMON
):
2990 DepexList
.append({(Arch
, ModuleType
): DepexExpr
})
2992 if Arch
.upper() == TAB_ARCH_COMMON
or \
2993 (Arch
.upper() == self
.Arch
.upper() and \
2994 ModuleType
.upper() in [TAB_ARCH_COMMON
, self
.ModuleType
.upper()]):
2995 DepexList
.append({(Arch
, ModuleType
): DepexExpr
})
2997 #the type of build module is USER_DEFINED.
2998 if self
.ModuleType
.upper() == SUP_MODULE_USER_DEFINED
:
2999 for Depex
in DepexList
:
3001 DepexStr
+= '[Depex.%s.%s]\n' % key
3002 DepexStr
+= '\n'.join('# '+ val
for val
in Depex
[key
])
3005 return '[Depex.%s]\n' % self
.Arch
3008 #the type of build module not is USER_DEFINED.
3010 for Depex
in DepexList
:
3015 for D
in Depex
.values():
3016 DepexStr
+= ' '.join(val
for val
in D
)
3017 Index
= DepexStr
.find('END')
3018 if Index
> -1 and Index
== len(DepexStr
) - 3:
3019 DepexStr
= DepexStr
[:-3]
3020 DepexStr
= DepexStr
.strip()
3023 DepexStr
= DepexStr
.lstrip('(').rstrip(')').strip()
3025 return '[Depex.%s]\n' % self
.Arch
3026 return '[Depex.%s]\n# ' % self
.Arch
+ DepexStr
3028 ## Merge dependency expression
3030 # @retval list The token list of the dependency expression after parsed
3032 def _GetDepexTokenList(self
):
3033 if self
._DepexList
is None:
3034 self
._DepexList
= {}
3035 if self
.DxsFile
or self
.IsLibrary
or TAB_DEPENDENCY_EXPRESSION_FILE
in self
.FileTypes
:
3036 return self
._DepexList
3038 self
._DepexList
[self
.ModuleType
] = []
3040 for ModuleType
in self
._DepexList
:
3041 DepexList
= self
._DepexList
[ModuleType
]
3043 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
3045 for M
in [self
.Module
] + self
.DependentLibraryList
:
3047 for D
in M
.Depex
[self
.Arch
, ModuleType
]:
3049 DepexList
.append('AND')
3050 DepexList
.append('(')
3052 if DepexList
[-1] == 'END': # no need of a END at this time
3054 DepexList
.append(')')
3057 EdkLogger
.verbose("DEPEX[%s] (+%s) = %s" % (self
.Name
, M
.BaseName
, DepexList
))
3058 if 'BEFORE' in DepexList
or 'AFTER' in DepexList
:
3060 if len(DepexList
) > 0:
3061 EdkLogger
.verbose('')
3062 return self
._DepexList
3064 ## Merge dependency expression
3066 # @retval list The token list of the dependency expression after parsed
3068 def _GetDepexExpressionTokenList(self
):
3069 if self
._DepexExpressionList
is None:
3070 self
._DepexExpressionList
= {}
3071 if self
.DxsFile
or self
.IsLibrary
or TAB_DEPENDENCY_EXPRESSION_FILE
in self
.FileTypes
:
3072 return self
._DepexExpressionList
3074 self
._DepexExpressionList
[self
.ModuleType
] = ''
3076 for ModuleType
in self
._DepexExpressionList
:
3077 DepexExpressionList
= self
._DepexExpressionList
[ModuleType
]
3079 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
3081 for M
in [self
.Module
] + self
.DependentLibraryList
:
3083 for D
in M
.DepexExpression
[self
.Arch
, ModuleType
]:
3084 if DepexExpressionList
!= '':
3085 DepexExpressionList
+= ' AND '
3086 DepexExpressionList
+= '('
3087 DepexExpressionList
+= D
3088 DepexExpressionList
= DepexExpressionList
.rstrip('END').strip()
3089 DepexExpressionList
+= ')'
3092 EdkLogger
.verbose("DEPEX[%s] (+%s) = %s" % (self
.Name
, M
.BaseName
, DepexExpressionList
))
3093 if 'BEFORE' in DepexExpressionList
or 'AFTER' in DepexExpressionList
:
3095 if len(DepexExpressionList
) > 0:
3096 EdkLogger
.verbose('')
3097 self
._DepexExpressionList
[ModuleType
] = DepexExpressionList
3098 return self
._DepexExpressionList
3100 # Get the tiano core user extension, it is contain dependent library.
3101 # @retval: a list contain tiano core userextension.
3103 def _GetTianoCoreUserExtensionList(self
):
3104 TianoCoreUserExtentionList
= []
3105 for M
in [self
.Module
] + self
.DependentLibraryList
:
3106 Filename
= M
.MetaFile
.Path
3107 InfObj
= InfSectionParser
.InfSectionParser(Filename
)
3108 TianoCoreUserExtenList
= InfObj
.GetUserExtensionTianoCore()
3109 for TianoCoreUserExtent
in TianoCoreUserExtenList
:
3110 for Section
in TianoCoreUserExtent
:
3111 ItemList
= Section
.split(TAB_SPLIT
)
3113 if len(ItemList
) == 4:
3115 if Arch
.upper() == TAB_ARCH_COMMON
or Arch
.upper() == self
.Arch
.upper():
3117 TianoCoreList
.extend([TAB_SECTION_START
+ Section
+ TAB_SECTION_END
])
3118 TianoCoreList
.extend(TianoCoreUserExtent
[Section
][:])
3119 TianoCoreList
.append('\n')
3120 TianoCoreUserExtentionList
.append(TianoCoreList
)
3122 return TianoCoreUserExtentionList
3124 ## Return the list of specification version required for the module
3126 # @retval list The list of specification defined in module file
3128 def _GetSpecification(self
):
3129 return self
.Module
.Specification
3131 ## Tool option for the module build
3133 # @param PlatformInfo The object of PlatformBuildInfo
3134 # @retval dict The dict containing valid options
3136 def _GetModuleBuildOption(self
):
3137 if self
._BuildOption
is None:
3138 self
._BuildOption
, self
.BuildRuleOrder
= self
.PlatformInfo
.ApplyBuildOption(self
.Module
)
3139 if self
.BuildRuleOrder
:
3140 self
.BuildRuleOrder
= ['.%s' % Ext
for Ext
in self
.BuildRuleOrder
.split()]
3141 return self
._BuildOption
3143 ## Get include path list from tool option for the module build
3145 # @retval list The include path list
3147 def _GetBuildOptionIncPathList(self
):
3148 if self
._BuildOptionIncPathList
is None:
3150 # Regular expression for finding Include Directories, the difference between MSFT and INTEL/GCC/RVCT
3151 # is the former use /I , the Latter used -I to specify include directories
3153 if self
.PlatformInfo
.ToolChainFamily
in ('MSFT'):
3154 BuildOptIncludeRegEx
= gBuildOptIncludePatternMsft
3155 elif self
.PlatformInfo
.ToolChainFamily
in ('INTEL', 'GCC', 'RVCT'):
3156 BuildOptIncludeRegEx
= gBuildOptIncludePatternOther
3159 # New ToolChainFamily, don't known whether there is option to specify include directories
3161 self
._BuildOptionIncPathList
= []
3162 return self
._BuildOptionIncPathList
3164 BuildOptionIncPathList
= []
3165 for Tool
in ('CC', 'PP', 'VFRPP', 'ASLPP', 'ASLCC', 'APP', 'ASM'):
3168 FlagOption
= self
.BuildOption
[Tool
][Attr
]
3172 if self
.PlatformInfo
.ToolChainFamily
!= 'RVCT':
3173 IncPathList
= [NormPath(Path
, self
.Macros
) for Path
in BuildOptIncludeRegEx
.findall(FlagOption
)]
3176 # RVCT may specify a list of directory seperated by commas
3179 for Path
in BuildOptIncludeRegEx
.findall(FlagOption
):
3180 PathList
= GetSplitList(Path
, TAB_COMMA_SPLIT
)
3181 IncPathList
+= [NormPath(PathEntry
, self
.Macros
) for PathEntry
in PathList
]
3184 # EDK II modules must not reference header files outside of the packages they depend on or
3185 # within the module's directory tree. Report error if violation.
3187 if self
.AutoGenVersion
>= 0x00010005 and len(IncPathList
) > 0:
3188 for Path
in IncPathList
:
3189 if (Path
not in self
.IncludePathList
) and (CommonPath([Path
, self
.MetaFile
.Dir
]) != self
.MetaFile
.Dir
):
3190 ErrMsg
= "The include directory for the EDK II module in this line is invalid %s specified in %s FLAGS '%s'" % (Path
, Tool
, FlagOption
)
3191 EdkLogger
.error("build",
3194 File
=str(self
.MetaFile
))
3197 BuildOptionIncPathList
+= IncPathList
3199 self
._BuildOptionIncPathList
= BuildOptionIncPathList
3201 return self
._BuildOptionIncPathList
3203 ## Return a list of files which can be built from source
3205 # What kind of files can be built is determined by build rules in
3206 # $(CONF_DIRECTORY)/build_rule.txt and toolchain family.
3208 def _GetSourceFileList(self
):
3209 if self
._SourceFileList
is None:
3210 self
._SourceFileList
= []
3211 for F
in self
.Module
.Sources
:
3213 if F
.TagName
not in ("", "*", self
.ToolChain
):
3214 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "The toolchain [%s] for processing file [%s] is found, "
3215 "but [%s] is needed" % (F
.TagName
, str(F
), self
.ToolChain
))
3217 # match tool chain family or build rule family
3218 if F
.ToolChainFamily
not in ("", "*", self
.ToolChainFamily
, self
.BuildRuleFamily
):
3221 "The file [%s] must be built by tools of [%s], " \
3222 "but current toolchain family is [%s], buildrule family is [%s]" \
3223 % (str(F
), F
.ToolChainFamily
, self
.ToolChainFamily
, self
.BuildRuleFamily
))
3226 # add the file path into search path list for file including
3227 if F
.Dir
not in self
.IncludePathList
and self
.AutoGenVersion
>= 0x00010005:
3228 self
.IncludePathList
.insert(0, F
.Dir
)
3229 self
._SourceFileList
.append(F
)
3231 self
._MatchBuildRuleOrder
(self
._SourceFileList
)
3233 for F
in self
._SourceFileList
:
3234 self
._ApplyBuildRule
(F
, TAB_UNKNOWN_FILE
)
3235 return self
._SourceFileList
3237 def _MatchBuildRuleOrder(self
, FileList
):
3239 self
._GetModuleBuildOption
()
3240 for SingleFile
in FileList
:
3241 if self
.BuildRuleOrder
and SingleFile
.Ext
in self
.BuildRuleOrder
and SingleFile
.Ext
in self
.BuildRules
:
3242 key
= SingleFile
.Path
.split(SingleFile
.Ext
)[0]
3243 if key
in Order_Dict
:
3244 Order_Dict
[key
].append(SingleFile
.Ext
)
3246 Order_Dict
[key
] = [SingleFile
.Ext
]
3249 for F
in Order_Dict
:
3250 if len(Order_Dict
[F
]) > 1:
3251 Order_Dict
[F
].sort(key
=lambda i
: self
.BuildRuleOrder
.index(i
))
3252 for Ext
in Order_Dict
[F
][1:]:
3253 RemoveList
.append(F
+ Ext
)
3255 for item
in RemoveList
:
3256 FileList
.remove(item
)
3260 ## Return the list of unicode files
3261 def _GetUnicodeFileList(self
):
3262 if self
._UnicodeFileList
is None:
3263 if TAB_UNICODE_FILE
in self
.FileTypes
:
3264 self
._UnicodeFileList
= self
.FileTypes
[TAB_UNICODE_FILE
]
3266 self
._UnicodeFileList
= []
3267 return self
._UnicodeFileList
3269 ## Return the list of vfr files
3270 def _GetVfrFileList(self
):
3271 if self
._VfrFileList
is None:
3272 if TAB_VFR_FILE
in self
.FileTypes
:
3273 self
._VfrFileList
= self
.FileTypes
[TAB_VFR_FILE
]
3275 self
._VfrFileList
= []
3276 return self
._VfrFileList
3278 ## Return the list of Image Definition files
3279 def _GetIdfFileList(self
):
3280 if self
._IdfFileList
is None:
3281 if TAB_IMAGE_FILE
in self
.FileTypes
:
3282 self
._IdfFileList
= self
.FileTypes
[TAB_IMAGE_FILE
]
3284 self
._IdfFileList
= []
3285 return self
._IdfFileList
3287 ## Return a list of files which can be built from binary
3289 # "Build" binary files are just to copy them to build directory.
3291 # @retval list The list of files which can be built later
3293 def _GetBinaryFiles(self
):
3294 if self
._BinaryFileList
is None:
3295 self
._BinaryFileList
= []
3296 for F
in self
.Module
.Binaries
:
3297 if F
.Target
not in [TAB_ARCH_COMMON
, '*'] and F
.Target
!= self
.BuildTarget
:
3299 self
._BinaryFileList
.append(F
)
3300 self
._ApplyBuildRule
(F
, F
.Type
)
3301 return self
._BinaryFileList
3303 def _GetBuildRules(self
):
3304 if self
._BuildRules
is None:
3306 BuildRuleDatabase
= self
.PlatformInfo
.BuildRule
3307 for Type
in BuildRuleDatabase
.FileTypeList
:
3308 #first try getting build rule by BuildRuleFamily
3309 RuleObject
= BuildRuleDatabase
[Type
, self
.BuildType
, self
.Arch
, self
.BuildRuleFamily
]
3311 # build type is always module type, but ...
3312 if self
.ModuleType
!= self
.BuildType
:
3313 RuleObject
= BuildRuleDatabase
[Type
, self
.ModuleType
, self
.Arch
, self
.BuildRuleFamily
]
3314 #second try getting build rule by ToolChainFamily
3316 RuleObject
= BuildRuleDatabase
[Type
, self
.BuildType
, self
.Arch
, self
.ToolChainFamily
]
3318 # build type is always module type, but ...
3319 if self
.ModuleType
!= self
.BuildType
:
3320 RuleObject
= BuildRuleDatabase
[Type
, self
.ModuleType
, self
.Arch
, self
.ToolChainFamily
]
3323 RuleObject
= RuleObject
.Instantiate(self
.Macros
)
3324 BuildRules
[Type
] = RuleObject
3325 for Ext
in RuleObject
.SourceFileExtList
:
3326 BuildRules
[Ext
] = RuleObject
3327 self
._BuildRules
= BuildRules
3328 return self
._BuildRules
3330 def _ApplyBuildRule(self
, File
, FileType
):
3331 if self
._BuildTargets
is None:
3332 self
._IntroBuildTargetList
= set()
3333 self
._FinalBuildTargetList
= set()
3334 self
._BuildTargets
= defaultdict(set)
3335 self
._FileTypes
= defaultdict(set)
3337 SubDirectory
= os
.path
.join(self
.OutputDir
, File
.SubDir
)
3338 if not os
.path
.exists(SubDirectory
):
3339 CreateDirectory(SubDirectory
)
3345 # Make sure to get build rule order value
3347 self
._GetModuleBuildOption
()
3349 while Index
< len(SourceList
):
3350 Source
= SourceList
[Index
]
3354 CreateDirectory(Source
.Dir
)
3356 if File
.IsBinary
and File
== Source
and self
._BinaryFileList
is not None and File
in self
._BinaryFileList
:
3357 # Skip all files that are not binary libraries
3358 if not self
.IsLibrary
:
3360 RuleObject
= self
.BuildRules
[TAB_DEFAULT_BINARY_FILE
]
3361 elif FileType
in self
.BuildRules
:
3362 RuleObject
= self
.BuildRules
[FileType
]
3363 elif Source
.Ext
in self
.BuildRules
:
3364 RuleObject
= self
.BuildRules
[Source
.Ext
]
3366 # stop at no more rules
3368 self
._FinalBuildTargetList
.add(LastTarget
)
3371 FileType
= RuleObject
.SourceFileType
3372 self
._FileTypes
[FileType
].add(Source
)
3374 # stop at STATIC_LIBRARY for library
3375 if self
.IsLibrary
and FileType
== TAB_STATIC_LIBRARY
:
3377 self
._FinalBuildTargetList
.add(LastTarget
)
3380 Target
= RuleObject
.Apply(Source
, self
.BuildRuleOrder
)
3383 self
._FinalBuildTargetList
.add(LastTarget
)
3385 elif not Target
.Outputs
:
3386 # Only do build for target with outputs
3387 self
._FinalBuildTargetList
.add(Target
)
3389 self
._BuildTargets
[FileType
].add(Target
)
3391 if not Source
.IsBinary
and Source
== File
:
3392 self
._IntroBuildTargetList
.add(Target
)
3394 # to avoid cyclic rule
3395 if FileType
in RuleChain
:
3398 RuleChain
.append(FileType
)
3399 SourceList
.extend(Target
.Outputs
)
3401 FileType
= TAB_UNKNOWN_FILE
3403 def _GetTargets(self
):
3404 if self
._BuildTargets
is None:
3405 self
._IntroBuildTargetList
= set()
3406 self
._FinalBuildTargetList
= set()
3407 self
._BuildTargets
= defaultdict(set)
3408 self
._FileTypes
= defaultdict(set)
3410 #TRICK: call _GetSourceFileList to apply build rule for source files
3411 if self
.SourceFileList
:
3414 #TRICK: call _GetBinaryFileList to apply build rule for binary files
3415 if self
.BinaryFileList
:
3418 return self
._BuildTargets
3420 def _GetIntroTargetList(self
):
3422 return self
._IntroBuildTargetList
3424 def _GetFinalTargetList(self
):
3426 return self
._FinalBuildTargetList
3428 def _GetFileTypes(self
):
3430 return self
._FileTypes
3432 ## Get the list of package object the module depends on
3434 # @retval list The package object list
3436 def _GetDependentPackageList(self
):
3437 return self
.Module
.Packages
3439 ## Return the list of auto-generated code file
3441 # @retval list The list of auto-generated file
3443 def _GetAutoGenFileList(self
):
3444 UniStringAutoGenC
= True
3445 IdfStringAutoGenC
= True
3446 UniStringBinBuffer
= StringIO()
3447 IdfGenBinBuffer
= StringIO()
3448 if self
.BuildType
== 'UEFI_HII':
3449 UniStringAutoGenC
= False
3450 IdfStringAutoGenC
= False
3451 if self
._AutoGenFileList
is None:
3452 self
._AutoGenFileList
= {}
3453 AutoGenC
= TemplateString()
3454 AutoGenH
= TemplateString()
3455 StringH
= TemplateString()
3456 StringIdf
= TemplateString()
3457 GenC
.CreateCode(self
, AutoGenC
, AutoGenH
, StringH
, UniStringAutoGenC
, UniStringBinBuffer
, StringIdf
, IdfStringAutoGenC
, IdfGenBinBuffer
)
3459 # AutoGen.c is generated if there are library classes in inf, or there are object files
3461 if str(AutoGenC
) != "" and (len(self
.Module
.LibraryClasses
) > 0
3462 or TAB_OBJECT_FILE
in self
.FileTypes
):
3463 AutoFile
= PathClass(gAutoGenCodeFileName
, self
.DebugDir
)
3464 self
._AutoGenFileList
[AutoFile
] = str(AutoGenC
)
3465 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3466 if str(AutoGenH
) != "":
3467 AutoFile
= PathClass(gAutoGenHeaderFileName
, self
.DebugDir
)
3468 self
._AutoGenFileList
[AutoFile
] = str(AutoGenH
)
3469 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3470 if str(StringH
) != "":
3471 AutoFile
= PathClass(gAutoGenStringFileName
% {"module_name":self
.Name
}, self
.DebugDir
)
3472 self
._AutoGenFileList
[AutoFile
] = str(StringH
)
3473 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3474 if UniStringBinBuffer
is not None and UniStringBinBuffer
.getvalue() != "":
3475 AutoFile
= PathClass(gAutoGenStringFormFileName
% {"module_name":self
.Name
}, self
.OutputDir
)
3476 self
._AutoGenFileList
[AutoFile
] = UniStringBinBuffer
.getvalue()
3477 AutoFile
.IsBinary
= True
3478 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3479 if UniStringBinBuffer
is not None:
3480 UniStringBinBuffer
.close()
3481 if str(StringIdf
) != "":
3482 AutoFile
= PathClass(gAutoGenImageDefFileName
% {"module_name":self
.Name
}, self
.DebugDir
)
3483 self
._AutoGenFileList
[AutoFile
] = str(StringIdf
)
3484 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3485 if IdfGenBinBuffer
is not None and IdfGenBinBuffer
.getvalue() != "":
3486 AutoFile
= PathClass(gAutoGenIdfFileName
% {"module_name":self
.Name
}, self
.OutputDir
)
3487 self
._AutoGenFileList
[AutoFile
] = IdfGenBinBuffer
.getvalue()
3488 AutoFile
.IsBinary
= True
3489 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3490 if IdfGenBinBuffer
is not None:
3491 IdfGenBinBuffer
.close()
3492 return self
._AutoGenFileList
3494 ## Return the list of library modules explicitly or implicityly used by this module
3495 def _GetLibraryList(self
):
3496 if self
._DependentLibraryList
is None:
3497 # only merge library classes and PCD for non-library module
3499 self
._DependentLibraryList
= []
3501 if self
.AutoGenVersion
< 0x00010005:
3502 self
._DependentLibraryList
= self
.PlatformInfo
.ResolveLibraryReference(self
.Module
)
3504 self
._DependentLibraryList
= self
.PlatformInfo
.ApplyLibraryInstance(self
.Module
)
3505 return self
._DependentLibraryList
3508 def UpdateComments(Recver
, Src
):
3510 if Key
not in Recver
:
3512 Recver
[Key
].extend(Src
[Key
])
3513 ## Get the list of PCDs from current module
3515 # @retval list The list of PCD
3517 def _GetModulePcdList(self
):
3518 if self
._ModulePcdList
is None:
3519 # apply PCD settings from platform
3520 self
._ModulePcdList
= self
.PlatformInfo
.ApplyPcdSetting(self
.Module
, self
.Module
.Pcds
)
3521 self
.UpdateComments(self
._PcdComments
, self
.Module
.PcdComments
)
3522 return self
._ModulePcdList
3524 ## Get the list of PCDs from dependent libraries
3526 # @retval list The list of PCD
3528 def _GetLibraryPcdList(self
):
3529 if self
._LibraryPcdList
is None:
3530 Pcds
= OrderedDict()
3531 if not self
.IsLibrary
:
3532 # get PCDs from dependent libraries
3533 self
._LibraryPcdList
= []
3534 for Library
in self
.DependentLibraryList
:
3535 PcdsInLibrary
= OrderedDict()
3536 self
.UpdateComments(self
._PcdComments
, Library
.PcdComments
)
3537 for Key
in Library
.Pcds
:
3538 # skip duplicated PCDs
3539 if Key
in self
.Module
.Pcds
or Key
in Pcds
:
3541 Pcds
[Key
] = copy
.copy(Library
.Pcds
[Key
])
3542 PcdsInLibrary
[Key
] = Pcds
[Key
]
3543 self
._LibraryPcdList
.extend(self
.PlatformInfo
.ApplyPcdSetting(self
.Module
, PcdsInLibrary
, Library
=Library
))
3545 self
._LibraryPcdList
= []
3546 return self
._LibraryPcdList
3548 ## Get the GUID value mapping
3550 # @retval dict The mapping between GUID cname and its value
3552 def _GetGuidList(self
):
3553 if self
._GuidList
is None:
3554 self
._GuidList
= OrderedDict()
3555 self
._GuidList
.update(self
.Module
.Guids
)
3556 for Library
in self
.DependentLibraryList
:
3557 self
._GuidList
.update(Library
.Guids
)
3558 self
.UpdateComments(self
._GuidComments
, Library
.GuidComments
)
3559 self
.UpdateComments(self
._GuidComments
, self
.Module
.GuidComments
)
3560 return self
._GuidList
3562 def GetGuidsUsedByPcd(self
):
3563 if self
._GuidsUsedByPcd
is None:
3564 self
._GuidsUsedByPcd
= OrderedDict()
3565 self
._GuidsUsedByPcd
.update(self
.Module
.GetGuidsUsedByPcd())
3566 for Library
in self
.DependentLibraryList
:
3567 self
._GuidsUsedByPcd
.update(Library
.GetGuidsUsedByPcd())
3568 return self
._GuidsUsedByPcd
3569 ## Get the protocol value mapping
3571 # @retval dict The mapping between protocol cname and its value
3573 def _GetProtocolList(self
):
3574 if self
._ProtocolList
is None:
3575 self
._ProtocolList
= OrderedDict()
3576 self
._ProtocolList
.update(self
.Module
.Protocols
)
3577 for Library
in self
.DependentLibraryList
:
3578 self
._ProtocolList
.update(Library
.Protocols
)
3579 self
.UpdateComments(self
._ProtocolComments
, Library
.ProtocolComments
)
3580 self
.UpdateComments(self
._ProtocolComments
, self
.Module
.ProtocolComments
)
3581 return self
._ProtocolList
3583 ## Get the PPI value mapping
3585 # @retval dict The mapping between PPI cname and its value
3587 def _GetPpiList(self
):
3588 if self
._PpiList
is None:
3589 self
._PpiList
= OrderedDict()
3590 self
._PpiList
.update(self
.Module
.Ppis
)
3591 for Library
in self
.DependentLibraryList
:
3592 self
._PpiList
.update(Library
.Ppis
)
3593 self
.UpdateComments(self
._PpiComments
, Library
.PpiComments
)
3594 self
.UpdateComments(self
._PpiComments
, self
.Module
.PpiComments
)
3595 return self
._PpiList
3597 ## Get the list of include search path
3599 # @retval list The list path
3601 def _GetIncludePathList(self
):
3602 if self
._IncludePathList
is None:
3603 self
._IncludePathList
= []
3604 if self
.AutoGenVersion
< 0x00010005:
3605 for Inc
in self
.Module
.Includes
:
3606 if Inc
not in self
._IncludePathList
:
3607 self
._IncludePathList
.append(Inc
)
3609 Inc
= path
.join(Inc
, self
.Arch
.capitalize())
3610 if os
.path
.exists(Inc
) and Inc
not in self
._IncludePathList
:
3611 self
._IncludePathList
.append(Inc
)
3612 # Edk module needs to put DEBUG_DIR at the end of search path and not to use SOURCE_DIR all the time
3613 self
._IncludePathList
.append(self
.DebugDir
)
3615 self
._IncludePathList
.append(self
.MetaFile
.Dir
)
3616 self
._IncludePathList
.append(self
.DebugDir
)
3618 for Package
in self
.Module
.Packages
:
3619 PackageDir
= mws
.join(self
.WorkspaceDir
, Package
.MetaFile
.Dir
)
3620 if PackageDir
not in self
._IncludePathList
:
3621 self
._IncludePathList
.append(PackageDir
)
3622 IncludesList
= Package
.Includes
3623 if Package
._PrivateIncludes
:
3624 if not self
.MetaFile
.Path
.startswith(PackageDir
):
3625 IncludesList
= list(set(Package
.Includes
).difference(set(Package
._PrivateIncludes
)))
3626 for Inc
in IncludesList
:
3627 if Inc
not in self
._IncludePathList
:
3628 self
._IncludePathList
.append(str(Inc
))
3629 return self
._IncludePathList
3631 def _GetIncludePathLength(self
):
3632 self
._IncludePathLength
= 0
3633 if self
._IncludePathList
:
3634 for inc
in self
._IncludePathList
:
3635 self
._IncludePathLength
+= len(' ' + inc
)
3636 return self
._IncludePathLength
3638 ## Get HII EX PCDs which maybe used by VFR
3640 # efivarstore used by VFR may relate with HII EX PCDs
3641 # Get the variable name and GUID from efivarstore and HII EX PCD
3642 # List the HII EX PCDs in As Built INF if both name and GUID match.
3644 # @retval list HII EX PCDs
3646 def _GetPcdsMaybeUsedByVfr(self
):
3647 if not self
.SourceFileList
:
3651 for SrcFile
in self
.SourceFileList
:
3652 if SrcFile
.Ext
.lower() != '.vfr':
3654 Vfri
= os
.path
.join(self
.OutputDir
, SrcFile
.BaseName
+ '.i')
3655 if not os
.path
.exists(Vfri
):
3657 VfriFile
= open(Vfri
, 'r')
3658 Content
= VfriFile
.read()
3660 Pos
= Content
.find('efivarstore')
3663 # Make sure 'efivarstore' is the start of efivarstore statement
3664 # In case of the value of 'name' (name = efivarstore) is equal to 'efivarstore'
3667 while Index
>= 0 and Content
[Index
] in ' \t\r\n':
3669 if Index
>= 0 and Content
[Index
] != ';':
3670 Pos
= Content
.find('efivarstore', Pos
+ len('efivarstore'))
3673 # 'efivarstore' must be followed by name and guid
3675 Name
= gEfiVarStoreNamePattern
.search(Content
, Pos
)
3678 Guid
= gEfiVarStoreGuidPattern
.search(Content
, Pos
)
3681 NameArray
= ConvertStringToByteArray('L"' + Name
.group(1) + '"')
3682 NameGuids
.add((NameArray
, GuidStructureStringToGuidString(Guid
.group(1))))
3683 Pos
= Content
.find('efivarstore', Name
.end())
3687 for Pcd
in self
.PlatformInfo
.Platform
.Pcds
.values():
3688 if Pcd
.Type
!= TAB_PCDS_DYNAMIC_EX_HII
:
3690 for SkuName
in Pcd
.SkuInfoList
:
3691 SkuInfo
= Pcd
.SkuInfoList
[SkuName
]
3692 Name
= ConvertStringToByteArray(SkuInfo
.VariableName
)
3693 Value
= GuidValue(SkuInfo
.VariableGuid
, self
.PlatformInfo
.PackageList
, self
.MetaFile
.Path
)
3696 Guid
= GuidStructureStringToGuidString(Value
)
3697 if (Name
, Guid
) in NameGuids
and Pcd
not in HiiExPcds
:
3698 HiiExPcds
.append(Pcd
)
3703 def _GenOffsetBin(self
):
3705 for SourceFile
in self
.Module
.Sources
:
3706 if SourceFile
.Type
.upper() == ".VFR" :
3708 # search the .map file to find the offset of vfr binary in the PE32+/TE file.
3710 VfrUniBaseName
[SourceFile
.BaseName
] = (SourceFile
.BaseName
+ "Bin")
3711 if SourceFile
.Type
.upper() == ".UNI" :
3713 # search the .map file to find the offset of Uni strings binary in the PE32+/TE file.
3715 VfrUniBaseName
["UniOffsetName"] = (self
.Name
+ "Strings")
3717 if len(VfrUniBaseName
) == 0:
3719 MapFileName
= os
.path
.join(self
.OutputDir
, self
.Name
+ ".map")
3720 EfiFileName
= os
.path
.join(self
.OutputDir
, self
.Name
+ ".efi")
3721 VfrUniOffsetList
= GetVariableOffset(MapFileName
, EfiFileName
, VfrUniBaseName
.values())
3722 if not VfrUniOffsetList
:
3725 OutputName
= '%sOffset.bin' % self
.Name
3726 UniVfrOffsetFileName
= os
.path
.join( self
.OutputDir
, OutputName
)
3729 fInputfile
= open(UniVfrOffsetFileName
, "wb+", 0)
3731 EdkLogger
.error("build", FILE_OPEN_FAILURE
, "File open failed for %s" % UniVfrOffsetFileName
,None)
3733 # Use a instance of StringIO to cache data
3734 fStringIO
= StringIO('')
3736 for Item
in VfrUniOffsetList
:
3737 if (Item
[0].find("Strings") != -1):
3739 # UNI offset in image.
3741 # { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } }
3743 UniGuid
= [0xe0, 0xc5, 0x13, 0x89, 0xf6, 0x33, 0x86, 0x4d, 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66]
3744 UniGuid
= [chr(ItemGuid
) for ItemGuid
in UniGuid
]
3745 fStringIO
.write(''.join(UniGuid
))
3746 UniValue
= pack ('Q', int (Item
[1], 16))
3747 fStringIO
.write (UniValue
)
3750 # VFR binary offset in image.
3752 # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } };
3754 VfrGuid
= [0xb4, 0x7c, 0xbc, 0xd0, 0x47, 0x6a, 0x5f, 0x49, 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2]
3755 VfrGuid
= [chr(ItemGuid
) for ItemGuid
in VfrGuid
]
3756 fStringIO
.write(''.join(VfrGuid
))
3757 VfrValue
= pack ('Q', int (Item
[1], 16))
3758 fStringIO
.write (VfrValue
)
3760 # write data into file.
3763 fInputfile
.write (fStringIO
.getvalue())
3765 EdkLogger
.error("build", FILE_WRITE_FAILURE
, "Write data to file %s failed, please check whether the "
3766 "file been locked or using by other applications." %UniVfrOffsetFileName
,None)
3772 ## Create AsBuilt INF file the module
3774 def CreateAsBuiltInf(self
, IsOnlyCopy
= False):
3775 self
.OutputFile
= set()
3777 if GlobalData
.gBinCacheDest
:
3778 self
.CopyModuleToCache()
3781 if self
.IsAsBuiltInfCreated
:
3784 # Skip the following code for EDK I inf
3785 if self
.AutoGenVersion
< 0x00010005:
3788 # Skip the following code for libraries
3792 # Skip the following code for modules with no source files
3793 if not self
.SourceFileList
:
3796 # Skip the following code for modules without any binary files
3797 if self
.BinaryFileList
:
3800 ### TODO: How to handles mixed source and binary modules
3802 # Find all DynamicEx and PatchableInModule PCDs used by this module and dependent libraries
3803 # Also find all packages that the DynamicEx PCDs depend on
3808 PcdTokenSpaceList
= []
3809 for Pcd
in self
.ModulePcdList
+ self
.LibraryPcdList
:
3810 if Pcd
.Type
== TAB_PCDS_PATCHABLE_IN_MODULE
:
3811 PatchablePcds
+= [Pcd
]
3812 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, TAB_PCDS_PATCHABLE_IN_MODULE
))
3813 elif Pcd
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
3816 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, TAB_PCDS_DYNAMIC_EX
))
3817 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, TAB_PCDS_DYNAMIC
))
3818 PcdTokenSpaceList
.append(Pcd
.TokenSpaceGuidCName
)
3819 GuidList
= OrderedDict()
3820 GuidList
.update(self
.GuidList
)
3821 for TokenSpace
in self
.GetGuidsUsedByPcd():
3822 # If token space is not referred by patch PCD or Ex PCD, remove the GUID from GUID list
3823 # The GUIDs in GUIDs section should really be the GUIDs in source INF or referred by Ex an patch PCDs
3824 if TokenSpace
not in PcdTokenSpaceList
and TokenSpace
in GuidList
:
3825 GuidList
.pop(TokenSpace
)
3826 CheckList
= (GuidList
, self
.PpiList
, self
.ProtocolList
, PcdCheckList
)
3827 for Package
in self
.DerivedPackageList
:
3828 if Package
in Packages
:
3830 BeChecked
= (Package
.Guids
, Package
.Ppis
, Package
.Protocols
, Package
.Pcds
)
3832 for Index
in range(len(BeChecked
)):
3833 for Item
in CheckList
[Index
]:
3834 if Item
in BeChecked
[Index
]:
3835 Packages
+= [Package
]
3840 VfrPcds
= self
._GetPcdsMaybeUsedByVfr
()
3841 for Pkg
in self
.PlatformInfo
.PackageList
:
3844 for VfrPcd
in VfrPcds
:
3845 if ((VfrPcd
.TokenCName
, VfrPcd
.TokenSpaceGuidCName
, TAB_PCDS_DYNAMIC_EX
) in Pkg
.Pcds
or
3846 (VfrPcd
.TokenCName
, VfrPcd
.TokenSpaceGuidCName
, TAB_PCDS_DYNAMIC
) in Pkg
.Pcds
):
3850 ModuleType
= self
.ModuleType
3851 if ModuleType
== SUP_MODULE_UEFI_DRIVER
and self
.DepexGenerated
:
3852 ModuleType
= SUP_MODULE_DXE_DRIVER
3855 if self
.PcdIsDriver
!= '':
3856 DriverType
= self
.PcdIsDriver
3859 MDefs
= self
.Module
.Defines
3862 'module_name' : self
.Name
,
3863 'module_guid' : Guid
,
3864 'module_module_type' : ModuleType
,
3865 'module_version_string' : [MDefs
['VERSION_STRING']] if 'VERSION_STRING' in MDefs
else [],
3866 'pcd_is_driver_string' : [],
3867 'module_uefi_specification_version' : [],
3868 'module_pi_specification_version' : [],
3869 'module_entry_point' : self
.Module
.ModuleEntryPointList
,
3870 'module_unload_image' : self
.Module
.ModuleUnloadImageList
,
3871 'module_constructor' : self
.Module
.ConstructorList
,
3872 'module_destructor' : self
.Module
.DestructorList
,
3873 'module_shadow' : [MDefs
['SHADOW']] if 'SHADOW' in MDefs
else [],
3874 'module_pci_vendor_id' : [MDefs
['PCI_VENDOR_ID']] if 'PCI_VENDOR_ID' in MDefs
else [],
3875 'module_pci_device_id' : [MDefs
['PCI_DEVICE_ID']] if 'PCI_DEVICE_ID' in MDefs
else [],
3876 'module_pci_class_code' : [MDefs
['PCI_CLASS_CODE']] if 'PCI_CLASS_CODE' in MDefs
else [],
3877 'module_pci_revision' : [MDefs
['PCI_REVISION']] if 'PCI_REVISION' in MDefs
else [],
3878 'module_build_number' : [MDefs
['BUILD_NUMBER']] if 'BUILD_NUMBER' in MDefs
else [],
3879 'module_spec' : [MDefs
['SPEC']] if 'SPEC' in MDefs
else [],
3880 'module_uefi_hii_resource_section' : [MDefs
['UEFI_HII_RESOURCE_SECTION']] if 'UEFI_HII_RESOURCE_SECTION' in MDefs
else [],
3881 'module_uni_file' : [MDefs
['MODULE_UNI_FILE']] if 'MODULE_UNI_FILE' in MDefs
else [],
3882 'module_arch' : self
.Arch
,
3883 'package_item' : ['%s' % (Package
.MetaFile
.File
.replace('\\', '/')) for Package
in Packages
],
3885 'patchablepcd_item' : [],
3887 'protocol_item' : [],
3891 'libraryclasses_item' : []
3894 if 'MODULE_UNI_FILE' in MDefs
:
3895 UNIFile
= os
.path
.join(self
.MetaFile
.Dir
, MDefs
['MODULE_UNI_FILE'])
3896 if os
.path
.isfile(UNIFile
):
3897 shutil
.copy2(UNIFile
, self
.OutputDir
)
3899 if self
.AutoGenVersion
> int(gInfSpecVersion
, 0):
3900 AsBuiltInfDict
['module_inf_version'] = '0x%08x' % self
.AutoGenVersion
3902 AsBuiltInfDict
['module_inf_version'] = gInfSpecVersion
3905 AsBuiltInfDict
['pcd_is_driver_string'] += [DriverType
]
3907 if 'UEFI_SPECIFICATION_VERSION' in self
.Specification
:
3908 AsBuiltInfDict
['module_uefi_specification_version'] += [self
.Specification
['UEFI_SPECIFICATION_VERSION']]
3909 if 'PI_SPECIFICATION_VERSION' in self
.Specification
:
3910 AsBuiltInfDict
['module_pi_specification_version'] += [self
.Specification
['PI_SPECIFICATION_VERSION']]
3912 OutputDir
= self
.OutputDir
.replace('\\', '/').strip('/')
3913 DebugDir
= self
.DebugDir
.replace('\\', '/').strip('/')
3914 for Item
in self
.CodaTargetList
:
3915 File
= Item
.Target
.Path
.replace('\\', '/').strip('/').replace(DebugDir
, '').replace(OutputDir
, '').strip('/')
3916 self
.OutputFile
.add(File
)
3917 if os
.path
.isabs(File
):
3918 File
= File
.replace('\\', '/').strip('/').replace(OutputDir
, '').strip('/')
3919 if Item
.Target
.Ext
.lower() == '.aml':
3920 AsBuiltInfDict
['binary_item'] += ['ASL|' + File
]
3921 elif Item
.Target
.Ext
.lower() == '.acpi':
3922 AsBuiltInfDict
['binary_item'] += ['ACPI|' + File
]
3923 elif Item
.Target
.Ext
.lower() == '.efi':
3924 AsBuiltInfDict
['binary_item'] += ['PE32|' + self
.Name
+ '.efi']
3926 AsBuiltInfDict
['binary_item'] += ['BIN|' + File
]
3927 if self
.DepexGenerated
:
3928 self
.OutputFile
.add(self
.Name
+ '.depex')
3929 if self
.ModuleType
in [SUP_MODULE_PEIM
]:
3930 AsBuiltInfDict
['binary_item'] += ['PEI_DEPEX|' + self
.Name
+ '.depex']
3931 if self
.ModuleType
in [SUP_MODULE_DXE_DRIVER
, SUP_MODULE_DXE_RUNTIME_DRIVER
, SUP_MODULE_DXE_SAL_DRIVER
, SUP_MODULE_UEFI_DRIVER
]:
3932 AsBuiltInfDict
['binary_item'] += ['DXE_DEPEX|' + self
.Name
+ '.depex']
3933 if self
.ModuleType
in [SUP_MODULE_DXE_SMM_DRIVER
]:
3934 AsBuiltInfDict
['binary_item'] += ['SMM_DEPEX|' + self
.Name
+ '.depex']
3936 Bin
= self
._GenOffsetBin
()
3938 AsBuiltInfDict
['binary_item'] += ['BIN|%s' % Bin
]
3939 self
.OutputFile
.add(Bin
)
3941 for Root
, Dirs
, Files
in os
.walk(OutputDir
):
3943 if File
.lower().endswith('.pdb'):
3944 AsBuiltInfDict
['binary_item'] += ['DISPOSABLE|' + File
]
3945 self
.OutputFile
.add(File
)
3946 HeaderComments
= self
.Module
.HeaderComments
3948 for Index
in range(len(HeaderComments
)):
3949 if HeaderComments
[Index
].find('@BinaryHeader') != -1:
3950 HeaderComments
[Index
] = HeaderComments
[Index
].replace('@BinaryHeader', '@file')
3953 AsBuiltInfDict
['header_comments'] = '\n'.join(HeaderComments
[StartPos
:]).replace(':#', '://')
3954 AsBuiltInfDict
['tail_comments'] = '\n'.join(self
.Module
.TailComments
)
3957 (self
.ProtocolList
, self
._ProtocolComments
, 'protocol_item'),
3958 (self
.PpiList
, self
._PpiComments
, 'ppi_item'),
3959 (GuidList
, self
._GuidComments
, 'guid_item')
3961 for Item
in GenList
:
3962 for CName
in Item
[0]:
3964 if CName
in Item
[1]:
3965 Comments
= '\n '.join(Item
[1][CName
])
3968 Entry
= Comments
+ '\n ' + CName
3969 AsBuiltInfDict
[Item
[2]].append(Entry
)
3970 PatchList
= parsePcdInfoFromMapFile(
3971 os
.path
.join(self
.OutputDir
, self
.Name
+ '.map'),
3972 os
.path
.join(self
.OutputDir
, self
.Name
+ '.efi')
3975 for Pcd
in PatchablePcds
:
3976 TokenCName
= Pcd
.TokenCName
3977 for PcdItem
in GlobalData
.MixedPcd
:
3978 if (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
3979 TokenCName
= PcdItem
[0]
3981 for PatchPcd
in PatchList
:
3982 if TokenCName
== PatchPcd
[0]:
3987 if Pcd
.DatumType
== 'BOOLEAN':
3988 BoolValue
= Pcd
.DefaultValue
.upper()
3989 if BoolValue
== 'TRUE':
3990 Pcd
.DefaultValue
= '1'
3991 elif BoolValue
== 'FALSE':
3992 Pcd
.DefaultValue
= '0'
3994 if Pcd
.DatumType
in TAB_PCD_NUMERIC_TYPES
:
3995 HexFormat
= '0x%02x'
3996 if Pcd
.DatumType
== TAB_UINT16
:
3997 HexFormat
= '0x%04x'
3998 elif Pcd
.DatumType
== TAB_UINT32
:
3999 HexFormat
= '0x%08x'
4000 elif Pcd
.DatumType
== TAB_UINT64
:
4001 HexFormat
= '0x%016x'
4002 PcdValue
= HexFormat
% int(Pcd
.DefaultValue
, 0)
4004 if Pcd
.MaxDatumSize
is None or Pcd
.MaxDatumSize
== '':
4005 EdkLogger
.error("build", AUTOGEN_ERROR
,
4006 "Unknown [MaxDatumSize] of PCD [%s.%s]" % (Pcd
.TokenSpaceGuidCName
, TokenCName
)
4008 ArraySize
= int(Pcd
.MaxDatumSize
, 0)
4009 PcdValue
= Pcd
.DefaultValue
4010 if PcdValue
[0] != '{':
4012 if PcdValue
[0] == 'L':
4014 PcdValue
= PcdValue
.lstrip('L')
4015 PcdValue
= eval(PcdValue
)
4017 for Index
in range(0, len(PcdValue
)):
4019 CharVal
= ord(PcdValue
[Index
])
4020 NewValue
= NewValue
+ '0x%02x' % (CharVal
& 0x00FF) + ', ' \
4021 + '0x%02x' % (CharVal
>> 8) + ', '
4023 NewValue
= NewValue
+ '0x%02x' % (ord(PcdValue
[Index
]) % 0x100) + ', '
4026 Padding
= Padding
* 2
4027 ArraySize
= ArraySize
/ 2
4028 if ArraySize
< (len(PcdValue
) + 1):
4029 if Pcd
.MaxSizeUserSet
:
4030 EdkLogger
.error("build", AUTOGEN_ERROR
,
4031 "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd
.TokenSpaceGuidCName
, TokenCName
)
4034 ArraySize
= len(PcdValue
) + 1
4035 if ArraySize
> len(PcdValue
) + 1:
4036 NewValue
= NewValue
+ Padding
* (ArraySize
- len(PcdValue
) - 1)
4037 PcdValue
= NewValue
+ Padding
.strip().rstrip(',') + '}'
4038 elif len(PcdValue
.split(',')) <= ArraySize
:
4039 PcdValue
= PcdValue
.rstrip('}') + ', 0x00' * (ArraySize
- len(PcdValue
.split(',')))
4042 if Pcd
.MaxSizeUserSet
:
4043 EdkLogger
.error("build", AUTOGEN_ERROR
,
4044 "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd
.TokenSpaceGuidCName
, TokenCName
)
4047 ArraySize
= len(PcdValue
) + 1
4048 PcdItem
= '%s.%s|%s|0x%X' % \
4049 (Pcd
.TokenSpaceGuidCName
, TokenCName
, PcdValue
, PatchPcd
[1])
4051 if (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) in self
._PcdComments
:
4052 PcdComments
= '\n '.join(self
._PcdComments
[Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
])
4054 PcdItem
= PcdComments
+ '\n ' + PcdItem
4055 AsBuiltInfDict
['patchablepcd_item'].append(PcdItem
)
4058 for Pcd
in Pcds
+ VfrPcds
:
4063 TokenCName
= Pcd
.TokenCName
4064 for PcdItem
in GlobalData
.MixedPcd
:
4065 if (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
4066 TokenCName
= PcdItem
[0]
4068 if Pcd
.Type
== TAB_PCDS_DYNAMIC_EX_HII
:
4069 for SkuName
in Pcd
.SkuInfoList
:
4070 SkuInfo
= Pcd
.SkuInfoList
[SkuName
]
4071 SkuId
= SkuInfo
.SkuId
4072 HiiInfo
= '## %s|%s|%s' % (SkuInfo
.VariableName
, SkuInfo
.VariableGuid
, SkuInfo
.VariableOffset
)
4076 # Don't generate duplicated HII PCD
4078 if (SkuId
, Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) in HiiPcds
:
4080 HiiPcds
.add((SkuId
, Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
4081 if (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) in self
._PcdComments
:
4082 PcdCommentList
= self
._PcdComments
[Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
][:]
4086 for Index
, Comment
in enumerate(PcdCommentList
):
4087 for Usage
in UsageList
:
4088 if Comment
.find(Usage
) != -1:
4092 if UsageIndex
!= -1:
4093 PcdCommentList
[UsageIndex
] = '## %s %s %s' % (UsageStr
, HiiInfo
, PcdCommentList
[UsageIndex
].replace(UsageStr
, ''))
4095 PcdCommentList
.append('## UNDEFINED ' + HiiInfo
)
4096 PcdComments
= '\n '.join(PcdCommentList
)
4097 PcdEntry
= Pcd
.TokenSpaceGuidCName
+ '.' + TokenCName
4099 PcdEntry
= PcdComments
+ '\n ' + PcdEntry
4100 AsBuiltInfDict
['pcd_item'] += [PcdEntry
]
4101 for Item
in self
.BuildOption
:
4102 if 'FLAGS' in self
.BuildOption
[Item
]:
4103 AsBuiltInfDict
['flags_item'] += ['%s:%s_%s_%s_%s_FLAGS = %s' % (self
.ToolChainFamily
, self
.BuildTarget
, self
.ToolChain
, self
.Arch
, Item
, self
.BuildOption
[Item
]['FLAGS'].strip())]
4105 # Generated LibraryClasses section in comments.
4106 for Library
in self
.LibraryAutoGenList
:
4107 AsBuiltInfDict
['libraryclasses_item'] += [Library
.MetaFile
.File
.replace('\\', '/')]
4109 # Generated UserExtensions TianoCore section.
4110 # All tianocore user extensions are copied.
4112 for TianoCore
in self
._GetTianoCoreUserExtensionList
():
4113 UserExtStr
+= '\n'.join(TianoCore
)
4114 ExtensionFile
= os
.path
.join(self
.MetaFile
.Dir
, TianoCore
[1])
4115 if os
.path
.isfile(ExtensionFile
):
4116 shutil
.copy2(ExtensionFile
, self
.OutputDir
)
4117 AsBuiltInfDict
['userextension_tianocore_item'] = UserExtStr
4119 # Generated depex expression section in comments.
4120 AsBuiltInfDict
['depexsection_item'] = ''
4121 DepexExpresion
= self
._GetDepexExpresionString
()
4123 AsBuiltInfDict
['depexsection_item'] = DepexExpresion
4125 AsBuiltInf
= TemplateString()
4126 AsBuiltInf
.Append(gAsBuiltInfHeaderString
.Replace(AsBuiltInfDict
))
4128 SaveFileOnChange(os
.path
.join(self
.OutputDir
, self
.Name
+ '.inf'), str(AsBuiltInf
), False)
4130 self
.IsAsBuiltInfCreated
= True
4131 if GlobalData
.gBinCacheDest
:
4132 self
.CopyModuleToCache()
4134 def CopyModuleToCache(self
):
4135 FileDir
= path
.join(GlobalData
.gBinCacheDest
, self
.Arch
, self
.SourceDir
, self
.MetaFile
.BaseName
)
4136 CreateDirectory (FileDir
)
4137 HashFile
= path
.join(self
.BuildDir
, self
.Name
+ '.hash')
4138 ModuleFile
= path
.join(self
.OutputDir
, self
.Name
+ '.inf')
4139 if os
.path
.exists(HashFile
):
4140 shutil
.copy2(HashFile
, FileDir
)
4141 if os
.path
.exists(ModuleFile
):
4142 shutil
.copy2(ModuleFile
, FileDir
)
4143 if not self
.OutputFile
:
4144 Ma
= self
.Workspace
.BuildDatabase
[PathClass(ModuleFile
), self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
4145 self
.OutputFile
= Ma
.Binaries
4147 for File
in self
.OutputFile
:
4149 if not os
.path
.isabs(File
):
4150 File
= os
.path
.join(self
.OutputDir
, File
)
4151 if os
.path
.exists(File
):
4152 shutil
.copy2(File
, FileDir
)
4154 def AttemptModuleCacheCopy(self
):
4155 if self
.IsBinaryModule
:
4157 FileDir
= path
.join(GlobalData
.gBinCacheSource
, self
.Arch
, self
.SourceDir
, self
.MetaFile
.BaseName
)
4158 HashFile
= path
.join(FileDir
, self
.Name
+ '.hash')
4159 if os
.path
.exists(HashFile
):
4160 f
= open(HashFile
, 'r')
4161 CacheHash
= f
.read()
4163 if GlobalData
.gModuleHash
[self
.Arch
][self
.Name
]:
4164 if CacheHash
== GlobalData
.gModuleHash
[self
.Arch
][self
.Name
]:
4165 for root
, dir, files
in os
.walk(FileDir
):
4167 if self
.Name
+ '.hash' in f
:
4168 shutil
.copy2(HashFile
, self
.BuildDir
)
4170 File
= path
.join(root
, f
)
4171 shutil
.copy2(File
, self
.OutputDir
)
4172 if self
.Name
== "PcdPeim" or self
.Name
== "PcdDxe":
4173 CreatePcdDatabaseCode(self
, TemplateString(), TemplateString())
4177 ## Create makefile for the module and its dependent libraries
4179 # @param CreateLibraryMakeFile Flag indicating if or not the makefiles of
4180 # dependent libraries will be created
4182 def CreateMakeFile(self
, CreateLibraryMakeFile
=True, GenFfsList
= []):
4183 # Ignore generating makefile when it is a binary module
4184 if self
.IsBinaryModule
:
4187 if self
.IsMakeFileCreated
:
4189 self
.GenFfsList
= GenFfsList
4190 if not self
.IsLibrary
and CreateLibraryMakeFile
:
4191 for LibraryAutoGen
in self
.LibraryAutoGenList
:
4192 LibraryAutoGen
.CreateMakeFile()
4197 if len(self
.CustomMakefile
) == 0:
4198 Makefile
= GenMake
.ModuleMakefile(self
)
4200 Makefile
= GenMake
.CustomMakefile(self
)
4201 if Makefile
.Generate():
4202 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated makefile for module %s [%s]" %
4203 (self
.Name
, self
.Arch
))
4205 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Skipped the generation of makefile for module %s [%s]" %
4206 (self
.Name
, self
.Arch
))
4208 self
.CreateTimeStamp(Makefile
)
4209 self
.IsMakeFileCreated
= True
4211 def CopyBinaryFiles(self
):
4212 for File
in self
.Module
.Binaries
:
4214 DstPath
= os
.path
.join(self
.OutputDir
, os
.path
.basename(SrcPath
))
4215 CopyLongFilePath(SrcPath
, DstPath
)
4216 ## Create autogen code for the module and its dependent libraries
4218 # @param CreateLibraryCodeFile Flag indicating if or not the code of
4219 # dependent libraries will be created
4221 def CreateCodeFile(self
, CreateLibraryCodeFile
=True):
4222 if self
.IsCodeFileCreated
:
4225 # Need to generate PcdDatabase even PcdDriver is binarymodule
4226 if self
.IsBinaryModule
and self
.PcdIsDriver
!= '':
4227 CreatePcdDatabaseCode(self
, TemplateString(), TemplateString())
4229 if self
.IsBinaryModule
:
4231 self
.CopyBinaryFiles()
4234 if not self
.IsLibrary
and CreateLibraryCodeFile
:
4235 for LibraryAutoGen
in self
.LibraryAutoGenList
:
4236 LibraryAutoGen
.CreateCodeFile()
4242 IgoredAutoGenList
= []
4244 for File
in self
.AutoGenFileList
:
4245 if GenC
.Generate(File
.Path
, self
.AutoGenFileList
[File
], File
.IsBinary
):
4246 #Ignore Edk AutoGen.c
4247 if self
.AutoGenVersion
< 0x00010005 and File
.Name
== 'AutoGen.c':
4250 AutoGenList
.append(str(File
))
4252 IgoredAutoGenList
.append(str(File
))
4254 # Skip the following code for EDK I inf
4255 if self
.AutoGenVersion
< 0x00010005:
4258 for ModuleType
in self
.DepexList
:
4259 # Ignore empty [depex] section or [depex] section for SUP_MODULE_USER_DEFINED module
4260 if len(self
.DepexList
[ModuleType
]) == 0 or ModuleType
== SUP_MODULE_USER_DEFINED
:
4263 Dpx
= GenDepex
.DependencyExpression(self
.DepexList
[ModuleType
], ModuleType
, True)
4264 DpxFile
= gAutoGenDepexFileName
% {"module_name" : self
.Name
}
4266 if len(Dpx
.PostfixNotation
) <> 0:
4267 self
.DepexGenerated
= True
4269 if Dpx
.Generate(path
.join(self
.OutputDir
, DpxFile
)):
4270 AutoGenList
.append(str(DpxFile
))
4272 IgoredAutoGenList
.append(str(DpxFile
))
4274 if IgoredAutoGenList
== []:
4275 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated [%s] files for module %s [%s]" %
4276 (" ".join(AutoGenList
), self
.Name
, self
.Arch
))
4277 elif AutoGenList
== []:
4278 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Skipped the generation of [%s] files for module %s [%s]" %
4279 (" ".join(IgoredAutoGenList
), self
.Name
, self
.Arch
))
4281 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated [%s] (skipped %s) files for module %s [%s]" %
4282 (" ".join(AutoGenList
), " ".join(IgoredAutoGenList
), self
.Name
, self
.Arch
))
4284 self
.IsCodeFileCreated
= True
4287 ## Summarize the ModuleAutoGen objects of all libraries used by this module
4288 def _GetLibraryAutoGenList(self
):
4289 if self
._LibraryAutoGenList
is None:
4290 self
._LibraryAutoGenList
= []
4291 for Library
in self
.DependentLibraryList
:
4298 self
.PlatformInfo
.MetaFile
4300 if La
not in self
._LibraryAutoGenList
:
4301 self
._LibraryAutoGenList
.append(La
)
4302 for Lib
in La
.CodaTargetList
:
4303 self
._ApplyBuildRule
(Lib
.Target
, TAB_UNKNOWN_FILE
)
4304 return self
._LibraryAutoGenList
4306 def GenModuleHash(self
):
4307 if self
.Arch
not in GlobalData
.gModuleHash
:
4308 GlobalData
.gModuleHash
[self
.Arch
] = {}
4310 # Add Platform level hash
4311 m
.update(GlobalData
.gPlatformHash
)
4312 # Add Package level hash
4313 if self
.DependentPackageList
:
4314 for Pkg
in sorted(self
.DependentPackageList
, key
=lambda x
: x
.PackageName
):
4315 if Pkg
.PackageName
in GlobalData
.gPackageHash
[self
.Arch
]:
4316 m
.update(GlobalData
.gPackageHash
[self
.Arch
][Pkg
.PackageName
])
4319 if self
.LibraryAutoGenList
:
4320 for Lib
in sorted(self
.LibraryAutoGenList
, key
=lambda x
: x
.Name
):
4321 if Lib
.Name
not in GlobalData
.gModuleHash
[self
.Arch
]:
4323 m
.update(GlobalData
.gModuleHash
[self
.Arch
][Lib
.Name
])
4326 f
= open(str(self
.MetaFile
), 'r')
4330 # Add Module's source files
4331 if self
.SourceFileList
:
4332 for File
in sorted(self
.SourceFileList
, key
=lambda x
: str(x
)):
4333 f
= open(str(File
), 'r')
4338 ModuleHashFile
= path
.join(self
.BuildDir
, self
.Name
+ ".hash")
4339 if self
.Name
not in GlobalData
.gModuleHash
[self
.Arch
]:
4340 GlobalData
.gModuleHash
[self
.Arch
][self
.Name
] = m
.hexdigest()
4341 if GlobalData
.gBinCacheSource
:
4342 CacheValid
= self
.AttemptModuleCacheCopy()
4345 return SaveFileOnChange(ModuleHashFile
, m
.hexdigest(), True)
4347 ## Decide whether we can skip the ModuleAutoGen process
4348 def CanSkipbyHash(self
):
4349 if GlobalData
.gUseHashCache
:
4350 return not self
.GenModuleHash()
4352 ## Decide whether we can skip the ModuleAutoGen process
4353 # If any source file is newer than the module than we cannot skip
4356 if not os
.path
.exists(self
.GetTimeStampPath()):
4358 #last creation time of the module
4359 DstTimeStamp
= os
.stat(self
.GetTimeStampPath())[8]
4361 SrcTimeStamp
= self
.Workspace
._SrcTimeStamp
4362 if SrcTimeStamp
> DstTimeStamp
:
4365 with
open(self
.GetTimeStampPath(),'r') as f
:
4367 source
= source
.rstrip('\n')
4368 if not os
.path
.exists(source
):
4370 if source
not in ModuleAutoGen
.TimeDict
:
4371 ModuleAutoGen
.TimeDict
[source
] = os
.stat(source
)[8]
4372 if ModuleAutoGen
.TimeDict
[source
] > DstTimeStamp
:
4376 def GetTimeStampPath(self
):
4377 if self
._TimeStampPath
is None:
4378 self
._TimeStampPath
= os
.path
.join(self
.MakeFileDir
, 'AutoGenTimeStamp')
4379 return self
._TimeStampPath
4380 def CreateTimeStamp(self
, Makefile
):
4384 FileSet
.add (self
.MetaFile
.Path
)
4386 for SourceFile
in self
.Module
.Sources
:
4387 FileSet
.add (SourceFile
.Path
)
4389 for Lib
in self
.DependentLibraryList
:
4390 FileSet
.add (Lib
.MetaFile
.Path
)
4392 for f
in self
.AutoGenDepSet
:
4393 FileSet
.add (f
.Path
)
4395 if os
.path
.exists (self
.GetTimeStampPath()):
4396 os
.remove (self
.GetTimeStampPath())
4397 with
open(self
.GetTimeStampPath(), 'w+') as file:
4401 Module
= property(_GetModule
)
4402 Name
= property(_GetBaseName
)
4403 Guid
= property(_GetGuid
)
4404 Version
= property(_GetVersion
)
4405 ModuleType
= property(_GetModuleType
)
4406 ComponentType
= property(_GetComponentType
)
4407 BuildType
= property(_GetBuildType
)
4408 PcdIsDriver
= property(_GetPcdIsDriver
)
4409 AutoGenVersion
= property(_GetAutoGenVersion
)
4410 Macros
= property(_GetMacros
)
4411 Specification
= property(_GetSpecification
)
4413 IsLibrary
= property(_IsLibrary
)
4414 IsBinaryModule
= property(_IsBinaryModule
)
4415 BuildDir
= property(_GetBuildDir
)
4416 OutputDir
= property(_GetOutputDir
)
4417 FfsOutputDir
= property(_GetFfsOutputDir
)
4418 DebugDir
= property(_GetDebugDir
)
4419 MakeFileDir
= property(_GetMakeFileDir
)
4420 CustomMakefile
= property(_GetCustomMakefile
)
4422 IncludePathList
= property(_GetIncludePathList
)
4423 IncludePathLength
= property(_GetIncludePathLength
)
4424 AutoGenFileList
= property(_GetAutoGenFileList
)
4425 UnicodeFileList
= property(_GetUnicodeFileList
)
4426 VfrFileList
= property(_GetVfrFileList
)
4427 SourceFileList
= property(_GetSourceFileList
)
4428 BinaryFileList
= property(_GetBinaryFiles
) # FileType : [File List]
4429 Targets
= property(_GetTargets
)
4430 IntroTargetList
= property(_GetIntroTargetList
)
4431 CodaTargetList
= property(_GetFinalTargetList
)
4432 FileTypes
= property(_GetFileTypes
)
4433 BuildRules
= property(_GetBuildRules
)
4434 IdfFileList
= property(_GetIdfFileList
)
4436 DependentPackageList
= property(_GetDependentPackageList
)
4437 DependentLibraryList
= property(_GetLibraryList
)
4438 LibraryAutoGenList
= property(_GetLibraryAutoGenList
)
4439 DerivedPackageList
= property(_GetDerivedPackageList
)
4441 ModulePcdList
= property(_GetModulePcdList
)
4442 LibraryPcdList
= property(_GetLibraryPcdList
)
4443 GuidList
= property(_GetGuidList
)
4444 ProtocolList
= property(_GetProtocolList
)
4445 PpiList
= property(_GetPpiList
)
4446 DepexList
= property(_GetDepexTokenList
)
4447 DxsFile
= property(_GetDxsFile
)
4448 DepexExpressionList
= property(_GetDepexExpressionTokenList
)
4449 BuildOption
= property(_GetModuleBuildOption
)
4450 BuildOptionIncPathList
= property(_GetBuildOptionIncPathList
)
4451 BuildCommand
= property(_GetBuildCommand
)
4453 FixedAtBuildPcds
= property(_GetFixedAtBuildPcds
)
4455 # This acts like the main() function for the script, unless it is 'import'ed into another script.
4456 if __name__
== '__main__':