2 # Generate AutoGen.h, AutoGen.c and *.depex files
4 # Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
5 # This program and the accompanying materials
6 # are licensed and made available under the terms and conditions of the BSD License
7 # which accompanies this distribution. The full text of the license may be found at
8 # http://opensource.org/licenses/bsd-license.php
10 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 import Common
.LongFilePathOs
as os
18 import os
.path
as path
25 from StringIO
import StringIO
27 from StrGather
import *
28 from BuildEngine
import BuildRule
30 from Common
.LongFilePathSupport
import CopyLongFilePath
31 from Common
.BuildToolError
import *
32 from Common
.DataType
import *
33 from Common
.Misc
import *
34 from Common
.String
import *
35 import Common
.GlobalData
as GlobalData
36 from GenFds
.FdfParser
import *
37 from CommonDataClass
.CommonClass
import SkuInfoClass
38 from Workspace
.BuildClassObject
import *
39 from GenPatchPcdTable
.GenPatchPcdTable
import parsePcdInfoFromMapFile
40 import Common
.VpdInfoFile
as VpdInfoFile
41 from GenPcdDb
import CreatePcdDatabaseCode
42 from Workspace
.MetaFileCommentParser
import UsageList
43 from Common
.MultipleWorkspace
import MultipleWorkspace
as mws
44 import InfSectionParser
47 from GenVar
import VariableMgr
,var_info
48 from collections
import OrderedDict
50 ## Regular expression for splitting Dependency Expression string into tokens
51 gDepexTokenPattern
= re
.compile("(\(|\)|\w+| \S+\.inf)")
53 ## Regular expression for match: PCD(xxxx.yyy)
54 gPCDAsGuidPattern
= re
.compile(r
"^PCD\(.+\..+\)$")
57 # Regular expression for finding Include Directories, the difference between MSFT and INTEL/GCC/RVCT
58 # is the former use /I , the Latter used -I to specify include directories
60 gBuildOptIncludePatternMsft
= re
.compile(r
"(?:.*?)/I[ \t]*([^ ]*)", re
.MULTILINE | re
.DOTALL
)
61 gBuildOptIncludePatternOther
= re
.compile(r
"(?:.*?)-I[ \t]*([^ ]*)", re
.MULTILINE | re
.DOTALL
)
64 # Match name = variable
66 gEfiVarStoreNamePattern
= re
.compile("\s*name\s*=\s*(\w+)")
68 # The format of guid in efivarstore statement likes following and must be correct:
69 # guid = {0xA04A27f4, 0xDF00, 0x4D42, {0xB5, 0x52, 0x39, 0x51, 0x13, 0x02, 0x11, 0x3D}}
71 gEfiVarStoreGuidPattern
= re
.compile("\s*guid\s*=\s*({.*?{.*?}\s*})")
73 ## Mapping Makefile type
74 gMakeTypeMap
= {"MSFT":"nmake", "GCC":"gmake"}
77 ## Build rule configuration file
78 gDefaultBuildRuleFile
= 'build_rule.txt'
80 ## Tools definition configuration file
81 gDefaultToolsDefFile
= 'tools_def.txt'
83 ## Build rule default version
84 AutoGenReqBuildRuleVerNum
= "0.1"
86 ## default file name for AutoGen
87 gAutoGenCodeFileName
= "AutoGen.c"
88 gAutoGenHeaderFileName
= "AutoGen.h"
89 gAutoGenStringFileName
= "%(module_name)sStrDefs.h"
90 gAutoGenStringFormFileName
= "%(module_name)sStrDefs.hpk"
91 gAutoGenDepexFileName
= "%(module_name)s.depex"
92 gAutoGenImageDefFileName
= "%(module_name)sImgDefs.h"
93 gAutoGenIdfFileName
= "%(module_name)sIdf.hpk"
94 gInfSpecVersion
= "0x00010017"
97 # Template string to generic AsBuilt INF
99 gAsBuiltInfHeaderString
= TemplateString("""${header_comments}
102 # FILE auto-generated
105 INF_VERSION = ${module_inf_version}
106 BASE_NAME = ${module_name}
107 FILE_GUID = ${module_guid}
108 MODULE_TYPE = ${module_module_type}${BEGIN}
109 VERSION_STRING = ${module_version_string}${END}${BEGIN}
110 PCD_IS_DRIVER = ${pcd_is_driver_string}${END}${BEGIN}
111 UEFI_SPECIFICATION_VERSION = ${module_uefi_specification_version}${END}${BEGIN}
112 PI_SPECIFICATION_VERSION = ${module_pi_specification_version}${END}${BEGIN}
113 ENTRY_POINT = ${module_entry_point}${END}${BEGIN}
114 UNLOAD_IMAGE = ${module_unload_image}${END}${BEGIN}
115 CONSTRUCTOR = ${module_constructor}${END}${BEGIN}
116 DESTRUCTOR = ${module_destructor}${END}${BEGIN}
117 SHADOW = ${module_shadow}${END}${BEGIN}
118 PCI_VENDOR_ID = ${module_pci_vendor_id}${END}${BEGIN}
119 PCI_DEVICE_ID = ${module_pci_device_id}${END}${BEGIN}
120 PCI_CLASS_CODE = ${module_pci_class_code}${END}${BEGIN}
121 PCI_REVISION = ${module_pci_revision}${END}${BEGIN}
122 BUILD_NUMBER = ${module_build_number}${END}${BEGIN}
123 SPEC = ${module_spec}${END}${BEGIN}
124 UEFI_HII_RESOURCE_SECTION = ${module_uefi_hii_resource_section}${END}${BEGIN}
125 MODULE_UNI_FILE = ${module_uni_file}${END}
127 [Packages.${module_arch}]${BEGIN}
128 ${package_item}${END}
130 [Binaries.${module_arch}]${BEGIN}
133 [PatchPcd.${module_arch}]${BEGIN}
137 [Protocols.${module_arch}]${BEGIN}
141 [Ppis.${module_arch}]${BEGIN}
145 [Guids.${module_arch}]${BEGIN}
149 [PcdEx.${module_arch}]${BEGIN}
153 [LibraryClasses.${module_arch}]
154 ## @LIB_INSTANCES${BEGIN}
155 # ${libraryclasses_item}${END}
159 ${userextension_tianocore_item}
163 [BuildOptions.${module_arch}]
165 ## ${flags_item}${END}
168 ## Base class for AutoGen
170 # This class just implements the cache mechanism of AutoGen objects.
172 class AutoGen(object):
173 # database to maintain the objects in each child class
174 __ObjectCache
= {} # (BuildTarget, ToolChain, ARCH, platform file): AutoGen object
178 # @param Class class object of real AutoGen class
179 # (WorkspaceAutoGen, ModuleAutoGen or PlatformAutoGen)
180 # @param Workspace Workspace directory or WorkspaceAutoGen object
181 # @param MetaFile The path of meta file
182 # @param Target Build target
183 # @param Toolchain Tool chain name
184 # @param Arch Target arch
185 # @param *args The specific class related parameters
186 # @param **kwargs The specific class related dict parameters
188 def __new__(cls
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
189 # check if the object has been created
190 Key
= (Target
, Toolchain
, Arch
, MetaFile
)
192 # if it exists, just return it directly
193 return cls
.__ObjectCache
[Key
]
195 # it didnt exist. create it, cache it, then return it
196 cls
.__ObjectCache
[Key
] = super(AutoGen
, cls
).__new
__(cls
)
197 return cls
.__ObjectCache
[Key
]
199 def __init__ (self
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
200 super(AutoGen
, self
).__init
__(self
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
)
204 # The file path of platform file will be used to represent hash value of this object
206 # @retval int Hash value of the file path of platform file
209 return hash(self
.MetaFile
)
213 # The file path of platform file will be used to represent this object
215 # @retval string String of platform file path
218 return str(self
.MetaFile
)
221 def __eq__(self
, Other
):
222 return Other
and self
.MetaFile
== Other
224 ## Workspace AutoGen class
226 # This class is used mainly to control the whole platform build for different
227 # architecture. This class will generate top level makefile.
229 class WorkspaceAutoGen(AutoGen
):
230 # call super().__init__ then call the worker function with different parameter count
231 def __init__(self
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
235 super(WorkspaceAutoGen
, self
).__init
__(Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
)
236 self
._InitWorker
(Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
)
239 ## Initialize WorkspaceAutoGen
241 # @param WorkspaceDir Root directory of workspace
242 # @param ActivePlatform Meta-file of active platform
243 # @param Target Build target
244 # @param Toolchain Tool chain name
245 # @param ArchList List of architecture of current build
246 # @param MetaFileDb Database containing meta-files
247 # @param BuildConfig Configuration of build
248 # @param ToolDefinition Tool chain definitions
249 # @param FlashDefinitionFile File of flash definition
250 # @param Fds FD list to be generated
251 # @param Fvs FV list to be generated
252 # @param Caps Capsule list to be generated
253 # @param SkuId SKU id from command line
255 def _InitWorker(self
, WorkspaceDir
, ActivePlatform
, Target
, Toolchain
, ArchList
, MetaFileDb
,
256 BuildConfig
, ToolDefinition
, FlashDefinitionFile
='', Fds
=None, Fvs
=None, Caps
=None, SkuId
='', UniFlag
=None,
257 Progress
=None, BuildModule
=None):
264 self
.BuildDatabase
= MetaFileDb
265 self
.MetaFile
= ActivePlatform
266 self
.WorkspaceDir
= WorkspaceDir
267 self
.Platform
= self
.BuildDatabase
[self
.MetaFile
, 'COMMON', Target
, Toolchain
]
268 GlobalData
.gActivePlatform
= self
.Platform
269 self
.BuildTarget
= Target
270 self
.ToolChain
= Toolchain
271 self
.ArchList
= ArchList
273 self
.UniFlag
= UniFlag
275 self
.TargetTxt
= BuildConfig
276 self
.ToolDef
= ToolDefinition
277 self
.FdfFile
= FlashDefinitionFile
278 self
.FdTargetList
= Fds
279 self
.FvTargetList
= Fvs
280 self
.CapTargetList
= Caps
281 self
.AutoGenObjectList
= []
282 self
._BuildDir
= None
284 self
._MakeFileDir
= None
285 self
._BuildCommand
= None
288 # there's many relative directory operations, so ...
289 os
.chdir(self
.WorkspaceDir
)
294 if not self
.ArchList
:
295 ArchList
= set(self
.Platform
.SupArchList
)
297 ArchList
= set(self
.ArchList
) & set(self
.Platform
.SupArchList
)
299 EdkLogger
.error("build", PARAMETER_INVALID
,
300 ExtraData
= "Invalid ARCH specified. [Valid ARCH: %s]" % (" ".join(self
.Platform
.SupArchList
)))
301 elif self
.ArchList
and len(ArchList
) != len(self
.ArchList
):
302 SkippedArchList
= set(self
.ArchList
).symmetric_difference(set(self
.Platform
.SupArchList
))
303 EdkLogger
.verbose("\nArch [%s] is ignored because the platform supports [%s] only!"
304 % (" ".join(SkippedArchList
), " ".join(self
.Platform
.SupArchList
)))
305 self
.ArchList
= tuple(ArchList
)
307 # Validate build target
308 if self
.BuildTarget
not in self
.Platform
.BuildTargets
:
309 EdkLogger
.error("build", PARAMETER_INVALID
,
310 ExtraData
="Build target [%s] is not supported by the platform. [Valid target: %s]"
311 % (self
.BuildTarget
, " ".join(self
.Platform
.BuildTargets
)))
314 # parse FDF file to get PCDs in it, if any
316 self
.FdfFile
= self
.Platform
.FlashDefinition
320 EdkLogger
.info('%-16s = %s' % ("Architecture(s)", ' '.join(self
.ArchList
)))
321 EdkLogger
.info('%-16s = %s' % ("Build target", self
.BuildTarget
))
322 EdkLogger
.info('%-16s = %s' % ("Toolchain", self
.ToolChain
))
324 EdkLogger
.info('\n%-24s = %s' % ("Active Platform", self
.Platform
))
326 EdkLogger
.info('%-24s = %s' % ("Active Module", BuildModule
))
329 EdkLogger
.info('%-24s = %s' % ("Flash Image Definition", self
.FdfFile
))
331 EdkLogger
.verbose("\nFLASH_DEFINITION = %s" % self
.FdfFile
)
334 Progress
.Start("\nProcessing meta-data")
338 # Mark now build in AutoGen Phase
340 GlobalData
.gAutoGenPhase
= True
341 Fdf
= FdfParser(self
.FdfFile
.Path
)
343 GlobalData
.gFdfParser
= Fdf
344 GlobalData
.gAutoGenPhase
= False
345 PcdSet
= Fdf
.Profile
.PcdDict
346 if Fdf
.CurrentFdName
and Fdf
.CurrentFdName
in Fdf
.Profile
.FdDict
:
347 FdDict
= Fdf
.Profile
.FdDict
[Fdf
.CurrentFdName
]
348 for FdRegion
in FdDict
.RegionList
:
349 if str(FdRegion
.RegionType
) is 'FILE' and self
.Platform
.VpdToolGuid
in str(FdRegion
.RegionDataList
):
350 if int(FdRegion
.Offset
) % 8 != 0:
351 EdkLogger
.error("build", FORMAT_INVALID
, 'The VPD Base Address %s must be 8-byte aligned.' % (FdRegion
.Offset
))
352 ModuleList
= Fdf
.Profile
.InfList
353 self
.FdfProfile
= Fdf
.Profile
354 for fvname
in self
.FvTargetList
:
355 if fvname
.upper() not in self
.FdfProfile
.FvDict
:
356 EdkLogger
.error("build", OPTION_VALUE_INVALID
,
357 "No such an FV in FDF file: %s" % fvname
)
359 # In DSC file may use FILE_GUID to override the module, then in the Platform.Modules use FILE_GUIDmodule.inf as key,
360 # but the path (self.MetaFile.Path) is the real path
361 for key
in self
.FdfProfile
.InfDict
:
365 for Arch
in self
.ArchList
:
366 Platform_cache
[Arch
] = self
.BuildDatabase
[self
.MetaFile
, Arch
, Target
, Toolchain
]
367 MetaFile_cache
[Arch
] = []
368 for Pkey
in Platform_cache
[Arch
].Modules
.keys():
369 MetaFile_cache
[Arch
].append(Platform_cache
[Arch
].Modules
[Pkey
].MetaFile
)
370 for Inf
in self
.FdfProfile
.InfDict
[key
]:
371 ModuleFile
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, Arch
)
372 for Arch
in self
.ArchList
:
373 if ModuleFile
in MetaFile_cache
[Arch
]:
376 ModuleData
= self
.BuildDatabase
[ModuleFile
, Arch
, Target
, Toolchain
]
377 if not ModuleData
.IsBinaryModule
:
378 EdkLogger
.error('build', PARSER_ERROR
, "Module %s NOT found in DSC file; Is it really a binary module?" % ModuleFile
)
381 for Arch
in self
.ArchList
:
383 Platform
= self
.BuildDatabase
[self
.MetaFile
, Arch
, Target
, Toolchain
]
385 for Pkey
in Platform
.Modules
.keys():
386 MetaFileList
.append(Platform
.Modules
[Pkey
].MetaFile
)
387 for Inf
in self
.FdfProfile
.InfDict
[key
]:
388 ModuleFile
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, Arch
)
389 if ModuleFile
in MetaFileList
:
391 ModuleData
= self
.BuildDatabase
[ModuleFile
, Arch
, Target
, Toolchain
]
392 if not ModuleData
.IsBinaryModule
:
393 EdkLogger
.error('build', PARSER_ERROR
, "Module %s NOT found in DSC file; Is it really a binary module?" % ModuleFile
)
398 self
.FdfProfile
= None
399 if self
.FdTargetList
:
400 EdkLogger
.info("No flash definition file found. FD [%s] will be ignored." % " ".join(self
.FdTargetList
))
401 self
.FdTargetList
= []
402 if self
.FvTargetList
:
403 EdkLogger
.info("No flash definition file found. FV [%s] will be ignored." % " ".join(self
.FvTargetList
))
404 self
.FvTargetList
= []
405 if self
.CapTargetList
:
406 EdkLogger
.info("No flash definition file found. Capsule [%s] will be ignored." % " ".join(self
.CapTargetList
))
407 self
.CapTargetList
= []
409 # apply SKU and inject PCDs from Flash Definition file
410 for Arch
in self
.ArchList
:
411 Platform
= self
.BuildDatabase
[self
.MetaFile
, Arch
, Target
, Toolchain
]
418 SourcePcdDict
= {'DynamicEx':[], 'PatchableInModule':[],'Dynamic':[],'FixedAtBuild':[]}
419 BinaryPcdDict
= {'DynamicEx':[], 'PatchableInModule':[]}
420 SourcePcdDict_Keys
= SourcePcdDict
.keys()
421 BinaryPcdDict_Keys
= BinaryPcdDict
.keys()
423 # generate the SourcePcdDict and BinaryPcdDict
424 PGen
= PlatformAutoGen(self
, self
.MetaFile
, Target
, Toolchain
, Arch
)
425 for BuildData
in PGen
.BuildDatabase
._CACHE
_.values():
426 if BuildData
.Arch
!= Arch
:
428 if BuildData
.MetaFile
.Ext
== '.inf':
429 for key
in BuildData
.Pcds
:
430 if BuildData
.Pcds
[key
].Pending
:
431 if key
in Platform
.Pcds
:
432 PcdInPlatform
= Platform
.Pcds
[key
]
433 if PcdInPlatform
.Type
not in [None, '']:
434 BuildData
.Pcds
[key
].Type
= PcdInPlatform
.Type
436 if BuildData
.MetaFile
in Platform
.Modules
:
437 PlatformModule
= Platform
.Modules
[str(BuildData
.MetaFile
)]
438 if key
in PlatformModule
.Pcds
:
439 PcdInPlatform
= PlatformModule
.Pcds
[key
]
440 if PcdInPlatform
.Type
not in [None, '']:
441 BuildData
.Pcds
[key
].Type
= PcdInPlatform
.Type
443 if 'DynamicEx' in BuildData
.Pcds
[key
].Type
:
444 if BuildData
.IsBinaryModule
:
445 if (BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
) not in BinaryPcdDict
['DynamicEx']:
446 BinaryPcdDict
['DynamicEx'].append((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
448 if (BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
) not in SourcePcdDict
['DynamicEx']:
449 SourcePcdDict
['DynamicEx'].append((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
451 elif 'PatchableInModule' in BuildData
.Pcds
[key
].Type
:
452 if BuildData
.MetaFile
.Ext
== '.inf':
453 if BuildData
.IsBinaryModule
:
454 if (BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
) not in BinaryPcdDict
['PatchableInModule']:
455 BinaryPcdDict
['PatchableInModule'].append((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
457 if (BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
) not in SourcePcdDict
['PatchableInModule']:
458 SourcePcdDict
['PatchableInModule'].append((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
460 elif 'Dynamic' in BuildData
.Pcds
[key
].Type
:
461 if (BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
) not in SourcePcdDict
['Dynamic']:
462 SourcePcdDict
['Dynamic'].append((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
463 elif 'FixedAtBuild' in BuildData
.Pcds
[key
].Type
:
464 if (BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
) not in SourcePcdDict
['FixedAtBuild']:
465 SourcePcdDict
['FixedAtBuild'].append((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
469 # A PCD can only use one type for all source modules
471 for i
in SourcePcdDict_Keys
:
472 for j
in SourcePcdDict_Keys
:
474 IntersectionList
= list(set(SourcePcdDict
[i
]).intersection(set(SourcePcdDict
[j
])))
475 if len(IntersectionList
) > 0:
479 "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
),
480 ExtraData
="%s" % '\n\t'.join([str(P
[1]+'.'+P
[0]) for P
in IntersectionList
])
486 # intersection the BinaryPCD for Mixed PCD
488 for i
in BinaryPcdDict_Keys
:
489 for j
in BinaryPcdDict_Keys
:
491 IntersectionList
= list(set(BinaryPcdDict
[i
]).intersection(set(BinaryPcdDict
[j
])))
492 for item
in IntersectionList
:
493 NewPcd1
= (item
[0] + '_' + i
, item
[1])
494 NewPcd2
= (item
[0] + '_' + j
, item
[1])
495 if item
not in GlobalData
.MixedPcd
:
496 GlobalData
.MixedPcd
[item
] = [NewPcd1
, NewPcd2
]
498 if NewPcd1
not in GlobalData
.MixedPcd
[item
]:
499 GlobalData
.MixedPcd
[item
].append(NewPcd1
)
500 if NewPcd2
not in GlobalData
.MixedPcd
[item
]:
501 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 IntersectionList
= list(set(SourcePcdDict
[i
]).intersection(set(BinaryPcdDict
[j
])))
512 for item
in IntersectionList
:
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
)
525 for BuildData
in PGen
.BuildDatabase
._CACHE
_.values():
526 if BuildData
.Arch
!= Arch
:
528 for key
in BuildData
.Pcds
:
529 for SinglePcd
in GlobalData
.MixedPcd
:
530 if (BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
) == SinglePcd
:
531 for item
in GlobalData
.MixedPcd
[SinglePcd
]:
532 Pcd_Type
= item
[0].split('_')[-1]
533 if (Pcd_Type
== BuildData
.Pcds
[key
].Type
) or (Pcd_Type
== TAB_PCDS_DYNAMIC_EX
and BuildData
.Pcds
[key
].Type
in GenC
.gDynamicExPcd
) or \
534 (Pcd_Type
== TAB_PCDS_DYNAMIC
and BuildData
.Pcds
[key
].Type
in GenC
.gDynamicPcd
):
535 Value
= BuildData
.Pcds
[key
]
536 Value
.TokenCName
= BuildData
.Pcds
[key
].TokenCName
+ '_' + Pcd_Type
538 newkey
= (Value
.TokenCName
, key
[1])
540 newkey
= (Value
.TokenCName
, key
[1], key
[2])
541 del BuildData
.Pcds
[key
]
542 BuildData
.Pcds
[newkey
] = Value
550 # handle the mixed pcd in FDF file
552 if key
in GlobalData
.MixedPcd
:
555 for item
in GlobalData
.MixedPcd
[key
]:
558 #Collect package set information from INF of FDF
560 for Inf
in ModuleList
:
561 ModuleFile
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, Arch
)
562 if ModuleFile
in Platform
.Modules
:
564 ModuleData
= self
.BuildDatabase
[ModuleFile
, Arch
, Target
, Toolchain
]
565 PkgSet
.update(ModuleData
.Packages
)
566 Pkgs
= list(PkgSet
) + list(PGen
.PackageList
)
571 DecPcds
[Pcd
[0], Pcd
[1]] = Pkg
.Pcds
[Pcd
]
572 DecPcdsKey
.add((Pcd
[0], Pcd
[1], Pcd
[2]))
574 Platform
.SkuName
= self
.SkuId
575 for Name
, Guid
in PcdSet
:
576 if (Name
, Guid
) not in DecPcds
:
580 "PCD (%s.%s) used in FDF is not declared in DEC files." % (Guid
, Name
),
581 File
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
][0],
582 Line
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
][1]
585 # Check whether Dynamic or DynamicEx PCD used in FDF file. If used, build break and give a error message.
586 if (Name
, Guid
, TAB_PCDS_FIXED_AT_BUILD
) in DecPcdsKey \
587 or (Name
, Guid
, TAB_PCDS_PATCHABLE_IN_MODULE
) in DecPcdsKey \
588 or (Name
, Guid
, TAB_PCDS_FEATURE_FLAG
) in DecPcdsKey
:
589 Platform
.AddPcd(Name
, Guid
, PcdSet
[Name
, Guid
])
591 elif (Name
, Guid
, TAB_PCDS_DYNAMIC
) in DecPcdsKey
or (Name
, Guid
, TAB_PCDS_DYNAMIC_EX
) in DecPcdsKey
:
595 "Using Dynamic or DynamicEx type of PCD [%s.%s] in FDF file is not allowed." % (Guid
, Name
),
596 File
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
][0],
597 Line
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
][1]
600 Pa
= PlatformAutoGen(self
, self
.MetaFile
, Target
, Toolchain
, Arch
)
602 # Explicitly collect platform's dynamic PCDs
604 Pa
.CollectPlatformDynamicPcds()
605 Pa
.CollectFixedAtBuildPcds()
606 self
.AutoGenObjectList
.append(Pa
)
609 # Generate Package level hash value
611 GlobalData
.gPackageHash
[Arch
] = {}
612 if GlobalData
.gUseHashCache
:
614 self
._GenPkgLevelHash
(Pkg
)
617 # Check PCDs token value conflict in each DEC file.
619 self
._CheckAllPcdsTokenValueConflict
()
622 # Check PCD type and definition between DSC and DEC
624 self
._CheckPcdDefineAndType
()
627 # self._CheckDuplicateInFV(Fdf)
630 # Create BuildOptions Macro & PCD metafile, also add the Active Platform and FDF file.
632 content
= 'gCommandLineDefines: '
633 content
+= str(GlobalData
.gCommandLineDefines
)
634 content
+= os
.linesep
635 content
+= 'BuildOptionPcd: '
636 content
+= str(GlobalData
.BuildOptionPcd
)
637 content
+= os
.linesep
638 content
+= 'Active Platform: '
639 content
+= str(self
.Platform
)
640 content
+= os
.linesep
642 content
+= 'Flash Image Definition: '
643 content
+= str(self
.FdfFile
)
644 content
+= os
.linesep
645 SaveFileOnChange(os
.path
.join(self
.BuildDir
, 'BuildOptions'), content
, False)
648 # Create PcdToken Number file for Dynamic/DynamicEx Pcd.
650 PcdTokenNumber
= 'PcdTokenNumber: '
651 if Pa
.PcdTokenNumber
:
652 if Pa
.DynamicPcdList
:
653 for Pcd
in Pa
.DynamicPcdList
:
654 PcdTokenNumber
+= os
.linesep
655 PcdTokenNumber
+= str((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
))
656 PcdTokenNumber
+= ' : '
657 PcdTokenNumber
+= str(Pa
.PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
])
658 SaveFileOnChange(os
.path
.join(self
.BuildDir
, 'PcdTokenNumber'), PcdTokenNumber
, False)
661 # Get set of workspace metafiles
663 AllWorkSpaceMetaFiles
= self
._GetMetaFiles
(Target
, Toolchain
, Arch
)
666 # Retrieve latest modified time of all metafiles
669 for f
in AllWorkSpaceMetaFiles
:
670 if os
.stat(f
)[8] > SrcTimeStamp
:
671 SrcTimeStamp
= os
.stat(f
)[8]
672 self
._SrcTimeStamp
= SrcTimeStamp
674 if GlobalData
.gUseHashCache
:
676 for files
in AllWorkSpaceMetaFiles
:
677 if files
.endswith('.dec'):
683 SaveFileOnChange(os
.path
.join(self
.BuildDir
, 'AutoGen.hash'), m
.hexdigest(), True)
684 GlobalData
.gPlatformHash
= m
.hexdigest()
687 # Write metafile list to build directory
689 AutoGenFilePath
= os
.path
.join(self
.BuildDir
, 'AutoGen')
690 if os
.path
.exists (AutoGenFilePath
):
691 os
.remove(AutoGenFilePath
)
692 if not os
.path
.exists(self
.BuildDir
):
693 os
.makedirs(self
.BuildDir
)
694 with
open(os
.path
.join(self
.BuildDir
, 'AutoGen'), 'w+') as file:
695 for f
in AllWorkSpaceMetaFiles
:
699 def _GenPkgLevelHash(self
, Pkg
):
700 PkgDir
= os
.path
.join(self
.BuildDir
, Pkg
.Arch
, Pkg
.PackageName
)
701 CreateDirectory(PkgDir
)
702 HashFile
= os
.path
.join(PkgDir
, Pkg
.PackageName
+ '.hash')
704 # Get .dec file's hash value
705 f
= open(Pkg
.MetaFile
.Path
, 'r')
709 # Get include files hash value
711 for inc
in Pkg
.Includes
:
712 for Root
, Dirs
, Files
in os
.walk(str(inc
)):
714 File_Path
= os
.path
.join(Root
, File
)
715 f
= open(File_Path
, 'r')
719 SaveFileOnChange(HashFile
, m
.hexdigest(), True)
720 if Pkg
.PackageName
not in GlobalData
.gPackageHash
[Pkg
.Arch
]:
721 GlobalData
.gPackageHash
[Pkg
.Arch
][Pkg
.PackageName
] = m
.hexdigest()
723 def _GetMetaFiles(self
, Target
, Toolchain
, Arch
):
724 AllWorkSpaceMetaFiles
= set()
729 AllWorkSpaceMetaFiles
.add (self
.FdfFile
.Path
)
731 FdfFiles
= GlobalData
.gFdfParser
.GetAllIncludedFile()
733 AllWorkSpaceMetaFiles
.add (f
.FileName
)
737 AllWorkSpaceMetaFiles
.add(self
.MetaFile
.Path
)
740 # add build_rule.txt & tools_def.txt
742 AllWorkSpaceMetaFiles
.add(os
.path
.join(GlobalData
.gConfDirectory
, gDefaultBuildRuleFile
))
743 AllWorkSpaceMetaFiles
.add(os
.path
.join(GlobalData
.gConfDirectory
, gDefaultToolsDefFile
))
745 # add BuildOption metafile
747 AllWorkSpaceMetaFiles
.add(os
.path
.join(self
.BuildDir
, 'BuildOptions'))
749 # add PcdToken Number file for Dynamic/DynamicEx Pcd
751 AllWorkSpaceMetaFiles
.add(os
.path
.join(self
.BuildDir
, 'PcdTokenNumber'))
753 for Arch
in self
.ArchList
:
754 Platform
= self
.BuildDatabase
[self
.MetaFile
, Arch
, Target
, Toolchain
]
755 PGen
= PlatformAutoGen(self
, self
.MetaFile
, Target
, Toolchain
, Arch
)
760 for Package
in PGen
.PackageList
:
761 AllWorkSpaceMetaFiles
.add(Package
.MetaFile
.Path
)
766 for filePath
in Platform
._RawData
.IncludedFiles
:
767 AllWorkSpaceMetaFiles
.add(filePath
.Path
)
769 return AllWorkSpaceMetaFiles
771 ## _CheckDuplicateInFV() method
773 # Check whether there is duplicate modules/files exist in FV section.
774 # The check base on the file GUID;
776 def _CheckDuplicateInFV(self
, Fdf
):
777 for Fv
in Fdf
.Profile
.FvDict
:
779 for FfsFile
in Fdf
.Profile
.FvDict
[Fv
].FfsList
:
780 if FfsFile
.InfFileName
and FfsFile
.NameGuid
is None:
785 for Pa
in self
.AutoGenObjectList
:
788 for Module
in Pa
.ModuleAutoGenList
:
789 if path
.normpath(Module
.MetaFile
.File
) == path
.normpath(FfsFile
.InfFileName
):
791 if not Module
.Guid
.upper() in _GuidDict
.keys():
792 _GuidDict
[Module
.Guid
.upper()] = FfsFile
795 EdkLogger
.error("build",
797 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile
.CurrentLineNum
,
798 FfsFile
.CurrentLineContent
,
799 _GuidDict
[Module
.Guid
.upper()].CurrentLineNum
,
800 _GuidDict
[Module
.Guid
.upper()].CurrentLineContent
,
801 Module
.Guid
.upper()),
802 ExtraData
=self
.FdfFile
)
804 # Some INF files not have entity in DSC file.
807 if FfsFile
.InfFileName
.find('$') == -1:
808 InfPath
= NormPath(FfsFile
.InfFileName
)
809 if not os
.path
.exists(InfPath
):
810 EdkLogger
.error('build', GENFDS_ERROR
, "Non-existant Module %s !" % (FfsFile
.InfFileName
))
812 PathClassObj
= PathClass(FfsFile
.InfFileName
, self
.WorkspaceDir
)
814 # Here we just need to get FILE_GUID from INF file, use 'COMMON' as ARCH attribute. and use
815 # BuildObject from one of AutoGenObjectList is enough.
817 InfObj
= self
.AutoGenObjectList
[0].BuildDatabase
.WorkspaceDb
.BuildObject
[PathClassObj
, 'COMMON', self
.BuildTarget
, self
.ToolChain
]
818 if not InfObj
.Guid
.upper() in _GuidDict
.keys():
819 _GuidDict
[InfObj
.Guid
.upper()] = FfsFile
821 EdkLogger
.error("build",
823 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile
.CurrentLineNum
,
824 FfsFile
.CurrentLineContent
,
825 _GuidDict
[InfObj
.Guid
.upper()].CurrentLineNum
,
826 _GuidDict
[InfObj
.Guid
.upper()].CurrentLineContent
,
827 InfObj
.Guid
.upper()),
828 ExtraData
=self
.FdfFile
)
831 if FfsFile
.NameGuid
is not None:
833 # If the NameGuid reference a PCD name.
834 # The style must match: PCD(xxxx.yyy)
836 if gPCDAsGuidPattern
.match(FfsFile
.NameGuid
):
838 # Replace the PCD value.
840 _PcdName
= FfsFile
.NameGuid
.lstrip("PCD(").rstrip(")")
842 for Pa
in self
.AutoGenObjectList
:
844 for PcdItem
in Pa
.AllPcdList
:
845 if (PcdItem
.TokenSpaceGuidCName
+ "." + PcdItem
.TokenCName
) == _PcdName
:
847 # First convert from CFormatGuid to GUID string
849 _PcdGuidString
= GuidStructureStringToGuidString(PcdItem
.DefaultValue
)
851 if not _PcdGuidString
:
853 # Then try Byte array.
855 _PcdGuidString
= GuidStructureByteArrayToGuidString(PcdItem
.DefaultValue
)
857 if not _PcdGuidString
:
859 # Not Byte array or CFormat GUID, raise error.
861 EdkLogger
.error("build",
863 "The format of PCD value is incorrect. PCD: %s , Value: %s\n" % (_PcdName
, PcdItem
.DefaultValue
),
864 ExtraData
=self
.FdfFile
)
866 if not _PcdGuidString
.upper() in _GuidDict
.keys():
867 _GuidDict
[_PcdGuidString
.upper()] = FfsFile
871 EdkLogger
.error("build",
873 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile
.CurrentLineNum
,
874 FfsFile
.CurrentLineContent
,
875 _GuidDict
[_PcdGuidString
.upper()].CurrentLineNum
,
876 _GuidDict
[_PcdGuidString
.upper()].CurrentLineContent
,
877 FfsFile
.NameGuid
.upper()),
878 ExtraData
=self
.FdfFile
)
880 if not FfsFile
.NameGuid
.upper() in _GuidDict
.keys():
881 _GuidDict
[FfsFile
.NameGuid
.upper()] = FfsFile
884 # Two raw file GUID conflict.
886 EdkLogger
.error("build",
888 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile
.CurrentLineNum
,
889 FfsFile
.CurrentLineContent
,
890 _GuidDict
[FfsFile
.NameGuid
.upper()].CurrentLineNum
,
891 _GuidDict
[FfsFile
.NameGuid
.upper()].CurrentLineContent
,
892 FfsFile
.NameGuid
.upper()),
893 ExtraData
=self
.FdfFile
)
896 def _CheckPcdDefineAndType(self
):
898 "FixedAtBuild", "PatchableInModule", "FeatureFlag",
899 "Dynamic", #"DynamicHii", "DynamicVpd",
900 "DynamicEx", # "DynamicExHii", "DynamicExVpd"
903 # This dict store PCDs which are not used by any modules with specified arches
904 UnusedPcd
= OrderedDict()
905 for Pa
in self
.AutoGenObjectList
:
906 # Key of DSC's Pcds dictionary is PcdCName, TokenSpaceGuid
907 for Pcd
in Pa
.Platform
.Pcds
:
908 PcdType
= Pa
.Platform
.Pcds
[Pcd
].Type
910 # If no PCD type, this PCD comes from FDF
914 # Try to remove Hii and Vpd suffix
915 if PcdType
.startswith("DynamicEx"):
916 PcdType
= "DynamicEx"
917 elif PcdType
.startswith("Dynamic"):
920 for Package
in Pa
.PackageList
:
921 # Key of DEC's Pcds dictionary is PcdCName, TokenSpaceGuid, PcdType
922 if (Pcd
[0], Pcd
[1], PcdType
) in Package
.Pcds
:
924 for Type
in PcdTypeList
:
925 if (Pcd
[0], Pcd
[1], Type
) in Package
.Pcds
:
929 "Type [%s] of PCD [%s.%s] in DSC file doesn't match the type [%s] defined in DEC file." \
930 % (Pa
.Platform
.Pcds
[Pcd
].Type
, Pcd
[1], Pcd
[0], Type
),
935 UnusedPcd
.setdefault(Pcd
, []).append(Pa
.Arch
)
937 for Pcd
in UnusedPcd
:
940 "The PCD was not specified by any INF module in the platform for the given architecture.\n"
941 "\tPCD: [%s.%s]\n\tPlatform: [%s]\n\tArch: %s"
942 % (Pcd
[1], Pcd
[0], os
.path
.basename(str(self
.MetaFile
)), str(UnusedPcd
[Pcd
])),
947 return "%s [%s]" % (self
.MetaFile
, ", ".join(self
.ArchList
))
949 ## Return the directory to store FV files
951 if self
._FvDir
is None:
952 self
._FvDir
= path
.join(self
.BuildDir
, 'FV')
955 ## Return the directory to store all intermediate and final files built
956 def _GetBuildDir(self
):
957 if self
._BuildDir
is None:
958 return self
.AutoGenObjectList
[0].BuildDir
960 ## Return the build output directory platform specifies
961 def _GetOutputDir(self
):
962 return self
.Platform
.OutputDirectory
964 ## Return platform name
966 return self
.Platform
.PlatformName
968 ## Return meta-file GUID
970 return self
.Platform
.Guid
972 ## Return platform version
973 def _GetVersion(self
):
974 return self
.Platform
.Version
976 ## Return paths of tools
977 def _GetToolDefinition(self
):
978 return self
.AutoGenObjectList
[0].ToolDefinition
980 ## Return directory of platform makefile
982 # @retval string Makefile directory
984 def _GetMakeFileDir(self
):
985 if self
._MakeFileDir
is None:
986 self
._MakeFileDir
= self
.BuildDir
987 return self
._MakeFileDir
989 ## Return build command string
991 # @retval string Build command string
993 def _GetBuildCommand(self
):
994 if self
._BuildCommand
is None:
995 # BuildCommand should be all the same. So just get one from platform AutoGen
996 self
._BuildCommand
= self
.AutoGenObjectList
[0].BuildCommand
997 return self
._BuildCommand
999 ## Check the PCDs token value conflict in each DEC file.
1001 # Will cause build break and raise error message while two PCDs conflict.
1005 def _CheckAllPcdsTokenValueConflict(self
):
1006 for Pa
in self
.AutoGenObjectList
:
1007 for Package
in Pa
.PackageList
:
1008 PcdList
= Package
.Pcds
.values()
1009 PcdList
.sort(lambda x
, y
: cmp(int(x
.TokenValue
, 0), int(y
.TokenValue
, 0)))
1011 while (Count
< len(PcdList
) - 1) :
1012 Item
= PcdList
[Count
]
1013 ItemNext
= PcdList
[Count
+ 1]
1015 # Make sure in the same token space the TokenValue should be unique
1017 if (int(Item
.TokenValue
, 0) == int(ItemNext
.TokenValue
, 0)):
1018 SameTokenValuePcdList
= []
1019 SameTokenValuePcdList
.append(Item
)
1020 SameTokenValuePcdList
.append(ItemNext
)
1021 RemainPcdListLength
= len(PcdList
) - Count
- 2
1022 for ValueSameCount
in range(RemainPcdListLength
):
1023 if int(PcdList
[len(PcdList
) - RemainPcdListLength
+ ValueSameCount
].TokenValue
, 0) == int(Item
.TokenValue
, 0):
1024 SameTokenValuePcdList
.append(PcdList
[len(PcdList
) - RemainPcdListLength
+ ValueSameCount
])
1028 # Sort same token value PCD list with TokenGuid and TokenCName
1030 SameTokenValuePcdList
.sort(lambda x
, y
: cmp("%s.%s" % (x
.TokenSpaceGuidCName
, x
.TokenCName
), "%s.%s" % (y
.TokenSpaceGuidCName
, y
.TokenCName
)))
1031 SameTokenValuePcdListCount
= 0
1032 while (SameTokenValuePcdListCount
< len(SameTokenValuePcdList
) - 1):
1034 TemListItem
= SameTokenValuePcdList
[SameTokenValuePcdListCount
]
1035 TemListItemNext
= SameTokenValuePcdList
[SameTokenValuePcdListCount
+ 1]
1037 if (TemListItem
.TokenSpaceGuidCName
== TemListItemNext
.TokenSpaceGuidCName
) and (TemListItem
.TokenCName
!= TemListItemNext
.TokenCName
):
1038 for PcdItem
in GlobalData
.MixedPcd
:
1039 if (TemListItem
.TokenCName
, TemListItem
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
] or \
1040 (TemListItemNext
.TokenCName
, TemListItemNext
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
1046 "The TokenValue [%s] of PCD [%s.%s] is conflict with: [%s.%s] in %s"\
1047 % (TemListItem
.TokenValue
, TemListItem
.TokenSpaceGuidCName
, TemListItem
.TokenCName
, TemListItemNext
.TokenSpaceGuidCName
, TemListItemNext
.TokenCName
, Package
),
1050 SameTokenValuePcdListCount
+= 1
1051 Count
+= SameTokenValuePcdListCount
1054 PcdList
= Package
.Pcds
.values()
1055 PcdList
.sort(lambda x
, y
: cmp("%s.%s" % (x
.TokenSpaceGuidCName
, x
.TokenCName
), "%s.%s" % (y
.TokenSpaceGuidCName
, y
.TokenCName
)))
1057 while (Count
< len(PcdList
) - 1) :
1058 Item
= PcdList
[Count
]
1059 ItemNext
= PcdList
[Count
+ 1]
1061 # Check PCDs with same TokenSpaceGuidCName.TokenCName have same token value as well.
1063 if (Item
.TokenSpaceGuidCName
== ItemNext
.TokenSpaceGuidCName
) and (Item
.TokenCName
== ItemNext
.TokenCName
) and (int(Item
.TokenValue
, 0) != int(ItemNext
.TokenValue
, 0)):
1067 "The TokenValue [%s] of PCD [%s.%s] in %s defined in two places should be same as well."\
1068 % (Item
.TokenValue
, Item
.TokenSpaceGuidCName
, Item
.TokenCName
, Package
),
1072 ## Generate fds command
1073 def _GenFdsCommand(self
):
1074 return (GenMake
.TopLevelMakefile(self
)._TEMPLATE
_.Replace(GenMake
.TopLevelMakefile(self
)._TemplateDict
)).strip()
1076 ## Create makefile for the platform and modules in it
1078 # @param CreateDepsMakeFile Flag indicating if the makefile for
1079 # modules will be created as well
1081 def CreateMakeFile(self
, CreateDepsMakeFile
=False):
1082 if CreateDepsMakeFile
:
1083 for Pa
in self
.AutoGenObjectList
:
1084 Pa
.CreateMakeFile(CreateDepsMakeFile
)
1086 ## Create autogen code for platform and modules
1088 # Since there's no autogen code for platform, this method will do nothing
1089 # if CreateModuleCodeFile is set to False.
1091 # @param CreateDepsCodeFile Flag indicating if creating module's
1092 # autogen code file or not
1094 def CreateCodeFile(self
, CreateDepsCodeFile
=False):
1095 if not CreateDepsCodeFile
:
1097 for Pa
in self
.AutoGenObjectList
:
1098 Pa
.CreateCodeFile(CreateDepsCodeFile
)
1100 ## Create AsBuilt INF file the platform
1102 def CreateAsBuiltInf(self
):
1105 Name
= property(_GetName
)
1106 Guid
= property(_GetGuid
)
1107 Version
= property(_GetVersion
)
1108 OutputDir
= property(_GetOutputDir
)
1110 ToolDefinition
= property(_GetToolDefinition
) # toolcode : tool path
1112 BuildDir
= property(_GetBuildDir
)
1113 FvDir
= property(_GetFvDir
)
1114 MakeFileDir
= property(_GetMakeFileDir
)
1115 BuildCommand
= property(_GetBuildCommand
)
1116 GenFdsCommand
= property(_GenFdsCommand
)
1118 ## AutoGen class for platform
1120 # PlatformAutoGen class will process the original information in platform
1121 # file in order to generate makefile for platform.
1123 class PlatformAutoGen(AutoGen
):
1124 # call super().__init__ then call the worker function with different parameter count
1125 def __init__(self
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
1129 super(PlatformAutoGen
, self
).__init
__(self
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
)
1130 self
._InitWorker
(Workspace
, MetaFile
, Target
, Toolchain
, Arch
)
1133 # Used to store all PCDs for both PEI and DXE phase, in order to generate
1134 # correct PCD database
1137 _NonDynaPcdList_
= []
1141 # The priority list while override build option
1143 PrioList
= {"0x11111" : 16, # TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE (Highest)
1144 "0x01111" : 15, # ******_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
1145 "0x10111" : 14, # TARGET_*********_ARCH_COMMANDTYPE_ATTRIBUTE
1146 "0x00111" : 13, # ******_*********_ARCH_COMMANDTYPE_ATTRIBUTE
1147 "0x11011" : 12, # TARGET_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
1148 "0x01011" : 11, # ******_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
1149 "0x10011" : 10, # TARGET_*********_****_COMMANDTYPE_ATTRIBUTE
1150 "0x00011" : 9, # ******_*********_****_COMMANDTYPE_ATTRIBUTE
1151 "0x11101" : 8, # TARGET_TOOLCHAIN_ARCH_***********_ATTRIBUTE
1152 "0x01101" : 7, # ******_TOOLCHAIN_ARCH_***********_ATTRIBUTE
1153 "0x10101" : 6, # TARGET_*********_ARCH_***********_ATTRIBUTE
1154 "0x00101" : 5, # ******_*********_ARCH_***********_ATTRIBUTE
1155 "0x11001" : 4, # TARGET_TOOLCHAIN_****_***********_ATTRIBUTE
1156 "0x01001" : 3, # ******_TOOLCHAIN_****_***********_ATTRIBUTE
1157 "0x10001" : 2, # TARGET_*********_****_***********_ATTRIBUTE
1158 "0x00001" : 1} # ******_*********_****_***********_ATTRIBUTE (Lowest)
1160 ## Initialize PlatformAutoGen
1163 # @param Workspace WorkspaceAutoGen object
1164 # @param PlatformFile Platform file (DSC file)
1165 # @param Target Build target (DEBUG, RELEASE)
1166 # @param Toolchain Name of tool chain
1167 # @param Arch arch of the platform supports
1169 def _InitWorker(self
, Workspace
, PlatformFile
, Target
, Toolchain
, Arch
):
1170 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "AutoGen platform [%s] [%s]" % (PlatformFile
, Arch
))
1171 GlobalData
.gProcessingFile
= "%s [%s, %s, %s]" % (PlatformFile
, Arch
, Toolchain
, Target
)
1173 self
.MetaFile
= PlatformFile
1174 self
.Workspace
= Workspace
1175 self
.WorkspaceDir
= Workspace
.WorkspaceDir
1176 self
.ToolChain
= Toolchain
1177 self
.BuildTarget
= Target
1179 self
.SourceDir
= PlatformFile
.SubDir
1180 self
.SourceOverrideDir
= None
1181 self
.FdTargetList
= self
.Workspace
.FdTargetList
1182 self
.FvTargetList
= self
.Workspace
.FvTargetList
1183 self
.AllPcdList
= []
1184 # get the original module/package/platform objects
1185 self
.BuildDatabase
= Workspace
.BuildDatabase
1186 self
.DscBuildDataObj
= Workspace
.Platform
1187 self
._GuidDict
= Workspace
._GuidDict
1189 # flag indicating if the makefile/C-code file has been created or not
1190 self
.IsMakeFileCreated
= False
1191 self
.IsCodeFileCreated
= False
1193 self
._Platform
= None
1196 self
._Version
= None
1198 self
._BuildRule
= None
1199 self
._SourceDir
= None
1200 self
._BuildDir
= None
1201 self
._OutputDir
= None
1203 self
._MakeFileDir
= None
1204 self
._FdfFile
= None
1206 self
._PcdTokenNumber
= None # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber
1207 self
._DynamicPcdList
= None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
1208 self
._NonDynamicPcdList
= None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
1209 self
._NonDynamicPcdDict
= {}
1211 self
._ToolDefinitions
= None
1212 self
._ToolDefFile
= None # toolcode : tool path
1213 self
._ToolChainFamily
= None
1214 self
._BuildRuleFamily
= None
1215 self
._BuildOption
= None # toolcode : option
1216 self
._EdkBuildOption
= None # edktoolcode : option
1217 self
._EdkIIBuildOption
= None # edkiitoolcode : option
1218 self
._PackageList
= None
1219 self
._ModuleAutoGenList
= None
1220 self
._LibraryAutoGenList
= None
1221 self
._BuildCommand
= None
1222 self
._AsBuildInfList
= []
1223 self
._AsBuildModuleList
= []
1225 self
.VariableInfo
= None
1227 if GlobalData
.gFdfParser
is not None:
1228 self
._AsBuildInfList
= GlobalData
.gFdfParser
.Profile
.InfList
1229 for Inf
in self
._AsBuildInfList
:
1230 InfClass
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, self
.Arch
)
1231 M
= self
.BuildDatabase
[InfClass
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1232 if not M
.IsSupportedArch
:
1234 self
._AsBuildModuleList
.append(InfClass
)
1235 # get library/modules for build
1236 self
.LibraryBuildDirectoryList
= []
1237 self
.ModuleBuildDirectoryList
= []
1242 return "%s [%s]" % (self
.MetaFile
, self
.Arch
)
1244 ## Create autogen code for platform and modules
1246 # Since there's no autogen code for platform, this method will do nothing
1247 # if CreateModuleCodeFile is set to False.
1249 # @param CreateModuleCodeFile Flag indicating if creating module's
1250 # autogen code file or not
1252 def CreateCodeFile(self
, CreateModuleCodeFile
=False):
1253 # only module has code to be greated, so do nothing if CreateModuleCodeFile is False
1254 if self
.IsCodeFileCreated
or not CreateModuleCodeFile
:
1257 for Ma
in self
.ModuleAutoGenList
:
1258 Ma
.CreateCodeFile(True)
1260 # don't do this twice
1261 self
.IsCodeFileCreated
= True
1263 ## Generate Fds Command
1264 def _GenFdsCommand(self
):
1265 return self
.Workspace
.GenFdsCommand
1267 ## Create makefile for the platform and mdoules in it
1269 # @param CreateModuleMakeFile Flag indicating if the makefile for
1270 # modules will be created as well
1272 def CreateMakeFile(self
, CreateModuleMakeFile
=False, FfsCommand
= {}):
1273 if CreateModuleMakeFile
:
1274 for ModuleFile
in self
.Platform
.Modules
:
1275 Ma
= ModuleAutoGen(self
.Workspace
, ModuleFile
, self
.BuildTarget
,
1276 self
.ToolChain
, self
.Arch
, self
.MetaFile
)
1277 if (ModuleFile
.File
, self
.Arch
) in FfsCommand
:
1278 Ma
.CreateMakeFile(True, FfsCommand
[ModuleFile
.File
, self
.Arch
])
1280 Ma
.CreateMakeFile(True)
1281 #Ma.CreateAsBuiltInf()
1283 # no need to create makefile for the platform more than once
1284 if self
.IsMakeFileCreated
:
1287 # create library/module build dirs for platform
1288 Makefile
= GenMake
.PlatformMakefile(self
)
1289 self
.LibraryBuildDirectoryList
= Makefile
.GetLibraryBuildDirectoryList()
1290 self
.ModuleBuildDirectoryList
= Makefile
.GetModuleBuildDirectoryList()
1292 self
.IsMakeFileCreated
= True
1294 ## Deal with Shared FixedAtBuild Pcds
1296 def CollectFixedAtBuildPcds(self
):
1297 for LibAuto
in self
.LibraryAutoGenList
:
1298 FixedAtBuildPcds
= {}
1299 ShareFixedAtBuildPcdsSameValue
= {}
1300 for Module
in LibAuto
._ReferenceModules
:
1301 for Pcd
in Module
.FixedAtBuildPcds
+ LibAuto
.FixedAtBuildPcds
:
1302 key
= ".".join((Pcd
.TokenSpaceGuidCName
,Pcd
.TokenCName
))
1303 if key
not in FixedAtBuildPcds
:
1304 ShareFixedAtBuildPcdsSameValue
[key
] = True
1305 FixedAtBuildPcds
[key
] = Pcd
.DefaultValue
1307 if FixedAtBuildPcds
[key
] != Pcd
.DefaultValue
:
1308 ShareFixedAtBuildPcdsSameValue
[key
] = False
1309 for Pcd
in LibAuto
.FixedAtBuildPcds
:
1310 key
= ".".join((Pcd
.TokenSpaceGuidCName
,Pcd
.TokenCName
))
1311 if (Pcd
.TokenCName
,Pcd
.TokenSpaceGuidCName
) not in self
.NonDynamicPcdDict
:
1314 DscPcd
= self
.NonDynamicPcdDict
[(Pcd
.TokenCName
,Pcd
.TokenSpaceGuidCName
)]
1315 if DscPcd
.Type
!= "FixedAtBuild":
1317 if key
in ShareFixedAtBuildPcdsSameValue
and ShareFixedAtBuildPcdsSameValue
[key
]:
1318 LibAuto
.ConstPcd
[key
] = Pcd
.DefaultValue
1320 def CollectVariables(self
, DynamicPcdSet
):
1324 if self
.Workspace
.FdfFile
:
1325 FdDict
= self
.Workspace
.FdfProfile
.FdDict
[GlobalData
.gFdfParser
.CurrentFdName
]
1326 for FdRegion
in FdDict
.RegionList
:
1327 for item
in FdRegion
.RegionDataList
:
1328 if self
.Platform
.VpdToolGuid
.strip() and self
.Platform
.VpdToolGuid
in item
:
1329 VpdRegionSize
= FdRegion
.Size
1330 VpdRegionBase
= FdRegion
.Offset
1334 VariableInfo
= VariableMgr(self
.DscBuildDataObj
._GetDefaultStores
(),self
.DscBuildDataObj
._GetSkuIds
())
1335 VariableInfo
.SetVpdRegionMaxSize(VpdRegionSize
)
1336 VariableInfo
.SetVpdRegionOffset(VpdRegionBase
)
1338 for Pcd
in DynamicPcdSet
:
1339 pcdname
= ".".join((Pcd
.TokenSpaceGuidCName
,Pcd
.TokenCName
))
1340 for SkuName
in Pcd
.SkuInfoList
:
1341 Sku
= Pcd
.SkuInfoList
[SkuName
]
1343 if SkuId
is None or SkuId
== '':
1345 if len(Sku
.VariableName
) > 0:
1346 VariableGuidStructure
= Sku
.VariableGuidValue
1347 VariableGuid
= GuidStructureStringToGuidString(VariableGuidStructure
)
1348 for StorageName
in Sku
.DefaultStoreDict
:
1349 VariableInfo
.append_variable(var_info(Index
,pcdname
,StorageName
,SkuName
, StringToArray(Sku
.VariableName
),VariableGuid
, Sku
.VariableOffset
, Sku
.VariableAttribute
, Sku
.HiiDefaultValue
,Sku
.DefaultStoreDict
[StorageName
],Pcd
.DatumType
))
1353 def UpdateNVStoreMaxSize(self
,OrgVpdFile
):
1354 if self
.VariableInfo
:
1355 VpdMapFilePath
= os
.path
.join(self
.BuildDir
, "FV", "%s.map" % self
.Platform
.VpdToolGuid
)
1356 PcdNvStoreDfBuffer
= [item
for item
in self
._DynamicPcdList
if item
.TokenCName
== "PcdNvStoreDefaultValueBuffer" and item
.TokenSpaceGuidCName
== "gEfiMdeModulePkgTokenSpaceGuid"]
1358 if PcdNvStoreDfBuffer
:
1359 if os
.path
.exists(VpdMapFilePath
):
1360 OrgVpdFile
.Read(VpdMapFilePath
)
1361 PcdItems
= OrgVpdFile
.GetOffset(PcdNvStoreDfBuffer
[0])
1362 NvStoreOffset
= PcdItems
.values()[0].strip() if PcdItems
else '0'
1364 EdkLogger
.error("build", FILE_READ_FAILURE
, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath
)
1366 NvStoreOffset
= int(NvStoreOffset
,16) if NvStoreOffset
.upper().startswith("0X") else int(NvStoreOffset
)
1367 default_skuobj
= PcdNvStoreDfBuffer
[0].SkuInfoList
.get("DEFAULT")
1368 maxsize
= self
.VariableInfo
.VpdRegionSize
- NvStoreOffset
if self
.VariableInfo
.VpdRegionSize
else len(default_skuobj
.DefaultValue
.split(","))
1369 var_data
= self
.VariableInfo
.PatchNVStoreDefaultMaxSize(maxsize
)
1371 if var_data
and default_skuobj
:
1372 default_skuobj
.DefaultValue
= var_data
1373 PcdNvStoreDfBuffer
[0].DefaultValue
= var_data
1374 PcdNvStoreDfBuffer
[0].SkuInfoList
.clear()
1375 PcdNvStoreDfBuffer
[0].SkuInfoList
['DEFAULT'] = default_skuobj
1376 PcdNvStoreDfBuffer
[0].MaxDatumSize
= str(len(default_skuobj
.DefaultValue
.split(",")))
1380 ## Collect dynamic PCDs
1382 # Gather dynamic PCDs list from each module and their settings from platform
1383 # This interface should be invoked explicitly when platform action is created.
1385 def CollectPlatformDynamicPcds(self
):
1387 for key
in self
.Platform
.Pcds
:
1388 for SinglePcd
in GlobalData
.MixedPcd
:
1389 if (self
.Platform
.Pcds
[key
].TokenCName
, self
.Platform
.Pcds
[key
].TokenSpaceGuidCName
) == SinglePcd
:
1390 for item
in GlobalData
.MixedPcd
[SinglePcd
]:
1391 Pcd_Type
= item
[0].split('_')[-1]
1392 if (Pcd_Type
== self
.Platform
.Pcds
[key
].Type
) or (Pcd_Type
== TAB_PCDS_DYNAMIC_EX
and self
.Platform
.Pcds
[key
].Type
in GenC
.gDynamicExPcd
) or \
1393 (Pcd_Type
== TAB_PCDS_DYNAMIC
and self
.Platform
.Pcds
[key
].Type
in GenC
.gDynamicPcd
):
1394 Value
= self
.Platform
.Pcds
[key
]
1395 Value
.TokenCName
= self
.Platform
.Pcds
[key
].TokenCName
+ '_' + Pcd_Type
1397 newkey
= (Value
.TokenCName
, key
[1])
1399 newkey
= (Value
.TokenCName
, key
[1], key
[2])
1400 del self
.Platform
.Pcds
[key
]
1401 self
.Platform
.Pcds
[newkey
] = Value
1409 # for gathering error information
1410 NoDatumTypePcdList
= set()
1412 self
._GuidValue
= {}
1414 for InfName
in self
._AsBuildInfList
:
1415 InfName
= mws
.join(self
.WorkspaceDir
, InfName
)
1416 FdfModuleList
.append(os
.path
.normpath(InfName
))
1417 for F
in self
.Platform
.Modules
.keys():
1418 M
= ModuleAutoGen(self
.Workspace
, F
, self
.BuildTarget
, self
.ToolChain
, self
.Arch
, self
.MetaFile
)
1419 #GuidValue.update(M.Guids)
1421 self
.Platform
.Modules
[F
].M
= M
1423 for PcdFromModule
in M
.ModulePcdList
+ M
.LibraryPcdList
:
1424 # make sure that the "VOID*" kind of datum has MaxDatumSize set
1425 if PcdFromModule
.DatumType
== "VOID*" and PcdFromModule
.MaxDatumSize
in [None, '']:
1426 NoDatumTypePcdList
.add("%s.%s [%s]" % (PcdFromModule
.TokenSpaceGuidCName
, PcdFromModule
.TokenCName
, F
))
1428 # Check the PCD from Binary INF or Source INF
1429 if M
.IsBinaryModule
== True:
1430 PcdFromModule
.IsFromBinaryInf
= True
1432 # Check the PCD from DSC or not
1433 if (PcdFromModule
.TokenCName
, PcdFromModule
.TokenSpaceGuidCName
) in self
.Platform
.Pcds
.keys():
1434 PcdFromModule
.IsFromDsc
= True
1436 PcdFromModule
.IsFromDsc
= False
1437 if PcdFromModule
.Type
in GenC
.gDynamicPcd
or PcdFromModule
.Type
in GenC
.gDynamicExPcd
:
1438 if F
.Path
not in FdfModuleList
:
1439 # If one of the Source built modules listed in the DSC is not listed
1440 # in FDF modules, and the INF lists a PCD can only use the PcdsDynamic
1441 # access method (it is only listed in the DEC file that declares the
1442 # PCD as PcdsDynamic), then build tool will report warning message
1443 # notify the PI that they are attempting to build a module that must
1444 # be included in a flash image in order to be functional. These Dynamic
1445 # PCD will not be added into the Database unless it is used by other
1446 # modules that are included in the FDF file.
1447 if PcdFromModule
.Type
in GenC
.gDynamicPcd
and \
1448 PcdFromModule
.IsFromBinaryInf
== False:
1449 # Print warning message to let the developer make a determine.
1450 if PcdFromModule
not in PcdNotInDb
:
1451 PcdNotInDb
.append(PcdFromModule
)
1453 # If one of the Source built modules listed in the DSC is not listed in
1454 # FDF modules, and the INF lists a PCD can only use the PcdsDynamicEx
1455 # access method (it is only listed in the DEC file that declares the
1456 # PCD as PcdsDynamicEx), then DO NOT break the build; DO NOT add the
1457 # PCD to the Platform's PCD Database.
1458 if PcdFromModule
.Type
in GenC
.gDynamicExPcd
:
1459 if PcdFromModule
not in PcdNotInDb
:
1460 PcdNotInDb
.append(PcdFromModule
)
1463 # If a dynamic PCD used by a PEM module/PEI module & DXE module,
1464 # it should be stored in Pcd PEI database, If a dynamic only
1465 # used by DXE module, it should be stored in DXE PCD database.
1466 # The default Phase is DXE
1468 if M
.ModuleType
in ["PEIM", "PEI_CORE"]:
1469 PcdFromModule
.Phase
= "PEI"
1470 if PcdFromModule
not in self
._DynaPcdList
_:
1471 self
._DynaPcdList
_.append(PcdFromModule
)
1472 elif PcdFromModule
.Phase
== 'PEI':
1473 # overwrite any the same PCD existing, if Phase is PEI
1474 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1475 self
._DynaPcdList
_[Index
] = PcdFromModule
1476 elif PcdFromModule
not in self
._NonDynaPcdList
_:
1477 self
._NonDynaPcdList
_.append(PcdFromModule
)
1478 elif PcdFromModule
in self
._NonDynaPcdList
_ and PcdFromModule
.IsFromBinaryInf
== True:
1479 Index
= self
._NonDynaPcdList
_.index(PcdFromModule
)
1480 if self
._NonDynaPcdList
_[Index
].IsFromBinaryInf
== False:
1481 #The PCD from Binary INF will override the same one from source INF
1482 self
._NonDynaPcdList
_.remove (self
._NonDynaPcdList
_[Index
])
1483 PcdFromModule
.Pending
= False
1484 self
._NonDynaPcdList
_.append (PcdFromModule
)
1485 # Parse the DynamicEx PCD from the AsBuild INF module list of FDF.
1487 for ModuleInf
in self
.Platform
.Modules
.keys():
1488 DscModuleList
.append (os
.path
.normpath(ModuleInf
.Path
))
1489 # add the PCD from modules that listed in FDF but not in DSC to Database
1490 for InfName
in FdfModuleList
:
1491 if InfName
not in DscModuleList
:
1492 InfClass
= PathClass(InfName
)
1493 M
= self
.BuildDatabase
[InfClass
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1494 # If a module INF in FDF but not in current arch's DSC module list, it must be module (either binary or source)
1495 # for different Arch. PCDs in source module for different Arch is already added before, so skip the source module here.
1496 # For binary module, if in current arch, we need to list the PCDs into database.
1497 if not M
.IsSupportedArch
:
1499 # Override the module PCD setting by platform setting
1500 ModulePcdList
= self
.ApplyPcdSetting(M
, M
.Pcds
)
1501 for PcdFromModule
in ModulePcdList
:
1502 PcdFromModule
.IsFromBinaryInf
= True
1503 PcdFromModule
.IsFromDsc
= False
1504 # Only allow the DynamicEx and Patchable PCD in AsBuild INF
1505 if PcdFromModule
.Type
not in GenC
.gDynamicExPcd
and PcdFromModule
.Type
not in TAB_PCDS_PATCHABLE_IN_MODULE
:
1506 EdkLogger
.error("build", AUTOGEN_ERROR
, "PCD setting error",
1508 ExtraData
="\n\tExisted %s PCD %s in:\n\t\t%s\n"
1509 % (PcdFromModule
.Type
, PcdFromModule
.TokenCName
, InfName
))
1510 # make sure that the "VOID*" kind of datum has MaxDatumSize set
1511 if PcdFromModule
.DatumType
== "VOID*" and PcdFromModule
.MaxDatumSize
in [None, '']:
1512 NoDatumTypePcdList
.add("%s.%s [%s]" % (PcdFromModule
.TokenSpaceGuidCName
, PcdFromModule
.TokenCName
, InfName
))
1513 if M
.ModuleType
in ["PEIM", "PEI_CORE"]:
1514 PcdFromModule
.Phase
= "PEI"
1515 if PcdFromModule
not in self
._DynaPcdList
_ and PcdFromModule
.Type
in GenC
.gDynamicExPcd
:
1516 self
._DynaPcdList
_.append(PcdFromModule
)
1517 elif PcdFromModule
not in self
._NonDynaPcdList
_ and PcdFromModule
.Type
in TAB_PCDS_PATCHABLE_IN_MODULE
:
1518 self
._NonDynaPcdList
_.append(PcdFromModule
)
1519 if PcdFromModule
in self
._DynaPcdList
_ and PcdFromModule
.Phase
== 'PEI' and PcdFromModule
.Type
in GenC
.gDynamicExPcd
:
1520 # Overwrite the phase of any the same PCD existing, if Phase is PEI.
1521 # It is to solve the case that a dynamic PCD used by a PEM module/PEI
1522 # module & DXE module at a same time.
1523 # Overwrite the type of the PCDs in source INF by the type of AsBuild
1524 # INF file as DynamicEx.
1525 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1526 self
._DynaPcdList
_[Index
].Phase
= PcdFromModule
.Phase
1527 self
._DynaPcdList
_[Index
].Type
= PcdFromModule
.Type
1528 for PcdFromModule
in self
._NonDynaPcdList
_:
1529 # If a PCD is not listed in the DSC file, but binary INF files used by
1530 # this platform all (that use this PCD) list the PCD in a [PatchPcds]
1531 # section, AND all source INF files used by this platform the build
1532 # that use the PCD list the PCD in either a [Pcds] or [PatchPcds]
1533 # section, then the tools must NOT add the PCD to the Platform's PCD
1534 # Database; the build must assign the access method for this PCD as
1535 # PcdsPatchableInModule.
1536 if PcdFromModule
not in self
._DynaPcdList
_:
1538 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1539 if PcdFromModule
.IsFromDsc
== False and \
1540 PcdFromModule
.Type
in TAB_PCDS_PATCHABLE_IN_MODULE
and \
1541 PcdFromModule
.IsFromBinaryInf
== True and \
1542 self
._DynaPcdList
_[Index
].IsFromBinaryInf
== False:
1543 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1544 self
._DynaPcdList
_.remove (self
._DynaPcdList
_[Index
])
1546 # print out error information and break the build, if error found
1547 if len(NoDatumTypePcdList
) > 0:
1548 NoDatumTypePcdListString
= "\n\t\t".join(NoDatumTypePcdList
)
1549 EdkLogger
.error("build", AUTOGEN_ERROR
, "PCD setting error",
1551 ExtraData
="\n\tPCD(s) without MaxDatumSize:\n\t\t%s\n"
1552 % NoDatumTypePcdListString
)
1553 self
._NonDynamicPcdList
= self
._NonDynaPcdList
_
1554 self
._DynamicPcdList
= self
._DynaPcdList
_
1556 # Sort dynamic PCD list to:
1557 # 1) If PCD's datum type is VOID* and value is unicode string which starts with L, the PCD item should
1558 # try to be put header of dynamicd List
1559 # 2) If PCD is HII type, the PCD item should be put after unicode type PCD
1561 # The reason of sorting is make sure the unicode string is in double-byte alignment in string table.
1563 UnicodePcdArray
= set()
1565 OtherPcdArray
= set()
1567 VpdFile
= VpdInfoFile
.VpdInfoFile()
1568 NeedProcessVpdMapFile
= False
1570 for pcd
in self
.Platform
.Pcds
.keys():
1571 if pcd
not in self
._PlatformPcds
.keys():
1572 self
._PlatformPcds
[pcd
] = self
.Platform
.Pcds
[pcd
]
1574 for item
in self
._PlatformPcds
:
1575 if self
._PlatformPcds
[item
].DatumType
and self
._PlatformPcds
[item
].DatumType
not in [TAB_UINT8
, TAB_UINT16
, TAB_UINT32
, TAB_UINT64
, TAB_VOID
, "BOOLEAN"]:
1576 self
._PlatformPcds
[item
].DatumType
= "VOID*"
1578 if (self
.Workspace
.ArchList
[-1] == self
.Arch
):
1579 for Pcd
in self
._DynamicPcdList
:
1580 # just pick the a value to determine whether is unicode string type
1581 Sku
= Pcd
.SkuInfoList
[Pcd
.SkuInfoList
.keys()[0]]
1582 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1584 if Pcd
.DatumType
not in [TAB_UINT8
, TAB_UINT16
, TAB_UINT32
, TAB_UINT64
, TAB_VOID
, "BOOLEAN"]:
1585 Pcd
.DatumType
= "VOID*"
1587 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
1588 # if found HII type PCD then insert to right of UnicodeIndex
1589 if Pcd
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
]:
1590 VpdPcdDict
[(Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
)] = Pcd
1592 #Collect DynamicHii PCD values and assign it to DynamicExVpd PCD gEfiMdeModulePkgTokenSpaceGuid.PcdNvStoreDefaultValueBuffer
1593 PcdNvStoreDfBuffer
= VpdPcdDict
.get(("PcdNvStoreDefaultValueBuffer","gEfiMdeModulePkgTokenSpaceGuid"))
1594 if PcdNvStoreDfBuffer
:
1595 self
.VariableInfo
= self
.CollectVariables(self
._DynamicPcdList
)
1596 vardump
= self
.VariableInfo
.dump()
1598 PcdNvStoreDfBuffer
.DefaultValue
= vardump
1599 for skuname
in PcdNvStoreDfBuffer
.SkuInfoList
:
1600 PcdNvStoreDfBuffer
.SkuInfoList
[skuname
].DefaultValue
= vardump
1601 PcdNvStoreDfBuffer
.MaxDatumSize
= str(len(vardump
.split(",")))
1603 PlatformPcds
= self
._PlatformPcds
.keys()
1606 # Add VPD type PCD into VpdFile and determine whether the VPD PCD need to be fixed up.
1609 for PcdKey
in PlatformPcds
:
1610 Pcd
= self
._PlatformPcds
[PcdKey
]
1611 if Pcd
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
] and \
1612 PcdKey
in VpdPcdDict
:
1613 Pcd
= VpdPcdDict
[PcdKey
]
1615 DefaultSku
= Pcd
.SkuInfoList
.get('DEFAULT')
1617 PcdValue
= DefaultSku
.DefaultValue
1618 if PcdValue
not in SkuValueMap
:
1619 SkuValueMap
[PcdValue
] = []
1620 VpdFile
.Add(Pcd
, 'DEFAULT',DefaultSku
.VpdOffset
)
1621 SkuValueMap
[PcdValue
].append(DefaultSku
)
1623 for (SkuName
,Sku
) in Pcd
.SkuInfoList
.items():
1624 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1625 PcdValue
= Sku
.DefaultValue
1627 PcdValue
= Pcd
.DefaultValue
1628 if Sku
.VpdOffset
!= '*':
1629 if PcdValue
.startswith("{"):
1631 elif PcdValue
.startswith("L"):
1636 VpdOffset
= int(Sku
.VpdOffset
)
1639 VpdOffset
= int(Sku
.VpdOffset
, 16)
1641 EdkLogger
.error("build", FORMAT_INVALID
, "Invalid offset value %s for PCD %s.%s." % (Sku
.VpdOffset
, Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
1642 if VpdOffset
% Alignment
!= 0:
1643 if PcdValue
.startswith("{"):
1644 EdkLogger
.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
), File
=self
.MetaFile
)
1646 EdkLogger
.error("build", FORMAT_INVALID
, 'The offset value of PCD %s.%s should be %s-byte aligned.' % (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
, Alignment
))
1647 if PcdValue
not in SkuValueMap
:
1648 SkuValueMap
[PcdValue
] = []
1649 VpdFile
.Add(Pcd
, SkuName
,Sku
.VpdOffset
)
1650 SkuValueMap
[PcdValue
].append(Sku
)
1651 # if the offset of a VPD is *, then it need to be fixed up by third party tool.
1652 if not NeedProcessVpdMapFile
and Sku
.VpdOffset
== "*":
1653 NeedProcessVpdMapFile
= True
1654 if self
.Platform
.VpdToolGuid
is None or self
.Platform
.VpdToolGuid
== '':
1655 EdkLogger
.error("Build", FILE_NOT_FOUND
, \
1656 "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.")
1658 VpdSkuMap
[PcdKey
] = SkuValueMap
1660 # Fix the PCDs define in VPD PCD section that never referenced by module.
1661 # An example is PCD for signature usage.
1663 for DscPcd
in PlatformPcds
:
1664 DscPcdEntry
= self
._PlatformPcds
[DscPcd
]
1665 if DscPcdEntry
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
]:
1666 if not (self
.Platform
.VpdToolGuid
is None or self
.Platform
.VpdToolGuid
== ''):
1668 for VpdPcd
in VpdFile
._VpdArray
.keys():
1669 # This PCD has been referenced by module
1670 if (VpdPcd
.TokenSpaceGuidCName
== DscPcdEntry
.TokenSpaceGuidCName
) and \
1671 (VpdPcd
.TokenCName
== DscPcdEntry
.TokenCName
):
1674 # Not found, it should be signature
1676 # just pick the a value to determine whether is unicode string type
1678 SkuObjList
= DscPcdEntry
.SkuInfoList
.items()
1679 DefaultSku
= DscPcdEntry
.SkuInfoList
.get('DEFAULT')
1681 defaultindex
= SkuObjList
.index(('DEFAULT',DefaultSku
))
1682 SkuObjList
[0],SkuObjList
[defaultindex
] = SkuObjList
[defaultindex
],SkuObjList
[0]
1683 for (SkuName
,Sku
) in SkuObjList
:
1684 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1686 # Need to iterate DEC pcd information to get the value & datumtype
1687 for eachDec
in self
.PackageList
:
1688 for DecPcd
in eachDec
.Pcds
:
1689 DecPcdEntry
= eachDec
.Pcds
[DecPcd
]
1690 if (DecPcdEntry
.TokenSpaceGuidCName
== DscPcdEntry
.TokenSpaceGuidCName
) and \
1691 (DecPcdEntry
.TokenCName
== DscPcdEntry
.TokenCName
):
1692 # Print warning message to let the developer make a determine.
1693 EdkLogger
.warn("build", "Unreferenced vpd pcd used!",
1694 File
=self
.MetaFile
, \
1695 ExtraData
= "PCD: %s.%s used in the DSC file %s is unreferenced." \
1696 %(DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
, self
.Platform
.MetaFile
.Path
))
1698 DscPcdEntry
.DatumType
= DecPcdEntry
.DatumType
1699 DscPcdEntry
.DefaultValue
= DecPcdEntry
.DefaultValue
1700 DscPcdEntry
.TokenValue
= DecPcdEntry
.TokenValue
1701 DscPcdEntry
.TokenSpaceGuidValue
= eachDec
.Guids
[DecPcdEntry
.TokenSpaceGuidCName
]
1702 # Only fix the value while no value provided in DSC file.
1703 if (Sku
.DefaultValue
== "" or Sku
.DefaultValue
==None):
1704 DscPcdEntry
.SkuInfoList
[DscPcdEntry
.SkuInfoList
.keys()[0]].DefaultValue
= DecPcdEntry
.DefaultValue
1706 if DscPcdEntry
not in self
._DynamicPcdList
:
1707 self
._DynamicPcdList
.append(DscPcdEntry
)
1708 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1709 PcdValue
= Sku
.DefaultValue
1711 PcdValue
= DscPcdEntry
.DefaultValue
1712 if Sku
.VpdOffset
!= '*':
1713 if PcdValue
.startswith("{"):
1715 elif PcdValue
.startswith("L"):
1720 VpdOffset
= int(Sku
.VpdOffset
)
1723 VpdOffset
= int(Sku
.VpdOffset
, 16)
1725 EdkLogger
.error("build", FORMAT_INVALID
, "Invalid offset value %s for PCD %s.%s." % (Sku
.VpdOffset
, DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
))
1726 if VpdOffset
% Alignment
!= 0:
1727 if PcdValue
.startswith("{"):
1728 EdkLogger
.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
), File
=self
.MetaFile
)
1730 EdkLogger
.error("build", FORMAT_INVALID
, 'The offset value of PCD %s.%s should be %s-byte aligned.' % (DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
, Alignment
))
1731 if PcdValue
not in SkuValueMap
:
1732 SkuValueMap
[PcdValue
] = []
1733 VpdFile
.Add(DscPcdEntry
, SkuName
,Sku
.VpdOffset
)
1734 SkuValueMap
[PcdValue
].append(Sku
)
1735 if not NeedProcessVpdMapFile
and Sku
.VpdOffset
== "*":
1736 NeedProcessVpdMapFile
= True
1737 if DscPcdEntry
.DatumType
== 'VOID*' and PcdValue
.startswith("L"):
1738 UnicodePcdArray
.add(DscPcdEntry
)
1739 elif len(Sku
.VariableName
) > 0:
1740 HiiPcdArray
.add(DscPcdEntry
)
1742 OtherPcdArray
.add(DscPcdEntry
)
1744 # if the offset of a VPD is *, then it need to be fixed up by third party tool.
1745 VpdSkuMap
[DscPcd
] = SkuValueMap
1746 if (self
.Platform
.FlashDefinition
is None or self
.Platform
.FlashDefinition
== '') and \
1747 VpdFile
.GetCount() != 0:
1748 EdkLogger
.error("build", ATTRIBUTE_NOT_AVAILABLE
,
1749 "Fail to get FLASH_DEFINITION definition in DSC file %s which is required when DSC contains VPD PCD." % str(self
.Platform
.MetaFile
))
1751 if VpdFile
.GetCount() != 0:
1753 self
.FixVpdOffset(VpdFile
)
1755 self
.FixVpdOffset(self
.UpdateNVStoreMaxSize(VpdFile
))
1757 # Process VPD map file generated by third party BPDG tool
1758 if NeedProcessVpdMapFile
:
1759 VpdMapFilePath
= os
.path
.join(self
.BuildDir
, "FV", "%s.map" % self
.Platform
.VpdToolGuid
)
1760 if os
.path
.exists(VpdMapFilePath
):
1761 VpdFile
.Read(VpdMapFilePath
)
1764 for pcd
in VpdSkuMap
:
1765 vpdinfo
= VpdFile
.GetVpdInfo(pcd
)
1767 # just pick the a value to determine whether is unicode string type
1769 for pcdvalue
in VpdSkuMap
[pcd
]:
1770 for sku
in VpdSkuMap
[pcd
][pcdvalue
]:
1771 for item
in vpdinfo
:
1772 if item
[2] == pcdvalue
:
1773 sku
.VpdOffset
= item
[1]
1775 EdkLogger
.error("build", FILE_READ_FAILURE
, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath
)
1777 # Delete the DynamicPcdList At the last time enter into this function
1778 for Pcd
in self
._DynamicPcdList
:
1779 # just pick the a value to determine whether is unicode string type
1780 Sku
= Pcd
.SkuInfoList
[Pcd
.SkuInfoList
.keys()[0]]
1781 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1783 if Pcd
.DatumType
not in [TAB_UINT8
, TAB_UINT16
, TAB_UINT32
, TAB_UINT64
, TAB_VOID
, "BOOLEAN"]:
1784 Pcd
.DatumType
= "VOID*"
1786 PcdValue
= Sku
.DefaultValue
1787 if Pcd
.DatumType
== 'VOID*' and PcdValue
.startswith("L"):
1788 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
1789 UnicodePcdArray
.add(Pcd
)
1790 elif len(Sku
.VariableName
) > 0:
1791 # if found HII type PCD then insert to right of UnicodeIndex
1792 HiiPcdArray
.add(Pcd
)
1794 OtherPcdArray
.add(Pcd
)
1795 del self
._DynamicPcdList
[:]
1796 self
._DynamicPcdList
.extend(list(UnicodePcdArray
))
1797 self
._DynamicPcdList
.extend(list(HiiPcdArray
))
1798 self
._DynamicPcdList
.extend(list(OtherPcdArray
))
1799 allskuset
= [(SkuName
,Sku
.SkuId
) for pcd
in self
._DynamicPcdList
for (SkuName
,Sku
) in pcd
.SkuInfoList
.items()]
1800 for pcd
in self
._DynamicPcdList
:
1801 if len(pcd
.SkuInfoList
) == 1:
1802 for (SkuName
,SkuId
) in allskuset
:
1803 if type(SkuId
) in (str,unicode) and eval(SkuId
) == 0 or SkuId
== 0:
1805 pcd
.SkuInfoList
[SkuName
] = copy
.deepcopy(pcd
.SkuInfoList
['DEFAULT'])
1806 pcd
.SkuInfoList
[SkuName
].SkuId
= SkuId
1807 self
.AllPcdList
= self
._NonDynamicPcdList
+ self
._DynamicPcdList
1809 def FixVpdOffset(self
,VpdFile
):
1810 FvPath
= os
.path
.join(self
.BuildDir
, "FV")
1811 if not os
.path
.exists(FvPath
):
1815 EdkLogger
.error("build", FILE_WRITE_FAILURE
, "Fail to create FV folder under %s" % self
.BuildDir
)
1817 VpdFilePath
= os
.path
.join(FvPath
, "%s.txt" % self
.Platform
.VpdToolGuid
)
1819 if VpdFile
.Write(VpdFilePath
):
1820 # retrieve BPDG tool's path from tool_def.txt according to VPD_TOOL_GUID defined in DSC file.
1822 for ToolDef
in self
.ToolDefinition
.values():
1823 if ToolDef
.has_key("GUID") and ToolDef
["GUID"] == self
.Platform
.VpdToolGuid
:
1824 if not ToolDef
.has_key("PATH"):
1825 EdkLogger
.error("build", ATTRIBUTE_NOT_AVAILABLE
, "PATH attribute was not provided for BPDG guid tool %s in tools_def.txt" % self
.Platform
.VpdToolGuid
)
1826 BPDGToolName
= ToolDef
["PATH"]
1828 # Call third party GUID BPDG tool.
1829 if BPDGToolName
is not None:
1830 VpdInfoFile
.CallExtenalBPDGTool(BPDGToolName
, VpdFilePath
)
1832 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.")
1834 ## Return the platform build data object
1835 def _GetPlatform(self
):
1836 if self
._Platform
is None:
1837 self
._Platform
= self
.BuildDatabase
[self
.MetaFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1838 return self
._Platform
1840 ## Return platform name
1842 return self
.Platform
.PlatformName
1844 ## Return the meta file GUID
1846 return self
.Platform
.Guid
1848 ## Return the platform version
1849 def _GetVersion(self
):
1850 return self
.Platform
.Version
1852 ## Return the FDF file name
1853 def _GetFdfFile(self
):
1854 if self
._FdfFile
is None:
1855 if self
.Workspace
.FdfFile
!= "":
1856 self
._FdfFile
= mws
.join(self
.WorkspaceDir
, self
.Workspace
.FdfFile
)
1859 return self
._FdfFile
1861 ## Return the build output directory platform specifies
1862 def _GetOutputDir(self
):
1863 return self
.Platform
.OutputDirectory
1865 ## Return the directory to store all intermediate and final files built
1866 def _GetBuildDir(self
):
1867 if self
._BuildDir
is None:
1868 if os
.path
.isabs(self
.OutputDir
):
1869 self
._BuildDir
= path
.join(
1870 path
.abspath(self
.OutputDir
),
1871 self
.BuildTarget
+ "_" + self
.ToolChain
,
1874 self
._BuildDir
= path
.join(
1877 self
.BuildTarget
+ "_" + self
.ToolChain
,
1879 GlobalData
.gBuildDirectory
= self
._BuildDir
1880 return self
._BuildDir
1882 ## Return directory of platform makefile
1884 # @retval string Makefile directory
1886 def _GetMakeFileDir(self
):
1887 if self
._MakeFileDir
is None:
1888 self
._MakeFileDir
= path
.join(self
.BuildDir
, self
.Arch
)
1889 return self
._MakeFileDir
1891 ## Return build command string
1893 # @retval string Build command string
1895 def _GetBuildCommand(self
):
1896 if self
._BuildCommand
is None:
1897 self
._BuildCommand
= []
1898 if "MAKE" in self
.ToolDefinition
and "PATH" in self
.ToolDefinition
["MAKE"]:
1899 self
._BuildCommand
+= SplitOption(self
.ToolDefinition
["MAKE"]["PATH"])
1900 if "FLAGS" in self
.ToolDefinition
["MAKE"]:
1901 NewOption
= self
.ToolDefinition
["MAKE"]["FLAGS"].strip()
1903 self
._BuildCommand
+= SplitOption(NewOption
)
1904 if "MAKE" in self
.EdkIIBuildOption
:
1905 if "FLAGS" in self
.EdkIIBuildOption
["MAKE"]:
1906 Flags
= self
.EdkIIBuildOption
["MAKE"]["FLAGS"]
1907 if Flags
.startswith('='):
1908 self
._BuildCommand
= [self
._BuildCommand
[0]] + [Flags
[1:]]
1910 self
._BuildCommand
+= [Flags
]
1911 return self
._BuildCommand
1913 ## Get tool chain definition
1915 # Get each tool defition for given tool chain from tools_def.txt and platform
1917 def _GetToolDefinition(self
):
1918 if self
._ToolDefinitions
is None:
1919 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDictionary
1920 if TAB_TOD_DEFINES_COMMAND_TYPE
not in self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
:
1921 EdkLogger
.error('build', RESOURCE_NOT_AVAILABLE
, "No tools found in configuration",
1922 ExtraData
="[%s]" % self
.MetaFile
)
1923 self
._ToolDefinitions
= {}
1925 for Def
in ToolDefinition
:
1926 Target
, Tag
, Arch
, Tool
, Attr
= Def
.split("_")
1927 if Target
!= self
.BuildTarget
or Tag
!= self
.ToolChain
or Arch
!= self
.Arch
:
1930 Value
= ToolDefinition
[Def
]
1931 # don't record the DLL
1933 DllPathList
.add(Value
)
1936 if Tool
not in self
._ToolDefinitions
:
1937 self
._ToolDefinitions
[Tool
] = {}
1938 self
._ToolDefinitions
[Tool
][Attr
] = Value
1942 if GlobalData
.gOptions
.SilentMode
and "MAKE" in self
._ToolDefinitions
:
1943 if "FLAGS" not in self
._ToolDefinitions
["MAKE"]:
1944 self
._ToolDefinitions
["MAKE"]["FLAGS"] = ""
1945 self
._ToolDefinitions
["MAKE"]["FLAGS"] += " -s"
1947 for Tool
in self
._ToolDefinitions
:
1948 for Attr
in self
._ToolDefinitions
[Tool
]:
1949 Value
= self
._ToolDefinitions
[Tool
][Attr
]
1950 if Tool
in self
.BuildOption
and Attr
in self
.BuildOption
[Tool
]:
1951 # check if override is indicated
1952 if self
.BuildOption
[Tool
][Attr
].startswith('='):
1953 Value
= self
.BuildOption
[Tool
][Attr
][1:]
1956 Value
+= " " + self
.BuildOption
[Tool
][Attr
]
1958 Value
= self
.BuildOption
[Tool
][Attr
]
1961 # Don't put MAKE definition in the file
1965 ToolsDef
+= "%s = %s\n" % (Tool
, Value
)
1967 # Don't put MAKE definition in the file
1972 ToolsDef
+= "%s_%s = %s\n" % (Tool
, Attr
, Value
)
1975 SaveFileOnChange(self
.ToolDefinitionFile
, ToolsDef
)
1976 for DllPath
in DllPathList
:
1977 os
.environ
["PATH"] = DllPath
+ os
.pathsep
+ os
.environ
["PATH"]
1978 os
.environ
["MAKE_FLAGS"] = MakeFlags
1980 return self
._ToolDefinitions
1982 ## Return the paths of tools
1983 def _GetToolDefFile(self
):
1984 if self
._ToolDefFile
is None:
1985 self
._ToolDefFile
= os
.path
.join(self
.MakeFileDir
, "TOOLS_DEF." + self
.Arch
)
1986 return self
._ToolDefFile
1988 ## Retrieve the toolchain family of given toolchain tag. Default to 'MSFT'.
1989 def _GetToolChainFamily(self
):
1990 if self
._ToolChainFamily
is None:
1991 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
1992 if TAB_TOD_DEFINES_FAMILY
not in ToolDefinition \
1993 or self
.ToolChain
not in ToolDefinition
[TAB_TOD_DEFINES_FAMILY
] \
1994 or not ToolDefinition
[TAB_TOD_DEFINES_FAMILY
][self
.ToolChain
]:
1995 EdkLogger
.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
1997 self
._ToolChainFamily
= "MSFT"
1999 self
._ToolChainFamily
= ToolDefinition
[TAB_TOD_DEFINES_FAMILY
][self
.ToolChain
]
2000 return self
._ToolChainFamily
2002 def _GetBuildRuleFamily(self
):
2003 if self
._BuildRuleFamily
is None:
2004 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
2005 if TAB_TOD_DEFINES_BUILDRULEFAMILY
not in ToolDefinition \
2006 or self
.ToolChain
not in ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
] \
2007 or not ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
][self
.ToolChain
]:
2008 EdkLogger
.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
2010 self
._BuildRuleFamily
= "MSFT"
2012 self
._BuildRuleFamily
= ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
][self
.ToolChain
]
2013 return self
._BuildRuleFamily
2015 ## Return the build options specific for all modules in this platform
2016 def _GetBuildOptions(self
):
2017 if self
._BuildOption
is None:
2018 self
._BuildOption
= self
._ExpandBuildOption
(self
.Platform
.BuildOptions
)
2019 return self
._BuildOption
2021 ## Return the build options specific for EDK modules in this platform
2022 def _GetEdkBuildOptions(self
):
2023 if self
._EdkBuildOption
is None:
2024 self
._EdkBuildOption
= self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, EDK_NAME
)
2025 return self
._EdkBuildOption
2027 ## Return the build options specific for EDKII modules in this platform
2028 def _GetEdkIIBuildOptions(self
):
2029 if self
._EdkIIBuildOption
is None:
2030 self
._EdkIIBuildOption
= self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, EDKII_NAME
)
2031 return self
._EdkIIBuildOption
2033 ## Parse build_rule.txt in Conf Directory.
2035 # @retval BuildRule object
2037 def _GetBuildRule(self
):
2038 if self
._BuildRule
is None:
2039 BuildRuleFile
= None
2040 if TAB_TAT_DEFINES_BUILD_RULE_CONF
in self
.Workspace
.TargetTxt
.TargetTxtDictionary
:
2041 BuildRuleFile
= self
.Workspace
.TargetTxt
.TargetTxtDictionary
[TAB_TAT_DEFINES_BUILD_RULE_CONF
]
2042 if BuildRuleFile
in [None, '']:
2043 BuildRuleFile
= gDefaultBuildRuleFile
2044 self
._BuildRule
= BuildRule(BuildRuleFile
)
2045 if self
._BuildRule
._FileVersion
== "":
2046 self
._BuildRule
._FileVersion
= AutoGenReqBuildRuleVerNum
2048 if self
._BuildRule
._FileVersion
< AutoGenReqBuildRuleVerNum
:
2049 # If Build Rule's version is less than the version number required by the tools, halting the build.
2050 EdkLogger
.error("build", AUTOGEN_ERROR
,
2051 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])"\
2052 % (self
._BuildRule
._FileVersion
, AutoGenReqBuildRuleVerNum
))
2054 return self
._BuildRule
2056 ## Summarize the packages used by modules in this platform
2057 def _GetPackageList(self
):
2058 if self
._PackageList
is None:
2059 self
._PackageList
= set()
2060 for La
in self
.LibraryAutoGenList
:
2061 self
._PackageList
.update(La
.DependentPackageList
)
2062 for Ma
in self
.ModuleAutoGenList
:
2063 self
._PackageList
.update(Ma
.DependentPackageList
)
2064 #Collect package set information from INF of FDF
2066 for ModuleFile
in self
._AsBuildModuleList
:
2067 if ModuleFile
in self
.Platform
.Modules
:
2069 ModuleData
= self
.BuildDatabase
[ModuleFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
2070 PkgSet
.update(ModuleData
.Packages
)
2071 self
._PackageList
= list(self
._PackageList
) + list (PkgSet
)
2072 return self
._PackageList
2074 def _GetNonDynamicPcdDict(self
):
2075 if self
._NonDynamicPcdDict
:
2076 return self
._NonDynamicPcdDict
2077 for Pcd
in self
.NonDynamicPcdList
:
2078 self
._NonDynamicPcdDict
[(Pcd
.TokenCName
,Pcd
.TokenSpaceGuidCName
)] = Pcd
2079 return self
._NonDynamicPcdDict
2081 ## Get list of non-dynamic PCDs
2082 def _GetNonDynamicPcdList(self
):
2083 if self
._NonDynamicPcdList
is None:
2084 self
.CollectPlatformDynamicPcds()
2085 return self
._NonDynamicPcdList
2087 ## Get list of dynamic PCDs
2088 def _GetDynamicPcdList(self
):
2089 if self
._DynamicPcdList
is None:
2090 self
.CollectPlatformDynamicPcds()
2091 return self
._DynamicPcdList
2093 ## Generate Token Number for all PCD
2094 def _GetPcdTokenNumbers(self
):
2095 if self
._PcdTokenNumber
is None:
2096 self
._PcdTokenNumber
= OrderedDict()
2099 # Make the Dynamic and DynamicEx PCD use within different TokenNumber area.
2103 # TokenNumber 0 ~ 10
2105 # TokeNumber 11 ~ 20
2107 for Pcd
in self
.DynamicPcdList
:
2108 if Pcd
.Phase
== "PEI":
2109 if Pcd
.Type
in ["Dynamic", "DynamicDefault", "DynamicVpd", "DynamicHii"]:
2110 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
2111 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2114 for Pcd
in self
.DynamicPcdList
:
2115 if Pcd
.Phase
== "PEI":
2116 if Pcd
.Type
in ["DynamicEx", "DynamicExDefault", "DynamicExVpd", "DynamicExHii"]:
2117 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
2118 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2121 for Pcd
in self
.DynamicPcdList
:
2122 if Pcd
.Phase
== "DXE":
2123 if Pcd
.Type
in ["Dynamic", "DynamicDefault", "DynamicVpd", "DynamicHii"]:
2124 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
2125 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2128 for Pcd
in self
.DynamicPcdList
:
2129 if Pcd
.Phase
== "DXE":
2130 if Pcd
.Type
in ["DynamicEx", "DynamicExDefault", "DynamicExVpd", "DynamicExHii"]:
2131 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
2132 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2135 for Pcd
in self
.NonDynamicPcdList
:
2136 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2138 return self
._PcdTokenNumber
2140 ## Summarize ModuleAutoGen objects of all modules/libraries to be built for this platform
2141 def _GetAutoGenObjectList(self
):
2142 self
._ModuleAutoGenList
= []
2143 self
._LibraryAutoGenList
= []
2144 for ModuleFile
in self
.Platform
.Modules
:
2153 if Ma
not in self
._ModuleAutoGenList
:
2154 self
._ModuleAutoGenList
.append(Ma
)
2155 for La
in Ma
.LibraryAutoGenList
:
2156 if La
not in self
._LibraryAutoGenList
:
2157 self
._LibraryAutoGenList
.append(La
)
2158 if Ma
not in La
._ReferenceModules
:
2159 La
._ReferenceModules
.append(Ma
)
2161 ## Summarize ModuleAutoGen objects of all modules to be built for this platform
2162 def _GetModuleAutoGenList(self
):
2163 if self
._ModuleAutoGenList
is None:
2164 self
._GetAutoGenObjectList
()
2165 return self
._ModuleAutoGenList
2167 ## Summarize ModuleAutoGen objects of all libraries to be built for this platform
2168 def _GetLibraryAutoGenList(self
):
2169 if self
._LibraryAutoGenList
is None:
2170 self
._GetAutoGenObjectList
()
2171 return self
._LibraryAutoGenList
2173 ## Test if a module is supported by the platform
2175 # An error will be raised directly if the module or its arch is not supported
2176 # by the platform or current configuration
2178 def ValidModule(self
, Module
):
2179 return Module
in self
.Platform
.Modules
or Module
in self
.Platform
.LibraryInstances \
2180 or Module
in self
._AsBuildModuleList
2182 ## Resolve the library classes in a module to library instances
2184 # This method will not only resolve library classes but also sort the library
2185 # instances according to the dependency-ship.
2187 # @param Module The module from which the library classes will be resolved
2189 # @retval library_list List of library instances sorted
2191 def ApplyLibraryInstance(self
, Module
):
2192 # Cover the case that the binary INF file is list in the FDF file but not DSC file, return empty list directly
2193 if str(Module
) not in self
.Platform
.Modules
:
2196 ModuleType
= Module
.ModuleType
2198 # for overridding library instances with module specific setting
2199 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
2201 # add forced library instances (specified under LibraryClasses sections)
2203 # If a module has a MODULE_TYPE of USER_DEFINED,
2204 # do not link in NULL library class instances from the global [LibraryClasses.*] sections.
2206 if Module
.ModuleType
!= SUP_MODULE_USER_DEFINED
:
2207 for LibraryClass
in self
.Platform
.LibraryClasses
.GetKeys():
2208 if LibraryClass
.startswith("NULL") and self
.Platform
.LibraryClasses
[LibraryClass
, Module
.ModuleType
]:
2209 Module
.LibraryClasses
[LibraryClass
] = self
.Platform
.LibraryClasses
[LibraryClass
, Module
.ModuleType
]
2211 # add forced library instances (specified in module overrides)
2212 for LibraryClass
in PlatformModule
.LibraryClasses
:
2213 if LibraryClass
.startswith("NULL"):
2214 Module
.LibraryClasses
[LibraryClass
] = PlatformModule
.LibraryClasses
[LibraryClass
]
2217 LibraryConsumerList
= [Module
]
2219 ConsumedByList
= OrderedDict()
2220 LibraryInstance
= OrderedDict()
2222 EdkLogger
.verbose("")
2223 EdkLogger
.verbose("Library instances of module [%s] [%s]:" % (str(Module
), self
.Arch
))
2224 while len(LibraryConsumerList
) > 0:
2225 M
= LibraryConsumerList
.pop()
2226 for LibraryClassName
in M
.LibraryClasses
:
2227 if LibraryClassName
not in LibraryInstance
:
2228 # override library instance for this module
2229 if LibraryClassName
in PlatformModule
.LibraryClasses
:
2230 LibraryPath
= PlatformModule
.LibraryClasses
[LibraryClassName
]
2232 LibraryPath
= self
.Platform
.LibraryClasses
[LibraryClassName
, ModuleType
]
2233 if LibraryPath
is None or LibraryPath
== "":
2234 LibraryPath
= M
.LibraryClasses
[LibraryClassName
]
2235 if LibraryPath
is None or LibraryPath
== "":
2236 EdkLogger
.error("build", RESOURCE_NOT_AVAILABLE
,
2237 "Instance of library class [%s] is not found" % LibraryClassName
,
2239 ExtraData
="in [%s] [%s]\n\tconsumed by module [%s]" % (str(M
), self
.Arch
, str(Module
)))
2241 LibraryModule
= self
.BuildDatabase
[LibraryPath
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
2242 # for those forced library instance (NULL library), add a fake library class
2243 if LibraryClassName
.startswith("NULL"):
2244 LibraryModule
.LibraryClass
.append(LibraryClassObject(LibraryClassName
, [ModuleType
]))
2245 elif LibraryModule
.LibraryClass
is None \
2246 or len(LibraryModule
.LibraryClass
) == 0 \
2247 or (ModuleType
!= 'USER_DEFINED'
2248 and ModuleType
not in LibraryModule
.LibraryClass
[0].SupModList
):
2249 # only USER_DEFINED can link against any library instance despite of its SupModList
2250 EdkLogger
.error("build", OPTION_MISSING
,
2251 "Module type [%s] is not supported by library instance [%s]" \
2252 % (ModuleType
, LibraryPath
), File
=self
.MetaFile
,
2253 ExtraData
="consumed by [%s]" % str(Module
))
2255 LibraryInstance
[LibraryClassName
] = LibraryModule
2256 LibraryConsumerList
.append(LibraryModule
)
2257 EdkLogger
.verbose("\t" + str(LibraryClassName
) + " : " + str(LibraryModule
))
2259 LibraryModule
= LibraryInstance
[LibraryClassName
]
2261 if LibraryModule
is None:
2264 if LibraryModule
.ConstructorList
!= [] and LibraryModule
not in Constructor
:
2265 Constructor
.append(LibraryModule
)
2267 if LibraryModule
not in ConsumedByList
:
2268 ConsumedByList
[LibraryModule
] = []
2269 # don't add current module itself to consumer list
2271 if M
in ConsumedByList
[LibraryModule
]:
2273 ConsumedByList
[LibraryModule
].append(M
)
2275 # Initialize the sorted output list to the empty set
2277 SortedLibraryList
= []
2279 # Q <- Set of all nodes with no incoming edges
2281 LibraryList
= [] #LibraryInstance.values()
2283 for LibraryClassName
in LibraryInstance
:
2284 M
= LibraryInstance
[LibraryClassName
]
2285 LibraryList
.append(M
)
2286 if ConsumedByList
[M
] == []:
2290 # start the DAG algorithm
2294 while Q
== [] and EdgeRemoved
:
2296 # for each node Item with a Constructor
2297 for Item
in LibraryList
:
2298 if Item
not in Constructor
:
2300 # for each Node without a constructor with an edge e from Item to Node
2301 for Node
in ConsumedByList
[Item
]:
2302 if Node
in Constructor
:
2304 # remove edge e from the graph if Node has no constructor
2305 ConsumedByList
[Item
].remove(Node
)
2307 if ConsumedByList
[Item
] == []:
2308 # insert Item into Q
2313 # DAG is done if there's no more incoming edge for all nodes
2317 # remove node from Q
2320 SortedLibraryList
.append(Node
)
2322 # for each node Item with an edge e from Node to Item do
2323 for Item
in LibraryList
:
2324 if Node
not in ConsumedByList
[Item
]:
2326 # remove edge e from the graph
2327 ConsumedByList
[Item
].remove(Node
)
2329 if ConsumedByList
[Item
] != []:
2331 # insert Item into Q, if Item has no other incoming edges
2335 # if any remaining node Item in the graph has a constructor and an incoming edge, then the graph has a cycle
2337 for Item
in LibraryList
:
2338 if ConsumedByList
[Item
] != [] and Item
in Constructor
and len(Constructor
) > 1:
2339 ErrorMessage
= "\tconsumed by " + "\n\tconsumed by ".join([str(L
) for L
in ConsumedByList
[Item
]])
2340 EdkLogger
.error("build", BUILD_ERROR
, 'Library [%s] with constructors has a cycle' % str(Item
),
2341 ExtraData
=ErrorMessage
, File
=self
.MetaFile
)
2342 if Item
not in SortedLibraryList
:
2343 SortedLibraryList
.append(Item
)
2346 # Build the list of constructor and destructir names
2347 # The DAG Topo sort produces the destructor order, so the list of constructors must generated in the reverse order
2349 SortedLibraryList
.reverse()
2350 return SortedLibraryList
2353 ## Override PCD setting (type, value, ...)
2355 # @param ToPcd The PCD to be overrided
2356 # @param FromPcd The PCD overrideing from
2358 def _OverridePcd(self
, ToPcd
, FromPcd
, Module
=""):
2360 # in case there's PCDs coming from FDF file, which have no type given.
2361 # at this point, ToPcd.Type has the type found from dependent
2364 TokenCName
= ToPcd
.TokenCName
2365 for PcdItem
in GlobalData
.MixedPcd
:
2366 if (ToPcd
.TokenCName
, ToPcd
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
2367 TokenCName
= PcdItem
[0]
2369 if FromPcd
is not None:
2370 if ToPcd
.Pending
and FromPcd
.Type
not in [None, '']:
2371 ToPcd
.Type
= FromPcd
.Type
2372 elif (ToPcd
.Type
not in [None, '']) and (FromPcd
.Type
not in [None, ''])\
2373 and (ToPcd
.Type
!= FromPcd
.Type
) and (ToPcd
.Type
in FromPcd
.Type
):
2374 if ToPcd
.Type
.strip() == "DynamicEx":
2375 ToPcd
.Type
= FromPcd
.Type
2376 elif ToPcd
.Type
not in [None, ''] and FromPcd
.Type
not in [None, ''] \
2377 and ToPcd
.Type
!= FromPcd
.Type
:
2378 EdkLogger
.error("build", OPTION_CONFLICT
, "Mismatched PCD type",
2379 ExtraData
="%s.%s is defined as [%s] in module %s, but as [%s] in platform."\
2380 % (ToPcd
.TokenSpaceGuidCName
, TokenCName
,
2381 ToPcd
.Type
, Module
, FromPcd
.Type
),
2384 if FromPcd
.MaxDatumSize
not in [None, '']:
2385 ToPcd
.MaxDatumSize
= FromPcd
.MaxDatumSize
2386 if FromPcd
.DefaultValue
not in [None, '']:
2387 ToPcd
.DefaultValue
= FromPcd
.DefaultValue
2388 if FromPcd
.TokenValue
not in [None, '']:
2389 ToPcd
.TokenValue
= FromPcd
.TokenValue
2390 if FromPcd
.MaxDatumSize
not in [None, '']:
2391 ToPcd
.MaxDatumSize
= FromPcd
.MaxDatumSize
2392 if FromPcd
.DatumType
not in [None, '']:
2393 ToPcd
.DatumType
= FromPcd
.DatumType
2394 if FromPcd
.SkuInfoList
not in [None, '', []]:
2395 ToPcd
.SkuInfoList
= FromPcd
.SkuInfoList
2396 # Add Flexible PCD format parse
2397 if ToPcd
.DefaultValue
:
2399 ToPcd
.DefaultValue
= ValueExpressionEx(ToPcd
.DefaultValue
, ToPcd
.DatumType
, self
._GuidDict
)(True)
2400 except BadExpression
, Value
:
2401 EdkLogger
.error('Parser', FORMAT_INVALID
, 'PCD [%s.%s] Value "%s", %s' %(ToPcd
.TokenSpaceGuidCName
, ToPcd
.TokenCName
, ToPcd
.DefaultValue
, Value
),
2404 # check the validation of datum
2405 IsValid
, Cause
= CheckPcdDatum(ToPcd
.DatumType
, ToPcd
.DefaultValue
)
2407 EdkLogger
.error('build', FORMAT_INVALID
, Cause
, File
=self
.MetaFile
,
2408 ExtraData
="%s.%s" % (ToPcd
.TokenSpaceGuidCName
, TokenCName
))
2409 ToPcd
.validateranges
= FromPcd
.validateranges
2410 ToPcd
.validlists
= FromPcd
.validlists
2411 ToPcd
.expressions
= FromPcd
.expressions
2413 if FromPcd
is not None and ToPcd
.DatumType
== "VOID*" and ToPcd
.MaxDatumSize
in ['', None]:
2414 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "No MaxDatumSize specified for PCD %s.%s" \
2415 % (ToPcd
.TokenSpaceGuidCName
, TokenCName
))
2416 Value
= ToPcd
.DefaultValue
2417 if Value
in [None, '']:
2418 ToPcd
.MaxDatumSize
= '1'
2419 elif Value
[0] == 'L':
2420 ToPcd
.MaxDatumSize
= str((len(Value
) - 2) * 2)
2421 elif Value
[0] == '{':
2422 ToPcd
.MaxDatumSize
= str(len(Value
.split(',')))
2424 ToPcd
.MaxDatumSize
= str(len(Value
) - 1)
2426 # apply default SKU for dynamic PCDS if specified one is not available
2427 if (ToPcd
.Type
in PCD_DYNAMIC_TYPE_LIST
or ToPcd
.Type
in PCD_DYNAMIC_EX_TYPE_LIST
) \
2428 and ToPcd
.SkuInfoList
in [None, {}, '']:
2429 if self
.Platform
.SkuName
in self
.Platform
.SkuIds
:
2430 SkuName
= self
.Platform
.SkuName
2433 ToPcd
.SkuInfoList
= {
2434 SkuName
: SkuInfoClass(SkuName
, self
.Platform
.SkuIds
[SkuName
][0], '', '', '', '', '', ToPcd
.DefaultValue
)
2437 ## Apply PCD setting defined platform to a module
2439 # @param Module The module from which the PCD setting will be overrided
2441 # @retval PCD_list The list PCDs with settings from platform
2443 def ApplyPcdSetting(self
, Module
, Pcds
):
2444 # for each PCD in module
2445 for Name
, Guid
in Pcds
:
2446 PcdInModule
= Pcds
[Name
, Guid
]
2447 # find out the PCD setting in platform
2448 if (Name
, Guid
) in self
.Platform
.Pcds
:
2449 PcdInPlatform
= self
.Platform
.Pcds
[Name
, Guid
]
2451 PcdInPlatform
= None
2452 # then override the settings if any
2453 self
._OverridePcd
(PcdInModule
, PcdInPlatform
, Module
)
2454 # resolve the VariableGuid value
2455 for SkuId
in PcdInModule
.SkuInfoList
:
2456 Sku
= PcdInModule
.SkuInfoList
[SkuId
]
2457 if Sku
.VariableGuid
== '': continue
2458 Sku
.VariableGuidValue
= GuidValue(Sku
.VariableGuid
, self
.PackageList
, self
.MetaFile
.Path
)
2459 if Sku
.VariableGuidValue
is None:
2460 PackageList
= "\n\t".join([str(P
) for P
in self
.PackageList
])
2463 RESOURCE_NOT_AVAILABLE
,
2464 "Value of GUID [%s] is not found in" % Sku
.VariableGuid
,
2465 ExtraData
=PackageList
+ "\n\t(used with %s.%s from module %s)" \
2466 % (Guid
, Name
, str(Module
)),
2470 # override PCD settings with module specific setting
2471 if Module
in self
.Platform
.Modules
:
2472 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
2473 for Key
in PlatformModule
.Pcds
:
2478 elif Key
in GlobalData
.MixedPcd
:
2479 for PcdItem
in GlobalData
.MixedPcd
[Key
]:
2481 ToPcd
= Pcds
[PcdItem
]
2485 self
._OverridePcd
(ToPcd
, PlatformModule
.Pcds
[Key
], Module
)
2486 # use PCD value to calculate the MaxDatumSize when it is not specified
2487 for Name
, Guid
in Pcds
:
2488 Pcd
= Pcds
[Name
, Guid
]
2489 if Pcd
.DatumType
== "VOID*" and Pcd
.MaxDatumSize
in ['', None]:
2490 Value
= Pcd
.DefaultValue
2491 if Value
in [None, '']:
2492 Pcd
.MaxDatumSize
= '1'
2493 elif Value
[0] == 'L':
2494 Pcd
.MaxDatumSize
= str((len(Value
) - 2) * 2)
2495 elif Value
[0] == '{':
2496 Pcd
.MaxDatumSize
= str(len(Value
.split(',')))
2498 Pcd
.MaxDatumSize
= str(len(Value
) - 1)
2499 return Pcds
.values()
2501 ## Resolve library names to library modules
2503 # (for Edk.x modules)
2505 # @param Module The module from which the library names will be resolved
2507 # @retval library_list The list of library modules
2509 def ResolveLibraryReference(self
, Module
):
2510 EdkLogger
.verbose("")
2511 EdkLogger
.verbose("Library instances of module [%s] [%s]:" % (str(Module
), self
.Arch
))
2512 LibraryConsumerList
= [Module
]
2514 # "CompilerStub" is a must for Edk modules
2515 if Module
.Libraries
:
2516 Module
.Libraries
.append("CompilerStub")
2518 while len(LibraryConsumerList
) > 0:
2519 M
= LibraryConsumerList
.pop()
2520 for LibraryName
in M
.Libraries
:
2521 Library
= self
.Platform
.LibraryClasses
[LibraryName
, ':dummy:']
2523 for Key
in self
.Platform
.LibraryClasses
.data
.keys():
2524 if LibraryName
.upper() == Key
.upper():
2525 Library
= self
.Platform
.LibraryClasses
[Key
, ':dummy:']
2528 EdkLogger
.warn("build", "Library [%s] is not found" % LibraryName
, File
=str(M
),
2529 ExtraData
="\t%s [%s]" % (str(Module
), self
.Arch
))
2532 if Library
not in LibraryList
:
2533 LibraryList
.append(Library
)
2534 LibraryConsumerList
.append(Library
)
2535 EdkLogger
.verbose("\t" + LibraryName
+ " : " + str(Library
) + ' ' + str(type(Library
)))
2538 ## Calculate the priority value of the build option
2540 # @param Key Build option definition contain: TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
2542 # @retval Value Priority value based on the priority list.
2544 def CalculatePriorityValue(self
, Key
):
2545 Target
, ToolChain
, Arch
, CommandType
, Attr
= Key
.split('_')
2546 PriorityValue
= 0x11111
2548 PriorityValue
&= 0x01111
2549 if ToolChain
== "*":
2550 PriorityValue
&= 0x10111
2552 PriorityValue
&= 0x11011
2553 if CommandType
== "*":
2554 PriorityValue
&= 0x11101
2556 PriorityValue
&= 0x11110
2558 return self
.PrioList
["0x%0.5x" % PriorityValue
]
2561 ## Expand * in build option key
2563 # @param Options Options to be expanded
2565 # @retval options Options expanded
2567 def _ExpandBuildOption(self
, Options
, ModuleStyle
=None):
2574 # Construct a list contain the build options which need override.
2578 # Key[0] -- tool family
2579 # Key[1] -- TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
2581 if (Key
[0] == self
.BuildRuleFamily
and
2582 (ModuleStyle
is None or len(Key
) < 3 or (len(Key
) > 2 and Key
[2] == ModuleStyle
))):
2583 Target
, ToolChain
, Arch
, CommandType
, Attr
= Key
[1].split('_')
2584 if Target
== self
.BuildTarget
or Target
== "*":
2585 if ToolChain
== self
.ToolChain
or ToolChain
== "*":
2586 if Arch
== self
.Arch
or Arch
== "*":
2587 if Options
[Key
].startswith("="):
2588 if OverrideList
.get(Key
[1]) is not None:
2589 OverrideList
.pop(Key
[1])
2590 OverrideList
[Key
[1]] = Options
[Key
]
2593 # Use the highest priority value.
2595 if (len(OverrideList
) >= 2):
2596 KeyList
= OverrideList
.keys()
2597 for Index
in range(len(KeyList
)):
2598 NowKey
= KeyList
[Index
]
2599 Target1
, ToolChain1
, Arch1
, CommandType1
, Attr1
= NowKey
.split("_")
2600 for Index1
in range(len(KeyList
) - Index
- 1):
2601 NextKey
= KeyList
[Index1
+ Index
+ 1]
2603 # Compare two Key, if one is included by another, choose the higher priority one
2605 Target2
, ToolChain2
, Arch2
, CommandType2
, Attr2
= NextKey
.split("_")
2606 if Target1
== Target2
or Target1
== "*" or Target2
== "*":
2607 if ToolChain1
== ToolChain2
or ToolChain1
== "*" or ToolChain2
== "*":
2608 if Arch1
== Arch2
or Arch1
== "*" or Arch2
== "*":
2609 if CommandType1
== CommandType2
or CommandType1
== "*" or CommandType2
== "*":
2610 if Attr1
== Attr2
or Attr1
== "*" or Attr2
== "*":
2611 if self
.CalculatePriorityValue(NowKey
) > self
.CalculatePriorityValue(NextKey
):
2612 if Options
.get((self
.BuildRuleFamily
, NextKey
)) is not None:
2613 Options
.pop((self
.BuildRuleFamily
, NextKey
))
2615 if Options
.get((self
.BuildRuleFamily
, NowKey
)) is not None:
2616 Options
.pop((self
.BuildRuleFamily
, NowKey
))
2619 if ModuleStyle
is not None and len (Key
) > 2:
2620 # Check Module style is EDK or EDKII.
2621 # Only append build option for the matched style module.
2622 if ModuleStyle
== EDK_NAME
and Key
[2] != EDK_NAME
:
2624 elif ModuleStyle
== EDKII_NAME
and Key
[2] != EDKII_NAME
:
2627 Target
, Tag
, Arch
, Tool
, Attr
= Key
[1].split("_")
2628 # if tool chain family doesn't match, skip it
2629 if Tool
in self
.ToolDefinition
and Family
!= "":
2630 FamilyIsNull
= False
2631 if self
.ToolDefinition
[Tool
].get(TAB_TOD_DEFINES_BUILDRULEFAMILY
, "") != "":
2632 if Family
!= self
.ToolDefinition
[Tool
][TAB_TOD_DEFINES_BUILDRULEFAMILY
]:
2634 elif Family
!= self
.ToolDefinition
[Tool
][TAB_TOD_DEFINES_FAMILY
]:
2637 # expand any wildcard
2638 if Target
== "*" or Target
== self
.BuildTarget
:
2639 if Tag
== "*" or Tag
== self
.ToolChain
:
2640 if Arch
== "*" or Arch
== self
.Arch
:
2641 if Tool
not in BuildOptions
:
2642 BuildOptions
[Tool
] = {}
2643 if Attr
!= "FLAGS" or Attr
not in BuildOptions
[Tool
] or Options
[Key
].startswith('='):
2644 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2646 # append options for the same tool except PATH
2648 BuildOptions
[Tool
][Attr
] += " " + Options
[Key
]
2650 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2651 # Build Option Family has been checked, which need't to be checked again for family.
2652 if FamilyMatch
or FamilyIsNull
:
2656 if ModuleStyle
is not None and len (Key
) > 2:
2657 # Check Module style is EDK or EDKII.
2658 # Only append build option for the matched style module.
2659 if ModuleStyle
== EDK_NAME
and Key
[2] != EDK_NAME
:
2661 elif ModuleStyle
== EDKII_NAME
and Key
[2] != EDKII_NAME
:
2664 Target
, Tag
, Arch
, Tool
, Attr
= Key
[1].split("_")
2665 # if tool chain family doesn't match, skip it
2666 if Tool
not in self
.ToolDefinition
or Family
== "":
2668 # option has been added before
2669 if Family
!= self
.ToolDefinition
[Tool
][TAB_TOD_DEFINES_FAMILY
]:
2672 # expand any wildcard
2673 if Target
== "*" or Target
== self
.BuildTarget
:
2674 if Tag
== "*" or Tag
== self
.ToolChain
:
2675 if Arch
== "*" or Arch
== self
.Arch
:
2676 if Tool
not in BuildOptions
:
2677 BuildOptions
[Tool
] = {}
2678 if Attr
!= "FLAGS" or Attr
not in BuildOptions
[Tool
] or Options
[Key
].startswith('='):
2679 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2681 # append options for the same tool except PATH
2683 BuildOptions
[Tool
][Attr
] += " " + Options
[Key
]
2685 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2688 ## Append build options in platform to a module
2690 # @param Module The module to which the build options will be appened
2692 # @retval options The options appended with build options in platform
2694 def ApplyBuildOption(self
, Module
):
2695 # Get the different options for the different style module
2696 if Module
.AutoGenVersion
< 0x00010005:
2697 PlatformOptions
= self
.EdkBuildOption
2698 ModuleTypeOptions
= self
.Platform
.GetBuildOptionsByModuleType(EDK_NAME
, Module
.ModuleType
)
2700 PlatformOptions
= self
.EdkIIBuildOption
2701 ModuleTypeOptions
= self
.Platform
.GetBuildOptionsByModuleType(EDKII_NAME
, Module
.ModuleType
)
2702 ModuleTypeOptions
= self
._ExpandBuildOption
(ModuleTypeOptions
)
2703 ModuleOptions
= self
._ExpandBuildOption
(Module
.BuildOptions
)
2704 if Module
in self
.Platform
.Modules
:
2705 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
2706 PlatformModuleOptions
= self
._ExpandBuildOption
(PlatformModule
.BuildOptions
)
2708 PlatformModuleOptions
= {}
2710 BuildRuleOrder
= None
2711 for Options
in [self
.ToolDefinition
, ModuleOptions
, PlatformOptions
, ModuleTypeOptions
, PlatformModuleOptions
]:
2712 for Tool
in Options
:
2713 for Attr
in Options
[Tool
]:
2714 if Attr
== TAB_TOD_DEFINES_BUILDRULEORDER
:
2715 BuildRuleOrder
= Options
[Tool
][Attr
]
2717 AllTools
= set(ModuleOptions
.keys() + PlatformOptions
.keys() +
2718 PlatformModuleOptions
.keys() + ModuleTypeOptions
.keys() +
2719 self
.ToolDefinition
.keys())
2721 for Tool
in AllTools
:
2722 if Tool
not in BuildOptions
:
2723 BuildOptions
[Tool
] = {}
2725 for Options
in [self
.ToolDefinition
, ModuleOptions
, PlatformOptions
, ModuleTypeOptions
, PlatformModuleOptions
]:
2726 if Tool
not in Options
:
2728 for Attr
in Options
[Tool
]:
2729 Value
= Options
[Tool
][Attr
]
2731 # Do not generate it in Makefile
2733 if Attr
== TAB_TOD_DEFINES_BUILDRULEORDER
:
2735 if Attr
not in BuildOptions
[Tool
]:
2736 BuildOptions
[Tool
][Attr
] = ""
2737 # check if override is indicated
2738 if Value
.startswith('='):
2739 ToolPath
= Value
[1:]
2740 ToolPath
= mws
.handleWsMacro(ToolPath
)
2741 BuildOptions
[Tool
][Attr
] = ToolPath
2743 Value
= mws
.handleWsMacro(Value
)
2745 BuildOptions
[Tool
][Attr
] += " " + Value
2747 BuildOptions
[Tool
][Attr
] = Value
2748 if Module
.AutoGenVersion
< 0x00010005 and self
.Workspace
.UniFlag
is not None:
2750 # Override UNI flag only for EDK module.
2752 if 'BUILD' not in BuildOptions
:
2753 BuildOptions
['BUILD'] = {}
2754 BuildOptions
['BUILD']['FLAGS'] = self
.Workspace
.UniFlag
2755 return BuildOptions
, BuildRuleOrder
2757 Platform
= property(_GetPlatform
)
2758 Name
= property(_GetName
)
2759 Guid
= property(_GetGuid
)
2760 Version
= property(_GetVersion
)
2762 OutputDir
= property(_GetOutputDir
)
2763 BuildDir
= property(_GetBuildDir
)
2764 MakeFileDir
= property(_GetMakeFileDir
)
2765 FdfFile
= property(_GetFdfFile
)
2767 PcdTokenNumber
= property(_GetPcdTokenNumbers
) # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber
2768 DynamicPcdList
= property(_GetDynamicPcdList
) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
2769 NonDynamicPcdList
= property(_GetNonDynamicPcdList
) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
2770 NonDynamicPcdDict
= property(_GetNonDynamicPcdDict
)
2771 PackageList
= property(_GetPackageList
)
2773 ToolDefinition
= property(_GetToolDefinition
) # toolcode : tool path
2774 ToolDefinitionFile
= property(_GetToolDefFile
) # toolcode : lib path
2775 ToolChainFamily
= property(_GetToolChainFamily
)
2776 BuildRuleFamily
= property(_GetBuildRuleFamily
)
2777 BuildOption
= property(_GetBuildOptions
) # toolcode : option
2778 EdkBuildOption
= property(_GetEdkBuildOptions
) # edktoolcode : option
2779 EdkIIBuildOption
= property(_GetEdkIIBuildOptions
) # edkiitoolcode : option
2781 BuildCommand
= property(_GetBuildCommand
)
2782 BuildRule
= property(_GetBuildRule
)
2783 ModuleAutoGenList
= property(_GetModuleAutoGenList
)
2784 LibraryAutoGenList
= property(_GetLibraryAutoGenList
)
2785 GenFdsCommand
= property(_GenFdsCommand
)
2787 ## ModuleAutoGen class
2789 # This class encapsules the AutoGen behaviors for the build tools. In addition to
2790 # the generation of AutoGen.h and AutoGen.c, it will generate *.depex file according
2791 # to the [depex] section in module's inf file.
2793 class ModuleAutoGen(AutoGen
):
2794 # call super().__init__ then call the worker function with different parameter count
2795 def __init__(self
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
2799 super(ModuleAutoGen
, self
).__init
__(Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
)
2800 self
._InitWorker
(Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
)
2803 ## Cache the timestamps of metafiles of every module in a class variable
2807 def __new__(cls
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
2808 obj
= super(ModuleAutoGen
, cls
).__new
__(cls
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
)
2809 # check if this module is employed by active platform
2810 if not PlatformAutoGen(Workspace
, args
[0], Target
, Toolchain
, Arch
).ValidModule(MetaFile
):
2811 EdkLogger
.verbose("Module [%s] for [%s] is not employed by active platform\n" \
2816 ## Initialize ModuleAutoGen
2818 # @param Workspace EdkIIWorkspaceBuild object
2819 # @param ModuleFile The path of module file
2820 # @param Target Build target (DEBUG, RELEASE)
2821 # @param Toolchain Name of tool chain
2822 # @param Arch The arch the module supports
2823 # @param PlatformFile Platform meta-file
2825 def _InitWorker(self
, Workspace
, ModuleFile
, Target
, Toolchain
, Arch
, PlatformFile
):
2826 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "AutoGen module [%s] [%s]" % (ModuleFile
, Arch
))
2827 GlobalData
.gProcessingFile
= "%s [%s, %s, %s]" % (ModuleFile
, Arch
, Toolchain
, Target
)
2829 self
.Workspace
= Workspace
2830 self
.WorkspaceDir
= Workspace
.WorkspaceDir
2832 self
.MetaFile
= ModuleFile
2833 self
.PlatformInfo
= PlatformAutoGen(Workspace
, PlatformFile
, Target
, Toolchain
, Arch
)
2835 self
.SourceDir
= self
.MetaFile
.SubDir
2836 self
.SourceDir
= mws
.relpath(self
.SourceDir
, self
.WorkspaceDir
)
2838 self
.SourceOverrideDir
= None
2839 # use overrided path defined in DSC file
2840 if self
.MetaFile
.Key
in GlobalData
.gOverrideDir
:
2841 self
.SourceOverrideDir
= GlobalData
.gOverrideDir
[self
.MetaFile
.Key
]
2843 self
.ToolChain
= Toolchain
2844 self
.BuildTarget
= Target
2846 self
.ToolChainFamily
= self
.PlatformInfo
.ToolChainFamily
2847 self
.BuildRuleFamily
= self
.PlatformInfo
.BuildRuleFamily
2849 self
.IsMakeFileCreated
= False
2850 self
.IsCodeFileCreated
= False
2851 self
.IsAsBuiltInfCreated
= False
2852 self
.DepexGenerated
= False
2854 self
.BuildDatabase
= self
.Workspace
.BuildDatabase
2855 self
.BuildRuleOrder
= None
2861 self
._Version
= None
2862 self
._ModuleType
= None
2863 self
._ComponentType
= None
2864 self
._PcdIsDriver
= None
2865 self
._AutoGenVersion
= None
2866 self
._LibraryFlag
= None
2867 self
._CustomMakefile
= None
2870 self
._BuildDir
= None
2871 self
._OutputDir
= None
2872 self
._FfsOutputDir
= None
2873 self
._DebugDir
= None
2874 self
._MakeFileDir
= None
2876 self
._IncludePathList
= None
2877 self
._IncludePathLength
= 0
2878 self
._AutoGenFileList
= None
2879 self
._UnicodeFileList
= None
2880 self
._VfrFileList
= None
2881 self
._IdfFileList
= None
2882 self
._SourceFileList
= None
2883 self
._ObjectFileList
= None
2884 self
._BinaryFileList
= None
2886 self
._DependentPackageList
= None
2887 self
._DependentLibraryList
= None
2888 self
._LibraryAutoGenList
= None
2889 self
._DerivedPackageList
= None
2890 self
._ModulePcdList
= None
2891 self
._LibraryPcdList
= None
2892 self
._PcdComments
= OrderedDict()
2893 self
._GuidList
= None
2894 self
._GuidsUsedByPcd
= None
2895 self
._GuidComments
= OrderedDict()
2896 self
._ProtocolList
= None
2897 self
._ProtocolComments
= OrderedDict()
2898 self
._PpiList
= None
2899 self
._PpiComments
= OrderedDict()
2900 self
._DepexList
= None
2901 self
._DepexExpressionList
= None
2902 self
._BuildOption
= None
2903 self
._BuildOptionIncPathList
= None
2904 self
._BuildTargets
= None
2905 self
._IntroBuildTargetList
= None
2906 self
._FinalBuildTargetList
= None
2907 self
._FileTypes
= None
2908 self
._BuildRules
= None
2910 self
._TimeStampPath
= None
2912 self
.AutoGenDepSet
= set()
2915 ## The Modules referenced to this Library
2916 # Only Library has this attribute
2917 self
._ReferenceModules
= []
2919 ## Store the FixedAtBuild Pcds
2921 self
._FixedAtBuildPcds
= []
2926 return "%s [%s]" % (self
.MetaFile
, self
.Arch
)
2928 # Get FixedAtBuild Pcds of this Module
2929 def _GetFixedAtBuildPcds(self
):
2930 if self
._FixedAtBuildPcds
:
2931 return self
._FixedAtBuildPcds
2932 for Pcd
in self
.ModulePcdList
:
2933 if Pcd
.Type
!= "FixedAtBuild":
2935 if Pcd
not in self
._FixedAtBuildPcds
:
2936 self
._FixedAtBuildPcds
.append(Pcd
)
2938 return self
._FixedAtBuildPcds
2940 def _GetUniqueBaseName(self
):
2941 BaseName
= self
.Name
2942 for Module
in self
.PlatformInfo
.ModuleAutoGenList
:
2943 if Module
.MetaFile
== self
.MetaFile
:
2945 if Module
.Name
== self
.Name
:
2946 if uuid
.UUID(Module
.Guid
) == uuid
.UUID(self
.Guid
):
2947 EdkLogger
.error("build", FILE_DUPLICATED
, 'Modules have same BaseName and FILE_GUID:\n'
2948 ' %s\n %s' % (Module
.MetaFile
, self
.MetaFile
))
2949 BaseName
= '%s_%s' % (self
.Name
, self
.Guid
)
2952 # Macros could be used in build_rule.txt (also Makefile)
2953 def _GetMacros(self
):
2954 if self
._Macro
is None:
2955 self
._Macro
= OrderedDict()
2956 self
._Macro
["WORKSPACE" ] = self
.WorkspaceDir
2957 self
._Macro
["MODULE_NAME" ] = self
.Name
2958 self
._Macro
["MODULE_NAME_GUID" ] = self
._GetUniqueBaseName
()
2959 self
._Macro
["MODULE_GUID" ] = self
.Guid
2960 self
._Macro
["MODULE_VERSION" ] = self
.Version
2961 self
._Macro
["MODULE_TYPE" ] = self
.ModuleType
2962 self
._Macro
["MODULE_FILE" ] = str(self
.MetaFile
)
2963 self
._Macro
["MODULE_FILE_BASE_NAME" ] = self
.MetaFile
.BaseName
2964 self
._Macro
["MODULE_RELATIVE_DIR" ] = self
.SourceDir
2965 self
._Macro
["MODULE_DIR" ] = self
.SourceDir
2967 self
._Macro
["BASE_NAME" ] = self
.Name
2969 self
._Macro
["ARCH" ] = self
.Arch
2970 self
._Macro
["TOOLCHAIN" ] = self
.ToolChain
2971 self
._Macro
["TOOLCHAIN_TAG" ] = self
.ToolChain
2972 self
._Macro
["TOOL_CHAIN_TAG" ] = self
.ToolChain
2973 self
._Macro
["TARGET" ] = self
.BuildTarget
2975 self
._Macro
["BUILD_DIR" ] = self
.PlatformInfo
.BuildDir
2976 self
._Macro
["BIN_DIR" ] = os
.path
.join(self
.PlatformInfo
.BuildDir
, self
.Arch
)
2977 self
._Macro
["LIB_DIR" ] = os
.path
.join(self
.PlatformInfo
.BuildDir
, self
.Arch
)
2978 self
._Macro
["MODULE_BUILD_DIR" ] = self
.BuildDir
2979 self
._Macro
["OUTPUT_DIR" ] = self
.OutputDir
2980 self
._Macro
["DEBUG_DIR" ] = self
.DebugDir
2981 self
._Macro
["DEST_DIR_OUTPUT" ] = self
.OutputDir
2982 self
._Macro
["DEST_DIR_DEBUG" ] = self
.DebugDir
2983 self
._Macro
["PLATFORM_NAME" ] = self
.PlatformInfo
.Name
2984 self
._Macro
["PLATFORM_GUID" ] = self
.PlatformInfo
.Guid
2985 self
._Macro
["PLATFORM_VERSION" ] = self
.PlatformInfo
.Version
2986 self
._Macro
["PLATFORM_RELATIVE_DIR" ] = self
.PlatformInfo
.SourceDir
2987 self
._Macro
["PLATFORM_DIR" ] = mws
.join(self
.WorkspaceDir
, self
.PlatformInfo
.SourceDir
)
2988 self
._Macro
["PLATFORM_OUTPUT_DIR" ] = self
.PlatformInfo
.OutputDir
2989 self
._Macro
["FFS_OUTPUT_DIR" ] = self
.FfsOutputDir
2992 ## Return the module build data object
2993 def _GetModule(self
):
2994 if self
._Module
is None:
2995 self
._Module
= self
.Workspace
.BuildDatabase
[self
.MetaFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
2998 ## Return the module name
2999 def _GetBaseName(self
):
3000 return self
.Module
.BaseName
3002 ## Return the module DxsFile if exist
3003 def _GetDxsFile(self
):
3004 return self
.Module
.DxsFile
3006 ## Return the module SourceOverridePath
3007 def _GetSourceOverridePath(self
):
3008 return self
.Module
.SourceOverridePath
3010 ## Return the module meta-file GUID
3013 # To build same module more than once, the module path with FILE_GUID overridden has
3014 # the file name FILE_GUIDmodule.inf, but the relative path (self.MetaFile.File) is the realy path
3015 # in DSC. The overridden GUID can be retrieved from file name
3017 if os
.path
.basename(self
.MetaFile
.File
) != os
.path
.basename(self
.MetaFile
.Path
):
3019 # Length of GUID is 36
3021 return os
.path
.basename(self
.MetaFile
.Path
)[:36]
3022 return self
.Module
.Guid
3024 ## Return the module version
3025 def _GetVersion(self
):
3026 return self
.Module
.Version
3028 ## Return the module type
3029 def _GetModuleType(self
):
3030 return self
.Module
.ModuleType
3032 ## Return the component type (for Edk.x style of module)
3033 def _GetComponentType(self
):
3034 return self
.Module
.ComponentType
3036 ## Return the build type
3037 def _GetBuildType(self
):
3038 return self
.Module
.BuildType
3040 ## Return the PCD_IS_DRIVER setting
3041 def _GetPcdIsDriver(self
):
3042 return self
.Module
.PcdIsDriver
3044 ## Return the autogen version, i.e. module meta-file version
3045 def _GetAutoGenVersion(self
):
3046 return self
.Module
.AutoGenVersion
3048 ## Check if the module is library or not
3049 def _IsLibrary(self
):
3050 if self
._LibraryFlag
is None:
3051 if self
.Module
.LibraryClass
is not None and self
.Module
.LibraryClass
!= []:
3052 self
._LibraryFlag
= True
3054 self
._LibraryFlag
= False
3055 return self
._LibraryFlag
3057 ## Check if the module is binary module or not
3058 def _IsBinaryModule(self
):
3059 return self
.Module
.IsBinaryModule
3061 ## Return the directory to store intermediate files of the module
3062 def _GetBuildDir(self
):
3063 if self
._BuildDir
is None:
3064 self
._BuildDir
= path
.join(
3065 self
.PlatformInfo
.BuildDir
,
3068 self
.MetaFile
.BaseName
3070 CreateDirectory(self
._BuildDir
)
3071 return self
._BuildDir
3073 ## Return the directory to store the intermediate object files of the mdoule
3074 def _GetOutputDir(self
):
3075 if self
._OutputDir
is None:
3076 self
._OutputDir
= path
.join(self
.BuildDir
, "OUTPUT")
3077 CreateDirectory(self
._OutputDir
)
3078 return self
._OutputDir
3080 ## Return the directory to store ffs file
3081 def _GetFfsOutputDir(self
):
3082 if self
._FfsOutputDir
is None:
3083 if GlobalData
.gFdfParser
is not None:
3084 self
._FfsOutputDir
= path
.join(self
.PlatformInfo
.BuildDir
, "FV", "Ffs", self
.Guid
+ self
.Name
)
3086 self
._FfsOutputDir
= ''
3087 return self
._FfsOutputDir
3089 ## Return the directory to store auto-gened source files of the mdoule
3090 def _GetDebugDir(self
):
3091 if self
._DebugDir
is None:
3092 self
._DebugDir
= path
.join(self
.BuildDir
, "DEBUG")
3093 CreateDirectory(self
._DebugDir
)
3094 return self
._DebugDir
3096 ## Return the path of custom file
3097 def _GetCustomMakefile(self
):
3098 if self
._CustomMakefile
is None:
3099 self
._CustomMakefile
= {}
3100 for Type
in self
.Module
.CustomMakefile
:
3101 if Type
in gMakeTypeMap
:
3102 MakeType
= gMakeTypeMap
[Type
]
3105 if self
.SourceOverrideDir
is not None:
3106 File
= os
.path
.join(self
.SourceOverrideDir
, self
.Module
.CustomMakefile
[Type
])
3107 if not os
.path
.exists(File
):
3108 File
= os
.path
.join(self
.SourceDir
, self
.Module
.CustomMakefile
[Type
])
3110 File
= os
.path
.join(self
.SourceDir
, self
.Module
.CustomMakefile
[Type
])
3111 self
._CustomMakefile
[MakeType
] = File
3112 return self
._CustomMakefile
3114 ## Return the directory of the makefile
3116 # @retval string The directory string of module's makefile
3118 def _GetMakeFileDir(self
):
3119 return self
.BuildDir
3121 ## Return build command string
3123 # @retval string Build command string
3125 def _GetBuildCommand(self
):
3126 return self
.PlatformInfo
.BuildCommand
3128 ## Get object list of all packages the module and its dependent libraries belong to
3130 # @retval list The list of package object
3132 def _GetDerivedPackageList(self
):
3134 for M
in [self
.Module
] + self
.DependentLibraryList
:
3135 for Package
in M
.Packages
:
3136 if Package
in PackageList
:
3138 PackageList
.append(Package
)
3141 ## Get the depex string
3143 # @return : a string contain all depex expresion.
3144 def _GetDepexExpresionString(self
):
3147 ## DPX_SOURCE IN Define section.
3148 if self
.Module
.DxsFile
:
3150 for M
in [self
.Module
] + self
.DependentLibraryList
:
3151 Filename
= M
.MetaFile
.Path
3152 InfObj
= InfSectionParser
.InfSectionParser(Filename
)
3153 DepexExpresionList
= InfObj
.GetDepexExpresionList()
3154 for DepexExpresion
in DepexExpresionList
:
3155 for key
in DepexExpresion
.keys():
3156 Arch
, ModuleType
= key
3157 DepexExpr
= [x
for x
in DepexExpresion
[key
] if not str(x
).startswith('#')]
3158 # the type of build module is USER_DEFINED.
3159 # All different DEPEX section tags would be copied into the As Built INF file
3160 # and there would be separate DEPEX section tags
3161 if self
.ModuleType
.upper() == SUP_MODULE_USER_DEFINED
:
3162 if (Arch
.upper() == self
.Arch
.upper()) and (ModuleType
.upper() != TAB_ARCH_COMMON
):
3163 DepexList
.append({(Arch
, ModuleType
): DepexExpr
})
3165 if Arch
.upper() == TAB_ARCH_COMMON
or \
3166 (Arch
.upper() == self
.Arch
.upper() and \
3167 ModuleType
.upper() in [TAB_ARCH_COMMON
, self
.ModuleType
.upper()]):
3168 DepexList
.append({(Arch
, ModuleType
): DepexExpr
})
3170 #the type of build module is USER_DEFINED.
3171 if self
.ModuleType
.upper() == SUP_MODULE_USER_DEFINED
:
3172 for Depex
in DepexList
:
3173 for key
in Depex
.keys():
3174 DepexStr
+= '[Depex.%s.%s]\n' % key
3175 DepexStr
+= '\n'.join(['# '+ val
for val
in Depex
[key
]])
3178 return '[Depex.%s]\n' % self
.Arch
3181 #the type of build module not is USER_DEFINED.
3183 for Depex
in DepexList
:
3188 for D
in Depex
.values():
3189 DepexStr
+= ' '.join([val
for val
in D
])
3190 Index
= DepexStr
.find('END')
3191 if Index
> -1 and Index
== len(DepexStr
) - 3:
3192 DepexStr
= DepexStr
[:-3]
3193 DepexStr
= DepexStr
.strip()
3196 DepexStr
= DepexStr
.lstrip('(').rstrip(')').strip()
3198 return '[Depex.%s]\n' % self
.Arch
3199 return '[Depex.%s]\n# ' % self
.Arch
+ DepexStr
3201 ## Merge dependency expression
3203 # @retval list The token list of the dependency expression after parsed
3205 def _GetDepexTokenList(self
):
3206 if self
._DepexList
is None:
3207 self
._DepexList
= {}
3208 if self
.DxsFile
or self
.IsLibrary
or TAB_DEPENDENCY_EXPRESSION_FILE
in self
.FileTypes
:
3209 return self
._DepexList
3211 self
._DepexList
[self
.ModuleType
] = []
3213 for ModuleType
in self
._DepexList
:
3214 DepexList
= self
._DepexList
[ModuleType
]
3216 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
3218 for M
in [self
.Module
] + self
.DependentLibraryList
:
3220 for D
in M
.Depex
[self
.Arch
, ModuleType
]:
3222 DepexList
.append('AND')
3223 DepexList
.append('(')
3225 if DepexList
[-1] == 'END': # no need of a END at this time
3227 DepexList
.append(')')
3230 EdkLogger
.verbose("DEPEX[%s] (+%s) = %s" % (self
.Name
, M
.BaseName
, DepexList
))
3231 if 'BEFORE' in DepexList
or 'AFTER' in DepexList
:
3233 if len(DepexList
) > 0:
3234 EdkLogger
.verbose('')
3235 return self
._DepexList
3237 ## Merge dependency expression
3239 # @retval list The token list of the dependency expression after parsed
3241 def _GetDepexExpressionTokenList(self
):
3242 if self
._DepexExpressionList
is None:
3243 self
._DepexExpressionList
= {}
3244 if self
.DxsFile
or self
.IsLibrary
or TAB_DEPENDENCY_EXPRESSION_FILE
in self
.FileTypes
:
3245 return self
._DepexExpressionList
3247 self
._DepexExpressionList
[self
.ModuleType
] = ''
3249 for ModuleType
in self
._DepexExpressionList
:
3250 DepexExpressionList
= self
._DepexExpressionList
[ModuleType
]
3252 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
3254 for M
in [self
.Module
] + self
.DependentLibraryList
:
3256 for D
in M
.DepexExpression
[self
.Arch
, ModuleType
]:
3257 if DepexExpressionList
!= '':
3258 DepexExpressionList
+= ' AND '
3259 DepexExpressionList
+= '('
3260 DepexExpressionList
+= D
3261 DepexExpressionList
= DepexExpressionList
.rstrip('END').strip()
3262 DepexExpressionList
+= ')'
3265 EdkLogger
.verbose("DEPEX[%s] (+%s) = %s" % (self
.Name
, M
.BaseName
, DepexExpressionList
))
3266 if 'BEFORE' in DepexExpressionList
or 'AFTER' in DepexExpressionList
:
3268 if len(DepexExpressionList
) > 0:
3269 EdkLogger
.verbose('')
3270 self
._DepexExpressionList
[ModuleType
] = DepexExpressionList
3271 return self
._DepexExpressionList
3273 # Get the tiano core user extension, it is contain dependent library.
3274 # @retval: a list contain tiano core userextension.
3276 def _GetTianoCoreUserExtensionList(self
):
3277 TianoCoreUserExtentionList
= []
3278 for M
in [self
.Module
] + self
.DependentLibraryList
:
3279 Filename
= M
.MetaFile
.Path
3280 InfObj
= InfSectionParser
.InfSectionParser(Filename
)
3281 TianoCoreUserExtenList
= InfObj
.GetUserExtensionTianoCore()
3282 for TianoCoreUserExtent
in TianoCoreUserExtenList
:
3283 for Section
in TianoCoreUserExtent
.keys():
3284 ItemList
= Section
.split(TAB_SPLIT
)
3286 if len(ItemList
) == 4:
3288 if Arch
.upper() == TAB_ARCH_COMMON
or Arch
.upper() == self
.Arch
.upper():
3290 TianoCoreList
.extend([TAB_SECTION_START
+ Section
+ TAB_SECTION_END
])
3291 TianoCoreList
.extend(TianoCoreUserExtent
[Section
][:])
3292 TianoCoreList
.append('\n')
3293 TianoCoreUserExtentionList
.append(TianoCoreList
)
3295 return TianoCoreUserExtentionList
3297 ## Return the list of specification version required for the module
3299 # @retval list The list of specification defined in module file
3301 def _GetSpecification(self
):
3302 return self
.Module
.Specification
3304 ## Tool option for the module build
3306 # @param PlatformInfo The object of PlatformBuildInfo
3307 # @retval dict The dict containing valid options
3309 def _GetModuleBuildOption(self
):
3310 if self
._BuildOption
is None:
3311 self
._BuildOption
, self
.BuildRuleOrder
= self
.PlatformInfo
.ApplyBuildOption(self
.Module
)
3312 if self
.BuildRuleOrder
:
3313 self
.BuildRuleOrder
= ['.%s' % Ext
for Ext
in self
.BuildRuleOrder
.split()]
3314 return self
._BuildOption
3316 ## Get include path list from tool option for the module build
3318 # @retval list The include path list
3320 def _GetBuildOptionIncPathList(self
):
3321 if self
._BuildOptionIncPathList
is None:
3323 # Regular expression for finding Include Directories, the difference between MSFT and INTEL/GCC/RVCT
3324 # is the former use /I , the Latter used -I to specify include directories
3326 if self
.PlatformInfo
.ToolChainFamily
in ('MSFT'):
3327 BuildOptIncludeRegEx
= gBuildOptIncludePatternMsft
3328 elif self
.PlatformInfo
.ToolChainFamily
in ('INTEL', 'GCC', 'RVCT'):
3329 BuildOptIncludeRegEx
= gBuildOptIncludePatternOther
3332 # New ToolChainFamily, don't known whether there is option to specify include directories
3334 self
._BuildOptionIncPathList
= []
3335 return self
._BuildOptionIncPathList
3337 BuildOptionIncPathList
= []
3338 for Tool
in ('CC', 'PP', 'VFRPP', 'ASLPP', 'ASLCC', 'APP', 'ASM'):
3341 FlagOption
= self
.BuildOption
[Tool
][Attr
]
3345 if self
.PlatformInfo
.ToolChainFamily
!= 'RVCT':
3346 IncPathList
= [NormPath(Path
, self
.Macros
) for Path
in BuildOptIncludeRegEx
.findall(FlagOption
)]
3349 # RVCT may specify a list of directory seperated by commas
3352 for Path
in BuildOptIncludeRegEx
.findall(FlagOption
):
3353 PathList
= GetSplitList(Path
, TAB_COMMA_SPLIT
)
3354 IncPathList
+= [NormPath(PathEntry
, self
.Macros
) for PathEntry
in PathList
]
3357 # EDK II modules must not reference header files outside of the packages they depend on or
3358 # within the module's directory tree. Report error if violation.
3360 if self
.AutoGenVersion
>= 0x00010005 and len(IncPathList
) > 0:
3361 for Path
in IncPathList
:
3362 if (Path
not in self
.IncludePathList
) and (CommonPath([Path
, self
.MetaFile
.Dir
]) != self
.MetaFile
.Dir
):
3363 ErrMsg
= "The include directory for the EDK II module in this line is invalid %s specified in %s FLAGS '%s'" % (Path
, Tool
, FlagOption
)
3364 EdkLogger
.error("build",
3367 File
=str(self
.MetaFile
))
3370 BuildOptionIncPathList
+= IncPathList
3372 self
._BuildOptionIncPathList
= BuildOptionIncPathList
3374 return self
._BuildOptionIncPathList
3376 ## Return a list of files which can be built from source
3378 # What kind of files can be built is determined by build rules in
3379 # $(CONF_DIRECTORY)/build_rule.txt and toolchain family.
3381 def _GetSourceFileList(self
):
3382 if self
._SourceFileList
is None:
3383 self
._SourceFileList
= []
3384 for F
in self
.Module
.Sources
:
3386 if F
.TagName
not in ("", "*", self
.ToolChain
):
3387 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "The toolchain [%s] for processing file [%s] is found, "
3388 "but [%s] is needed" % (F
.TagName
, str(F
), self
.ToolChain
))
3390 # match tool chain family or build rule family
3391 if F
.ToolChainFamily
not in ("", "*", self
.ToolChainFamily
, self
.BuildRuleFamily
):
3394 "The file [%s] must be built by tools of [%s], " \
3395 "but current toolchain family is [%s], buildrule family is [%s]" \
3396 % (str(F
), F
.ToolChainFamily
, self
.ToolChainFamily
, self
.BuildRuleFamily
))
3399 # add the file path into search path list for file including
3400 if F
.Dir
not in self
.IncludePathList
and self
.AutoGenVersion
>= 0x00010005:
3401 self
.IncludePathList
.insert(0, F
.Dir
)
3402 self
._SourceFileList
.append(F
)
3404 self
._MatchBuildRuleOrder
(self
._SourceFileList
)
3406 for F
in self
._SourceFileList
:
3407 self
._ApplyBuildRule
(F
, TAB_UNKNOWN_FILE
)
3408 return self
._SourceFileList
3410 def _MatchBuildRuleOrder(self
, FileList
):
3412 self
._GetModuleBuildOption
()
3413 for SingleFile
in FileList
:
3414 if self
.BuildRuleOrder
and SingleFile
.Ext
in self
.BuildRuleOrder
and SingleFile
.Ext
in self
.BuildRules
:
3415 key
= SingleFile
.Path
.split(SingleFile
.Ext
)[0]
3416 if key
in Order_Dict
:
3417 Order_Dict
[key
].append(SingleFile
.Ext
)
3419 Order_Dict
[key
] = [SingleFile
.Ext
]
3422 for F
in Order_Dict
:
3423 if len(Order_Dict
[F
]) > 1:
3424 Order_Dict
[F
].sort(key
=lambda i
: self
.BuildRuleOrder
.index(i
))
3425 for Ext
in Order_Dict
[F
][1:]:
3426 RemoveList
.append(F
+ Ext
)
3428 for item
in RemoveList
:
3429 FileList
.remove(item
)
3433 ## Return the list of unicode files
3434 def _GetUnicodeFileList(self
):
3435 if self
._UnicodeFileList
is None:
3436 if TAB_UNICODE_FILE
in self
.FileTypes
:
3437 self
._UnicodeFileList
= self
.FileTypes
[TAB_UNICODE_FILE
]
3439 self
._UnicodeFileList
= []
3440 return self
._UnicodeFileList
3442 ## Return the list of vfr files
3443 def _GetVfrFileList(self
):
3444 if self
._VfrFileList
is None:
3445 if TAB_VFR_FILE
in self
.FileTypes
:
3446 self
._VfrFileList
= self
.FileTypes
[TAB_VFR_FILE
]
3448 self
._VfrFileList
= []
3449 return self
._VfrFileList
3451 ## Return the list of Image Definition files
3452 def _GetIdfFileList(self
):
3453 if self
._IdfFileList
is None:
3454 if TAB_IMAGE_FILE
in self
.FileTypes
:
3455 self
._IdfFileList
= self
.FileTypes
[TAB_IMAGE_FILE
]
3457 self
._IdfFileList
= []
3458 return self
._IdfFileList
3460 ## Return a list of files which can be built from binary
3462 # "Build" binary files are just to copy them to build directory.
3464 # @retval list The list of files which can be built later
3466 def _GetBinaryFiles(self
):
3467 if self
._BinaryFileList
is None:
3468 self
._BinaryFileList
= []
3469 for F
in self
.Module
.Binaries
:
3470 if F
.Target
not in ['COMMON', '*'] and F
.Target
!= self
.BuildTarget
:
3472 self
._BinaryFileList
.append(F
)
3473 self
._ApplyBuildRule
(F
, F
.Type
)
3474 return self
._BinaryFileList
3476 def _GetBuildRules(self
):
3477 if self
._BuildRules
is None:
3479 BuildRuleDatabase
= self
.PlatformInfo
.BuildRule
3480 for Type
in BuildRuleDatabase
.FileTypeList
:
3481 #first try getting build rule by BuildRuleFamily
3482 RuleObject
= BuildRuleDatabase
[Type
, self
.BuildType
, self
.Arch
, self
.BuildRuleFamily
]
3484 # build type is always module type, but ...
3485 if self
.ModuleType
!= self
.BuildType
:
3486 RuleObject
= BuildRuleDatabase
[Type
, self
.ModuleType
, self
.Arch
, self
.BuildRuleFamily
]
3487 #second try getting build rule by ToolChainFamily
3489 RuleObject
= BuildRuleDatabase
[Type
, self
.BuildType
, self
.Arch
, self
.ToolChainFamily
]
3491 # build type is always module type, but ...
3492 if self
.ModuleType
!= self
.BuildType
:
3493 RuleObject
= BuildRuleDatabase
[Type
, self
.ModuleType
, self
.Arch
, self
.ToolChainFamily
]
3496 RuleObject
= RuleObject
.Instantiate(self
.Macros
)
3497 BuildRules
[Type
] = RuleObject
3498 for Ext
in RuleObject
.SourceFileExtList
:
3499 BuildRules
[Ext
] = RuleObject
3500 self
._BuildRules
= BuildRules
3501 return self
._BuildRules
3503 def _ApplyBuildRule(self
, File
, FileType
):
3504 if self
._BuildTargets
is None:
3505 self
._IntroBuildTargetList
= set()
3506 self
._FinalBuildTargetList
= set()
3507 self
._BuildTargets
= {}
3508 self
._FileTypes
= {}
3510 SubDirectory
= os
.path
.join(self
.OutputDir
, File
.SubDir
)
3511 if not os
.path
.exists(SubDirectory
):
3512 CreateDirectory(SubDirectory
)
3518 # Make sure to get build rule order value
3520 self
._GetModuleBuildOption
()
3522 while Index
< len(SourceList
):
3523 Source
= SourceList
[Index
]
3527 CreateDirectory(Source
.Dir
)
3529 if File
.IsBinary
and File
== Source
and self
._BinaryFileList
is not None and File
in self
._BinaryFileList
:
3530 # Skip all files that are not binary libraries
3531 if not self
.IsLibrary
:
3533 RuleObject
= self
.BuildRules
[TAB_DEFAULT_BINARY_FILE
]
3534 elif FileType
in self
.BuildRules
:
3535 RuleObject
= self
.BuildRules
[FileType
]
3536 elif Source
.Ext
in self
.BuildRules
:
3537 RuleObject
= self
.BuildRules
[Source
.Ext
]
3539 # stop at no more rules
3541 self
._FinalBuildTargetList
.add(LastTarget
)
3544 FileType
= RuleObject
.SourceFileType
3545 if FileType
not in self
._FileTypes
:
3546 self
._FileTypes
[FileType
] = set()
3547 self
._FileTypes
[FileType
].add(Source
)
3549 # stop at STATIC_LIBRARY for library
3550 if self
.IsLibrary
and FileType
== TAB_STATIC_LIBRARY
:
3552 self
._FinalBuildTargetList
.add(LastTarget
)
3555 Target
= RuleObject
.Apply(Source
, self
.BuildRuleOrder
)
3558 self
._FinalBuildTargetList
.add(LastTarget
)
3560 elif not Target
.Outputs
:
3561 # Only do build for target with outputs
3562 self
._FinalBuildTargetList
.add(Target
)
3564 if FileType
not in self
._BuildTargets
:
3565 self
._BuildTargets
[FileType
] = set()
3566 self
._BuildTargets
[FileType
].add(Target
)
3568 if not Source
.IsBinary
and Source
== File
:
3569 self
._IntroBuildTargetList
.add(Target
)
3571 # to avoid cyclic rule
3572 if FileType
in RuleChain
:
3575 RuleChain
.append(FileType
)
3576 SourceList
.extend(Target
.Outputs
)
3578 FileType
= TAB_UNKNOWN_FILE
3580 def _GetTargets(self
):
3581 if self
._BuildTargets
is None:
3582 self
._IntroBuildTargetList
= set()
3583 self
._FinalBuildTargetList
= set()
3584 self
._BuildTargets
= {}
3585 self
._FileTypes
= {}
3587 #TRICK: call _GetSourceFileList to apply build rule for source files
3588 if self
.SourceFileList
:
3591 #TRICK: call _GetBinaryFileList to apply build rule for binary files
3592 if self
.BinaryFileList
:
3595 return self
._BuildTargets
3597 def _GetIntroTargetList(self
):
3599 return self
._IntroBuildTargetList
3601 def _GetFinalTargetList(self
):
3603 return self
._FinalBuildTargetList
3605 def _GetFileTypes(self
):
3607 return self
._FileTypes
3609 ## Get the list of package object the module depends on
3611 # @retval list The package object list
3613 def _GetDependentPackageList(self
):
3614 return self
.Module
.Packages
3616 ## Return the list of auto-generated code file
3618 # @retval list The list of auto-generated file
3620 def _GetAutoGenFileList(self
):
3621 UniStringAutoGenC
= True
3622 IdfStringAutoGenC
= True
3623 UniStringBinBuffer
= StringIO()
3624 IdfGenBinBuffer
= StringIO()
3625 if self
.BuildType
== 'UEFI_HII':
3626 UniStringAutoGenC
= False
3627 IdfStringAutoGenC
= False
3628 if self
._AutoGenFileList
is None:
3629 self
._AutoGenFileList
= {}
3630 AutoGenC
= TemplateString()
3631 AutoGenH
= TemplateString()
3632 StringH
= TemplateString()
3633 StringIdf
= TemplateString()
3634 GenC
.CreateCode(self
, AutoGenC
, AutoGenH
, StringH
, UniStringAutoGenC
, UniStringBinBuffer
, StringIdf
, IdfStringAutoGenC
, IdfGenBinBuffer
)
3636 # AutoGen.c is generated if there are library classes in inf, or there are object files
3638 if str(AutoGenC
) != "" and (len(self
.Module
.LibraryClasses
) > 0
3639 or TAB_OBJECT_FILE
in self
.FileTypes
):
3640 AutoFile
= PathClass(gAutoGenCodeFileName
, self
.DebugDir
)
3641 self
._AutoGenFileList
[AutoFile
] = str(AutoGenC
)
3642 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3643 if str(AutoGenH
) != "":
3644 AutoFile
= PathClass(gAutoGenHeaderFileName
, self
.DebugDir
)
3645 self
._AutoGenFileList
[AutoFile
] = str(AutoGenH
)
3646 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3647 if str(StringH
) != "":
3648 AutoFile
= PathClass(gAutoGenStringFileName
% {"module_name":self
.Name
}, self
.DebugDir
)
3649 self
._AutoGenFileList
[AutoFile
] = str(StringH
)
3650 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3651 if UniStringBinBuffer
is not None and UniStringBinBuffer
.getvalue() != "":
3652 AutoFile
= PathClass(gAutoGenStringFormFileName
% {"module_name":self
.Name
}, self
.OutputDir
)
3653 self
._AutoGenFileList
[AutoFile
] = UniStringBinBuffer
.getvalue()
3654 AutoFile
.IsBinary
= True
3655 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3656 if UniStringBinBuffer
is not None:
3657 UniStringBinBuffer
.close()
3658 if str(StringIdf
) != "":
3659 AutoFile
= PathClass(gAutoGenImageDefFileName
% {"module_name":self
.Name
}, self
.DebugDir
)
3660 self
._AutoGenFileList
[AutoFile
] = str(StringIdf
)
3661 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3662 if IdfGenBinBuffer
is not None and IdfGenBinBuffer
.getvalue() != "":
3663 AutoFile
= PathClass(gAutoGenIdfFileName
% {"module_name":self
.Name
}, self
.OutputDir
)
3664 self
._AutoGenFileList
[AutoFile
] = IdfGenBinBuffer
.getvalue()
3665 AutoFile
.IsBinary
= True
3666 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3667 if IdfGenBinBuffer
is not None:
3668 IdfGenBinBuffer
.close()
3669 return self
._AutoGenFileList
3671 ## Return the list of library modules explicitly or implicityly used by this module
3672 def _GetLibraryList(self
):
3673 if self
._DependentLibraryList
is None:
3674 # only merge library classes and PCD for non-library module
3676 self
._DependentLibraryList
= []
3678 if self
.AutoGenVersion
< 0x00010005:
3679 self
._DependentLibraryList
= self
.PlatformInfo
.ResolveLibraryReference(self
.Module
)
3681 self
._DependentLibraryList
= self
.PlatformInfo
.ApplyLibraryInstance(self
.Module
)
3682 return self
._DependentLibraryList
3685 def UpdateComments(Recver
, Src
):
3687 if Key
not in Recver
:
3689 Recver
[Key
].extend(Src
[Key
])
3690 ## Get the list of PCDs from current module
3692 # @retval list The list of PCD
3694 def _GetModulePcdList(self
):
3695 if self
._ModulePcdList
is None:
3696 # apply PCD settings from platform
3697 self
._ModulePcdList
= self
.PlatformInfo
.ApplyPcdSetting(self
.Module
, self
.Module
.Pcds
)
3698 self
.UpdateComments(self
._PcdComments
, self
.Module
.PcdComments
)
3699 return self
._ModulePcdList
3701 ## Get the list of PCDs from dependent libraries
3703 # @retval list The list of PCD
3705 def _GetLibraryPcdList(self
):
3706 if self
._LibraryPcdList
is None:
3707 Pcds
= OrderedDict()
3708 if not self
.IsLibrary
:
3709 # get PCDs from dependent libraries
3710 for Library
in self
.DependentLibraryList
:
3711 self
.UpdateComments(self
._PcdComments
, Library
.PcdComments
)
3712 for Key
in Library
.Pcds
:
3713 # skip duplicated PCDs
3714 if Key
in self
.Module
.Pcds
or Key
in Pcds
:
3716 Pcds
[Key
] = copy
.copy(Library
.Pcds
[Key
])
3717 # apply PCD settings from platform
3718 self
._LibraryPcdList
= self
.PlatformInfo
.ApplyPcdSetting(self
.Module
, Pcds
)
3720 self
._LibraryPcdList
= []
3721 return self
._LibraryPcdList
3723 ## Get the GUID value mapping
3725 # @retval dict The mapping between GUID cname and its value
3727 def _GetGuidList(self
):
3728 if self
._GuidList
is None:
3729 self
._GuidList
= OrderedDict()
3730 self
._GuidList
.update(self
.Module
.Guids
)
3731 for Library
in self
.DependentLibraryList
:
3732 self
._GuidList
.update(Library
.Guids
)
3733 self
.UpdateComments(self
._GuidComments
, Library
.GuidComments
)
3734 self
.UpdateComments(self
._GuidComments
, self
.Module
.GuidComments
)
3735 return self
._GuidList
3737 def GetGuidsUsedByPcd(self
):
3738 if self
._GuidsUsedByPcd
is None:
3739 self
._GuidsUsedByPcd
= OrderedDict()
3740 self
._GuidsUsedByPcd
.update(self
.Module
.GetGuidsUsedByPcd())
3741 for Library
in self
.DependentLibraryList
:
3742 self
._GuidsUsedByPcd
.update(Library
.GetGuidsUsedByPcd())
3743 return self
._GuidsUsedByPcd
3744 ## Get the protocol value mapping
3746 # @retval dict The mapping between protocol cname and its value
3748 def _GetProtocolList(self
):
3749 if self
._ProtocolList
is None:
3750 self
._ProtocolList
= OrderedDict()
3751 self
._ProtocolList
.update(self
.Module
.Protocols
)
3752 for Library
in self
.DependentLibraryList
:
3753 self
._ProtocolList
.update(Library
.Protocols
)
3754 self
.UpdateComments(self
._ProtocolComments
, Library
.ProtocolComments
)
3755 self
.UpdateComments(self
._ProtocolComments
, self
.Module
.ProtocolComments
)
3756 return self
._ProtocolList
3758 ## Get the PPI value mapping
3760 # @retval dict The mapping between PPI cname and its value
3762 def _GetPpiList(self
):
3763 if self
._PpiList
is None:
3764 self
._PpiList
= OrderedDict()
3765 self
._PpiList
.update(self
.Module
.Ppis
)
3766 for Library
in self
.DependentLibraryList
:
3767 self
._PpiList
.update(Library
.Ppis
)
3768 self
.UpdateComments(self
._PpiComments
, Library
.PpiComments
)
3769 self
.UpdateComments(self
._PpiComments
, self
.Module
.PpiComments
)
3770 return self
._PpiList
3772 ## Get the list of include search path
3774 # @retval list The list path
3776 def _GetIncludePathList(self
):
3777 if self
._IncludePathList
is None:
3778 self
._IncludePathList
= []
3779 if self
.AutoGenVersion
< 0x00010005:
3780 for Inc
in self
.Module
.Includes
:
3781 if Inc
not in self
._IncludePathList
:
3782 self
._IncludePathList
.append(Inc
)
3784 Inc
= path
.join(Inc
, self
.Arch
.capitalize())
3785 if os
.path
.exists(Inc
) and Inc
not in self
._IncludePathList
:
3786 self
._IncludePathList
.append(Inc
)
3787 # Edk module needs to put DEBUG_DIR at the end of search path and not to use SOURCE_DIR all the time
3788 self
._IncludePathList
.append(self
.DebugDir
)
3790 self
._IncludePathList
.append(self
.MetaFile
.Dir
)
3791 self
._IncludePathList
.append(self
.DebugDir
)
3793 for Package
in self
.Module
.Packages
:
3794 PackageDir
= mws
.join(self
.WorkspaceDir
, Package
.MetaFile
.Dir
)
3795 if PackageDir
not in self
._IncludePathList
:
3796 self
._IncludePathList
.append(PackageDir
)
3797 IncludesList
= Package
.Includes
3798 if Package
._PrivateIncludes
:
3799 if not self
.MetaFile
.Path
.startswith(PackageDir
):
3800 IncludesList
= list(set(Package
.Includes
).difference(set(Package
._PrivateIncludes
)))
3801 for Inc
in IncludesList
:
3802 if Inc
not in self
._IncludePathList
:
3803 self
._IncludePathList
.append(str(Inc
))
3804 return self
._IncludePathList
3806 def _GetIncludePathLength(self
):
3807 self
._IncludePathLength
= 0
3808 if self
._IncludePathList
:
3809 for inc
in self
._IncludePathList
:
3810 self
._IncludePathLength
+= len(' ' + inc
)
3811 return self
._IncludePathLength
3813 ## Get HII EX PCDs which maybe used by VFR
3815 # efivarstore used by VFR may relate with HII EX PCDs
3816 # Get the variable name and GUID from efivarstore and HII EX PCD
3817 # List the HII EX PCDs in As Built INF if both name and GUID match.
3819 # @retval list HII EX PCDs
3821 def _GetPcdsMaybeUsedByVfr(self
):
3822 if not self
.SourceFileList
:
3826 for SrcFile
in self
.SourceFileList
:
3827 if SrcFile
.Ext
.lower() != '.vfr':
3829 Vfri
= os
.path
.join(self
.OutputDir
, SrcFile
.BaseName
+ '.i')
3830 if not os
.path
.exists(Vfri
):
3832 VfriFile
= open(Vfri
, 'r')
3833 Content
= VfriFile
.read()
3835 Pos
= Content
.find('efivarstore')
3838 # Make sure 'efivarstore' is the start of efivarstore statement
3839 # In case of the value of 'name' (name = efivarstore) is equal to 'efivarstore'
3842 while Index
>= 0 and Content
[Index
] in ' \t\r\n':
3844 if Index
>= 0 and Content
[Index
] != ';':
3845 Pos
= Content
.find('efivarstore', Pos
+ len('efivarstore'))
3848 # 'efivarstore' must be followed by name and guid
3850 Name
= gEfiVarStoreNamePattern
.search(Content
, Pos
)
3853 Guid
= gEfiVarStoreGuidPattern
.search(Content
, Pos
)
3856 NameArray
= ConvertStringToByteArray('L"' + Name
.group(1) + '"')
3857 NameGuids
.append((NameArray
, GuidStructureStringToGuidString(Guid
.group(1))))
3858 Pos
= Content
.find('efivarstore', Name
.end())
3862 for Pcd
in self
.PlatformInfo
.Platform
.Pcds
.values():
3863 if Pcd
.Type
!= TAB_PCDS_DYNAMIC_EX_HII
:
3865 for SkuName
in Pcd
.SkuInfoList
:
3866 SkuInfo
= Pcd
.SkuInfoList
[SkuName
]
3867 Name
= ConvertStringToByteArray(SkuInfo
.VariableName
)
3868 Value
= GuidValue(SkuInfo
.VariableGuid
, self
.PlatformInfo
.PackageList
, self
.MetaFile
.Path
)
3871 Guid
= GuidStructureStringToGuidString(Value
)
3872 if (Name
, Guid
) in NameGuids
and Pcd
not in HiiExPcds
:
3873 HiiExPcds
.append(Pcd
)
3878 def _GenOffsetBin(self
):
3880 for SourceFile
in self
.Module
.Sources
:
3881 if SourceFile
.Type
.upper() == ".VFR" :
3883 # search the .map file to find the offset of vfr binary in the PE32+/TE file.
3885 VfrUniBaseName
[SourceFile
.BaseName
] = (SourceFile
.BaseName
+ "Bin")
3886 if SourceFile
.Type
.upper() == ".UNI" :
3888 # search the .map file to find the offset of Uni strings binary in the PE32+/TE file.
3890 VfrUniBaseName
["UniOffsetName"] = (self
.Name
+ "Strings")
3892 if len(VfrUniBaseName
) == 0:
3894 MapFileName
= os
.path
.join(self
.OutputDir
, self
.Name
+ ".map")
3895 EfiFileName
= os
.path
.join(self
.OutputDir
, self
.Name
+ ".efi")
3896 VfrUniOffsetList
= GetVariableOffset(MapFileName
, EfiFileName
, VfrUniBaseName
.values())
3897 if not VfrUniOffsetList
:
3900 OutputName
= '%sOffset.bin' % self
.Name
3901 UniVfrOffsetFileName
= os
.path
.join( self
.OutputDir
, OutputName
)
3904 fInputfile
= open(UniVfrOffsetFileName
, "wb+", 0)
3906 EdkLogger
.error("build", FILE_OPEN_FAILURE
, "File open failed for %s" % UniVfrOffsetFileName
,None)
3908 # Use a instance of StringIO to cache data
3909 fStringIO
= StringIO('')
3911 for Item
in VfrUniOffsetList
:
3912 if (Item
[0].find("Strings") != -1):
3914 # UNI offset in image.
3916 # { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } }
3918 UniGuid
= [0xe0, 0xc5, 0x13, 0x89, 0xf6, 0x33, 0x86, 0x4d, 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66]
3919 UniGuid
= [chr(ItemGuid
) for ItemGuid
in UniGuid
]
3920 fStringIO
.write(''.join(UniGuid
))
3921 UniValue
= pack ('Q', int (Item
[1], 16))
3922 fStringIO
.write (UniValue
)
3925 # VFR binary offset in image.
3927 # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } };
3929 VfrGuid
= [0xb4, 0x7c, 0xbc, 0xd0, 0x47, 0x6a, 0x5f, 0x49, 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2]
3930 VfrGuid
= [chr(ItemGuid
) for ItemGuid
in VfrGuid
]
3931 fStringIO
.write(''.join(VfrGuid
))
3933 VfrValue
= pack ('Q', int (Item
[1], 16))
3934 fStringIO
.write (VfrValue
)
3936 # write data into file.
3939 fInputfile
.write (fStringIO
.getvalue())
3941 EdkLogger
.error("build", FILE_WRITE_FAILURE
, "Write data to file %s failed, please check whether the "
3942 "file been locked or using by other applications." %UniVfrOffsetFileName
,None)
3948 ## Create AsBuilt INF file the module
3950 def CreateAsBuiltInf(self
, IsOnlyCopy
= False):
3951 self
.OutputFile
= []
3953 if GlobalData
.gBinCacheDest
:
3954 self
.CopyModuleToCache()
3957 if self
.IsAsBuiltInfCreated
:
3960 # Skip the following code for EDK I inf
3961 if self
.AutoGenVersion
< 0x00010005:
3964 # Skip the following code for libraries
3968 # Skip the following code for modules with no source files
3969 if self
.SourceFileList
is None or self
.SourceFileList
== []:
3972 # Skip the following code for modules without any binary files
3973 if self
.BinaryFileList
<> None and self
.BinaryFileList
<> []:
3976 ### TODO: How to handles mixed source and binary modules
3978 # Find all DynamicEx and PatchableInModule PCDs used by this module and dependent libraries
3979 # Also find all packages that the DynamicEx PCDs depend on
3984 PcdTokenSpaceList
= []
3985 for Pcd
in self
.ModulePcdList
+ self
.LibraryPcdList
:
3986 if Pcd
.Type
== TAB_PCDS_PATCHABLE_IN_MODULE
:
3987 PatchablePcds
+= [Pcd
]
3988 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, 'PatchableInModule'))
3989 elif Pcd
.Type
in GenC
.gDynamicExPcd
:
3992 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, 'DynamicEx'))
3993 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, 'Dynamic'))
3994 PcdTokenSpaceList
.append(Pcd
.TokenSpaceGuidCName
)
3995 GuidList
= OrderedDict()
3996 GuidList
.update(self
.GuidList
)
3997 for TokenSpace
in self
.GetGuidsUsedByPcd():
3998 # If token space is not referred by patch PCD or Ex PCD, remove the GUID from GUID list
3999 # The GUIDs in GUIDs section should really be the GUIDs in source INF or referred by Ex an patch PCDs
4000 if TokenSpace
not in PcdTokenSpaceList
and TokenSpace
in GuidList
:
4001 GuidList
.pop(TokenSpace
)
4002 CheckList
= (GuidList
, self
.PpiList
, self
.ProtocolList
, PcdCheckList
)
4003 for Package
in self
.DerivedPackageList
:
4004 if Package
in Packages
:
4006 BeChecked
= (Package
.Guids
, Package
.Ppis
, Package
.Protocols
, Package
.Pcds
)
4008 for Index
in range(len(BeChecked
)):
4009 for Item
in CheckList
[Index
]:
4010 if Item
in BeChecked
[Index
]:
4011 Packages
+= [Package
]
4016 VfrPcds
= self
._GetPcdsMaybeUsedByVfr
()
4017 for Pkg
in self
.PlatformInfo
.PackageList
:
4020 for VfrPcd
in VfrPcds
:
4021 if ((VfrPcd
.TokenCName
, VfrPcd
.TokenSpaceGuidCName
, 'DynamicEx') in Pkg
.Pcds
or
4022 (VfrPcd
.TokenCName
, VfrPcd
.TokenSpaceGuidCName
, 'Dynamic') in Pkg
.Pcds
):
4026 ModuleType
= self
.ModuleType
4027 if ModuleType
== 'UEFI_DRIVER' and self
.DepexGenerated
:
4028 ModuleType
= 'DXE_DRIVER'
4031 if self
.PcdIsDriver
!= '':
4032 DriverType
= self
.PcdIsDriver
4035 MDefs
= self
.Module
.Defines
4038 'module_name' : self
.Name
,
4039 'module_guid' : Guid
,
4040 'module_module_type' : ModuleType
,
4041 'module_version_string' : [MDefs
['VERSION_STRING']] if 'VERSION_STRING' in MDefs
else [],
4042 'pcd_is_driver_string' : [],
4043 'module_uefi_specification_version' : [],
4044 'module_pi_specification_version' : [],
4045 'module_entry_point' : self
.Module
.ModuleEntryPointList
,
4046 'module_unload_image' : self
.Module
.ModuleUnloadImageList
,
4047 'module_constructor' : self
.Module
.ConstructorList
,
4048 'module_destructor' : self
.Module
.DestructorList
,
4049 'module_shadow' : [MDefs
['SHADOW']] if 'SHADOW' in MDefs
else [],
4050 'module_pci_vendor_id' : [MDefs
['PCI_VENDOR_ID']] if 'PCI_VENDOR_ID' in MDefs
else [],
4051 'module_pci_device_id' : [MDefs
['PCI_DEVICE_ID']] if 'PCI_DEVICE_ID' in MDefs
else [],
4052 'module_pci_class_code' : [MDefs
['PCI_CLASS_CODE']] if 'PCI_CLASS_CODE' in MDefs
else [],
4053 'module_pci_revision' : [MDefs
['PCI_REVISION']] if 'PCI_REVISION' in MDefs
else [],
4054 'module_build_number' : [MDefs
['BUILD_NUMBER']] if 'BUILD_NUMBER' in MDefs
else [],
4055 'module_spec' : [MDefs
['SPEC']] if 'SPEC' in MDefs
else [],
4056 'module_uefi_hii_resource_section' : [MDefs
['UEFI_HII_RESOURCE_SECTION']] if 'UEFI_HII_RESOURCE_SECTION' in MDefs
else [],
4057 'module_uni_file' : [MDefs
['MODULE_UNI_FILE']] if 'MODULE_UNI_FILE' in MDefs
else [],
4058 'module_arch' : self
.Arch
,
4059 'package_item' : ['%s' % (Package
.MetaFile
.File
.replace('\\', '/')) for Package
in Packages
],
4061 'patchablepcd_item' : [],
4063 'protocol_item' : [],
4067 'libraryclasses_item' : []
4070 if 'MODULE_UNI_FILE' in MDefs
:
4071 UNIFile
= os
.path
.join(self
.MetaFile
.Dir
, MDefs
['MODULE_UNI_FILE'])
4072 if os
.path
.isfile(UNIFile
):
4073 shutil
.copy2(UNIFile
, self
.OutputDir
)
4075 if self
.AutoGenVersion
> int(gInfSpecVersion
, 0):
4076 AsBuiltInfDict
['module_inf_version'] = '0x%08x' % self
.AutoGenVersion
4078 AsBuiltInfDict
['module_inf_version'] = gInfSpecVersion
4081 AsBuiltInfDict
['pcd_is_driver_string'] += [DriverType
]
4083 if 'UEFI_SPECIFICATION_VERSION' in self
.Specification
:
4084 AsBuiltInfDict
['module_uefi_specification_version'] += [self
.Specification
['UEFI_SPECIFICATION_VERSION']]
4085 if 'PI_SPECIFICATION_VERSION' in self
.Specification
:
4086 AsBuiltInfDict
['module_pi_specification_version'] += [self
.Specification
['PI_SPECIFICATION_VERSION']]
4088 OutputDir
= self
.OutputDir
.replace('\\', '/').strip('/')
4089 DebugDir
= self
.DebugDir
.replace('\\', '/').strip('/')
4090 for Item
in self
.CodaTargetList
:
4091 File
= Item
.Target
.Path
.replace('\\', '/').strip('/').replace(DebugDir
, '').replace(OutputDir
, '').strip('/')
4092 if File
not in self
.OutputFile
:
4093 self
.OutputFile
.append(File
)
4094 if os
.path
.isabs(File
):
4095 File
= File
.replace('\\', '/').strip('/').replace(OutputDir
, '').strip('/')
4096 if Item
.Target
.Ext
.lower() == '.aml':
4097 AsBuiltInfDict
['binary_item'] += ['ASL|' + File
]
4098 elif Item
.Target
.Ext
.lower() == '.acpi':
4099 AsBuiltInfDict
['binary_item'] += ['ACPI|' + File
]
4100 elif Item
.Target
.Ext
.lower() == '.efi':
4101 AsBuiltInfDict
['binary_item'] += ['PE32|' + self
.Name
+ '.efi']
4103 AsBuiltInfDict
['binary_item'] += ['BIN|' + File
]
4104 if self
.DepexGenerated
:
4105 if self
.Name
+ '.depex' not in self
.OutputFile
:
4106 self
.OutputFile
.append(self
.Name
+ '.depex')
4107 if self
.ModuleType
in ['PEIM']:
4108 AsBuiltInfDict
['binary_item'] += ['PEI_DEPEX|' + self
.Name
+ '.depex']
4109 if self
.ModuleType
in ['DXE_DRIVER', 'DXE_RUNTIME_DRIVER', 'DXE_SAL_DRIVER', 'UEFI_DRIVER']:
4110 AsBuiltInfDict
['binary_item'] += ['DXE_DEPEX|' + self
.Name
+ '.depex']
4111 if self
.ModuleType
in ['DXE_SMM_DRIVER']:
4112 AsBuiltInfDict
['binary_item'] += ['SMM_DEPEX|' + self
.Name
+ '.depex']
4114 Bin
= self
._GenOffsetBin
()
4116 AsBuiltInfDict
['binary_item'] += ['BIN|%s' % Bin
]
4117 if Bin
not in self
.OutputFile
:
4118 self
.OutputFile
.append(Bin
)
4120 for Root
, Dirs
, Files
in os
.walk(OutputDir
):
4122 if File
.lower().endswith('.pdb'):
4123 AsBuiltInfDict
['binary_item'] += ['DISPOSABLE|' + File
]
4124 if File
not in self
.OutputFile
:
4125 self
.OutputFile
.append(File
)
4126 HeaderComments
= self
.Module
.HeaderComments
4128 for Index
in range(len(HeaderComments
)):
4129 if HeaderComments
[Index
].find('@BinaryHeader') != -1:
4130 HeaderComments
[Index
] = HeaderComments
[Index
].replace('@BinaryHeader', '@file')
4133 AsBuiltInfDict
['header_comments'] = '\n'.join(HeaderComments
[StartPos
:]).replace(':#', '://')
4134 AsBuiltInfDict
['tail_comments'] = '\n'.join(self
.Module
.TailComments
)
4137 (self
.ProtocolList
, self
._ProtocolComments
, 'protocol_item'),
4138 (self
.PpiList
, self
._PpiComments
, 'ppi_item'),
4139 (GuidList
, self
._GuidComments
, 'guid_item')
4141 for Item
in GenList
:
4142 for CName
in Item
[0]:
4144 if CName
in Item
[1]:
4145 Comments
= '\n '.join(Item
[1][CName
])
4148 Entry
= Comments
+ '\n ' + CName
4149 AsBuiltInfDict
[Item
[2]].append(Entry
)
4150 PatchList
= parsePcdInfoFromMapFile(
4151 os
.path
.join(self
.OutputDir
, self
.Name
+ '.map'),
4152 os
.path
.join(self
.OutputDir
, self
.Name
+ '.efi')
4155 for Pcd
in PatchablePcds
:
4156 TokenCName
= Pcd
.TokenCName
4157 for PcdItem
in GlobalData
.MixedPcd
:
4158 if (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
4159 TokenCName
= PcdItem
[0]
4161 for PatchPcd
in PatchList
:
4162 if TokenCName
== PatchPcd
[0]:
4167 if Pcd
.DatumType
== 'BOOLEAN':
4168 BoolValue
= Pcd
.DefaultValue
.upper()
4169 if BoolValue
== 'TRUE':
4170 Pcd
.DefaultValue
= '1'
4171 elif BoolValue
== 'FALSE':
4172 Pcd
.DefaultValue
= '0'
4174 if Pcd
.DatumType
in ['UINT8', 'UINT16', 'UINT32', 'UINT64', 'BOOLEAN']:
4175 HexFormat
= '0x%02x'
4176 if Pcd
.DatumType
== 'UINT16':
4177 HexFormat
= '0x%04x'
4178 elif Pcd
.DatumType
== 'UINT32':
4179 HexFormat
= '0x%08x'
4180 elif Pcd
.DatumType
== 'UINT64':
4181 HexFormat
= '0x%016x'
4182 PcdValue
= HexFormat
% int(Pcd
.DefaultValue
, 0)
4184 if Pcd
.MaxDatumSize
is None or Pcd
.MaxDatumSize
== '':
4185 EdkLogger
.error("build", AUTOGEN_ERROR
,
4186 "Unknown [MaxDatumSize] of PCD [%s.%s]" % (Pcd
.TokenSpaceGuidCName
, TokenCName
)
4188 ArraySize
= int(Pcd
.MaxDatumSize
, 0)
4189 PcdValue
= Pcd
.DefaultValue
4190 if PcdValue
[0] != '{':
4192 if PcdValue
[0] == 'L':
4194 PcdValue
= PcdValue
.lstrip('L')
4195 PcdValue
= eval(PcdValue
)
4197 for Index
in range(0, len(PcdValue
)):
4199 CharVal
= ord(PcdValue
[Index
])
4200 NewValue
= NewValue
+ '0x%02x' % (CharVal
& 0x00FF) + ', ' \
4201 + '0x%02x' % (CharVal
>> 8) + ', '
4203 NewValue
= NewValue
+ '0x%02x' % (ord(PcdValue
[Index
]) % 0x100) + ', '
4206 Padding
= Padding
* 2
4207 ArraySize
= ArraySize
/ 2
4208 if ArraySize
< (len(PcdValue
) + 1):
4209 EdkLogger
.error("build", AUTOGEN_ERROR
,
4210 "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd
.TokenSpaceGuidCName
, TokenCName
)
4212 if ArraySize
> len(PcdValue
) + 1:
4213 NewValue
= NewValue
+ Padding
* (ArraySize
- len(PcdValue
) - 1)
4214 PcdValue
= NewValue
+ Padding
.strip().rstrip(',') + '}'
4215 elif len(PcdValue
.split(',')) <= ArraySize
:
4216 PcdValue
= PcdValue
.rstrip('}') + ', 0x00' * (ArraySize
- len(PcdValue
.split(',')))
4219 EdkLogger
.error("build", AUTOGEN_ERROR
,
4220 "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd
.TokenSpaceGuidCName
, TokenCName
)
4222 PcdItem
= '%s.%s|%s|0x%X' % \
4223 (Pcd
.TokenSpaceGuidCName
, TokenCName
, PcdValue
, PatchPcd
[1])
4225 if (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) in self
._PcdComments
:
4226 PcdComments
= '\n '.join(self
._PcdComments
[Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
])
4228 PcdItem
= PcdComments
+ '\n ' + PcdItem
4229 AsBuiltInfDict
['patchablepcd_item'].append(PcdItem
)
4232 for Pcd
in Pcds
+ VfrPcds
:
4237 TokenCName
= Pcd
.TokenCName
4238 for PcdItem
in GlobalData
.MixedPcd
:
4239 if (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
4240 TokenCName
= PcdItem
[0]
4242 if Pcd
.Type
== TAB_PCDS_DYNAMIC_EX_HII
:
4243 for SkuName
in Pcd
.SkuInfoList
:
4244 SkuInfo
= Pcd
.SkuInfoList
[SkuName
]
4245 SkuId
= SkuInfo
.SkuId
4246 HiiInfo
= '## %s|%s|%s' % (SkuInfo
.VariableName
, SkuInfo
.VariableGuid
, SkuInfo
.VariableOffset
)
4250 # Don't generate duplicated HII PCD
4252 if (SkuId
, Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) in HiiPcds
:
4255 HiiPcds
.append((SkuId
, Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
4256 if (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) in self
._PcdComments
:
4257 PcdCommentList
= self
._PcdComments
[Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
][:]
4261 for Index
, Comment
in enumerate(PcdCommentList
):
4262 for Usage
in UsageList
:
4263 if Comment
.find(Usage
) != -1:
4267 if UsageIndex
!= -1:
4268 PcdCommentList
[UsageIndex
] = '## %s %s %s' % (UsageStr
, HiiInfo
, PcdCommentList
[UsageIndex
].replace(UsageStr
, ''))
4270 PcdCommentList
.append('## UNDEFINED ' + HiiInfo
)
4271 PcdComments
= '\n '.join(PcdCommentList
)
4272 PcdEntry
= Pcd
.TokenSpaceGuidCName
+ '.' + TokenCName
4274 PcdEntry
= PcdComments
+ '\n ' + PcdEntry
4275 AsBuiltInfDict
['pcd_item'] += [PcdEntry
]
4276 for Item
in self
.BuildOption
:
4277 if 'FLAGS' in self
.BuildOption
[Item
]:
4278 AsBuiltInfDict
['flags_item'] += ['%s:%s_%s_%s_%s_FLAGS = %s' % (self
.ToolChainFamily
, self
.BuildTarget
, self
.ToolChain
, self
.Arch
, Item
, self
.BuildOption
[Item
]['FLAGS'].strip())]
4280 # Generated LibraryClasses section in comments.
4281 for Library
in self
.LibraryAutoGenList
:
4282 AsBuiltInfDict
['libraryclasses_item'] += [Library
.MetaFile
.File
.replace('\\', '/')]
4284 # Generated UserExtensions TianoCore section.
4285 # All tianocore user extensions are copied.
4287 for TianoCore
in self
._GetTianoCoreUserExtensionList
():
4288 UserExtStr
+= '\n'.join(TianoCore
)
4289 ExtensionFile
= os
.path
.join(self
.MetaFile
.Dir
, TianoCore
[1])
4290 if os
.path
.isfile(ExtensionFile
):
4291 shutil
.copy2(ExtensionFile
, self
.OutputDir
)
4292 AsBuiltInfDict
['userextension_tianocore_item'] = UserExtStr
4294 # Generated depex expression section in comments.
4295 AsBuiltInfDict
['depexsection_item'] = ''
4296 DepexExpresion
= self
._GetDepexExpresionString
()
4298 AsBuiltInfDict
['depexsection_item'] = DepexExpresion
4300 AsBuiltInf
= TemplateString()
4301 AsBuiltInf
.Append(gAsBuiltInfHeaderString
.Replace(AsBuiltInfDict
))
4303 SaveFileOnChange(os
.path
.join(self
.OutputDir
, self
.Name
+ '.inf'), str(AsBuiltInf
), False)
4305 self
.IsAsBuiltInfCreated
= True
4306 if GlobalData
.gBinCacheDest
:
4307 self
.CopyModuleToCache()
4309 def CopyModuleToCache(self
):
4310 FileDir
= path
.join(GlobalData
.gBinCacheDest
, self
.Arch
, self
.SourceDir
, self
.MetaFile
.BaseName
)
4311 CreateDirectory (FileDir
)
4312 HashFile
= path
.join(self
.BuildDir
, self
.Name
+ '.hash')
4313 ModuleFile
= path
.join(self
.OutputDir
, self
.Name
+ '.inf')
4314 if os
.path
.exists(HashFile
):
4315 shutil
.copy2(HashFile
, FileDir
)
4316 if os
.path
.exists(ModuleFile
):
4317 shutil
.copy2(ModuleFile
, FileDir
)
4318 if not self
.OutputFile
:
4319 Ma
= self
.Workspace
.BuildDatabase
[PathClass(ModuleFile
), self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
4320 self
.OutputFile
= Ma
.Binaries
4322 for File
in self
.OutputFile
:
4324 if not os
.path
.isabs(File
):
4325 File
= os
.path
.join(self
.OutputDir
, File
)
4326 if os
.path
.exists(File
):
4327 shutil
.copy2(File
, FileDir
)
4329 def AttemptModuleCacheCopy(self
):
4330 if self
.IsBinaryModule
:
4332 FileDir
= path
.join(GlobalData
.gBinCacheSource
, self
.Arch
, self
.SourceDir
, self
.MetaFile
.BaseName
)
4333 HashFile
= path
.join(FileDir
, self
.Name
+ '.hash')
4334 if os
.path
.exists(HashFile
):
4335 f
= open(HashFile
, 'r')
4336 CacheHash
= f
.read()
4338 if GlobalData
.gModuleHash
[self
.Arch
][self
.Name
]:
4339 if CacheHash
== GlobalData
.gModuleHash
[self
.Arch
][self
.Name
]:
4340 for root
, dir, files
in os
.walk(FileDir
):
4342 if self
.Name
+ '.hash' in f
:
4343 shutil
.copy2(HashFile
, self
.BuildDir
)
4345 File
= path
.join(root
, f
)
4346 shutil
.copy2(File
, self
.OutputDir
)
4347 if self
.Name
== "PcdPeim" or self
.Name
== "PcdDxe":
4348 CreatePcdDatabaseCode(self
, TemplateString(), TemplateString())
4352 ## Create makefile for the module and its dependent libraries
4354 # @param CreateLibraryMakeFile Flag indicating if or not the makefiles of
4355 # dependent libraries will be created
4357 def CreateMakeFile(self
, CreateLibraryMakeFile
=True, GenFfsList
= []):
4358 # Ignore generating makefile when it is a binary module
4359 if self
.IsBinaryModule
:
4362 if self
.IsMakeFileCreated
:
4364 self
.GenFfsList
= GenFfsList
4365 if not self
.IsLibrary
and CreateLibraryMakeFile
:
4366 for LibraryAutoGen
in self
.LibraryAutoGenList
:
4367 LibraryAutoGen
.CreateMakeFile()
4372 if len(self
.CustomMakefile
) == 0:
4373 Makefile
= GenMake
.ModuleMakefile(self
)
4375 Makefile
= GenMake
.CustomMakefile(self
)
4376 if Makefile
.Generate():
4377 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated makefile for module %s [%s]" %
4378 (self
.Name
, self
.Arch
))
4380 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Skipped the generation of makefile for module %s [%s]" %
4381 (self
.Name
, self
.Arch
))
4383 self
.CreateTimeStamp(Makefile
)
4384 self
.IsMakeFileCreated
= True
4386 def CopyBinaryFiles(self
):
4387 for File
in self
.Module
.Binaries
:
4389 DstPath
= os
.path
.join(self
.OutputDir
, os
.path
.basename(SrcPath
))
4390 CopyLongFilePath(SrcPath
, DstPath
)
4391 ## Create autogen code for the module and its dependent libraries
4393 # @param CreateLibraryCodeFile Flag indicating if or not the code of
4394 # dependent libraries will be created
4396 def CreateCodeFile(self
, CreateLibraryCodeFile
=True):
4397 if self
.IsCodeFileCreated
:
4400 # Need to generate PcdDatabase even PcdDriver is binarymodule
4401 if self
.IsBinaryModule
and self
.PcdIsDriver
!= '':
4402 CreatePcdDatabaseCode(self
, TemplateString(), TemplateString())
4404 if self
.IsBinaryModule
:
4406 self
.CopyBinaryFiles()
4409 if not self
.IsLibrary
and CreateLibraryCodeFile
:
4410 for LibraryAutoGen
in self
.LibraryAutoGenList
:
4411 LibraryAutoGen
.CreateCodeFile()
4417 IgoredAutoGenList
= []
4419 for File
in self
.AutoGenFileList
:
4420 if GenC
.Generate(File
.Path
, self
.AutoGenFileList
[File
], File
.IsBinary
):
4421 #Ignore Edk AutoGen.c
4422 if self
.AutoGenVersion
< 0x00010005 and File
.Name
== 'AutoGen.c':
4425 AutoGenList
.append(str(File
))
4427 IgoredAutoGenList
.append(str(File
))
4429 # Skip the following code for EDK I inf
4430 if self
.AutoGenVersion
< 0x00010005:
4433 for ModuleType
in self
.DepexList
:
4434 # Ignore empty [depex] section or [depex] section for "USER_DEFINED" module
4435 if len(self
.DepexList
[ModuleType
]) == 0 or ModuleType
== "USER_DEFINED":
4438 Dpx
= GenDepex
.DependencyExpression(self
.DepexList
[ModuleType
], ModuleType
, True)
4439 DpxFile
= gAutoGenDepexFileName
% {"module_name" : self
.Name
}
4441 if len(Dpx
.PostfixNotation
) <> 0:
4442 self
.DepexGenerated
= True
4444 if Dpx
.Generate(path
.join(self
.OutputDir
, DpxFile
)):
4445 AutoGenList
.append(str(DpxFile
))
4447 IgoredAutoGenList
.append(str(DpxFile
))
4449 if IgoredAutoGenList
== []:
4450 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated [%s] files for module %s [%s]" %
4451 (" ".join(AutoGenList
), self
.Name
, self
.Arch
))
4452 elif AutoGenList
== []:
4453 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Skipped the generation of [%s] files for module %s [%s]" %
4454 (" ".join(IgoredAutoGenList
), self
.Name
, self
.Arch
))
4456 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated [%s] (skipped %s) files for module %s [%s]" %
4457 (" ".join(AutoGenList
), " ".join(IgoredAutoGenList
), self
.Name
, self
.Arch
))
4459 self
.IsCodeFileCreated
= True
4462 ## Summarize the ModuleAutoGen objects of all libraries used by this module
4463 def _GetLibraryAutoGenList(self
):
4464 if self
._LibraryAutoGenList
is None:
4465 self
._LibraryAutoGenList
= []
4466 for Library
in self
.DependentLibraryList
:
4473 self
.PlatformInfo
.MetaFile
4475 if La
not in self
._LibraryAutoGenList
:
4476 self
._LibraryAutoGenList
.append(La
)
4477 for Lib
in La
.CodaTargetList
:
4478 self
._ApplyBuildRule
(Lib
.Target
, TAB_UNKNOWN_FILE
)
4479 return self
._LibraryAutoGenList
4481 def GenModuleHash(self
):
4482 if self
.Arch
not in GlobalData
.gModuleHash
:
4483 GlobalData
.gModuleHash
[self
.Arch
] = {}
4485 # Add Platform level hash
4486 m
.update(GlobalData
.gPlatformHash
)
4487 # Add Package level hash
4488 if self
.DependentPackageList
:
4489 for Pkg
in self
.DependentPackageList
:
4490 if Pkg
.PackageName
in GlobalData
.gPackageHash
[self
.Arch
]:
4491 m
.update(GlobalData
.gPackageHash
[self
.Arch
][Pkg
.PackageName
])
4494 if self
.LibraryAutoGenList
:
4495 for Lib
in self
.LibraryAutoGenList
:
4496 if Lib
.Name
not in GlobalData
.gModuleHash
[self
.Arch
]:
4498 m
.update(GlobalData
.gModuleHash
[self
.Arch
][Lib
.Name
])
4501 f
= open(str(self
.MetaFile
), 'r')
4505 # Add Module's source files
4506 if self
.SourceFileList
:
4507 for File
in self
.SourceFileList
:
4508 f
= open(str(File
), 'r')
4513 ModuleHashFile
= path
.join(self
.BuildDir
, self
.Name
+ ".hash")
4514 if self
.Name
not in GlobalData
.gModuleHash
[self
.Arch
]:
4515 GlobalData
.gModuleHash
[self
.Arch
][self
.Name
] = m
.hexdigest()
4516 if GlobalData
.gBinCacheSource
:
4517 CacheValid
= self
.AttemptModuleCacheCopy()
4520 return SaveFileOnChange(ModuleHashFile
, m
.hexdigest(), True)
4522 ## Decide whether we can skip the ModuleAutoGen process
4523 def CanSkipbyHash(self
):
4524 if GlobalData
.gUseHashCache
:
4525 return not self
.GenModuleHash()
4527 ## Decide whether we can skip the ModuleAutoGen process
4528 # If any source file is newer than the module than we cannot skip
4531 if not os
.path
.exists(self
.GetTimeStampPath()):
4533 #last creation time of the module
4534 DstTimeStamp
= os
.stat(self
.GetTimeStampPath())[8]
4536 SrcTimeStamp
= self
.Workspace
._SrcTimeStamp
4537 if SrcTimeStamp
> DstTimeStamp
:
4540 with
open(self
.GetTimeStampPath(),'r') as f
:
4542 source
= source
.rstrip('\n')
4543 if not os
.path
.exists(source
):
4545 if source
not in ModuleAutoGen
.TimeDict
:
4546 ModuleAutoGen
.TimeDict
[source
] = os
.stat(source
)[8]
4547 if ModuleAutoGen
.TimeDict
[source
] > DstTimeStamp
:
4551 def GetTimeStampPath(self
):
4552 if self
._TimeStampPath
is None:
4553 self
._TimeStampPath
= os
.path
.join(self
.MakeFileDir
, 'AutoGenTimeStamp')
4554 return self
._TimeStampPath
4555 def CreateTimeStamp(self
, Makefile
):
4559 FileSet
.add (self
.MetaFile
.Path
)
4561 for SourceFile
in self
.Module
.Sources
:
4562 FileSet
.add (SourceFile
.Path
)
4564 for Lib
in self
.DependentLibraryList
:
4565 FileSet
.add (Lib
.MetaFile
.Path
)
4567 for f
in self
.AutoGenDepSet
:
4568 FileSet
.add (f
.Path
)
4570 if os
.path
.exists (self
.GetTimeStampPath()):
4571 os
.remove (self
.GetTimeStampPath())
4572 with
open(self
.GetTimeStampPath(), 'w+') as file:
4576 Module
= property(_GetModule
)
4577 Name
= property(_GetBaseName
)
4578 Guid
= property(_GetGuid
)
4579 Version
= property(_GetVersion
)
4580 ModuleType
= property(_GetModuleType
)
4581 ComponentType
= property(_GetComponentType
)
4582 BuildType
= property(_GetBuildType
)
4583 PcdIsDriver
= property(_GetPcdIsDriver
)
4584 AutoGenVersion
= property(_GetAutoGenVersion
)
4585 Macros
= property(_GetMacros
)
4586 Specification
= property(_GetSpecification
)
4588 IsLibrary
= property(_IsLibrary
)
4589 IsBinaryModule
= property(_IsBinaryModule
)
4590 BuildDir
= property(_GetBuildDir
)
4591 OutputDir
= property(_GetOutputDir
)
4592 FfsOutputDir
= property(_GetFfsOutputDir
)
4593 DebugDir
= property(_GetDebugDir
)
4594 MakeFileDir
= property(_GetMakeFileDir
)
4595 CustomMakefile
= property(_GetCustomMakefile
)
4597 IncludePathList
= property(_GetIncludePathList
)
4598 IncludePathLength
= property(_GetIncludePathLength
)
4599 AutoGenFileList
= property(_GetAutoGenFileList
)
4600 UnicodeFileList
= property(_GetUnicodeFileList
)
4601 VfrFileList
= property(_GetVfrFileList
)
4602 SourceFileList
= property(_GetSourceFileList
)
4603 BinaryFileList
= property(_GetBinaryFiles
) # FileType : [File List]
4604 Targets
= property(_GetTargets
)
4605 IntroTargetList
= property(_GetIntroTargetList
)
4606 CodaTargetList
= property(_GetFinalTargetList
)
4607 FileTypes
= property(_GetFileTypes
)
4608 BuildRules
= property(_GetBuildRules
)
4609 IdfFileList
= property(_GetIdfFileList
)
4611 DependentPackageList
= property(_GetDependentPackageList
)
4612 DependentLibraryList
= property(_GetLibraryList
)
4613 LibraryAutoGenList
= property(_GetLibraryAutoGenList
)
4614 DerivedPackageList
= property(_GetDerivedPackageList
)
4616 ModulePcdList
= property(_GetModulePcdList
)
4617 LibraryPcdList
= property(_GetLibraryPcdList
)
4618 GuidList
= property(_GetGuidList
)
4619 ProtocolList
= property(_GetProtocolList
)
4620 PpiList
= property(_GetPpiList
)
4621 DepexList
= property(_GetDepexTokenList
)
4622 DxsFile
= property(_GetDxsFile
)
4623 DepexExpressionList
= property(_GetDepexExpressionTokenList
)
4624 BuildOption
= property(_GetModuleBuildOption
)
4625 BuildOptionIncPathList
= property(_GetBuildOptionIncPathList
)
4626 BuildCommand
= property(_GetBuildCommand
)
4628 FixedAtBuildPcds
= property(_GetFixedAtBuildPcds
)
4630 # This acts like the main() function for the script, unless it is 'import'ed into another script.
4631 if __name__
== '__main__':