2 # Generate AutoGen.h, AutoGen.c and *.depex files
4 # Copyright (c) 2007 - 2017, 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
48 ## Regular expression for splitting Dependency Expression string into tokens
49 gDepexTokenPattern
= re
.compile("(\(|\)|\w+| \S+\.inf)")
52 # Match name = variable
54 gEfiVarStoreNamePattern
= re
.compile("\s*name\s*=\s*(\w+)")
56 # The format of guid in efivarstore statement likes following and must be correct:
57 # guid = {0xA04A27f4, 0xDF00, 0x4D42, {0xB5, 0x52, 0x39, 0x51, 0x13, 0x02, 0x11, 0x3D}}
59 gEfiVarStoreGuidPattern
= re
.compile("\s*guid\s*=\s*({.*?{.*?}\s*})")
61 ## Mapping Makefile type
62 gMakeTypeMap
= {"MSFT":"nmake", "GCC":"gmake"}
65 ## Build rule configuration file
66 gDefaultBuildRuleFile
= 'build_rule.txt'
68 ## Tools definition configuration file
69 gDefaultToolsDefFile
= 'tools_def.txt'
71 ## Build rule default version
72 AutoGenReqBuildRuleVerNum
= "0.1"
74 ## default file name for AutoGen
75 gAutoGenCodeFileName
= "AutoGen.c"
76 gAutoGenHeaderFileName
= "AutoGen.h"
77 gAutoGenStringFileName
= "%(module_name)sStrDefs.h"
78 gAutoGenStringFormFileName
= "%(module_name)sStrDefs.hpk"
79 gAutoGenDepexFileName
= "%(module_name)s.depex"
80 gAutoGenImageDefFileName
= "%(module_name)sImgDefs.h"
81 gAutoGenIdfFileName
= "%(module_name)sIdf.hpk"
82 gInfSpecVersion
= "0x00010017"
85 # Template string to generic AsBuilt INF
87 gAsBuiltInfHeaderString
= TemplateString("""${header_comments}
93 INF_VERSION = ${module_inf_version}
94 BASE_NAME = ${module_name}
95 FILE_GUID = ${module_guid}
96 MODULE_TYPE = ${module_module_type}${BEGIN}
97 VERSION_STRING = ${module_version_string}${END}${BEGIN}
98 PCD_IS_DRIVER = ${pcd_is_driver_string}${END}${BEGIN}
99 UEFI_SPECIFICATION_VERSION = ${module_uefi_specification_version}${END}${BEGIN}
100 PI_SPECIFICATION_VERSION = ${module_pi_specification_version}${END}${BEGIN}
101 ENTRY_POINT = ${module_entry_point}${END}${BEGIN}
102 UNLOAD_IMAGE = ${module_unload_image}${END}${BEGIN}
103 CONSTRUCTOR = ${module_constructor}${END}${BEGIN}
104 DESTRUCTOR = ${module_destructor}${END}${BEGIN}
105 SHADOW = ${module_shadow}${END}${BEGIN}
106 PCI_VENDOR_ID = ${module_pci_vendor_id}${END}${BEGIN}
107 PCI_DEVICE_ID = ${module_pci_device_id}${END}${BEGIN}
108 PCI_CLASS_CODE = ${module_pci_class_code}${END}${BEGIN}
109 PCI_REVISION = ${module_pci_revision}${END}${BEGIN}
110 BUILD_NUMBER = ${module_build_number}${END}${BEGIN}
111 SPEC = ${module_spec}${END}${BEGIN}
112 UEFI_HII_RESOURCE_SECTION = ${module_uefi_hii_resource_section}${END}${BEGIN}
113 MODULE_UNI_FILE = ${module_uni_file}${END}
115 [Packages.${module_arch}]${BEGIN}
116 ${package_item}${END}
118 [Binaries.${module_arch}]${BEGIN}
121 [PatchPcd.${module_arch}]${BEGIN}
125 [Protocols.${module_arch}]${BEGIN}
129 [Ppis.${module_arch}]${BEGIN}
133 [Guids.${module_arch}]${BEGIN}
137 [PcdEx.${module_arch}]${BEGIN}
141 [LibraryClasses.${module_arch}]
142 ## @LIB_INSTANCES${BEGIN}
143 # ${libraryclasses_item}${END}
147 ${userextension_tianocore_item}
151 [BuildOptions.${module_arch}]
153 ## ${flags_item}${END}
156 ## Base class for AutoGen
158 # This class just implements the cache mechanism of AutoGen objects.
160 class AutoGen(object):
161 # database to maintain the objects of xxxAutoGen
162 _CACHE_
= {} # (BuildTarget, ToolChain) : {ARCH : {platform file: AutoGen object}}}
166 # @param Class class object of real AutoGen class
167 # (WorkspaceAutoGen, ModuleAutoGen or PlatformAutoGen)
168 # @param Workspace Workspace directory or WorkspaceAutoGen object
169 # @param MetaFile The path of meta file
170 # @param Target Build target
171 # @param Toolchain Tool chain name
172 # @param Arch Target arch
173 # @param *args The specific class related parameters
174 # @param **kwargs The specific class related dict parameters
176 def __new__(Class
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
177 # check if the object has been created
178 Key
= (Target
, Toolchain
)
179 if Key
not in Class
._CACHE
_ or Arch
not in Class
._CACHE
_[Key
] \
180 or MetaFile
not in Class
._CACHE
_[Key
][Arch
]:
181 AutoGenObject
= super(AutoGen
, Class
).__new
__(Class
)
182 # call real constructor
183 if not AutoGenObject
._Init
(Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
185 if Key
not in Class
._CACHE
_:
186 Class
._CACHE
_[Key
] = {}
187 if Arch
not in Class
._CACHE
_[Key
]:
188 Class
._CACHE
_[Key
][Arch
] = {}
189 Class
._CACHE
_[Key
][Arch
][MetaFile
] = AutoGenObject
191 AutoGenObject
= Class
._CACHE
_[Key
][Arch
][MetaFile
]
197 # The file path of platform file will be used to represent hash value of this object
199 # @retval int Hash value of the file path of platform file
202 return hash(self
.MetaFile
)
206 # The file path of platform file will be used to represent this object
208 # @retval string String of platform file path
211 return str(self
.MetaFile
)
214 def __eq__(self
, Other
):
215 return Other
and self
.MetaFile
== Other
217 ## Workspace AutoGen class
219 # This class is used mainly to control the whole platform build for different
220 # architecture. This class will generate top level makefile.
222 class WorkspaceAutoGen(AutoGen
):
223 ## Real constructor of WorkspaceAutoGen
225 # This method behaves the same as __init__ except that it needs explicit invoke
226 # (in super class's __new__ method)
228 # @param WorkspaceDir Root directory of workspace
229 # @param ActivePlatform Meta-file of active platform
230 # @param Target Build target
231 # @param Toolchain Tool chain name
232 # @param ArchList List of architecture of current build
233 # @param MetaFileDb Database containing meta-files
234 # @param BuildConfig Configuration of build
235 # @param ToolDefinition Tool chain definitions
236 # @param FlashDefinitionFile File of flash definition
237 # @param Fds FD list to be generated
238 # @param Fvs FV list to be generated
239 # @param Caps Capsule list to be generated
240 # @param SkuId SKU id from command line
242 def _Init(self
, WorkspaceDir
, ActivePlatform
, Target
, Toolchain
, ArchList
, MetaFileDb
,
243 BuildConfig
, ToolDefinition
, FlashDefinitionFile
='', Fds
=None, Fvs
=None, Caps
=None, SkuId
='', UniFlag
=None,
244 Progress
=None, BuildModule
=None):
251 self
.BuildDatabase
= MetaFileDb
252 self
.MetaFile
= ActivePlatform
253 self
.WorkspaceDir
= WorkspaceDir
254 self
.Platform
= self
.BuildDatabase
[self
.MetaFile
, 'COMMON', Target
, Toolchain
]
255 GlobalData
.gActivePlatform
= self
.Platform
256 self
.BuildTarget
= Target
257 self
.ToolChain
= Toolchain
258 self
.ArchList
= ArchList
260 self
.UniFlag
= UniFlag
262 self
.TargetTxt
= BuildConfig
263 self
.ToolDef
= ToolDefinition
264 self
.FdfFile
= FlashDefinitionFile
265 self
.FdTargetList
= Fds
266 self
.FvTargetList
= Fvs
267 self
.CapTargetList
= Caps
268 self
.AutoGenObjectList
= []
269 self
._BuildDir
= None
271 self
._MakeFileDir
= None
272 self
._BuildCommand
= None
274 # there's many relative directory operations, so ...
275 os
.chdir(self
.WorkspaceDir
)
280 if not self
.ArchList
:
281 ArchList
= set(self
.Platform
.SupArchList
)
283 ArchList
= set(self
.ArchList
) & set(self
.Platform
.SupArchList
)
285 EdkLogger
.error("build", PARAMETER_INVALID
,
286 ExtraData
= "Invalid ARCH specified. [Valid ARCH: %s]" % (" ".join(self
.Platform
.SupArchList
)))
287 elif self
.ArchList
and len(ArchList
) != len(self
.ArchList
):
288 SkippedArchList
= set(self
.ArchList
).symmetric_difference(set(self
.Platform
.SupArchList
))
289 EdkLogger
.verbose("\nArch [%s] is ignored because the platform supports [%s] only!"
290 % (" ".join(SkippedArchList
), " ".join(self
.Platform
.SupArchList
)))
291 self
.ArchList
= tuple(ArchList
)
293 # Validate build target
294 if self
.BuildTarget
not in self
.Platform
.BuildTargets
:
295 EdkLogger
.error("build", PARAMETER_INVALID
,
296 ExtraData
="Build target [%s] is not supported by the platform. [Valid target: %s]"
297 % (self
.BuildTarget
, " ".join(self
.Platform
.BuildTargets
)))
300 # parse FDF file to get PCDs in it, if any
302 self
.FdfFile
= self
.Platform
.FlashDefinition
306 EdkLogger
.info('%-16s = %s' % ("Architecture(s)", ' '.join(self
.ArchList
)))
307 EdkLogger
.info('%-16s = %s' % ("Build target", self
.BuildTarget
))
308 EdkLogger
.info('%-16s = %s' % ("Toolchain", self
.ToolChain
))
310 EdkLogger
.info('\n%-24s = %s' % ("Active Platform", self
.Platform
))
312 EdkLogger
.info('%-24s = %s' % ("Active Module", BuildModule
))
315 EdkLogger
.info('%-24s = %s' % ("Flash Image Definition", self
.FdfFile
))
317 EdkLogger
.verbose("\nFLASH_DEFINITION = %s" % self
.FdfFile
)
320 # Progress.Start("\nProcessing meta-data")
324 # Mark now build in AutoGen Phase
326 GlobalData
.gAutoGenPhase
= True
327 Fdf
= FdfParser(self
.FdfFile
.Path
)
329 GlobalData
.gFdfParser
= Fdf
330 GlobalData
.gAutoGenPhase
= False
331 PcdSet
= Fdf
.Profile
.PcdDict
332 if Fdf
.CurrentFdName
and Fdf
.CurrentFdName
in Fdf
.Profile
.FdDict
:
333 FdDict
= Fdf
.Profile
.FdDict
[Fdf
.CurrentFdName
]
334 for FdRegion
in FdDict
.RegionList
:
335 if str(FdRegion
.RegionType
) is 'FILE' and self
.Platform
.VpdToolGuid
in str(FdRegion
.RegionDataList
):
336 if int(FdRegion
.Offset
) % 8 != 0:
337 EdkLogger
.error("build", FORMAT_INVALID
, 'The VPD Base Address %s must be 8-byte aligned.' % (FdRegion
.Offset
))
338 ModuleList
= Fdf
.Profile
.InfList
339 self
.FdfProfile
= Fdf
.Profile
340 for fvname
in self
.FvTargetList
:
341 if fvname
.upper() not in self
.FdfProfile
.FvDict
:
342 EdkLogger
.error("build", OPTION_VALUE_INVALID
,
343 "No such an FV in FDF file: %s" % fvname
)
345 # In DSC file may use FILE_GUID to override the module, then in the Platform.Modules use FILE_GUIDmodule.inf as key,
346 # but the path (self.MetaFile.Path) is the real path
347 for key
in self
.FdfProfile
.InfDict
:
351 for Arch
in self
.ArchList
:
352 Platform_cache
[Arch
] = self
.BuildDatabase
[self
.MetaFile
, Arch
, Target
, Toolchain
]
353 MetaFile_cache
[Arch
] = []
354 for Pkey
in Platform_cache
[Arch
].Modules
.keys():
355 MetaFile_cache
[Arch
].append(Platform_cache
[Arch
].Modules
[Pkey
].MetaFile
)
356 for Inf
in self
.FdfProfile
.InfDict
[key
]:
357 ModuleFile
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, Arch
)
358 for Arch
in self
.ArchList
:
359 if ModuleFile
in MetaFile_cache
[Arch
]:
362 ModuleData
= self
.BuildDatabase
[ModuleFile
, Arch
, Target
, Toolchain
]
363 if not ModuleData
.IsBinaryModule
:
364 EdkLogger
.error('build', PARSER_ERROR
, "Module %s NOT found in DSC file; Is it really a binary module?" % ModuleFile
)
367 for Arch
in self
.ArchList
:
369 Platform
= self
.BuildDatabase
[self
.MetaFile
, Arch
, Target
, Toolchain
]
371 for Pkey
in Platform
.Modules
.keys():
372 MetaFileList
.append(Platform
.Modules
[Pkey
].MetaFile
)
373 for Inf
in self
.FdfProfile
.InfDict
[key
]:
374 ModuleFile
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, Arch
)
375 if ModuleFile
in MetaFileList
:
377 ModuleData
= self
.BuildDatabase
[ModuleFile
, Arch
, Target
, Toolchain
]
378 if not ModuleData
.IsBinaryModule
:
379 EdkLogger
.error('build', PARSER_ERROR
, "Module %s NOT found in DSC file; Is it really a binary module?" % ModuleFile
)
384 self
.FdfProfile
= None
385 if self
.FdTargetList
:
386 EdkLogger
.info("No flash definition file found. FD [%s] will be ignored." % " ".join(self
.FdTargetList
))
387 self
.FdTargetList
= []
388 if self
.FvTargetList
:
389 EdkLogger
.info("No flash definition file found. FV [%s] will be ignored." % " ".join(self
.FvTargetList
))
390 self
.FvTargetList
= []
391 if self
.CapTargetList
:
392 EdkLogger
.info("No flash definition file found. Capsule [%s] will be ignored." % " ".join(self
.CapTargetList
))
393 self
.CapTargetList
= []
395 # apply SKU and inject PCDs from Flash Definition file
396 for Arch
in self
.ArchList
:
397 Platform
= self
.BuildDatabase
[self
.MetaFile
, Arch
, Target
, Toolchain
]
401 PGen
= PlatformAutoGen(self
, self
.MetaFile
, Target
, Toolchain
, Arch
)
402 if GlobalData
.BuildOptionPcd
:
403 for i
, pcd
in enumerate(GlobalData
.BuildOptionPcd
):
404 if type(pcd
) is tuple:
406 (pcdname
, pcdvalue
) = pcd
.split('=')
408 EdkLogger
.error('build', AUTOGEN_ERROR
, "No Value specified for the PCD %s." % (pcdname
))
410 (TokenSpaceGuidCName
, TokenCName
) = pcdname
.split('.')
414 TokenSpaceGuidCName
= ''
415 HasTokenSpace
= False
416 TokenSpaceGuidCNameList
= []
420 for package
in PGen
.PackageList
:
421 for key
in package
.Pcds
:
422 PcdItem
= package
.Pcds
[key
]
424 if (PcdItem
.TokenCName
, PcdItem
.TokenSpaceGuidCName
) == (TokenCName
, TokenSpaceGuidCName
):
425 PcdDatumType
= PcdItem
.DatumType
426 NewValue
= BuildOptionPcdValueFormat(TokenSpaceGuidCName
, TokenCName
, PcdDatumType
, pcdvalue
)
429 if PcdItem
.TokenCName
== TokenCName
:
430 if not PcdItem
.TokenSpaceGuidCName
in TokenSpaceGuidCNameList
:
431 if len (TokenSpaceGuidCNameList
) < 1:
432 TokenSpaceGuidCNameList
.append(PcdItem
.TokenSpaceGuidCName
)
433 PcdDatumType
= PcdItem
.DatumType
434 TokenSpaceGuidCName
= PcdItem
.TokenSpaceGuidCName
435 NewValue
= BuildOptionPcdValueFormat(TokenSpaceGuidCName
, TokenCName
, PcdDatumType
, pcdvalue
)
441 "The Pcd %s is found under multiple different TokenSpaceGuid: %s and %s." % (TokenCName
, PcdItem
.TokenSpaceGuidCName
, TokenSpaceGuidCNameList
[0])
444 GlobalData
.BuildOptionPcd
[i
] = (TokenSpaceGuidCName
, TokenCName
, NewValue
)
448 EdkLogger
.error('build', AUTOGEN_ERROR
, "The Pcd %s.%s is not found in the DEC file." % (TokenSpaceGuidCName
, TokenCName
))
450 EdkLogger
.error('build', AUTOGEN_ERROR
, "The Pcd %s is not found in the DEC file." % (TokenCName
))
452 for BuildData
in PGen
.BuildDatabase
._CACHE
_.values():
453 if BuildData
.Arch
!= Arch
:
455 if BuildData
.MetaFile
.Ext
== '.dec':
457 for key
in BuildData
.Pcds
:
458 PcdItem
= BuildData
.Pcds
[key
]
459 if (TokenSpaceGuidCName
, TokenCName
) == (PcdItem
.TokenSpaceGuidCName
, PcdItem
.TokenCName
):
460 PcdItem
.DefaultValue
= NewValue
462 if (TokenCName
, TokenSpaceGuidCName
) in PcdSet
:
463 PcdSet
[(TokenCName
, TokenSpaceGuidCName
)] = NewValue
465 SourcePcdDict
= {'DynamicEx':[], 'PatchableInModule':[],'Dynamic':[],'FixedAtBuild':[]}
466 BinaryPcdDict
= {'DynamicEx':[], 'PatchableInModule':[]}
467 SourcePcdDict_Keys
= SourcePcdDict
.keys()
468 BinaryPcdDict_Keys
= BinaryPcdDict
.keys()
470 # generate the SourcePcdDict and BinaryPcdDict
471 for BuildData
in PGen
.BuildDatabase
._CACHE
_.values():
472 if BuildData
.Arch
!= Arch
:
474 if BuildData
.MetaFile
.Ext
== '.inf':
475 for key
in BuildData
.Pcds
:
476 if BuildData
.Pcds
[key
].Pending
:
477 if key
in Platform
.Pcds
:
478 PcdInPlatform
= Platform
.Pcds
[key
]
479 if PcdInPlatform
.Type
not in [None, '']:
480 BuildData
.Pcds
[key
].Type
= PcdInPlatform
.Type
482 if BuildData
.MetaFile
in Platform
.Modules
:
483 PlatformModule
= Platform
.Modules
[str(BuildData
.MetaFile
)]
484 if key
in PlatformModule
.Pcds
:
485 PcdInPlatform
= PlatformModule
.Pcds
[key
]
486 if PcdInPlatform
.Type
not in [None, '']:
487 BuildData
.Pcds
[key
].Type
= PcdInPlatform
.Type
489 if 'DynamicEx' in BuildData
.Pcds
[key
].Type
:
490 if BuildData
.IsBinaryModule
:
491 if (BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
) not in BinaryPcdDict
['DynamicEx']:
492 BinaryPcdDict
['DynamicEx'].append((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
494 if (BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
) not in SourcePcdDict
['DynamicEx']:
495 SourcePcdDict
['DynamicEx'].append((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
497 elif 'PatchableInModule' in BuildData
.Pcds
[key
].Type
:
498 if BuildData
.MetaFile
.Ext
== '.inf':
499 if BuildData
.IsBinaryModule
:
500 if (BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
) not in BinaryPcdDict
['PatchableInModule']:
501 BinaryPcdDict
['PatchableInModule'].append((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
503 if (BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
) not in SourcePcdDict
['PatchableInModule']:
504 SourcePcdDict
['PatchableInModule'].append((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
506 elif 'Dynamic' in BuildData
.Pcds
[key
].Type
:
507 if (BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
) not in SourcePcdDict
['Dynamic']:
508 SourcePcdDict
['Dynamic'].append((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
509 elif 'FixedAtBuild' in BuildData
.Pcds
[key
].Type
:
510 if (BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
) not in SourcePcdDict
['FixedAtBuild']:
511 SourcePcdDict
['FixedAtBuild'].append((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
515 # A PCD can only use one type for all source modules
517 for i
in SourcePcdDict_Keys
:
518 for j
in SourcePcdDict_Keys
:
520 IntersectionList
= list(set(SourcePcdDict
[i
]).intersection(set(SourcePcdDict
[j
])))
521 if len(IntersectionList
) > 0:
525 "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
),
526 ExtraData
="%s" % '\n\t'.join([str(P
[1]+'.'+P
[0]) for P
in IntersectionList
])
532 # intersection the BinaryPCD for Mixed PCD
534 for i
in BinaryPcdDict_Keys
:
535 for j
in BinaryPcdDict_Keys
:
537 IntersectionList
= list(set(BinaryPcdDict
[i
]).intersection(set(BinaryPcdDict
[j
])))
538 for item
in IntersectionList
:
539 NewPcd1
= (item
[0] + '_' + i
, item
[1])
540 NewPcd2
= (item
[0] + '_' + j
, item
[1])
541 if item
not in GlobalData
.MixedPcd
:
542 GlobalData
.MixedPcd
[item
] = [NewPcd1
, NewPcd2
]
544 if NewPcd1
not in GlobalData
.MixedPcd
[item
]:
545 GlobalData
.MixedPcd
[item
].append(NewPcd1
)
546 if NewPcd2
not in GlobalData
.MixedPcd
[item
]:
547 GlobalData
.MixedPcd
[item
].append(NewPcd2
)
552 # intersection the SourcePCD and BinaryPCD for Mixed PCD
554 for i
in SourcePcdDict_Keys
:
555 for j
in BinaryPcdDict_Keys
:
557 IntersectionList
= list(set(SourcePcdDict
[i
]).intersection(set(BinaryPcdDict
[j
])))
558 for item
in IntersectionList
:
559 NewPcd1
= (item
[0] + '_' + i
, item
[1])
560 NewPcd2
= (item
[0] + '_' + j
, item
[1])
561 if item
not in GlobalData
.MixedPcd
:
562 GlobalData
.MixedPcd
[item
] = [NewPcd1
, NewPcd2
]
564 if NewPcd1
not in GlobalData
.MixedPcd
[item
]:
565 GlobalData
.MixedPcd
[item
].append(NewPcd1
)
566 if NewPcd2
not in GlobalData
.MixedPcd
[item
]:
567 GlobalData
.MixedPcd
[item
].append(NewPcd2
)
571 for BuildData
in PGen
.BuildDatabase
._CACHE
_.values():
572 if BuildData
.Arch
!= Arch
:
574 for key
in BuildData
.Pcds
:
575 for SinglePcd
in GlobalData
.MixedPcd
:
576 if (BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
) == SinglePcd
:
577 for item
in GlobalData
.MixedPcd
[SinglePcd
]:
578 Pcd_Type
= item
[0].split('_')[-1]
579 if (Pcd_Type
== BuildData
.Pcds
[key
].Type
) or (Pcd_Type
== TAB_PCDS_DYNAMIC_EX
and BuildData
.Pcds
[key
].Type
in GenC
.gDynamicExPcd
) or \
580 (Pcd_Type
== TAB_PCDS_DYNAMIC
and BuildData
.Pcds
[key
].Type
in GenC
.gDynamicPcd
):
581 Value
= BuildData
.Pcds
[key
]
582 Value
.TokenCName
= BuildData
.Pcds
[key
].TokenCName
+ '_' + Pcd_Type
584 newkey
= (Value
.TokenCName
, key
[1])
586 newkey
= (Value
.TokenCName
, key
[1], key
[2])
587 del BuildData
.Pcds
[key
]
588 BuildData
.Pcds
[newkey
] = Value
596 # handle the mixed pcd in FDF file
598 if key
in GlobalData
.MixedPcd
:
601 for item
in GlobalData
.MixedPcd
[key
]:
604 #Collect package set information from INF of FDF
606 for Inf
in ModuleList
:
607 ModuleFile
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, Arch
)
608 if ModuleFile
in Platform
.Modules
:
610 ModuleData
= self
.BuildDatabase
[ModuleFile
, Arch
, Target
, Toolchain
]
611 PkgSet
.update(ModuleData
.Packages
)
612 Pkgs
= list(PkgSet
) + list(PGen
.PackageList
)
615 DecPcds
[Pcd
[0], Pcd
[1]] = Pkg
.Pcds
[Pcd
]
616 DecPcdsKey
.add((Pcd
[0], Pcd
[1], Pcd
[2]))
618 Platform
.SkuName
= self
.SkuId
619 for Name
, Guid
in PcdSet
:
620 if (Name
, Guid
) not in DecPcds
:
624 "PCD (%s.%s) used in FDF is not declared in DEC files." % (Guid
, Name
),
625 File
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
][0],
626 Line
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
][1]
629 # Check whether Dynamic or DynamicEx PCD used in FDF file. If used, build break and give a error message.
630 if (Name
, Guid
, TAB_PCDS_FIXED_AT_BUILD
) in DecPcdsKey \
631 or (Name
, Guid
, TAB_PCDS_PATCHABLE_IN_MODULE
) in DecPcdsKey \
632 or (Name
, Guid
, TAB_PCDS_FEATURE_FLAG
) in DecPcdsKey
:
633 Platform
.AddPcd(Name
, Guid
, PcdSet
[Name
, Guid
])
635 elif (Name
, Guid
, TAB_PCDS_DYNAMIC
) in DecPcdsKey
or (Name
, Guid
, TAB_PCDS_DYNAMIC_EX
) in DecPcdsKey
:
639 "Using Dynamic or DynamicEx type of PCD [%s.%s] in FDF file is not allowed." % (Guid
, Name
),
640 File
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
][0],
641 Line
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
][1]
644 Pa
= PlatformAutoGen(self
, self
.MetaFile
, Target
, Toolchain
, Arch
)
646 # Explicitly collect platform's dynamic PCDs
648 Pa
.CollectPlatformDynamicPcds()
649 Pa
.CollectFixedAtBuildPcds()
650 self
.AutoGenObjectList
.append(Pa
)
653 # Generate Package level hash value
655 GlobalData
.gPackageHash
[Arch
] = {}
656 if GlobalData
.gUseHashCache
:
658 self
._GenPkgLevelHash
(Pkg
)
661 # Check PCDs token value conflict in each DEC file.
663 self
._CheckAllPcdsTokenValueConflict
()
666 # Check PCD type and definition between DSC and DEC
668 self
._CheckPcdDefineAndType
()
671 # self._CheckDuplicateInFV(Fdf)
674 # Create BuildOptions Macro & PCD metafile, also add the Active Platform and FDF file.
676 content
= 'gCommandLineDefines: '
677 content
+= str(GlobalData
.gCommandLineDefines
)
678 content
+= os
.linesep
679 content
+= 'BuildOptionPcd: '
680 content
+= str(GlobalData
.BuildOptionPcd
)
681 content
+= os
.linesep
682 content
+= 'Active Platform: '
683 content
+= str(self
.Platform
)
684 content
+= os
.linesep
686 content
+= 'Flash Image Definition: '
687 content
+= str(self
.FdfFile
)
688 content
+= os
.linesep
689 SaveFileOnChange(os
.path
.join(self
.BuildDir
, 'BuildOptions'), content
, False)
692 # Create PcdToken Number file for Dynamic/DynamicEx Pcd.
694 PcdTokenNumber
= 'PcdTokenNumber: '
695 if Pa
.PcdTokenNumber
:
696 if Pa
.DynamicPcdList
:
697 for Pcd
in Pa
.DynamicPcdList
:
698 PcdTokenNumber
+= os
.linesep
699 PcdTokenNumber
+= str((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
))
700 PcdTokenNumber
+= ' : '
701 PcdTokenNumber
+= str(Pa
.PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
])
702 SaveFileOnChange(os
.path
.join(self
.BuildDir
, 'PcdTokenNumber'), PcdTokenNumber
, False)
705 # Get set of workspace metafiles
707 AllWorkSpaceMetaFiles
= self
._GetMetaFiles
(Target
, Toolchain
, Arch
)
710 # Retrieve latest modified time of all metafiles
713 for f
in AllWorkSpaceMetaFiles
:
714 if os
.stat(f
)[8] > SrcTimeStamp
:
715 SrcTimeStamp
= os
.stat(f
)[8]
716 self
._SrcTimeStamp
= SrcTimeStamp
718 if GlobalData
.gUseHashCache
:
720 for files
in AllWorkSpaceMetaFiles
:
721 if files
.endswith('.dec'):
727 SaveFileOnChange(os
.path
.join(self
.BuildDir
, 'AutoGen.hash'), m
.hexdigest(), True)
728 GlobalData
.gPlatformHash
= m
.hexdigest()
731 # Write metafile list to build directory
733 AutoGenFilePath
= os
.path
.join(self
.BuildDir
, 'AutoGen')
734 if os
.path
.exists (AutoGenFilePath
):
735 os
.remove(AutoGenFilePath
)
736 if not os
.path
.exists(self
.BuildDir
):
737 os
.makedirs(self
.BuildDir
)
738 with
open(os
.path
.join(self
.BuildDir
, 'AutoGen'), 'w+') as file:
739 for f
in AllWorkSpaceMetaFiles
:
743 def _GenPkgLevelHash(self
, Pkg
):
744 PkgDir
= os
.path
.join(self
.BuildDir
, Pkg
.Arch
, Pkg
.PackageName
)
745 CreateDirectory(PkgDir
)
746 HashFile
= os
.path
.join(PkgDir
, Pkg
.PackageName
+ '.hash')
748 # Get .dec file's hash value
749 f
= open(Pkg
.MetaFile
.Path
, 'r')
753 # Get include files hash value
755 for inc
in Pkg
.Includes
:
756 for Root
, Dirs
, Files
in os
.walk(str(inc
)):
758 File_Path
= os
.path
.join(Root
, File
)
759 f
= open(File_Path
, 'r')
763 SaveFileOnChange(HashFile
, m
.hexdigest(), True)
764 if Pkg
.PackageName
not in GlobalData
.gPackageHash
[Pkg
.Arch
]:
765 GlobalData
.gPackageHash
[Pkg
.Arch
][Pkg
.PackageName
] = m
.hexdigest()
767 def _GetMetaFiles(self
, Target
, Toolchain
, Arch
):
768 AllWorkSpaceMetaFiles
= set()
773 AllWorkSpaceMetaFiles
.add (self
.FdfFile
.Path
)
775 FdfFiles
= GlobalData
.gFdfParser
.GetAllIncludedFile()
777 AllWorkSpaceMetaFiles
.add (f
.FileName
)
781 AllWorkSpaceMetaFiles
.add(self
.MetaFile
.Path
)
784 # add build_rule.txt & tools_def.txt
786 AllWorkSpaceMetaFiles
.add(os
.path
.join(GlobalData
.gConfDirectory
, gDefaultBuildRuleFile
))
787 AllWorkSpaceMetaFiles
.add(os
.path
.join(GlobalData
.gConfDirectory
, gDefaultToolsDefFile
))
789 # add BuildOption metafile
791 AllWorkSpaceMetaFiles
.add(os
.path
.join(self
.BuildDir
, 'BuildOptions'))
793 # add PcdToken Number file for Dynamic/DynamicEx Pcd
795 AllWorkSpaceMetaFiles
.add(os
.path
.join(self
.BuildDir
, 'PcdTokenNumber'))
797 for Arch
in self
.ArchList
:
798 Platform
= self
.BuildDatabase
[self
.MetaFile
, Arch
, Target
, Toolchain
]
799 PGen
= PlatformAutoGen(self
, self
.MetaFile
, Target
, Toolchain
, Arch
)
804 for Package
in PGen
.PackageList
:
805 AllWorkSpaceMetaFiles
.add(Package
.MetaFile
.Path
)
810 for filePath
in Platform
._RawData
.IncludedFiles
:
811 AllWorkSpaceMetaFiles
.add(filePath
.Path
)
813 return AllWorkSpaceMetaFiles
815 ## _CheckDuplicateInFV() method
817 # Check whether there is duplicate modules/files exist in FV section.
818 # The check base on the file GUID;
820 def _CheckDuplicateInFV(self
, Fdf
):
821 for Fv
in Fdf
.Profile
.FvDict
:
823 for FfsFile
in Fdf
.Profile
.FvDict
[Fv
].FfsList
:
824 if FfsFile
.InfFileName
and FfsFile
.NameGuid
== None:
829 for Pa
in self
.AutoGenObjectList
:
832 for Module
in Pa
.ModuleAutoGenList
:
833 if path
.normpath(Module
.MetaFile
.File
) == path
.normpath(FfsFile
.InfFileName
):
835 if not Module
.Guid
.upper() in _GuidDict
.keys():
836 _GuidDict
[Module
.Guid
.upper()] = FfsFile
839 EdkLogger
.error("build",
841 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile
.CurrentLineNum
,
842 FfsFile
.CurrentLineContent
,
843 _GuidDict
[Module
.Guid
.upper()].CurrentLineNum
,
844 _GuidDict
[Module
.Guid
.upper()].CurrentLineContent
,
845 Module
.Guid
.upper()),
846 ExtraData
=self
.FdfFile
)
848 # Some INF files not have entity in DSC file.
851 if FfsFile
.InfFileName
.find('$') == -1:
852 InfPath
= NormPath(FfsFile
.InfFileName
)
853 if not os
.path
.exists(InfPath
):
854 EdkLogger
.error('build', GENFDS_ERROR
, "Non-existant Module %s !" % (FfsFile
.InfFileName
))
856 PathClassObj
= PathClass(FfsFile
.InfFileName
, self
.WorkspaceDir
)
858 # Here we just need to get FILE_GUID from INF file, use 'COMMON' as ARCH attribute. and use
859 # BuildObject from one of AutoGenObjectList is enough.
861 InfObj
= self
.AutoGenObjectList
[0].BuildDatabase
.WorkspaceDb
.BuildObject
[PathClassObj
, 'COMMON', self
.BuildTarget
, self
.ToolChain
]
862 if not InfObj
.Guid
.upper() in _GuidDict
.keys():
863 _GuidDict
[InfObj
.Guid
.upper()] = FfsFile
865 EdkLogger
.error("build",
867 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile
.CurrentLineNum
,
868 FfsFile
.CurrentLineContent
,
869 _GuidDict
[InfObj
.Guid
.upper()].CurrentLineNum
,
870 _GuidDict
[InfObj
.Guid
.upper()].CurrentLineContent
,
871 InfObj
.Guid
.upper()),
872 ExtraData
=self
.FdfFile
)
875 if FfsFile
.NameGuid
!= None:
876 _CheckPCDAsGuidPattern
= re
.compile("^PCD\(.+\..+\)$")
879 # If the NameGuid reference a PCD name.
880 # The style must match: PCD(xxxx.yyy)
882 if _CheckPCDAsGuidPattern
.match(FfsFile
.NameGuid
):
884 # Replace the PCD value.
886 _PcdName
= FfsFile
.NameGuid
.lstrip("PCD(").rstrip(")")
888 for Pa
in self
.AutoGenObjectList
:
890 for PcdItem
in Pa
.AllPcdList
:
891 if (PcdItem
.TokenSpaceGuidCName
+ "." + PcdItem
.TokenCName
) == _PcdName
:
893 # First convert from CFormatGuid to GUID string
895 _PcdGuidString
= GuidStructureStringToGuidString(PcdItem
.DefaultValue
)
897 if not _PcdGuidString
:
899 # Then try Byte array.
901 _PcdGuidString
= GuidStructureByteArrayToGuidString(PcdItem
.DefaultValue
)
903 if not _PcdGuidString
:
905 # Not Byte array or CFormat GUID, raise error.
907 EdkLogger
.error("build",
909 "The format of PCD value is incorrect. PCD: %s , Value: %s\n" % (_PcdName
, PcdItem
.DefaultValue
),
910 ExtraData
=self
.FdfFile
)
912 if not _PcdGuidString
.upper() in _GuidDict
.keys():
913 _GuidDict
[_PcdGuidString
.upper()] = FfsFile
917 EdkLogger
.error("build",
919 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile
.CurrentLineNum
,
920 FfsFile
.CurrentLineContent
,
921 _GuidDict
[_PcdGuidString
.upper()].CurrentLineNum
,
922 _GuidDict
[_PcdGuidString
.upper()].CurrentLineContent
,
923 FfsFile
.NameGuid
.upper()),
924 ExtraData
=self
.FdfFile
)
926 if not FfsFile
.NameGuid
.upper() in _GuidDict
.keys():
927 _GuidDict
[FfsFile
.NameGuid
.upper()] = FfsFile
930 # Two raw file GUID conflict.
932 EdkLogger
.error("build",
934 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile
.CurrentLineNum
,
935 FfsFile
.CurrentLineContent
,
936 _GuidDict
[FfsFile
.NameGuid
.upper()].CurrentLineNum
,
937 _GuidDict
[FfsFile
.NameGuid
.upper()].CurrentLineContent
,
938 FfsFile
.NameGuid
.upper()),
939 ExtraData
=self
.FdfFile
)
942 def _CheckPcdDefineAndType(self
):
944 "FixedAtBuild", "PatchableInModule", "FeatureFlag",
945 "Dynamic", #"DynamicHii", "DynamicVpd",
946 "DynamicEx", # "DynamicExHii", "DynamicExVpd"
949 # This dict store PCDs which are not used by any modules with specified arches
951 for Pa
in self
.AutoGenObjectList
:
952 # Key of DSC's Pcds dictionary is PcdCName, TokenSpaceGuid
953 for Pcd
in Pa
.Platform
.Pcds
:
954 PcdType
= Pa
.Platform
.Pcds
[Pcd
].Type
956 # If no PCD type, this PCD comes from FDF
960 # Try to remove Hii and Vpd suffix
961 if PcdType
.startswith("DynamicEx"):
962 PcdType
= "DynamicEx"
963 elif PcdType
.startswith("Dynamic"):
966 for Package
in Pa
.PackageList
:
967 # Key of DEC's Pcds dictionary is PcdCName, TokenSpaceGuid, PcdType
968 if (Pcd
[0], Pcd
[1], PcdType
) in Package
.Pcds
:
970 for Type
in PcdTypeList
:
971 if (Pcd
[0], Pcd
[1], Type
) in Package
.Pcds
:
975 "Type [%s] of PCD [%s.%s] in DSC file doesn't match the type [%s] defined in DEC file." \
976 % (Pa
.Platform
.Pcds
[Pcd
].Type
, Pcd
[1], Pcd
[0], Type
),
981 UnusedPcd
.setdefault(Pcd
, []).append(Pa
.Arch
)
983 for Pcd
in UnusedPcd
:
986 "The PCD was not specified by any INF module in the platform for the given architecture.\n"
987 "\tPCD: [%s.%s]\n\tPlatform: [%s]\n\tArch: %s"
988 % (Pcd
[1], Pcd
[0], os
.path
.basename(str(self
.MetaFile
)), str(UnusedPcd
[Pcd
])),
993 return "%s [%s]" % (self
.MetaFile
, ", ".join(self
.ArchList
))
995 ## Return the directory to store FV files
997 if self
._FvDir
== None:
998 self
._FvDir
= path
.join(self
.BuildDir
, 'FV')
1001 ## Return the directory to store all intermediate and final files built
1002 def _GetBuildDir(self
):
1003 if self
._BuildDir
== None:
1004 return self
.AutoGenObjectList
[0].BuildDir
1006 ## Return the build output directory platform specifies
1007 def _GetOutputDir(self
):
1008 return self
.Platform
.OutputDirectory
1010 ## Return platform name
1012 return self
.Platform
.PlatformName
1014 ## Return meta-file GUID
1016 return self
.Platform
.Guid
1018 ## Return platform version
1019 def _GetVersion(self
):
1020 return self
.Platform
.Version
1022 ## Return paths of tools
1023 def _GetToolDefinition(self
):
1024 return self
.AutoGenObjectList
[0].ToolDefinition
1026 ## Return directory of platform makefile
1028 # @retval string Makefile directory
1030 def _GetMakeFileDir(self
):
1031 if self
._MakeFileDir
== None:
1032 self
._MakeFileDir
= self
.BuildDir
1033 return self
._MakeFileDir
1035 ## Return build command string
1037 # @retval string Build command string
1039 def _GetBuildCommand(self
):
1040 if self
._BuildCommand
== None:
1041 # BuildCommand should be all the same. So just get one from platform AutoGen
1042 self
._BuildCommand
= self
.AutoGenObjectList
[0].BuildCommand
1043 return self
._BuildCommand
1045 ## Check the PCDs token value conflict in each DEC file.
1047 # Will cause build break and raise error message while two PCDs conflict.
1051 def _CheckAllPcdsTokenValueConflict(self
):
1052 for Pa
in self
.AutoGenObjectList
:
1053 for Package
in Pa
.PackageList
:
1054 PcdList
= Package
.Pcds
.values()
1055 PcdList
.sort(lambda x
, y
: cmp(int(x
.TokenValue
, 0), int(y
.TokenValue
, 0)))
1057 while (Count
< len(PcdList
) - 1) :
1058 Item
= PcdList
[Count
]
1059 ItemNext
= PcdList
[Count
+ 1]
1061 # Make sure in the same token space the TokenValue should be unique
1063 if (int(Item
.TokenValue
, 0) == int(ItemNext
.TokenValue
, 0)):
1064 SameTokenValuePcdList
= []
1065 SameTokenValuePcdList
.append(Item
)
1066 SameTokenValuePcdList
.append(ItemNext
)
1067 RemainPcdListLength
= len(PcdList
) - Count
- 2
1068 for ValueSameCount
in range(RemainPcdListLength
):
1069 if int(PcdList
[len(PcdList
) - RemainPcdListLength
+ ValueSameCount
].TokenValue
, 0) == int(Item
.TokenValue
, 0):
1070 SameTokenValuePcdList
.append(PcdList
[len(PcdList
) - RemainPcdListLength
+ ValueSameCount
])
1074 # Sort same token value PCD list with TokenGuid and TokenCName
1076 SameTokenValuePcdList
.sort(lambda x
, y
: cmp("%s.%s" % (x
.TokenSpaceGuidCName
, x
.TokenCName
), "%s.%s" % (y
.TokenSpaceGuidCName
, y
.TokenCName
)))
1077 SameTokenValuePcdListCount
= 0
1078 while (SameTokenValuePcdListCount
< len(SameTokenValuePcdList
) - 1):
1080 TemListItem
= SameTokenValuePcdList
[SameTokenValuePcdListCount
]
1081 TemListItemNext
= SameTokenValuePcdList
[SameTokenValuePcdListCount
+ 1]
1083 if (TemListItem
.TokenSpaceGuidCName
== TemListItemNext
.TokenSpaceGuidCName
) and (TemListItem
.TokenCName
!= TemListItemNext
.TokenCName
):
1084 for PcdItem
in GlobalData
.MixedPcd
:
1085 if (TemListItem
.TokenCName
, TemListItem
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
] or \
1086 (TemListItemNext
.TokenCName
, TemListItemNext
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
1092 "The TokenValue [%s] of PCD [%s.%s] is conflict with: [%s.%s] in %s"\
1093 % (TemListItem
.TokenValue
, TemListItem
.TokenSpaceGuidCName
, TemListItem
.TokenCName
, TemListItemNext
.TokenSpaceGuidCName
, TemListItemNext
.TokenCName
, Package
),
1096 SameTokenValuePcdListCount
+= 1
1097 Count
+= SameTokenValuePcdListCount
1100 PcdList
= Package
.Pcds
.values()
1101 PcdList
.sort(lambda x
, y
: cmp("%s.%s" % (x
.TokenSpaceGuidCName
, x
.TokenCName
), "%s.%s" % (y
.TokenSpaceGuidCName
, y
.TokenCName
)))
1103 while (Count
< len(PcdList
) - 1) :
1104 Item
= PcdList
[Count
]
1105 ItemNext
= PcdList
[Count
+ 1]
1107 # Check PCDs with same TokenSpaceGuidCName.TokenCName have same token value as well.
1109 if (Item
.TokenSpaceGuidCName
== ItemNext
.TokenSpaceGuidCName
) and (Item
.TokenCName
== ItemNext
.TokenCName
) and (int(Item
.TokenValue
, 0) != int(ItemNext
.TokenValue
, 0)):
1113 "The TokenValue [%s] of PCD [%s.%s] in %s defined in two places should be same as well."\
1114 % (Item
.TokenValue
, Item
.TokenSpaceGuidCName
, Item
.TokenCName
, Package
),
1118 ## Generate fds command
1119 def _GenFdsCommand(self
):
1120 return (GenMake
.TopLevelMakefile(self
)._TEMPLATE
_.Replace(GenMake
.TopLevelMakefile(self
)._TemplateDict
)).strip()
1122 ## Create makefile for the platform and modules in it
1124 # @param CreateDepsMakeFile Flag indicating if the makefile for
1125 # modules will be created as well
1127 def CreateMakeFile(self
, CreateDepsMakeFile
=False):
1128 if CreateDepsMakeFile
:
1129 for Pa
in self
.AutoGenObjectList
:
1130 Pa
.CreateMakeFile(CreateDepsMakeFile
)
1132 ## Create autogen code for platform and modules
1134 # Since there's no autogen code for platform, this method will do nothing
1135 # if CreateModuleCodeFile is set to False.
1137 # @param CreateDepsCodeFile Flag indicating if creating module's
1138 # autogen code file or not
1140 def CreateCodeFile(self
, CreateDepsCodeFile
=False):
1141 if not CreateDepsCodeFile
:
1143 for Pa
in self
.AutoGenObjectList
:
1144 Pa
.CreateCodeFile(CreateDepsCodeFile
)
1146 ## Create AsBuilt INF file the platform
1148 def CreateAsBuiltInf(self
):
1151 Name
= property(_GetName
)
1152 Guid
= property(_GetGuid
)
1153 Version
= property(_GetVersion
)
1154 OutputDir
= property(_GetOutputDir
)
1156 ToolDefinition
= property(_GetToolDefinition
) # toolcode : tool path
1158 BuildDir
= property(_GetBuildDir
)
1159 FvDir
= property(_GetFvDir
)
1160 MakeFileDir
= property(_GetMakeFileDir
)
1161 BuildCommand
= property(_GetBuildCommand
)
1162 GenFdsCommand
= property(_GenFdsCommand
)
1164 ## AutoGen class for platform
1166 # PlatformAutoGen class will process the original information in platform
1167 # file in order to generate makefile for platform.
1169 class PlatformAutoGen(AutoGen
):
1171 # Used to store all PCDs for both PEI and DXE phase, in order to generate
1172 # correct PCD database
1175 _NonDynaPcdList_
= []
1179 # The priority list while override build option
1181 PrioList
= {"0x11111" : 16, # TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE (Highest)
1182 "0x01111" : 15, # ******_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
1183 "0x10111" : 14, # TARGET_*********_ARCH_COMMANDTYPE_ATTRIBUTE
1184 "0x00111" : 13, # ******_*********_ARCH_COMMANDTYPE_ATTRIBUTE
1185 "0x11011" : 12, # TARGET_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
1186 "0x01011" : 11, # ******_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
1187 "0x10011" : 10, # TARGET_*********_****_COMMANDTYPE_ATTRIBUTE
1188 "0x00011" : 9, # ******_*********_****_COMMANDTYPE_ATTRIBUTE
1189 "0x11101" : 8, # TARGET_TOOLCHAIN_ARCH_***********_ATTRIBUTE
1190 "0x01101" : 7, # ******_TOOLCHAIN_ARCH_***********_ATTRIBUTE
1191 "0x10101" : 6, # TARGET_*********_ARCH_***********_ATTRIBUTE
1192 "0x00101" : 5, # ******_*********_ARCH_***********_ATTRIBUTE
1193 "0x11001" : 4, # TARGET_TOOLCHAIN_****_***********_ATTRIBUTE
1194 "0x01001" : 3, # ******_TOOLCHAIN_****_***********_ATTRIBUTE
1195 "0x10001" : 2, # TARGET_*********_****_***********_ATTRIBUTE
1196 "0x00001" : 1} # ******_*********_****_***********_ATTRIBUTE (Lowest)
1198 ## The real constructor of PlatformAutoGen
1200 # This method is not supposed to be called by users of PlatformAutoGen. It's
1201 # only used by factory method __new__() to do real initialization work for an
1202 # object of PlatformAutoGen
1204 # @param Workspace WorkspaceAutoGen object
1205 # @param PlatformFile Platform file (DSC file)
1206 # @param Target Build target (DEBUG, RELEASE)
1207 # @param Toolchain Name of tool chain
1208 # @param Arch arch of the platform supports
1210 def _Init(self
, Workspace
, PlatformFile
, Target
, Toolchain
, Arch
):
1211 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "AutoGen platform [%s] [%s]" % (PlatformFile
, Arch
))
1212 GlobalData
.gProcessingFile
= "%s [%s, %s, %s]" % (PlatformFile
, Arch
, Toolchain
, Target
)
1214 self
.MetaFile
= PlatformFile
1215 self
.Workspace
= Workspace
1216 self
.WorkspaceDir
= Workspace
.WorkspaceDir
1217 self
.ToolChain
= Toolchain
1218 self
.BuildTarget
= Target
1220 self
.SourceDir
= PlatformFile
.SubDir
1221 self
.SourceOverrideDir
= None
1222 self
.FdTargetList
= self
.Workspace
.FdTargetList
1223 self
.FvTargetList
= self
.Workspace
.FvTargetList
1224 self
.AllPcdList
= []
1225 # get the original module/package/platform objects
1226 self
.BuildDatabase
= Workspace
.BuildDatabase
1228 # flag indicating if the makefile/C-code file has been created or not
1229 self
.IsMakeFileCreated
= False
1230 self
.IsCodeFileCreated
= False
1232 self
._Platform
= None
1235 self
._Version
= None
1237 self
._BuildRule
= None
1238 self
._SourceDir
= None
1239 self
._BuildDir
= None
1240 self
._OutputDir
= None
1242 self
._MakeFileDir
= None
1243 self
._FdfFile
= None
1245 self
._PcdTokenNumber
= None # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber
1246 self
._DynamicPcdList
= None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
1247 self
._NonDynamicPcdList
= None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
1248 self
._NonDynamicPcdDict
= {}
1250 self
._ToolDefinitions
= None
1251 self
._ToolDefFile
= None # toolcode : tool path
1252 self
._ToolChainFamily
= None
1253 self
._BuildRuleFamily
= None
1254 self
._BuildOption
= None # toolcode : option
1255 self
._EdkBuildOption
= None # edktoolcode : option
1256 self
._EdkIIBuildOption
= None # edkiitoolcode : option
1257 self
._PackageList
= None
1258 self
._ModuleAutoGenList
= None
1259 self
._LibraryAutoGenList
= None
1260 self
._BuildCommand
= None
1261 self
._AsBuildInfList
= []
1262 self
._AsBuildModuleList
= []
1263 if GlobalData
.gFdfParser
!= None:
1264 self
._AsBuildInfList
= GlobalData
.gFdfParser
.Profile
.InfList
1265 for Inf
in self
._AsBuildInfList
:
1266 InfClass
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, self
.Arch
)
1267 M
= self
.BuildDatabase
[InfClass
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1268 if not M
.IsSupportedArch
:
1270 self
._AsBuildModuleList
.append(InfClass
)
1271 # get library/modules for build
1272 self
.LibraryBuildDirectoryList
= []
1273 self
.ModuleBuildDirectoryList
= []
1277 return "%s [%s]" % (self
.MetaFile
, self
.Arch
)
1279 ## Create autogen code for platform and modules
1281 # Since there's no autogen code for platform, this method will do nothing
1282 # if CreateModuleCodeFile is set to False.
1284 # @param CreateModuleCodeFile Flag indicating if creating module's
1285 # autogen code file or not
1287 def CreateCodeFile(self
, CreateModuleCodeFile
=False):
1288 # only module has code to be greated, so do nothing if CreateModuleCodeFile is False
1289 if self
.IsCodeFileCreated
or not CreateModuleCodeFile
:
1292 for Ma
in self
.ModuleAutoGenList
:
1293 Ma
.CreateCodeFile(True)
1295 # don't do this twice
1296 self
.IsCodeFileCreated
= True
1298 ## Generate Fds Command
1299 def _GenFdsCommand(self
):
1300 return self
.Workspace
.GenFdsCommand
1302 ## Create makefile for the platform and mdoules in it
1304 # @param CreateModuleMakeFile Flag indicating if the makefile for
1305 # modules will be created as well
1307 def CreateMakeFile(self
, CreateModuleMakeFile
=False, FfsCommand
= {}):
1308 if CreateModuleMakeFile
:
1309 for ModuleFile
in self
.Platform
.Modules
:
1310 Ma
= ModuleAutoGen(self
.Workspace
, ModuleFile
, self
.BuildTarget
,
1311 self
.ToolChain
, self
.Arch
, self
.MetaFile
)
1312 if (ModuleFile
.File
, self
.Arch
) in FfsCommand
:
1313 Ma
.CreateMakeFile(True, FfsCommand
[ModuleFile
.File
, self
.Arch
])
1315 Ma
.CreateMakeFile(True)
1316 #Ma.CreateAsBuiltInf()
1318 # no need to create makefile for the platform more than once
1319 if self
.IsMakeFileCreated
:
1322 # create library/module build dirs for platform
1323 Makefile
= GenMake
.PlatformMakefile(self
)
1324 self
.LibraryBuildDirectoryList
= Makefile
.GetLibraryBuildDirectoryList()
1325 self
.ModuleBuildDirectoryList
= Makefile
.GetModuleBuildDirectoryList()
1327 self
.IsMakeFileCreated
= True
1329 ## Deal with Shared FixedAtBuild Pcds
1331 def CollectFixedAtBuildPcds(self
):
1332 for LibAuto
in self
.LibraryAutoGenList
:
1333 FixedAtBuildPcds
= {}
1334 ShareFixedAtBuildPcdsSameValue
= {}
1335 for Module
in LibAuto
._ReferenceModules
:
1336 for Pcd
in Module
.FixedAtBuildPcds
+ LibAuto
.FixedAtBuildPcds
:
1337 key
= ".".join((Pcd
.TokenSpaceGuidCName
,Pcd
.TokenCName
))
1338 if key
not in FixedAtBuildPcds
:
1339 ShareFixedAtBuildPcdsSameValue
[key
] = True
1340 FixedAtBuildPcds
[key
] = Pcd
.DefaultValue
1342 if FixedAtBuildPcds
[key
] != Pcd
.DefaultValue
:
1343 ShareFixedAtBuildPcdsSameValue
[key
] = False
1344 for Pcd
in LibAuto
.FixedAtBuildPcds
:
1345 key
= ".".join((Pcd
.TokenSpaceGuidCName
,Pcd
.TokenCName
))
1346 if (Pcd
.TokenCName
,Pcd
.TokenSpaceGuidCName
) not in self
.NonDynamicPcdDict
:
1349 DscPcd
= self
.NonDynamicPcdDict
[(Pcd
.TokenCName
,Pcd
.TokenSpaceGuidCName
)]
1350 if DscPcd
.Type
!= "FixedAtBuild":
1352 if key
in ShareFixedAtBuildPcdsSameValue
and ShareFixedAtBuildPcdsSameValue
[key
]:
1353 LibAuto
.ConstPcd
[key
] = Pcd
.DefaultValue
1355 ## Collect dynamic PCDs
1357 # Gather dynamic PCDs list from each module and their settings from platform
1358 # This interface should be invoked explicitly when platform action is created.
1360 def CollectPlatformDynamicPcds(self
):
1361 # Override the platform Pcd's value by build option
1362 if GlobalData
.BuildOptionPcd
:
1363 for key
in self
.Platform
.Pcds
:
1364 PlatformPcd
= self
.Platform
.Pcds
[key
]
1365 for PcdItem
in GlobalData
.BuildOptionPcd
:
1366 if (PlatformPcd
.TokenSpaceGuidCName
, PlatformPcd
.TokenCName
) == (PcdItem
[0], PcdItem
[1]):
1367 PlatformPcd
.DefaultValue
= PcdItem
[2]
1368 if PlatformPcd
.SkuInfoList
:
1369 Sku
= PlatformPcd
.SkuInfoList
[PlatformPcd
.SkuInfoList
.keys()[0]]
1370 Sku
.DefaultValue
= PcdItem
[2]
1373 for key
in self
.Platform
.Pcds
:
1374 for SinglePcd
in GlobalData
.MixedPcd
:
1375 if (self
.Platform
.Pcds
[key
].TokenCName
, self
.Platform
.Pcds
[key
].TokenSpaceGuidCName
) == SinglePcd
:
1376 for item
in GlobalData
.MixedPcd
[SinglePcd
]:
1377 Pcd_Type
= item
[0].split('_')[-1]
1378 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 \
1379 (Pcd_Type
== TAB_PCDS_DYNAMIC
and self
.Platform
.Pcds
[key
].Type
in GenC
.gDynamicPcd
):
1380 Value
= self
.Platform
.Pcds
[key
]
1381 Value
.TokenCName
= self
.Platform
.Pcds
[key
].TokenCName
+ '_' + Pcd_Type
1383 newkey
= (Value
.TokenCName
, key
[1])
1385 newkey
= (Value
.TokenCName
, key
[1], key
[2])
1386 del self
.Platform
.Pcds
[key
]
1387 self
.Platform
.Pcds
[newkey
] = Value
1395 # for gathering error information
1396 NoDatumTypePcdList
= set()
1398 self
._GuidValue
= {}
1400 for InfName
in self
._AsBuildInfList
:
1401 InfName
= mws
.join(self
.WorkspaceDir
, InfName
)
1402 FdfModuleList
.append(os
.path
.normpath(InfName
))
1403 for F
in self
.Platform
.Modules
.keys():
1404 M
= ModuleAutoGen(self
.Workspace
, F
, self
.BuildTarget
, self
.ToolChain
, self
.Arch
, self
.MetaFile
)
1405 #GuidValue.update(M.Guids)
1407 self
.Platform
.Modules
[F
].M
= M
1409 for PcdFromModule
in M
.ModulePcdList
+ M
.LibraryPcdList
:
1410 # make sure that the "VOID*" kind of datum has MaxDatumSize set
1411 if PcdFromModule
.DatumType
== "VOID*" and PcdFromModule
.MaxDatumSize
in [None, '']:
1412 NoDatumTypePcdList
.add("%s.%s [%s]" % (PcdFromModule
.TokenSpaceGuidCName
, PcdFromModule
.TokenCName
, F
))
1414 # Check the PCD from Binary INF or Source INF
1415 if M
.IsBinaryModule
== True:
1416 PcdFromModule
.IsFromBinaryInf
= True
1418 # Check the PCD from DSC or not
1419 if (PcdFromModule
.TokenCName
, PcdFromModule
.TokenSpaceGuidCName
) in self
.Platform
.Pcds
.keys():
1420 PcdFromModule
.IsFromDsc
= True
1422 PcdFromModule
.IsFromDsc
= False
1423 if PcdFromModule
.Type
in GenC
.gDynamicPcd
or PcdFromModule
.Type
in GenC
.gDynamicExPcd
:
1424 if F
.Path
not in FdfModuleList
:
1425 # If one of the Source built modules listed in the DSC is not listed
1426 # in FDF modules, and the INF lists a PCD can only use the PcdsDynamic
1427 # access method (it is only listed in the DEC file that declares the
1428 # PCD as PcdsDynamic), then build tool will report warning message
1429 # notify the PI that they are attempting to build a module that must
1430 # be included in a flash image in order to be functional. These Dynamic
1431 # PCD will not be added into the Database unless it is used by other
1432 # modules that are included in the FDF file.
1433 if PcdFromModule
.Type
in GenC
.gDynamicPcd
and \
1434 PcdFromModule
.IsFromBinaryInf
== False:
1435 # Print warning message to let the developer make a determine.
1436 if PcdFromModule
not in PcdNotInDb
:
1437 PcdNotInDb
.append(PcdFromModule
)
1439 # If one of the Source built modules listed in the DSC is not listed in
1440 # FDF modules, and the INF lists a PCD can only use the PcdsDynamicEx
1441 # access method (it is only listed in the DEC file that declares the
1442 # PCD as PcdsDynamicEx), then DO NOT break the build; DO NOT add the
1443 # PCD to the Platform's PCD Database.
1444 if PcdFromModule
.Type
in GenC
.gDynamicExPcd
:
1445 if PcdFromModule
not in PcdNotInDb
:
1446 PcdNotInDb
.append(PcdFromModule
)
1449 # If a dynamic PCD used by a PEM module/PEI module & DXE module,
1450 # it should be stored in Pcd PEI database, If a dynamic only
1451 # used by DXE module, it should be stored in DXE PCD database.
1452 # The default Phase is DXE
1454 if M
.ModuleType
in ["PEIM", "PEI_CORE"]:
1455 PcdFromModule
.Phase
= "PEI"
1456 if PcdFromModule
not in self
._DynaPcdList
_:
1457 self
._DynaPcdList
_.append(PcdFromModule
)
1458 elif PcdFromModule
.Phase
== 'PEI':
1459 # overwrite any the same PCD existing, if Phase is PEI
1460 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1461 self
._DynaPcdList
_[Index
] = PcdFromModule
1462 elif PcdFromModule
not in self
._NonDynaPcdList
_:
1463 self
._NonDynaPcdList
_.append(PcdFromModule
)
1464 elif PcdFromModule
in self
._NonDynaPcdList
_ and PcdFromModule
.IsFromBinaryInf
== True:
1465 Index
= self
._NonDynaPcdList
_.index(PcdFromModule
)
1466 if self
._NonDynaPcdList
_[Index
].IsFromBinaryInf
== False:
1467 #The PCD from Binary INF will override the same one from source INF
1468 self
._NonDynaPcdList
_.remove (self
._NonDynaPcdList
_[Index
])
1469 PcdFromModule
.Pending
= False
1470 self
._NonDynaPcdList
_.append (PcdFromModule
)
1471 # Parse the DynamicEx PCD from the AsBuild INF module list of FDF.
1473 for ModuleInf
in self
.Platform
.Modules
.keys():
1474 DscModuleList
.append (os
.path
.normpath(ModuleInf
.Path
))
1475 # add the PCD from modules that listed in FDF but not in DSC to Database
1476 for InfName
in FdfModuleList
:
1477 if InfName
not in DscModuleList
:
1478 InfClass
= PathClass(InfName
)
1479 M
= self
.BuildDatabase
[InfClass
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1480 # If a module INF in FDF but not in current arch's DSC module list, it must be module (either binary or source)
1481 # for different Arch. PCDs in source module for different Arch is already added before, so skip the source module here.
1482 # For binary module, if in current arch, we need to list the PCDs into database.
1483 if not M
.IsSupportedArch
:
1485 # Override the module PCD setting by platform setting
1486 ModulePcdList
= self
.ApplyPcdSetting(M
, M
.Pcds
)
1487 for PcdFromModule
in ModulePcdList
:
1488 PcdFromModule
.IsFromBinaryInf
= True
1489 PcdFromModule
.IsFromDsc
= False
1490 # Only allow the DynamicEx and Patchable PCD in AsBuild INF
1491 if PcdFromModule
.Type
not in GenC
.gDynamicExPcd
and PcdFromModule
.Type
not in TAB_PCDS_PATCHABLE_IN_MODULE
:
1492 EdkLogger
.error("build", AUTOGEN_ERROR
, "PCD setting error",
1494 ExtraData
="\n\tExisted %s PCD %s in:\n\t\t%s\n"
1495 % (PcdFromModule
.Type
, PcdFromModule
.TokenCName
, InfName
))
1496 # make sure that the "VOID*" kind of datum has MaxDatumSize set
1497 if PcdFromModule
.DatumType
== "VOID*" and PcdFromModule
.MaxDatumSize
in [None, '']:
1498 NoDatumTypePcdList
.add("%s.%s [%s]" % (PcdFromModule
.TokenSpaceGuidCName
, PcdFromModule
.TokenCName
, InfName
))
1499 if M
.ModuleType
in ["PEIM", "PEI_CORE"]:
1500 PcdFromModule
.Phase
= "PEI"
1501 if PcdFromModule
not in self
._DynaPcdList
_ and PcdFromModule
.Type
in GenC
.gDynamicExPcd
:
1502 self
._DynaPcdList
_.append(PcdFromModule
)
1503 elif PcdFromModule
not in self
._NonDynaPcdList
_ and PcdFromModule
.Type
in TAB_PCDS_PATCHABLE_IN_MODULE
:
1504 self
._NonDynaPcdList
_.append(PcdFromModule
)
1505 if PcdFromModule
in self
._DynaPcdList
_ and PcdFromModule
.Phase
== 'PEI' and PcdFromModule
.Type
in GenC
.gDynamicExPcd
:
1506 # Overwrite the phase of any the same PCD existing, if Phase is PEI.
1507 # It is to solve the case that a dynamic PCD used by a PEM module/PEI
1508 # module & DXE module at a same time.
1509 # Overwrite the type of the PCDs in source INF by the type of AsBuild
1510 # INF file as DynamicEx.
1511 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1512 self
._DynaPcdList
_[Index
].Phase
= PcdFromModule
.Phase
1513 self
._DynaPcdList
_[Index
].Type
= PcdFromModule
.Type
1514 for PcdFromModule
in self
._NonDynaPcdList
_:
1515 # If a PCD is not listed in the DSC file, but binary INF files used by
1516 # this platform all (that use this PCD) list the PCD in a [PatchPcds]
1517 # section, AND all source INF files used by this platform the build
1518 # that use the PCD list the PCD in either a [Pcds] or [PatchPcds]
1519 # section, then the tools must NOT add the PCD to the Platform's PCD
1520 # Database; the build must assign the access method for this PCD as
1521 # PcdsPatchableInModule.
1522 if PcdFromModule
not in self
._DynaPcdList
_:
1524 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1525 if PcdFromModule
.IsFromDsc
== False and \
1526 PcdFromModule
.Type
in TAB_PCDS_PATCHABLE_IN_MODULE
and \
1527 PcdFromModule
.IsFromBinaryInf
== True and \
1528 self
._DynaPcdList
_[Index
].IsFromBinaryInf
== False:
1529 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1530 self
._DynaPcdList
_.remove (self
._DynaPcdList
_[Index
])
1532 # print out error information and break the build, if error found
1533 if len(NoDatumTypePcdList
) > 0:
1534 NoDatumTypePcdListString
= "\n\t\t".join(NoDatumTypePcdList
)
1535 EdkLogger
.error("build", AUTOGEN_ERROR
, "PCD setting error",
1537 ExtraData
="\n\tPCD(s) without MaxDatumSize:\n\t\t%s\n"
1538 % NoDatumTypePcdListString
)
1539 self
._NonDynamicPcdList
= self
._NonDynaPcdList
_
1540 self
._DynamicPcdList
= self
._DynaPcdList
_
1542 # Sort dynamic PCD list to:
1543 # 1) If PCD's datum type is VOID* and value is unicode string which starts with L, the PCD item should
1544 # try to be put header of dynamicd List
1545 # 2) If PCD is HII type, the PCD item should be put after unicode type PCD
1547 # The reason of sorting is make sure the unicode string is in double-byte alignment in string table.
1549 UnicodePcdArray
= []
1553 VpdFile
= VpdInfoFile
.VpdInfoFile()
1554 NeedProcessVpdMapFile
= False
1556 for pcd
in self
.Platform
.Pcds
.keys():
1557 if pcd
not in self
._PlatformPcds
.keys():
1558 self
._PlatformPcds
[pcd
] = self
.Platform
.Pcds
[pcd
]
1560 for item
in self
._PlatformPcds
:
1561 if self
._PlatformPcds
[item
].DatumType
and self
._PlatformPcds
[item
].DatumType
not in [TAB_UINT8
, TAB_UINT16
, TAB_UINT32
, TAB_UINT64
, TAB_VOID
, "BOOLEAN"]:
1562 self
._PlatformPcds
[item
].DatumType
= "VOID*"
1564 if (self
.Workspace
.ArchList
[-1] == self
.Arch
):
1565 for Pcd
in self
._DynamicPcdList
:
1566 # just pick the a value to determine whether is unicode string type
1567 Sku
= Pcd
.SkuInfoList
[Pcd
.SkuInfoList
.keys()[0]]
1568 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1570 if Pcd
.DatumType
not in [TAB_UINT8
, TAB_UINT16
, TAB_UINT32
, TAB_UINT64
, TAB_VOID
, "BOOLEAN"]:
1571 Pcd
.DatumType
= "VOID*"
1573 PcdValue
= Sku
.DefaultValue
1574 if Pcd
.DatumType
== 'VOID*' and PcdValue
.startswith("L"):
1575 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
1576 UnicodePcdArray
.append(Pcd
)
1577 elif len(Sku
.VariableName
) > 0:
1578 # if found HII type PCD then insert to right of UnicodeIndex
1579 HiiPcdArray
.append(Pcd
)
1581 OtherPcdArray
.append(Pcd
)
1582 if Pcd
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
]:
1583 VpdPcdDict
[(Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
)] = Pcd
1585 PlatformPcds
= self
._PlatformPcds
.keys()
1588 # Add VPD type PCD into VpdFile and determine whether the VPD PCD need to be fixed up.
1590 for PcdKey
in PlatformPcds
:
1591 Pcd
= self
._PlatformPcds
[PcdKey
]
1592 if Pcd
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
] and \
1593 PcdKey
in VpdPcdDict
:
1594 Pcd
= VpdPcdDict
[PcdKey
]
1595 for (SkuName
,Sku
) in Pcd
.SkuInfoList
.items():
1596 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1597 PcdValue
= Sku
.DefaultValue
1599 PcdValue
= Pcd
.DefaultValue
1600 if Sku
.VpdOffset
!= '*':
1601 if PcdValue
.startswith("{"):
1603 elif PcdValue
.startswith("L"):
1608 VpdOffset
= int(Sku
.VpdOffset
)
1611 VpdOffset
= int(Sku
.VpdOffset
, 16)
1613 EdkLogger
.error("build", FORMAT_INVALID
, "Invalid offset value %s for PCD %s.%s." % (Sku
.VpdOffset
, Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
1614 if VpdOffset
% Alignment
!= 0:
1615 if PcdValue
.startswith("{"):
1616 EdkLogger
.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
), File
=self
.MetaFile
)
1618 EdkLogger
.error("build", FORMAT_INVALID
, 'The offset value of PCD %s.%s should be %s-byte aligned.' % (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
, Alignment
))
1619 VpdFile
.Add(Pcd
, Sku
.VpdOffset
)
1620 # if the offset of a VPD is *, then it need to be fixed up by third party tool.
1621 if not NeedProcessVpdMapFile
and Sku
.VpdOffset
== "*":
1622 NeedProcessVpdMapFile
= True
1623 if self
.Platform
.VpdToolGuid
== None or self
.Platform
.VpdToolGuid
== '':
1624 EdkLogger
.error("Build", FILE_NOT_FOUND
, \
1625 "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.")
1629 # Fix the PCDs define in VPD PCD section that never referenced by module.
1630 # An example is PCD for signature usage.
1632 for DscPcd
in PlatformPcds
:
1633 DscPcdEntry
= self
._PlatformPcds
[DscPcd
]
1634 if DscPcdEntry
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
]:
1635 if not (self
.Platform
.VpdToolGuid
== None or self
.Platform
.VpdToolGuid
== ''):
1637 for VpdPcd
in VpdFile
._VpdArray
.keys():
1638 # This PCD has been referenced by module
1639 if (VpdPcd
.TokenSpaceGuidCName
== DscPcdEntry
.TokenSpaceGuidCName
) and \
1640 (VpdPcd
.TokenCName
== DscPcdEntry
.TokenCName
):
1643 # Not found, it should be signature
1645 # just pick the a value to determine whether is unicode string type
1646 for (SkuName
,Sku
) in DscPcdEntry
.SkuInfoList
.items():
1647 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1649 # Need to iterate DEC pcd information to get the value & datumtype
1650 for eachDec
in self
.PackageList
:
1651 for DecPcd
in eachDec
.Pcds
:
1652 DecPcdEntry
= eachDec
.Pcds
[DecPcd
]
1653 if (DecPcdEntry
.TokenSpaceGuidCName
== DscPcdEntry
.TokenSpaceGuidCName
) and \
1654 (DecPcdEntry
.TokenCName
== DscPcdEntry
.TokenCName
):
1655 # Print warning message to let the developer make a determine.
1656 EdkLogger
.warn("build", "Unreferenced vpd pcd used!",
1657 File
=self
.MetaFile
, \
1658 ExtraData
= "PCD: %s.%s used in the DSC file %s is unreferenced." \
1659 %(DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
, self
.Platform
.MetaFile
.Path
))
1661 DscPcdEntry
.DatumType
= DecPcdEntry
.DatumType
1662 DscPcdEntry
.DefaultValue
= DecPcdEntry
.DefaultValue
1663 DscPcdEntry
.TokenValue
= DecPcdEntry
.TokenValue
1664 DscPcdEntry
.TokenSpaceGuidValue
= eachDec
.Guids
[DecPcdEntry
.TokenSpaceGuidCName
]
1665 # Only fix the value while no value provided in DSC file.
1666 if (Sku
.DefaultValue
== "" or Sku
.DefaultValue
==None):
1667 DscPcdEntry
.SkuInfoList
[DscPcdEntry
.SkuInfoList
.keys()[0]].DefaultValue
= DecPcdEntry
.DefaultValue
1669 if DscPcdEntry
not in self
._DynamicPcdList
:
1670 self
._DynamicPcdList
.append(DscPcdEntry
)
1671 # Sku = DscPcdEntry.SkuInfoList[DscPcdEntry.SkuInfoList.keys()[0]]
1672 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1673 PcdValue
= Sku
.DefaultValue
1675 PcdValue
= DscPcdEntry
.DefaultValue
1676 if Sku
.VpdOffset
!= '*':
1677 if PcdValue
.startswith("{"):
1679 elif PcdValue
.startswith("L"):
1684 VpdOffset
= int(Sku
.VpdOffset
)
1687 VpdOffset
= int(Sku
.VpdOffset
, 16)
1689 EdkLogger
.error("build", FORMAT_INVALID
, "Invalid offset value %s for PCD %s.%s." % (Sku
.VpdOffset
, DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
))
1690 if VpdOffset
% Alignment
!= 0:
1691 if PcdValue
.startswith("{"):
1692 EdkLogger
.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
), File
=self
.MetaFile
)
1694 EdkLogger
.error("build", FORMAT_INVALID
, 'The offset value of PCD %s.%s should be %s-byte aligned.' % (DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
, Alignment
))
1695 VpdFile
.Add(DscPcdEntry
, Sku
.VpdOffset
)
1696 if not NeedProcessVpdMapFile
and Sku
.VpdOffset
== "*":
1697 NeedProcessVpdMapFile
= True
1698 if DscPcdEntry
.DatumType
== 'VOID*' and PcdValue
.startswith("L"):
1699 UnicodePcdArray
.append(DscPcdEntry
)
1700 elif len(Sku
.VariableName
) > 0:
1701 HiiPcdArray
.append(DscPcdEntry
)
1703 OtherPcdArray
.append(DscPcdEntry
)
1705 # if the offset of a VPD is *, then it need to be fixed up by third party tool.
1709 if (self
.Platform
.FlashDefinition
== None or self
.Platform
.FlashDefinition
== '') and \
1710 VpdFile
.GetCount() != 0:
1711 EdkLogger
.error("build", ATTRIBUTE_NOT_AVAILABLE
,
1712 "Fail to get FLASH_DEFINITION definition in DSC file %s which is required when DSC contains VPD PCD." % str(self
.Platform
.MetaFile
))
1714 if VpdFile
.GetCount() != 0:
1715 FvPath
= os
.path
.join(self
.BuildDir
, "FV")
1716 if not os
.path
.exists(FvPath
):
1720 EdkLogger
.error("build", FILE_WRITE_FAILURE
, "Fail to create FV folder under %s" % self
.BuildDir
)
1722 VpdFilePath
= os
.path
.join(FvPath
, "%s.txt" % self
.Platform
.VpdToolGuid
)
1724 if VpdFile
.Write(VpdFilePath
):
1725 # retrieve BPDG tool's path from tool_def.txt according to VPD_TOOL_GUID defined in DSC file.
1727 for ToolDef
in self
.ToolDefinition
.values():
1728 if ToolDef
.has_key("GUID") and ToolDef
["GUID"] == self
.Platform
.VpdToolGuid
:
1729 if not ToolDef
.has_key("PATH"):
1730 EdkLogger
.error("build", ATTRIBUTE_NOT_AVAILABLE
, "PATH attribute was not provided for BPDG guid tool %s in tools_def.txt" % self
.Platform
.VpdToolGuid
)
1731 BPDGToolName
= ToolDef
["PATH"]
1733 # Call third party GUID BPDG tool.
1734 if BPDGToolName
!= None:
1735 VpdInfoFile
.CallExtenalBPDGTool(BPDGToolName
, VpdFilePath
)
1737 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.")
1739 # Process VPD map file generated by third party BPDG tool
1740 if NeedProcessVpdMapFile
:
1741 VpdMapFilePath
= os
.path
.join(self
.BuildDir
, "FV", "%s.map" % self
.Platform
.VpdToolGuid
)
1742 if os
.path
.exists(VpdMapFilePath
):
1743 VpdFile
.Read(VpdMapFilePath
)
1746 for Pcd
in self
._DynamicPcdList
:
1747 # just pick the a value to determine whether is unicode string type
1749 for (SkuName
,Sku
) in Pcd
.SkuInfoList
.items():
1750 if Sku
.VpdOffset
== "*":
1751 Sku
.VpdOffset
= VpdFile
.GetOffset(Pcd
)[i
].strip()
1754 EdkLogger
.error("build", FILE_READ_FAILURE
, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath
)
1756 # Delete the DynamicPcdList At the last time enter into this function
1757 del self
._DynamicPcdList
[:]
1758 self
._DynamicPcdList
.extend(UnicodePcdArray
)
1759 self
._DynamicPcdList
.extend(HiiPcdArray
)
1760 self
._DynamicPcdList
.extend(OtherPcdArray
)
1761 self
.AllPcdList
= self
._NonDynamicPcdList
+ self
._DynamicPcdList
1763 ## Return the platform build data object
1764 def _GetPlatform(self
):
1765 if self
._Platform
== None:
1766 self
._Platform
= self
.BuildDatabase
[self
.MetaFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1767 return self
._Platform
1769 ## Return platform name
1771 return self
.Platform
.PlatformName
1773 ## Return the meta file GUID
1775 return self
.Platform
.Guid
1777 ## Return the platform version
1778 def _GetVersion(self
):
1779 return self
.Platform
.Version
1781 ## Return the FDF file name
1782 def _GetFdfFile(self
):
1783 if self
._FdfFile
== None:
1784 if self
.Workspace
.FdfFile
!= "":
1785 self
._FdfFile
= mws
.join(self
.WorkspaceDir
, self
.Workspace
.FdfFile
)
1788 return self
._FdfFile
1790 ## Return the build output directory platform specifies
1791 def _GetOutputDir(self
):
1792 return self
.Platform
.OutputDirectory
1794 ## Return the directory to store all intermediate and final files built
1795 def _GetBuildDir(self
):
1796 if self
._BuildDir
== None:
1797 if os
.path
.isabs(self
.OutputDir
):
1798 self
._BuildDir
= path
.join(
1799 path
.abspath(self
.OutputDir
),
1800 self
.BuildTarget
+ "_" + self
.ToolChain
,
1803 self
._BuildDir
= path
.join(
1806 self
.BuildTarget
+ "_" + self
.ToolChain
,
1808 GlobalData
.gBuildDirectory
= self
._BuildDir
1809 return self
._BuildDir
1811 ## Return directory of platform makefile
1813 # @retval string Makefile directory
1815 def _GetMakeFileDir(self
):
1816 if self
._MakeFileDir
== None:
1817 self
._MakeFileDir
= path
.join(self
.BuildDir
, self
.Arch
)
1818 return self
._MakeFileDir
1820 ## Return build command string
1822 # @retval string Build command string
1824 def _GetBuildCommand(self
):
1825 if self
._BuildCommand
== None:
1826 self
._BuildCommand
= []
1827 if "MAKE" in self
.ToolDefinition
and "PATH" in self
.ToolDefinition
["MAKE"]:
1828 self
._BuildCommand
+= SplitOption(self
.ToolDefinition
["MAKE"]["PATH"])
1829 if "FLAGS" in self
.ToolDefinition
["MAKE"]:
1830 NewOption
= self
.ToolDefinition
["MAKE"]["FLAGS"].strip()
1832 self
._BuildCommand
+= SplitOption(NewOption
)
1833 return self
._BuildCommand
1835 ## Get tool chain definition
1837 # Get each tool defition for given tool chain from tools_def.txt and platform
1839 def _GetToolDefinition(self
):
1840 if self
._ToolDefinitions
== None:
1841 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDictionary
1842 if TAB_TOD_DEFINES_COMMAND_TYPE
not in self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
:
1843 EdkLogger
.error('build', RESOURCE_NOT_AVAILABLE
, "No tools found in configuration",
1844 ExtraData
="[%s]" % self
.MetaFile
)
1845 self
._ToolDefinitions
= {}
1847 for Def
in ToolDefinition
:
1848 Target
, Tag
, Arch
, Tool
, Attr
= Def
.split("_")
1849 if Target
!= self
.BuildTarget
or Tag
!= self
.ToolChain
or Arch
!= self
.Arch
:
1852 Value
= ToolDefinition
[Def
]
1853 # don't record the DLL
1855 DllPathList
.add(Value
)
1858 if Tool
not in self
._ToolDefinitions
:
1859 self
._ToolDefinitions
[Tool
] = {}
1860 self
._ToolDefinitions
[Tool
][Attr
] = Value
1864 if GlobalData
.gOptions
.SilentMode
and "MAKE" in self
._ToolDefinitions
:
1865 if "FLAGS" not in self
._ToolDefinitions
["MAKE"]:
1866 self
._ToolDefinitions
["MAKE"]["FLAGS"] = ""
1867 self
._ToolDefinitions
["MAKE"]["FLAGS"] += " -s"
1869 for Tool
in self
._ToolDefinitions
:
1870 for Attr
in self
._ToolDefinitions
[Tool
]:
1871 Value
= self
._ToolDefinitions
[Tool
][Attr
]
1872 if Tool
in self
.BuildOption
and Attr
in self
.BuildOption
[Tool
]:
1873 # check if override is indicated
1874 if self
.BuildOption
[Tool
][Attr
].startswith('='):
1875 Value
= self
.BuildOption
[Tool
][Attr
][1:]
1878 Value
+= " " + self
.BuildOption
[Tool
][Attr
]
1880 Value
= self
.BuildOption
[Tool
][Attr
]
1883 # Don't put MAKE definition in the file
1887 ToolsDef
+= "%s = %s\n" % (Tool
, Value
)
1889 # Don't put MAKE definition in the file
1894 ToolsDef
+= "%s_%s = %s\n" % (Tool
, Attr
, Value
)
1897 SaveFileOnChange(self
.ToolDefinitionFile
, ToolsDef
)
1898 for DllPath
in DllPathList
:
1899 os
.environ
["PATH"] = DllPath
+ os
.pathsep
+ os
.environ
["PATH"]
1900 os
.environ
["MAKE_FLAGS"] = MakeFlags
1902 return self
._ToolDefinitions
1904 ## Return the paths of tools
1905 def _GetToolDefFile(self
):
1906 if self
._ToolDefFile
== None:
1907 self
._ToolDefFile
= os
.path
.join(self
.MakeFileDir
, "TOOLS_DEF." + self
.Arch
)
1908 return self
._ToolDefFile
1910 ## Retrieve the toolchain family of given toolchain tag. Default to 'MSFT'.
1911 def _GetToolChainFamily(self
):
1912 if self
._ToolChainFamily
== None:
1913 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
1914 if TAB_TOD_DEFINES_FAMILY
not in ToolDefinition \
1915 or self
.ToolChain
not in ToolDefinition
[TAB_TOD_DEFINES_FAMILY
] \
1916 or not ToolDefinition
[TAB_TOD_DEFINES_FAMILY
][self
.ToolChain
]:
1917 EdkLogger
.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
1919 self
._ToolChainFamily
= "MSFT"
1921 self
._ToolChainFamily
= ToolDefinition
[TAB_TOD_DEFINES_FAMILY
][self
.ToolChain
]
1922 return self
._ToolChainFamily
1924 def _GetBuildRuleFamily(self
):
1925 if self
._BuildRuleFamily
== None:
1926 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
1927 if TAB_TOD_DEFINES_BUILDRULEFAMILY
not in ToolDefinition \
1928 or self
.ToolChain
not in ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
] \
1929 or not ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
][self
.ToolChain
]:
1930 EdkLogger
.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
1932 self
._BuildRuleFamily
= "MSFT"
1934 self
._BuildRuleFamily
= ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
][self
.ToolChain
]
1935 return self
._BuildRuleFamily
1937 ## Return the build options specific for all modules in this platform
1938 def _GetBuildOptions(self
):
1939 if self
._BuildOption
== None:
1940 self
._BuildOption
= self
._ExpandBuildOption
(self
.Platform
.BuildOptions
)
1941 return self
._BuildOption
1943 ## Return the build options specific for EDK modules in this platform
1944 def _GetEdkBuildOptions(self
):
1945 if self
._EdkBuildOption
== None:
1946 self
._EdkBuildOption
= self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, EDK_NAME
)
1947 return self
._EdkBuildOption
1949 ## Return the build options specific for EDKII modules in this platform
1950 def _GetEdkIIBuildOptions(self
):
1951 if self
._EdkIIBuildOption
== None:
1952 self
._EdkIIBuildOption
= self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, EDKII_NAME
)
1953 return self
._EdkIIBuildOption
1955 ## Parse build_rule.txt in Conf Directory.
1957 # @retval BuildRule object
1959 def _GetBuildRule(self
):
1960 if self
._BuildRule
== None:
1961 BuildRuleFile
= None
1962 if TAB_TAT_DEFINES_BUILD_RULE_CONF
in self
.Workspace
.TargetTxt
.TargetTxtDictionary
:
1963 BuildRuleFile
= self
.Workspace
.TargetTxt
.TargetTxtDictionary
[TAB_TAT_DEFINES_BUILD_RULE_CONF
]
1964 if BuildRuleFile
in [None, '']:
1965 BuildRuleFile
= gDefaultBuildRuleFile
1966 self
._BuildRule
= BuildRule(BuildRuleFile
)
1967 if self
._BuildRule
._FileVersion
== "":
1968 self
._BuildRule
._FileVersion
= AutoGenReqBuildRuleVerNum
1970 if self
._BuildRule
._FileVersion
< AutoGenReqBuildRuleVerNum
:
1971 # If Build Rule's version is less than the version number required by the tools, halting the build.
1972 EdkLogger
.error("build", AUTOGEN_ERROR
,
1973 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])"\
1974 % (self
._BuildRule
._FileVersion
, AutoGenReqBuildRuleVerNum
))
1976 return self
._BuildRule
1978 ## Summarize the packages used by modules in this platform
1979 def _GetPackageList(self
):
1980 if self
._PackageList
== None:
1981 self
._PackageList
= set()
1982 for La
in self
.LibraryAutoGenList
:
1983 self
._PackageList
.update(La
.DependentPackageList
)
1984 for Ma
in self
.ModuleAutoGenList
:
1985 self
._PackageList
.update(Ma
.DependentPackageList
)
1986 #Collect package set information from INF of FDF
1988 for ModuleFile
in self
._AsBuildModuleList
:
1989 if ModuleFile
in self
.Platform
.Modules
:
1991 ModuleData
= self
.BuildDatabase
[ModuleFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1992 PkgSet
.update(ModuleData
.Packages
)
1993 self
._PackageList
= list(self
._PackageList
) + list (PkgSet
)
1994 return self
._PackageList
1996 def _GetNonDynamicPcdDict(self
):
1997 if self
._NonDynamicPcdDict
:
1998 return self
._NonDynamicPcdDict
1999 for Pcd
in self
.NonDynamicPcdList
:
2000 self
._NonDynamicPcdDict
[(Pcd
.TokenCName
,Pcd
.TokenSpaceGuidCName
)] = Pcd
2001 return self
._NonDynamicPcdDict
2003 ## Get list of non-dynamic PCDs
2004 def _GetNonDynamicPcdList(self
):
2005 if self
._NonDynamicPcdList
== None:
2006 self
.CollectPlatformDynamicPcds()
2007 return self
._NonDynamicPcdList
2009 ## Get list of dynamic PCDs
2010 def _GetDynamicPcdList(self
):
2011 if self
._DynamicPcdList
== None:
2012 self
.CollectPlatformDynamicPcds()
2013 return self
._DynamicPcdList
2015 ## Generate Token Number for all PCD
2016 def _GetPcdTokenNumbers(self
):
2017 if self
._PcdTokenNumber
== None:
2018 self
._PcdTokenNumber
= sdict()
2021 # Make the Dynamic and DynamicEx PCD use within different TokenNumber area.
2025 # TokenNumber 0 ~ 10
2027 # TokeNumber 11 ~ 20
2029 for Pcd
in self
.DynamicPcdList
:
2030 if Pcd
.Phase
== "PEI":
2031 if Pcd
.Type
in ["Dynamic", "DynamicDefault", "DynamicVpd", "DynamicHii"]:
2032 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
2033 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2036 for Pcd
in self
.DynamicPcdList
:
2037 if Pcd
.Phase
== "PEI":
2038 if Pcd
.Type
in ["DynamicEx", "DynamicExDefault", "DynamicExVpd", "DynamicExHii"]:
2039 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
2040 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2043 for Pcd
in self
.DynamicPcdList
:
2044 if Pcd
.Phase
== "DXE":
2045 if Pcd
.Type
in ["Dynamic", "DynamicDefault", "DynamicVpd", "DynamicHii"]:
2046 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
2047 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2050 for Pcd
in self
.DynamicPcdList
:
2051 if Pcd
.Phase
== "DXE":
2052 if Pcd
.Type
in ["DynamicEx", "DynamicExDefault", "DynamicExVpd", "DynamicExHii"]:
2053 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
2054 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2057 for Pcd
in self
.NonDynamicPcdList
:
2058 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2060 return self
._PcdTokenNumber
2062 ## Summarize ModuleAutoGen objects of all modules/libraries to be built for this platform
2063 def _GetAutoGenObjectList(self
):
2064 self
._ModuleAutoGenList
= []
2065 self
._LibraryAutoGenList
= []
2066 for ModuleFile
in self
.Platform
.Modules
:
2075 if Ma
not in self
._ModuleAutoGenList
:
2076 self
._ModuleAutoGenList
.append(Ma
)
2077 for La
in Ma
.LibraryAutoGenList
:
2078 if La
not in self
._LibraryAutoGenList
:
2079 self
._LibraryAutoGenList
.append(La
)
2080 if Ma
not in La
._ReferenceModules
:
2081 La
._ReferenceModules
.append(Ma
)
2083 ## Summarize ModuleAutoGen objects of all modules to be built for this platform
2084 def _GetModuleAutoGenList(self
):
2085 if self
._ModuleAutoGenList
== None:
2086 self
._GetAutoGenObjectList
()
2087 return self
._ModuleAutoGenList
2089 ## Summarize ModuleAutoGen objects of all libraries to be built for this platform
2090 def _GetLibraryAutoGenList(self
):
2091 if self
._LibraryAutoGenList
== None:
2092 self
._GetAutoGenObjectList
()
2093 return self
._LibraryAutoGenList
2095 ## Test if a module is supported by the platform
2097 # An error will be raised directly if the module or its arch is not supported
2098 # by the platform or current configuration
2100 def ValidModule(self
, Module
):
2101 return Module
in self
.Platform
.Modules
or Module
in self
.Platform
.LibraryInstances \
2102 or Module
in self
._AsBuildModuleList
2104 ## Resolve the library classes in a module to library instances
2106 # This method will not only resolve library classes but also sort the library
2107 # instances according to the dependency-ship.
2109 # @param Module The module from which the library classes will be resolved
2111 # @retval library_list List of library instances sorted
2113 def ApplyLibraryInstance(self
, Module
):
2114 # Cover the case that the binary INF file is list in the FDF file but not DSC file, return empty list directly
2115 if str(Module
) not in self
.Platform
.Modules
:
2118 ModuleType
= Module
.ModuleType
2120 # for overridding library instances with module specific setting
2121 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
2123 # add forced library instances (specified under LibraryClasses sections)
2125 # If a module has a MODULE_TYPE of USER_DEFINED,
2126 # do not link in NULL library class instances from the global [LibraryClasses.*] sections.
2128 if Module
.ModuleType
!= SUP_MODULE_USER_DEFINED
:
2129 for LibraryClass
in self
.Platform
.LibraryClasses
.GetKeys():
2130 if LibraryClass
.startswith("NULL") and self
.Platform
.LibraryClasses
[LibraryClass
, Module
.ModuleType
]:
2131 Module
.LibraryClasses
[LibraryClass
] = self
.Platform
.LibraryClasses
[LibraryClass
, Module
.ModuleType
]
2133 # add forced library instances (specified in module overrides)
2134 for LibraryClass
in PlatformModule
.LibraryClasses
:
2135 if LibraryClass
.startswith("NULL"):
2136 Module
.LibraryClasses
[LibraryClass
] = PlatformModule
.LibraryClasses
[LibraryClass
]
2139 LibraryConsumerList
= [Module
]
2141 ConsumedByList
= sdict()
2142 LibraryInstance
= sdict()
2144 EdkLogger
.verbose("")
2145 EdkLogger
.verbose("Library instances of module [%s] [%s]:" % (str(Module
), self
.Arch
))
2146 while len(LibraryConsumerList
) > 0:
2147 M
= LibraryConsumerList
.pop()
2148 for LibraryClassName
in M
.LibraryClasses
:
2149 if LibraryClassName
not in LibraryInstance
:
2150 # override library instance for this module
2151 if LibraryClassName
in PlatformModule
.LibraryClasses
:
2152 LibraryPath
= PlatformModule
.LibraryClasses
[LibraryClassName
]
2154 LibraryPath
= self
.Platform
.LibraryClasses
[LibraryClassName
, ModuleType
]
2155 if LibraryPath
== None or LibraryPath
== "":
2156 LibraryPath
= M
.LibraryClasses
[LibraryClassName
]
2157 if LibraryPath
== None or LibraryPath
== "":
2158 EdkLogger
.error("build", RESOURCE_NOT_AVAILABLE
,
2159 "Instance of library class [%s] is not found" % LibraryClassName
,
2161 ExtraData
="in [%s] [%s]\n\tconsumed by module [%s]" % (str(M
), self
.Arch
, str(Module
)))
2163 LibraryModule
= self
.BuildDatabase
[LibraryPath
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
2164 # for those forced library instance (NULL library), add a fake library class
2165 if LibraryClassName
.startswith("NULL"):
2166 LibraryModule
.LibraryClass
.append(LibraryClassObject(LibraryClassName
, [ModuleType
]))
2167 elif LibraryModule
.LibraryClass
== None \
2168 or len(LibraryModule
.LibraryClass
) == 0 \
2169 or (ModuleType
!= 'USER_DEFINED'
2170 and ModuleType
not in LibraryModule
.LibraryClass
[0].SupModList
):
2171 # only USER_DEFINED can link against any library instance despite of its SupModList
2172 EdkLogger
.error("build", OPTION_MISSING
,
2173 "Module type [%s] is not supported by library instance [%s]" \
2174 % (ModuleType
, LibraryPath
), File
=self
.MetaFile
,
2175 ExtraData
="consumed by [%s]" % str(Module
))
2177 LibraryInstance
[LibraryClassName
] = LibraryModule
2178 LibraryConsumerList
.append(LibraryModule
)
2179 EdkLogger
.verbose("\t" + str(LibraryClassName
) + " : " + str(LibraryModule
))
2181 LibraryModule
= LibraryInstance
[LibraryClassName
]
2183 if LibraryModule
== None:
2186 if LibraryModule
.ConstructorList
!= [] and LibraryModule
not in Constructor
:
2187 Constructor
.append(LibraryModule
)
2189 if LibraryModule
not in ConsumedByList
:
2190 ConsumedByList
[LibraryModule
] = []
2191 # don't add current module itself to consumer list
2193 if M
in ConsumedByList
[LibraryModule
]:
2195 ConsumedByList
[LibraryModule
].append(M
)
2197 # Initialize the sorted output list to the empty set
2199 SortedLibraryList
= []
2201 # Q <- Set of all nodes with no incoming edges
2203 LibraryList
= [] #LibraryInstance.values()
2205 for LibraryClassName
in LibraryInstance
:
2206 M
= LibraryInstance
[LibraryClassName
]
2207 LibraryList
.append(M
)
2208 if ConsumedByList
[M
] == []:
2212 # start the DAG algorithm
2216 while Q
== [] and EdgeRemoved
:
2218 # for each node Item with a Constructor
2219 for Item
in LibraryList
:
2220 if Item
not in Constructor
:
2222 # for each Node without a constructor with an edge e from Item to Node
2223 for Node
in ConsumedByList
[Item
]:
2224 if Node
in Constructor
:
2226 # remove edge e from the graph if Node has no constructor
2227 ConsumedByList
[Item
].remove(Node
)
2229 if ConsumedByList
[Item
] == []:
2230 # insert Item into Q
2235 # DAG is done if there's no more incoming edge for all nodes
2239 # remove node from Q
2242 SortedLibraryList
.append(Node
)
2244 # for each node Item with an edge e from Node to Item do
2245 for Item
in LibraryList
:
2246 if Node
not in ConsumedByList
[Item
]:
2248 # remove edge e from the graph
2249 ConsumedByList
[Item
].remove(Node
)
2251 if ConsumedByList
[Item
] != []:
2253 # insert Item into Q, if Item has no other incoming edges
2257 # if any remaining node Item in the graph has a constructor and an incoming edge, then the graph has a cycle
2259 for Item
in LibraryList
:
2260 if ConsumedByList
[Item
] != [] and Item
in Constructor
and len(Constructor
) > 1:
2261 ErrorMessage
= "\tconsumed by " + "\n\tconsumed by ".join([str(L
) for L
in ConsumedByList
[Item
]])
2262 EdkLogger
.error("build", BUILD_ERROR
, 'Library [%s] with constructors has a cycle' % str(Item
),
2263 ExtraData
=ErrorMessage
, File
=self
.MetaFile
)
2264 if Item
not in SortedLibraryList
:
2265 SortedLibraryList
.append(Item
)
2268 # Build the list of constructor and destructir names
2269 # The DAG Topo sort produces the destructor order, so the list of constructors must generated in the reverse order
2271 SortedLibraryList
.reverse()
2272 return SortedLibraryList
2275 ## Override PCD setting (type, value, ...)
2277 # @param ToPcd The PCD to be overrided
2278 # @param FromPcd The PCD overrideing from
2280 def _OverridePcd(self
, ToPcd
, FromPcd
, Module
=""):
2282 # in case there's PCDs coming from FDF file, which have no type given.
2283 # at this point, ToPcd.Type has the type found from dependent
2286 TokenCName
= ToPcd
.TokenCName
2287 for PcdItem
in GlobalData
.MixedPcd
:
2288 if (ToPcd
.TokenCName
, ToPcd
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
2289 TokenCName
= PcdItem
[0]
2292 if GlobalData
.BuildOptionPcd
:
2293 for pcd
in GlobalData
.BuildOptionPcd
:
2294 if (FromPcd
.TokenSpaceGuidCName
, FromPcd
.TokenCName
) == (pcd
[0], pcd
[1]):
2295 FromPcd
.DefaultValue
= pcd
[2]
2297 if ToPcd
.Pending
and FromPcd
.Type
not in [None, '']:
2298 ToPcd
.Type
= FromPcd
.Type
2299 elif (ToPcd
.Type
not in [None, '']) and (FromPcd
.Type
not in [None, ''])\
2300 and (ToPcd
.Type
!= FromPcd
.Type
) and (ToPcd
.Type
in FromPcd
.Type
):
2301 if ToPcd
.Type
.strip() == "DynamicEx":
2302 ToPcd
.Type
= FromPcd
.Type
2303 elif ToPcd
.Type
not in [None, ''] and FromPcd
.Type
not in [None, ''] \
2304 and ToPcd
.Type
!= FromPcd
.Type
:
2305 EdkLogger
.error("build", OPTION_CONFLICT
, "Mismatched PCD type",
2306 ExtraData
="%s.%s is defined as [%s] in module %s, but as [%s] in platform."\
2307 % (ToPcd
.TokenSpaceGuidCName
, TokenCName
,
2308 ToPcd
.Type
, Module
, FromPcd
.Type
),
2311 if FromPcd
.MaxDatumSize
not in [None, '']:
2312 ToPcd
.MaxDatumSize
= FromPcd
.MaxDatumSize
2313 if FromPcd
.DefaultValue
not in [None, '']:
2314 ToPcd
.DefaultValue
= FromPcd
.DefaultValue
2315 if FromPcd
.TokenValue
not in [None, '']:
2316 ToPcd
.TokenValue
= FromPcd
.TokenValue
2317 if FromPcd
.MaxDatumSize
not in [None, '']:
2318 ToPcd
.MaxDatumSize
= FromPcd
.MaxDatumSize
2319 if FromPcd
.DatumType
not in [None, '']:
2320 ToPcd
.DatumType
= FromPcd
.DatumType
2321 if FromPcd
.SkuInfoList
not in [None, '', []]:
2322 ToPcd
.SkuInfoList
= FromPcd
.SkuInfoList
2324 # check the validation of datum
2325 IsValid
, Cause
= CheckPcdDatum(ToPcd
.DatumType
, ToPcd
.DefaultValue
)
2327 EdkLogger
.error('build', FORMAT_INVALID
, Cause
, File
=self
.MetaFile
,
2328 ExtraData
="%s.%s" % (ToPcd
.TokenSpaceGuidCName
, TokenCName
))
2329 ToPcd
.validateranges
= FromPcd
.validateranges
2330 ToPcd
.validlists
= FromPcd
.validlists
2331 ToPcd
.expressions
= FromPcd
.expressions
2333 if ToPcd
.DatumType
== "VOID*" and ToPcd
.MaxDatumSize
in ['', None]:
2334 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "No MaxDatumSize specified for PCD %s.%s" \
2335 % (ToPcd
.TokenSpaceGuidCName
, TokenCName
))
2336 Value
= ToPcd
.DefaultValue
2337 if Value
in [None, '']:
2338 ToPcd
.MaxDatumSize
= '1'
2339 elif Value
[0] == 'L':
2340 ToPcd
.MaxDatumSize
= str((len(Value
) - 2) * 2)
2341 elif Value
[0] == '{':
2342 ToPcd
.MaxDatumSize
= str(len(Value
.split(',')))
2344 ToPcd
.MaxDatumSize
= str(len(Value
) - 1)
2346 # apply default SKU for dynamic PCDS if specified one is not available
2347 if (ToPcd
.Type
in PCD_DYNAMIC_TYPE_LIST
or ToPcd
.Type
in PCD_DYNAMIC_EX_TYPE_LIST
) \
2348 and ToPcd
.SkuInfoList
in [None, {}, '']:
2349 if self
.Platform
.SkuName
in self
.Platform
.SkuIds
:
2350 SkuName
= self
.Platform
.SkuName
2353 ToPcd
.SkuInfoList
= {
2354 SkuName
: SkuInfoClass(SkuName
, self
.Platform
.SkuIds
[SkuName
], '', '', '', '', '', ToPcd
.DefaultValue
)
2357 ## Apply PCD setting defined platform to a module
2359 # @param Module The module from which the PCD setting will be overrided
2361 # @retval PCD_list The list PCDs with settings from platform
2363 def ApplyPcdSetting(self
, Module
, Pcds
):
2364 # for each PCD in module
2365 for Name
, Guid
in Pcds
:
2366 PcdInModule
= Pcds
[Name
, Guid
]
2367 # find out the PCD setting in platform
2368 if (Name
, Guid
) in self
.Platform
.Pcds
:
2369 PcdInPlatform
= self
.Platform
.Pcds
[Name
, Guid
]
2371 PcdInPlatform
= None
2372 # then override the settings if any
2373 self
._OverridePcd
(PcdInModule
, PcdInPlatform
, Module
)
2374 # resolve the VariableGuid value
2375 for SkuId
in PcdInModule
.SkuInfoList
:
2376 Sku
= PcdInModule
.SkuInfoList
[SkuId
]
2377 if Sku
.VariableGuid
== '': continue
2378 Sku
.VariableGuidValue
= GuidValue(Sku
.VariableGuid
, self
.PackageList
, self
.MetaFile
.Path
)
2379 if Sku
.VariableGuidValue
== None:
2380 PackageList
= "\n\t".join([str(P
) for P
in self
.PackageList
])
2383 RESOURCE_NOT_AVAILABLE
,
2384 "Value of GUID [%s] is not found in" % Sku
.VariableGuid
,
2385 ExtraData
=PackageList
+ "\n\t(used with %s.%s from module %s)" \
2386 % (Guid
, Name
, str(Module
)),
2390 # override PCD settings with module specific setting
2391 if Module
in self
.Platform
.Modules
:
2392 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
2393 for Key
in PlatformModule
.Pcds
:
2398 elif Key
in GlobalData
.MixedPcd
:
2399 for PcdItem
in GlobalData
.MixedPcd
[Key
]:
2401 ToPcd
= Pcds
[PcdItem
]
2405 self
._OverridePcd
(ToPcd
, PlatformModule
.Pcds
[Key
], Module
)
2406 return Pcds
.values()
2408 ## Resolve library names to library modules
2410 # (for Edk.x modules)
2412 # @param Module The module from which the library names will be resolved
2414 # @retval library_list The list of library modules
2416 def ResolveLibraryReference(self
, Module
):
2417 EdkLogger
.verbose("")
2418 EdkLogger
.verbose("Library instances of module [%s] [%s]:" % (str(Module
), self
.Arch
))
2419 LibraryConsumerList
= [Module
]
2421 # "CompilerStub" is a must for Edk modules
2422 if Module
.Libraries
:
2423 Module
.Libraries
.append("CompilerStub")
2425 while len(LibraryConsumerList
) > 0:
2426 M
= LibraryConsumerList
.pop()
2427 for LibraryName
in M
.Libraries
:
2428 Library
= self
.Platform
.LibraryClasses
[LibraryName
, ':dummy:']
2430 for Key
in self
.Platform
.LibraryClasses
.data
.keys():
2431 if LibraryName
.upper() == Key
.upper():
2432 Library
= self
.Platform
.LibraryClasses
[Key
, ':dummy:']
2435 EdkLogger
.warn("build", "Library [%s] is not found" % LibraryName
, File
=str(M
),
2436 ExtraData
="\t%s [%s]" % (str(Module
), self
.Arch
))
2439 if Library
not in LibraryList
:
2440 LibraryList
.append(Library
)
2441 LibraryConsumerList
.append(Library
)
2442 EdkLogger
.verbose("\t" + LibraryName
+ " : " + str(Library
) + ' ' + str(type(Library
)))
2445 ## Calculate the priority value of the build option
2447 # @param Key Build option definition contain: TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
2449 # @retval Value Priority value based on the priority list.
2451 def CalculatePriorityValue(self
, Key
):
2452 Target
, ToolChain
, Arch
, CommandType
, Attr
= Key
.split('_')
2453 PriorityValue
= 0x11111
2455 PriorityValue
&= 0x01111
2456 if ToolChain
== "*":
2457 PriorityValue
&= 0x10111
2459 PriorityValue
&= 0x11011
2460 if CommandType
== "*":
2461 PriorityValue
&= 0x11101
2463 PriorityValue
&= 0x11110
2465 return self
.PrioList
["0x%0.5x" % PriorityValue
]
2468 ## Expand * in build option key
2470 # @param Options Options to be expanded
2472 # @retval options Options expanded
2474 def _ExpandBuildOption(self
, Options
, ModuleStyle
=None):
2481 # Construct a list contain the build options which need override.
2485 # Key[0] -- tool family
2486 # Key[1] -- TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
2488 if (Key
[0] == self
.BuildRuleFamily
and
2489 (ModuleStyle
== None or len(Key
) < 3 or (len(Key
) > 2 and Key
[2] == ModuleStyle
))):
2490 Target
, ToolChain
, Arch
, CommandType
, Attr
= Key
[1].split('_')
2491 if Target
== self
.BuildTarget
or Target
== "*":
2492 if ToolChain
== self
.ToolChain
or ToolChain
== "*":
2493 if Arch
== self
.Arch
or Arch
== "*":
2494 if Options
[Key
].startswith("="):
2495 if OverrideList
.get(Key
[1]) != None:
2496 OverrideList
.pop(Key
[1])
2497 OverrideList
[Key
[1]] = Options
[Key
]
2500 # Use the highest priority value.
2502 if (len(OverrideList
) >= 2):
2503 KeyList
= OverrideList
.keys()
2504 for Index
in range(len(KeyList
)):
2505 NowKey
= KeyList
[Index
]
2506 Target1
, ToolChain1
, Arch1
, CommandType1
, Attr1
= NowKey
.split("_")
2507 for Index1
in range(len(KeyList
) - Index
- 1):
2508 NextKey
= KeyList
[Index1
+ Index
+ 1]
2510 # Compare two Key, if one is included by another, choose the higher priority one
2512 Target2
, ToolChain2
, Arch2
, CommandType2
, Attr2
= NextKey
.split("_")
2513 if Target1
== Target2
or Target1
== "*" or Target2
== "*":
2514 if ToolChain1
== ToolChain2
or ToolChain1
== "*" or ToolChain2
== "*":
2515 if Arch1
== Arch2
or Arch1
== "*" or Arch2
== "*":
2516 if CommandType1
== CommandType2
or CommandType1
== "*" or CommandType2
== "*":
2517 if Attr1
== Attr2
or Attr1
== "*" or Attr2
== "*":
2518 if self
.CalculatePriorityValue(NowKey
) > self
.CalculatePriorityValue(NextKey
):
2519 if Options
.get((self
.BuildRuleFamily
, NextKey
)) != None:
2520 Options
.pop((self
.BuildRuleFamily
, NextKey
))
2522 if Options
.get((self
.BuildRuleFamily
, NowKey
)) != None:
2523 Options
.pop((self
.BuildRuleFamily
, NowKey
))
2526 if ModuleStyle
!= None and len (Key
) > 2:
2527 # Check Module style is EDK or EDKII.
2528 # Only append build option for the matched style module.
2529 if ModuleStyle
== EDK_NAME
and Key
[2] != EDK_NAME
:
2531 elif ModuleStyle
== EDKII_NAME
and Key
[2] != EDKII_NAME
:
2534 Target
, Tag
, Arch
, Tool
, Attr
= Key
[1].split("_")
2535 # if tool chain family doesn't match, skip it
2536 if Tool
in self
.ToolDefinition
and Family
!= "":
2537 FamilyIsNull
= False
2538 if self
.ToolDefinition
[Tool
].get(TAB_TOD_DEFINES_BUILDRULEFAMILY
, "") != "":
2539 if Family
!= self
.ToolDefinition
[Tool
][TAB_TOD_DEFINES_BUILDRULEFAMILY
]:
2541 elif Family
!= self
.ToolDefinition
[Tool
][TAB_TOD_DEFINES_FAMILY
]:
2544 # expand any wildcard
2545 if Target
== "*" or Target
== self
.BuildTarget
:
2546 if Tag
== "*" or Tag
== self
.ToolChain
:
2547 if Arch
== "*" or Arch
== self
.Arch
:
2548 if Tool
not in BuildOptions
:
2549 BuildOptions
[Tool
] = {}
2550 if Attr
!= "FLAGS" or Attr
not in BuildOptions
[Tool
] or Options
[Key
].startswith('='):
2551 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2553 # append options for the same tool except PATH
2555 BuildOptions
[Tool
][Attr
] += " " + Options
[Key
]
2557 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2558 # Build Option Family has been checked, which need't to be checked again for family.
2559 if FamilyMatch
or FamilyIsNull
:
2563 if ModuleStyle
!= None and len (Key
) > 2:
2564 # Check Module style is EDK or EDKII.
2565 # Only append build option for the matched style module.
2566 if ModuleStyle
== EDK_NAME
and Key
[2] != EDK_NAME
:
2568 elif ModuleStyle
== EDKII_NAME
and Key
[2] != EDKII_NAME
:
2571 Target
, Tag
, Arch
, Tool
, Attr
= Key
[1].split("_")
2572 # if tool chain family doesn't match, skip it
2573 if Tool
not in self
.ToolDefinition
or Family
== "":
2575 # option has been added before
2576 if Family
!= self
.ToolDefinition
[Tool
][TAB_TOD_DEFINES_FAMILY
]:
2579 # expand any wildcard
2580 if Target
== "*" or Target
== self
.BuildTarget
:
2581 if Tag
== "*" or Tag
== self
.ToolChain
:
2582 if Arch
== "*" or Arch
== self
.Arch
:
2583 if Tool
not in BuildOptions
:
2584 BuildOptions
[Tool
] = {}
2585 if Attr
!= "FLAGS" or Attr
not in BuildOptions
[Tool
] or Options
[Key
].startswith('='):
2586 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2588 # append options for the same tool except PATH
2590 BuildOptions
[Tool
][Attr
] += " " + Options
[Key
]
2592 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2595 ## Append build options in platform to a module
2597 # @param Module The module to which the build options will be appened
2599 # @retval options The options appended with build options in platform
2601 def ApplyBuildOption(self
, Module
):
2602 # Get the different options for the different style module
2603 if Module
.AutoGenVersion
< 0x00010005:
2604 PlatformOptions
= self
.EdkBuildOption
2605 ModuleTypeOptions
= self
.Platform
.GetBuildOptionsByModuleType(EDK_NAME
, Module
.ModuleType
)
2607 PlatformOptions
= self
.EdkIIBuildOption
2608 ModuleTypeOptions
= self
.Platform
.GetBuildOptionsByModuleType(EDKII_NAME
, Module
.ModuleType
)
2609 ModuleTypeOptions
= self
._ExpandBuildOption
(ModuleTypeOptions
)
2610 ModuleOptions
= self
._ExpandBuildOption
(Module
.BuildOptions
)
2611 if Module
in self
.Platform
.Modules
:
2612 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
2613 PlatformModuleOptions
= self
._ExpandBuildOption
(PlatformModule
.BuildOptions
)
2615 PlatformModuleOptions
= {}
2617 BuildRuleOrder
= None
2618 for Options
in [self
.ToolDefinition
, ModuleOptions
, PlatformOptions
, ModuleTypeOptions
, PlatformModuleOptions
]:
2619 for Tool
in Options
:
2620 for Attr
in Options
[Tool
]:
2621 if Attr
== TAB_TOD_DEFINES_BUILDRULEORDER
:
2622 BuildRuleOrder
= Options
[Tool
][Attr
]
2624 AllTools
= set(ModuleOptions
.keys() + PlatformOptions
.keys() +
2625 PlatformModuleOptions
.keys() + ModuleTypeOptions
.keys() +
2626 self
.ToolDefinition
.keys())
2628 for Tool
in AllTools
:
2629 if Tool
not in BuildOptions
:
2630 BuildOptions
[Tool
] = {}
2632 for Options
in [self
.ToolDefinition
, ModuleOptions
, PlatformOptions
, ModuleTypeOptions
, PlatformModuleOptions
]:
2633 if Tool
not in Options
:
2635 for Attr
in Options
[Tool
]:
2636 Value
= Options
[Tool
][Attr
]
2638 # Do not generate it in Makefile
2640 if Attr
== TAB_TOD_DEFINES_BUILDRULEORDER
:
2642 if Attr
not in BuildOptions
[Tool
]:
2643 BuildOptions
[Tool
][Attr
] = ""
2644 # check if override is indicated
2645 if Value
.startswith('='):
2646 ToolPath
= Value
[1:]
2647 ToolPath
= mws
.handleWsMacro(ToolPath
)
2648 BuildOptions
[Tool
][Attr
] = ToolPath
2650 Value
= mws
.handleWsMacro(Value
)
2652 BuildOptions
[Tool
][Attr
] += " " + Value
2654 BuildOptions
[Tool
][Attr
] = Value
2655 if Module
.AutoGenVersion
< 0x00010005 and self
.Workspace
.UniFlag
!= None:
2657 # Override UNI flag only for EDK module.
2659 if 'BUILD' not in BuildOptions
:
2660 BuildOptions
['BUILD'] = {}
2661 BuildOptions
['BUILD']['FLAGS'] = self
.Workspace
.UniFlag
2662 return BuildOptions
, BuildRuleOrder
2664 Platform
= property(_GetPlatform
)
2665 Name
= property(_GetName
)
2666 Guid
= property(_GetGuid
)
2667 Version
= property(_GetVersion
)
2669 OutputDir
= property(_GetOutputDir
)
2670 BuildDir
= property(_GetBuildDir
)
2671 MakeFileDir
= property(_GetMakeFileDir
)
2672 FdfFile
= property(_GetFdfFile
)
2674 PcdTokenNumber
= property(_GetPcdTokenNumbers
) # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber
2675 DynamicPcdList
= property(_GetDynamicPcdList
) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
2676 NonDynamicPcdList
= property(_GetNonDynamicPcdList
) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
2677 NonDynamicPcdDict
= property(_GetNonDynamicPcdDict
)
2678 PackageList
= property(_GetPackageList
)
2680 ToolDefinition
= property(_GetToolDefinition
) # toolcode : tool path
2681 ToolDefinitionFile
= property(_GetToolDefFile
) # toolcode : lib path
2682 ToolChainFamily
= property(_GetToolChainFamily
)
2683 BuildRuleFamily
= property(_GetBuildRuleFamily
)
2684 BuildOption
= property(_GetBuildOptions
) # toolcode : option
2685 EdkBuildOption
= property(_GetEdkBuildOptions
) # edktoolcode : option
2686 EdkIIBuildOption
= property(_GetEdkIIBuildOptions
) # edkiitoolcode : option
2688 BuildCommand
= property(_GetBuildCommand
)
2689 BuildRule
= property(_GetBuildRule
)
2690 ModuleAutoGenList
= property(_GetModuleAutoGenList
)
2691 LibraryAutoGenList
= property(_GetLibraryAutoGenList
)
2692 GenFdsCommand
= property(_GenFdsCommand
)
2694 ## ModuleAutoGen class
2696 # This class encapsules the AutoGen behaviors for the build tools. In addition to
2697 # the generation of AutoGen.h and AutoGen.c, it will generate *.depex file according
2698 # to the [depex] section in module's inf file.
2700 class ModuleAutoGen(AutoGen
):
2701 ## Cache the timestamps of metafiles of every module in a class variable
2705 ## The real constructor of ModuleAutoGen
2707 # This method is not supposed to be called by users of ModuleAutoGen. It's
2708 # only used by factory method __new__() to do real initialization work for an
2709 # object of ModuleAutoGen
2711 # @param Workspace EdkIIWorkspaceBuild object
2712 # @param ModuleFile The path of module file
2713 # @param Target Build target (DEBUG, RELEASE)
2714 # @param Toolchain Name of tool chain
2715 # @param Arch The arch the module supports
2716 # @param PlatformFile Platform meta-file
2718 def _Init(self
, Workspace
, ModuleFile
, Target
, Toolchain
, Arch
, PlatformFile
):
2719 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "AutoGen module [%s] [%s]" % (ModuleFile
, Arch
))
2720 GlobalData
.gProcessingFile
= "%s [%s, %s, %s]" % (ModuleFile
, Arch
, Toolchain
, Target
)
2722 self
.Workspace
= Workspace
2723 self
.WorkspaceDir
= Workspace
.WorkspaceDir
2725 self
.MetaFile
= ModuleFile
2726 self
.PlatformInfo
= PlatformAutoGen(Workspace
, PlatformFile
, Target
, Toolchain
, Arch
)
2727 # check if this module is employed by active platform
2728 if not self
.PlatformInfo
.ValidModule(self
.MetaFile
):
2729 EdkLogger
.verbose("Module [%s] for [%s] is not employed by active platform\n" \
2730 % (self
.MetaFile
, Arch
))
2733 self
.SourceDir
= self
.MetaFile
.SubDir
2734 self
.SourceDir
= mws
.relpath(self
.SourceDir
, self
.WorkspaceDir
)
2736 self
.SourceOverrideDir
= None
2737 # use overrided path defined in DSC file
2738 if self
.MetaFile
.Key
in GlobalData
.gOverrideDir
:
2739 self
.SourceOverrideDir
= GlobalData
.gOverrideDir
[self
.MetaFile
.Key
]
2741 self
.ToolChain
= Toolchain
2742 self
.BuildTarget
= Target
2744 self
.ToolChainFamily
= self
.PlatformInfo
.ToolChainFamily
2745 self
.BuildRuleFamily
= self
.PlatformInfo
.BuildRuleFamily
2747 self
.IsMakeFileCreated
= False
2748 self
.IsCodeFileCreated
= False
2749 self
.IsAsBuiltInfCreated
= False
2750 self
.DepexGenerated
= False
2752 self
.BuildDatabase
= self
.Workspace
.BuildDatabase
2753 self
.BuildRuleOrder
= None
2759 self
._Version
= None
2760 self
._ModuleType
= None
2761 self
._ComponentType
= None
2762 self
._PcdIsDriver
= None
2763 self
._AutoGenVersion
= None
2764 self
._LibraryFlag
= None
2765 self
._CustomMakefile
= None
2768 self
._BuildDir
= None
2769 self
._OutputDir
= None
2770 self
._FfsOutputDir
= None
2771 self
._DebugDir
= None
2772 self
._MakeFileDir
= None
2774 self
._IncludePathList
= None
2775 self
._IncludePathLength
= 0
2776 self
._AutoGenFileList
= None
2777 self
._UnicodeFileList
= None
2778 self
._VfrFileList
= None
2779 self
._IdfFileList
= None
2780 self
._SourceFileList
= None
2781 self
._ObjectFileList
= None
2782 self
._BinaryFileList
= None
2784 self
._DependentPackageList
= None
2785 self
._DependentLibraryList
= None
2786 self
._LibraryAutoGenList
= None
2787 self
._DerivedPackageList
= None
2788 self
._ModulePcdList
= None
2789 self
._LibraryPcdList
= None
2790 self
._PcdComments
= sdict()
2791 self
._GuidList
= None
2792 self
._GuidsUsedByPcd
= None
2793 self
._GuidComments
= sdict()
2794 self
._ProtocolList
= None
2795 self
._ProtocolComments
= sdict()
2796 self
._PpiList
= None
2797 self
._PpiComments
= sdict()
2798 self
._DepexList
= None
2799 self
._DepexExpressionList
= None
2800 self
._BuildOption
= None
2801 self
._BuildOptionIncPathList
= None
2802 self
._BuildTargets
= None
2803 self
._IntroBuildTargetList
= None
2804 self
._FinalBuildTargetList
= None
2805 self
._FileTypes
= None
2806 self
._BuildRules
= None
2808 self
._TimeStampPath
= None
2810 self
.AutoGenDepSet
= set()
2813 ## The Modules referenced to this Library
2814 # Only Library has this attribute
2815 self
._ReferenceModules
= []
2817 ## Store the FixedAtBuild Pcds
2819 self
._FixedAtBuildPcds
= []
2824 return "%s [%s]" % (self
.MetaFile
, self
.Arch
)
2826 # Get FixedAtBuild Pcds of this Module
2827 def _GetFixedAtBuildPcds(self
):
2828 if self
._FixedAtBuildPcds
:
2829 return self
._FixedAtBuildPcds
2830 for Pcd
in self
.ModulePcdList
:
2831 if Pcd
.Type
!= "FixedAtBuild":
2833 if Pcd
not in self
._FixedAtBuildPcds
:
2834 self
._FixedAtBuildPcds
.append(Pcd
)
2836 return self
._FixedAtBuildPcds
2838 def _GetUniqueBaseName(self
):
2839 BaseName
= self
.Name
2840 for Module
in self
.PlatformInfo
.ModuleAutoGenList
:
2841 if Module
.MetaFile
== self
.MetaFile
:
2843 if Module
.Name
== self
.Name
:
2844 if uuid
.UUID(Module
.Guid
) == uuid
.UUID(self
.Guid
):
2845 EdkLogger
.error("build", FILE_DUPLICATED
, 'Modules have same BaseName and FILE_GUID:\n'
2846 ' %s\n %s' % (Module
.MetaFile
, self
.MetaFile
))
2847 BaseName
= '%s_%s' % (self
.Name
, self
.Guid
)
2850 # Macros could be used in build_rule.txt (also Makefile)
2851 def _GetMacros(self
):
2852 if self
._Macro
== None:
2853 self
._Macro
= sdict()
2854 self
._Macro
["WORKSPACE" ] = self
.WorkspaceDir
2855 self
._Macro
["MODULE_NAME" ] = self
.Name
2856 self
._Macro
["MODULE_NAME_GUID" ] = self
._GetUniqueBaseName
()
2857 self
._Macro
["MODULE_GUID" ] = self
.Guid
2858 self
._Macro
["MODULE_VERSION" ] = self
.Version
2859 self
._Macro
["MODULE_TYPE" ] = self
.ModuleType
2860 self
._Macro
["MODULE_FILE" ] = str(self
.MetaFile
)
2861 self
._Macro
["MODULE_FILE_BASE_NAME" ] = self
.MetaFile
.BaseName
2862 self
._Macro
["MODULE_RELATIVE_DIR" ] = self
.SourceDir
2863 self
._Macro
["MODULE_DIR" ] = self
.SourceDir
2865 self
._Macro
["BASE_NAME" ] = self
.Name
2867 self
._Macro
["ARCH" ] = self
.Arch
2868 self
._Macro
["TOOLCHAIN" ] = self
.ToolChain
2869 self
._Macro
["TOOLCHAIN_TAG" ] = self
.ToolChain
2870 self
._Macro
["TOOL_CHAIN_TAG" ] = self
.ToolChain
2871 self
._Macro
["TARGET" ] = self
.BuildTarget
2873 self
._Macro
["BUILD_DIR" ] = self
.PlatformInfo
.BuildDir
2874 self
._Macro
["BIN_DIR" ] = os
.path
.join(self
.PlatformInfo
.BuildDir
, self
.Arch
)
2875 self
._Macro
["LIB_DIR" ] = os
.path
.join(self
.PlatformInfo
.BuildDir
, self
.Arch
)
2876 self
._Macro
["MODULE_BUILD_DIR" ] = self
.BuildDir
2877 self
._Macro
["OUTPUT_DIR" ] = self
.OutputDir
2878 self
._Macro
["DEBUG_DIR" ] = self
.DebugDir
2879 self
._Macro
["DEST_DIR_OUTPUT" ] = self
.OutputDir
2880 self
._Macro
["DEST_DIR_DEBUG" ] = self
.DebugDir
2881 self
._Macro
["PLATFORM_NAME" ] = self
.PlatformInfo
.Name
2882 self
._Macro
["PLATFORM_GUID" ] = self
.PlatformInfo
.Guid
2883 self
._Macro
["PLATFORM_VERSION" ] = self
.PlatformInfo
.Version
2884 self
._Macro
["PLATFORM_RELATIVE_DIR" ] = self
.PlatformInfo
.SourceDir
2885 self
._Macro
["PLATFORM_DIR" ] = mws
.join(self
.WorkspaceDir
, self
.PlatformInfo
.SourceDir
)
2886 self
._Macro
["PLATFORM_OUTPUT_DIR" ] = self
.PlatformInfo
.OutputDir
2887 self
._Macro
["FFS_OUTPUT_DIR" ] = self
.FfsOutputDir
2890 ## Return the module build data object
2891 def _GetModule(self
):
2892 if self
._Module
== None:
2893 self
._Module
= self
.Workspace
.BuildDatabase
[self
.MetaFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
2896 ## Return the module name
2897 def _GetBaseName(self
):
2898 return self
.Module
.BaseName
2900 ## Return the module DxsFile if exist
2901 def _GetDxsFile(self
):
2902 return self
.Module
.DxsFile
2904 ## Return the module SourceOverridePath
2905 def _GetSourceOverridePath(self
):
2906 return self
.Module
.SourceOverridePath
2908 ## Return the module meta-file GUID
2911 # To build same module more than once, the module path with FILE_GUID overridden has
2912 # the file name FILE_GUIDmodule.inf, but the relative path (self.MetaFile.File) is the realy path
2913 # in DSC. The overridden GUID can be retrieved from file name
2915 if os
.path
.basename(self
.MetaFile
.File
) != os
.path
.basename(self
.MetaFile
.Path
):
2917 # Length of GUID is 36
2919 return os
.path
.basename(self
.MetaFile
.Path
)[:36]
2920 return self
.Module
.Guid
2922 ## Return the module version
2923 def _GetVersion(self
):
2924 return self
.Module
.Version
2926 ## Return the module type
2927 def _GetModuleType(self
):
2928 return self
.Module
.ModuleType
2930 ## Return the component type (for Edk.x style of module)
2931 def _GetComponentType(self
):
2932 return self
.Module
.ComponentType
2934 ## Return the build type
2935 def _GetBuildType(self
):
2936 return self
.Module
.BuildType
2938 ## Return the PCD_IS_DRIVER setting
2939 def _GetPcdIsDriver(self
):
2940 return self
.Module
.PcdIsDriver
2942 ## Return the autogen version, i.e. module meta-file version
2943 def _GetAutoGenVersion(self
):
2944 return self
.Module
.AutoGenVersion
2946 ## Check if the module is library or not
2947 def _IsLibrary(self
):
2948 if self
._LibraryFlag
== None:
2949 if self
.Module
.LibraryClass
!= None and self
.Module
.LibraryClass
!= []:
2950 self
._LibraryFlag
= True
2952 self
._LibraryFlag
= False
2953 return self
._LibraryFlag
2955 ## Check if the module is binary module or not
2956 def _IsBinaryModule(self
):
2957 return self
.Module
.IsBinaryModule
2959 ## Return the directory to store intermediate files of the module
2960 def _GetBuildDir(self
):
2961 if self
._BuildDir
== None:
2962 self
._BuildDir
= path
.join(
2963 self
.PlatformInfo
.BuildDir
,
2966 self
.MetaFile
.BaseName
2968 CreateDirectory(self
._BuildDir
)
2969 return self
._BuildDir
2971 ## Return the directory to store the intermediate object files of the mdoule
2972 def _GetOutputDir(self
):
2973 if self
._OutputDir
== None:
2974 self
._OutputDir
= path
.join(self
.BuildDir
, "OUTPUT")
2975 CreateDirectory(self
._OutputDir
)
2976 return self
._OutputDir
2978 ## Return the directory to store ffs file
2979 def _GetFfsOutputDir(self
):
2980 if self
._FfsOutputDir
== None:
2981 if GlobalData
.gFdfParser
!= None:
2982 self
._FfsOutputDir
= path
.join(self
.PlatformInfo
.BuildDir
, "FV", "Ffs", self
.Guid
+ self
.Name
)
2984 self
._FfsOutputDir
= ''
2985 return self
._FfsOutputDir
2987 ## Return the directory to store auto-gened source files of the mdoule
2988 def _GetDebugDir(self
):
2989 if self
._DebugDir
== None:
2990 self
._DebugDir
= path
.join(self
.BuildDir
, "DEBUG")
2991 CreateDirectory(self
._DebugDir
)
2992 return self
._DebugDir
2994 ## Return the path of custom file
2995 def _GetCustomMakefile(self
):
2996 if self
._CustomMakefile
== None:
2997 self
._CustomMakefile
= {}
2998 for Type
in self
.Module
.CustomMakefile
:
2999 if Type
in gMakeTypeMap
:
3000 MakeType
= gMakeTypeMap
[Type
]
3003 if self
.SourceOverrideDir
!= None:
3004 File
= os
.path
.join(self
.SourceOverrideDir
, self
.Module
.CustomMakefile
[Type
])
3005 if not os
.path
.exists(File
):
3006 File
= os
.path
.join(self
.SourceDir
, self
.Module
.CustomMakefile
[Type
])
3008 File
= os
.path
.join(self
.SourceDir
, self
.Module
.CustomMakefile
[Type
])
3009 self
._CustomMakefile
[MakeType
] = File
3010 return self
._CustomMakefile
3012 ## Return the directory of the makefile
3014 # @retval string The directory string of module's makefile
3016 def _GetMakeFileDir(self
):
3017 return self
.BuildDir
3019 ## Return build command string
3021 # @retval string Build command string
3023 def _GetBuildCommand(self
):
3024 return self
.PlatformInfo
.BuildCommand
3026 ## Get object list of all packages the module and its dependent libraries belong to
3028 # @retval list The list of package object
3030 def _GetDerivedPackageList(self
):
3032 for M
in [self
.Module
] + self
.DependentLibraryList
:
3033 for Package
in M
.Packages
:
3034 if Package
in PackageList
:
3036 PackageList
.append(Package
)
3039 ## Get the depex string
3041 # @return : a string contain all depex expresion.
3042 def _GetDepexExpresionString(self
):
3045 ## DPX_SOURCE IN Define section.
3046 if self
.Module
.DxsFile
:
3048 for M
in [self
.Module
] + self
.DependentLibraryList
:
3049 Filename
= M
.MetaFile
.Path
3050 InfObj
= InfSectionParser
.InfSectionParser(Filename
)
3051 DepexExpresionList
= InfObj
.GetDepexExpresionList()
3052 for DepexExpresion
in DepexExpresionList
:
3053 for key
in DepexExpresion
.keys():
3054 Arch
, ModuleType
= key
3055 DepexExpr
= [x
for x
in DepexExpresion
[key
] if not str(x
).startswith('#')]
3056 # the type of build module is USER_DEFINED.
3057 # All different DEPEX section tags would be copied into the As Built INF file
3058 # and there would be separate DEPEX section tags
3059 if self
.ModuleType
.upper() == SUP_MODULE_USER_DEFINED
:
3060 if (Arch
.upper() == self
.Arch
.upper()) and (ModuleType
.upper() != TAB_ARCH_COMMON
):
3061 DepexList
.append({(Arch
, ModuleType
): DepexExpr
})
3063 if Arch
.upper() == TAB_ARCH_COMMON
or \
3064 (Arch
.upper() == self
.Arch
.upper() and \
3065 ModuleType
.upper() in [TAB_ARCH_COMMON
, self
.ModuleType
.upper()]):
3066 DepexList
.append({(Arch
, ModuleType
): DepexExpr
})
3068 #the type of build module is USER_DEFINED.
3069 if self
.ModuleType
.upper() == SUP_MODULE_USER_DEFINED
:
3070 for Depex
in DepexList
:
3071 for key
in Depex
.keys():
3072 DepexStr
+= '[Depex.%s.%s]\n' % key
3073 DepexStr
+= '\n'.join(['# '+ val
for val
in Depex
[key
]])
3076 return '[Depex.%s]\n' % self
.Arch
3079 #the type of build module not is USER_DEFINED.
3081 for Depex
in DepexList
:
3086 for D
in Depex
.values():
3087 DepexStr
+= ' '.join([val
for val
in D
])
3088 Index
= DepexStr
.find('END')
3089 if Index
> -1 and Index
== len(DepexStr
) - 3:
3090 DepexStr
= DepexStr
[:-3]
3091 DepexStr
= DepexStr
.strip()
3094 DepexStr
= DepexStr
.lstrip('(').rstrip(')').strip()
3096 return '[Depex.%s]\n' % self
.Arch
3097 return '[Depex.%s]\n# ' % self
.Arch
+ DepexStr
3099 ## Merge dependency expression
3101 # @retval list The token list of the dependency expression after parsed
3103 def _GetDepexTokenList(self
):
3104 if self
._DepexList
== None:
3105 self
._DepexList
= {}
3106 if self
.DxsFile
or self
.IsLibrary
or TAB_DEPENDENCY_EXPRESSION_FILE
in self
.FileTypes
:
3107 return self
._DepexList
3109 self
._DepexList
[self
.ModuleType
] = []
3111 for ModuleType
in self
._DepexList
:
3112 DepexList
= self
._DepexList
[ModuleType
]
3114 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
3116 for M
in [self
.Module
] + self
.DependentLibraryList
:
3118 for D
in M
.Depex
[self
.Arch
, ModuleType
]:
3120 DepexList
.append('AND')
3121 DepexList
.append('(')
3123 if DepexList
[-1] == 'END': # no need of a END at this time
3125 DepexList
.append(')')
3128 EdkLogger
.verbose("DEPEX[%s] (+%s) = %s" % (self
.Name
, M
.BaseName
, DepexList
))
3129 if 'BEFORE' in DepexList
or 'AFTER' in DepexList
:
3131 if len(DepexList
) > 0:
3132 EdkLogger
.verbose('')
3133 return self
._DepexList
3135 ## Merge dependency expression
3137 # @retval list The token list of the dependency expression after parsed
3139 def _GetDepexExpressionTokenList(self
):
3140 if self
._DepexExpressionList
== None:
3141 self
._DepexExpressionList
= {}
3142 if self
.DxsFile
or self
.IsLibrary
or TAB_DEPENDENCY_EXPRESSION_FILE
in self
.FileTypes
:
3143 return self
._DepexExpressionList
3145 self
._DepexExpressionList
[self
.ModuleType
] = ''
3147 for ModuleType
in self
._DepexExpressionList
:
3148 DepexExpressionList
= self
._DepexExpressionList
[ModuleType
]
3150 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
3152 for M
in [self
.Module
] + self
.DependentLibraryList
:
3154 for D
in M
.DepexExpression
[self
.Arch
, ModuleType
]:
3155 if DepexExpressionList
!= '':
3156 DepexExpressionList
+= ' AND '
3157 DepexExpressionList
+= '('
3158 DepexExpressionList
+= D
3159 DepexExpressionList
= DepexExpressionList
.rstrip('END').strip()
3160 DepexExpressionList
+= ')'
3163 EdkLogger
.verbose("DEPEX[%s] (+%s) = %s" % (self
.Name
, M
.BaseName
, DepexExpressionList
))
3164 if 'BEFORE' in DepexExpressionList
or 'AFTER' in DepexExpressionList
:
3166 if len(DepexExpressionList
) > 0:
3167 EdkLogger
.verbose('')
3168 self
._DepexExpressionList
[ModuleType
] = DepexExpressionList
3169 return self
._DepexExpressionList
3171 # Get the tiano core user extension, it is contain dependent library.
3172 # @retval: a list contain tiano core userextension.
3174 def _GetTianoCoreUserExtensionList(self
):
3175 TianoCoreUserExtentionList
= []
3176 for M
in [self
.Module
] + self
.DependentLibraryList
:
3177 Filename
= M
.MetaFile
.Path
3178 InfObj
= InfSectionParser
.InfSectionParser(Filename
)
3179 TianoCoreUserExtenList
= InfObj
.GetUserExtensionTianoCore()
3180 for TianoCoreUserExtent
in TianoCoreUserExtenList
:
3181 for Section
in TianoCoreUserExtent
.keys():
3182 ItemList
= Section
.split(TAB_SPLIT
)
3184 if len(ItemList
) == 4:
3186 if Arch
.upper() == TAB_ARCH_COMMON
or Arch
.upper() == self
.Arch
.upper():
3188 TianoCoreList
.extend([TAB_SECTION_START
+ Section
+ TAB_SECTION_END
])
3189 TianoCoreList
.extend(TianoCoreUserExtent
[Section
][:])
3190 TianoCoreList
.append('\n')
3191 TianoCoreUserExtentionList
.append(TianoCoreList
)
3193 return TianoCoreUserExtentionList
3195 ## Return the list of specification version required for the module
3197 # @retval list The list of specification defined in module file
3199 def _GetSpecification(self
):
3200 return self
.Module
.Specification
3202 ## Tool option for the module build
3204 # @param PlatformInfo The object of PlatformBuildInfo
3205 # @retval dict The dict containing valid options
3207 def _GetModuleBuildOption(self
):
3208 if self
._BuildOption
== None:
3209 self
._BuildOption
, self
.BuildRuleOrder
= self
.PlatformInfo
.ApplyBuildOption(self
.Module
)
3210 if self
.BuildRuleOrder
:
3211 self
.BuildRuleOrder
= ['.%s' % Ext
for Ext
in self
.BuildRuleOrder
.split()]
3212 return self
._BuildOption
3214 ## Get include path list from tool option for the module build
3216 # @retval list The include path list
3218 def _GetBuildOptionIncPathList(self
):
3219 if self
._BuildOptionIncPathList
== None:
3221 # Regular expression for finding Include Directories, the difference between MSFT and INTEL/GCC/RVCT
3222 # is the former use /I , the Latter used -I to specify include directories
3224 if self
.PlatformInfo
.ToolChainFamily
in ('MSFT'):
3225 gBuildOptIncludePattern
= re
.compile(r
"(?:.*?)/I[ \t]*([^ ]*)", re
.MULTILINE | re
.DOTALL
)
3226 elif self
.PlatformInfo
.ToolChainFamily
in ('INTEL', 'GCC', 'RVCT'):
3227 gBuildOptIncludePattern
= re
.compile(r
"(?:.*?)-I[ \t]*([^ ]*)", re
.MULTILINE | re
.DOTALL
)
3230 # New ToolChainFamily, don't known whether there is option to specify include directories
3232 self
._BuildOptionIncPathList
= []
3233 return self
._BuildOptionIncPathList
3235 BuildOptionIncPathList
= []
3236 for Tool
in ('CC', 'PP', 'VFRPP', 'ASLPP', 'ASLCC', 'APP', 'ASM'):
3239 FlagOption
= self
.BuildOption
[Tool
][Attr
]
3243 if self
.PlatformInfo
.ToolChainFamily
!= 'RVCT':
3244 IncPathList
= [NormPath(Path
, self
.Macros
) for Path
in gBuildOptIncludePattern
.findall(FlagOption
)]
3247 # RVCT may specify a list of directory seperated by commas
3250 for Path
in gBuildOptIncludePattern
.findall(FlagOption
):
3251 PathList
= GetSplitList(Path
, TAB_COMMA_SPLIT
)
3252 IncPathList
+= [NormPath(PathEntry
, self
.Macros
) for PathEntry
in PathList
]
3255 # EDK II modules must not reference header files outside of the packages they depend on or
3256 # within the module's directory tree. Report error if violation.
3258 if self
.AutoGenVersion
>= 0x00010005 and len(IncPathList
) > 0:
3259 for Path
in IncPathList
:
3260 if (Path
not in self
.IncludePathList
) and (CommonPath([Path
, self
.MetaFile
.Dir
]) != self
.MetaFile
.Dir
):
3261 ErrMsg
= "The include directory for the EDK II module in this line is invalid %s specified in %s FLAGS '%s'" % (Path
, Tool
, FlagOption
)
3262 EdkLogger
.error("build",
3265 File
=str(self
.MetaFile
))
3268 BuildOptionIncPathList
+= IncPathList
3270 self
._BuildOptionIncPathList
= BuildOptionIncPathList
3272 return self
._BuildOptionIncPathList
3274 ## Return a list of files which can be built from source
3276 # What kind of files can be built is determined by build rules in
3277 # $(CONF_DIRECTORY)/build_rule.txt and toolchain family.
3279 def _GetSourceFileList(self
):
3280 if self
._SourceFileList
== None:
3281 self
._SourceFileList
= []
3282 for F
in self
.Module
.Sources
:
3284 if F
.TagName
not in ("", "*", self
.ToolChain
):
3285 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "The toolchain [%s] for processing file [%s] is found, "
3286 "but [%s] is needed" % (F
.TagName
, str(F
), self
.ToolChain
))
3288 # match tool chain family or build rule family
3289 if F
.ToolChainFamily
not in ("", "*", self
.ToolChainFamily
, self
.BuildRuleFamily
):
3292 "The file [%s] must be built by tools of [%s], " \
3293 "but current toolchain family is [%s], buildrule family is [%s]" \
3294 % (str(F
), F
.ToolChainFamily
, self
.ToolChainFamily
, self
.BuildRuleFamily
))
3297 # add the file path into search path list for file including
3298 if F
.Dir
not in self
.IncludePathList
and self
.AutoGenVersion
>= 0x00010005:
3299 self
.IncludePathList
.insert(0, F
.Dir
)
3300 self
._SourceFileList
.append(F
)
3302 self
._MatchBuildRuleOrder
(self
._SourceFileList
)
3304 for F
in self
._SourceFileList
:
3305 self
._ApplyBuildRule
(F
, TAB_UNKNOWN_FILE
)
3306 return self
._SourceFileList
3308 def _MatchBuildRuleOrder(self
, FileList
):
3310 self
._GetModuleBuildOption
()
3311 for SingleFile
in FileList
:
3312 if self
.BuildRuleOrder
and SingleFile
.Ext
in self
.BuildRuleOrder
and SingleFile
.Ext
in self
.BuildRules
:
3313 key
= SingleFile
.Path
.split(SingleFile
.Ext
)[0]
3314 if key
in Order_Dict
:
3315 Order_Dict
[key
].append(SingleFile
.Ext
)
3317 Order_Dict
[key
] = [SingleFile
.Ext
]
3320 for F
in Order_Dict
:
3321 if len(Order_Dict
[F
]) > 1:
3322 Order_Dict
[F
].sort(key
=lambda i
: self
.BuildRuleOrder
.index(i
))
3323 for Ext
in Order_Dict
[F
][1:]:
3324 RemoveList
.append(F
+ Ext
)
3326 for item
in RemoveList
:
3327 FileList
.remove(item
)
3331 ## Return the list of unicode files
3332 def _GetUnicodeFileList(self
):
3333 if self
._UnicodeFileList
== None:
3334 if TAB_UNICODE_FILE
in self
.FileTypes
:
3335 self
._UnicodeFileList
= self
.FileTypes
[TAB_UNICODE_FILE
]
3337 self
._UnicodeFileList
= []
3338 return self
._UnicodeFileList
3340 ## Return the list of vfr files
3341 def _GetVfrFileList(self
):
3342 if self
._VfrFileList
== None:
3343 if TAB_VFR_FILE
in self
.FileTypes
:
3344 self
._VfrFileList
= self
.FileTypes
[TAB_VFR_FILE
]
3346 self
._VfrFileList
= []
3347 return self
._VfrFileList
3349 ## Return the list of Image Definition files
3350 def _GetIdfFileList(self
):
3351 if self
._IdfFileList
== None:
3352 if TAB_IMAGE_FILE
in self
.FileTypes
:
3353 self
._IdfFileList
= self
.FileTypes
[TAB_IMAGE_FILE
]
3355 self
._IdfFileList
= []
3356 return self
._IdfFileList
3358 ## Return a list of files which can be built from binary
3360 # "Build" binary files are just to copy them to build directory.
3362 # @retval list The list of files which can be built later
3364 def _GetBinaryFiles(self
):
3365 if self
._BinaryFileList
== None:
3366 self
._BinaryFileList
= []
3367 for F
in self
.Module
.Binaries
:
3368 if F
.Target
not in ['COMMON', '*'] and F
.Target
!= self
.BuildTarget
:
3370 self
._BinaryFileList
.append(F
)
3371 self
._ApplyBuildRule
(F
, F
.Type
)
3372 return self
._BinaryFileList
3374 def _GetBuildRules(self
):
3375 if self
._BuildRules
== None:
3377 BuildRuleDatabase
= self
.PlatformInfo
.BuildRule
3378 for Type
in BuildRuleDatabase
.FileTypeList
:
3379 #first try getting build rule by BuildRuleFamily
3380 RuleObject
= BuildRuleDatabase
[Type
, self
.BuildType
, self
.Arch
, self
.BuildRuleFamily
]
3382 # build type is always module type, but ...
3383 if self
.ModuleType
!= self
.BuildType
:
3384 RuleObject
= BuildRuleDatabase
[Type
, self
.ModuleType
, self
.Arch
, self
.BuildRuleFamily
]
3385 #second try getting build rule by ToolChainFamily
3387 RuleObject
= BuildRuleDatabase
[Type
, self
.BuildType
, self
.Arch
, self
.ToolChainFamily
]
3389 # build type is always module type, but ...
3390 if self
.ModuleType
!= self
.BuildType
:
3391 RuleObject
= BuildRuleDatabase
[Type
, self
.ModuleType
, self
.Arch
, self
.ToolChainFamily
]
3394 RuleObject
= RuleObject
.Instantiate(self
.Macros
)
3395 BuildRules
[Type
] = RuleObject
3396 for Ext
in RuleObject
.SourceFileExtList
:
3397 BuildRules
[Ext
] = RuleObject
3398 self
._BuildRules
= BuildRules
3399 return self
._BuildRules
3401 def _ApplyBuildRule(self
, File
, FileType
):
3402 if self
._BuildTargets
== None:
3403 self
._IntroBuildTargetList
= set()
3404 self
._FinalBuildTargetList
= set()
3405 self
._BuildTargets
= {}
3406 self
._FileTypes
= {}
3408 SubDirectory
= os
.path
.join(self
.OutputDir
, File
.SubDir
)
3409 if not os
.path
.exists(SubDirectory
):
3410 CreateDirectory(SubDirectory
)
3416 # Make sure to get build rule order value
3418 self
._GetModuleBuildOption
()
3420 while Index
< len(SourceList
):
3421 Source
= SourceList
[Index
]
3425 CreateDirectory(Source
.Dir
)
3427 if File
.IsBinary
and File
== Source
and self
._BinaryFileList
!= None and File
in self
._BinaryFileList
:
3428 # Skip all files that are not binary libraries
3429 if not self
.IsLibrary
:
3431 RuleObject
= self
.BuildRules
[TAB_DEFAULT_BINARY_FILE
]
3432 elif FileType
in self
.BuildRules
:
3433 RuleObject
= self
.BuildRules
[FileType
]
3434 elif Source
.Ext
in self
.BuildRules
:
3435 RuleObject
= self
.BuildRules
[Source
.Ext
]
3437 # stop at no more rules
3439 self
._FinalBuildTargetList
.add(LastTarget
)
3442 FileType
= RuleObject
.SourceFileType
3443 if FileType
not in self
._FileTypes
:
3444 self
._FileTypes
[FileType
] = set()
3445 self
._FileTypes
[FileType
].add(Source
)
3447 # stop at STATIC_LIBRARY for library
3448 if self
.IsLibrary
and FileType
== TAB_STATIC_LIBRARY
:
3450 self
._FinalBuildTargetList
.add(LastTarget
)
3453 Target
= RuleObject
.Apply(Source
, self
.BuildRuleOrder
)
3456 self
._FinalBuildTargetList
.add(LastTarget
)
3458 elif not Target
.Outputs
:
3459 # Only do build for target with outputs
3460 self
._FinalBuildTargetList
.add(Target
)
3462 if FileType
not in self
._BuildTargets
:
3463 self
._BuildTargets
[FileType
] = set()
3464 self
._BuildTargets
[FileType
].add(Target
)
3466 if not Source
.IsBinary
and Source
== File
:
3467 self
._IntroBuildTargetList
.add(Target
)
3469 # to avoid cyclic rule
3470 if FileType
in RuleChain
:
3473 RuleChain
.append(FileType
)
3474 SourceList
.extend(Target
.Outputs
)
3476 FileType
= TAB_UNKNOWN_FILE
3478 def _GetTargets(self
):
3479 if self
._BuildTargets
== None:
3480 self
._IntroBuildTargetList
= set()
3481 self
._FinalBuildTargetList
= set()
3482 self
._BuildTargets
= {}
3483 self
._FileTypes
= {}
3485 #TRICK: call _GetSourceFileList to apply build rule for source files
3486 if self
.SourceFileList
:
3489 #TRICK: call _GetBinaryFileList to apply build rule for binary files
3490 if self
.BinaryFileList
:
3493 return self
._BuildTargets
3495 def _GetIntroTargetList(self
):
3497 return self
._IntroBuildTargetList
3499 def _GetFinalTargetList(self
):
3501 return self
._FinalBuildTargetList
3503 def _GetFileTypes(self
):
3505 return self
._FileTypes
3507 ## Get the list of package object the module depends on
3509 # @retval list The package object list
3511 def _GetDependentPackageList(self
):
3512 return self
.Module
.Packages
3514 ## Return the list of auto-generated code file
3516 # @retval list The list of auto-generated file
3518 def _GetAutoGenFileList(self
):
3519 UniStringAutoGenC
= True
3520 IdfStringAutoGenC
= True
3521 UniStringBinBuffer
= StringIO()
3522 IdfGenBinBuffer
= StringIO()
3523 if self
.BuildType
== 'UEFI_HII':
3524 UniStringAutoGenC
= False
3525 IdfStringAutoGenC
= False
3526 if self
._AutoGenFileList
== None:
3527 self
._AutoGenFileList
= {}
3528 AutoGenC
= TemplateString()
3529 AutoGenH
= TemplateString()
3530 StringH
= TemplateString()
3531 StringIdf
= TemplateString()
3532 GenC
.CreateCode(self
, AutoGenC
, AutoGenH
, StringH
, UniStringAutoGenC
, UniStringBinBuffer
, StringIdf
, IdfStringAutoGenC
, IdfGenBinBuffer
)
3534 # AutoGen.c is generated if there are library classes in inf, or there are object files
3536 if str(AutoGenC
) != "" and (len(self
.Module
.LibraryClasses
) > 0
3537 or TAB_OBJECT_FILE
in self
.FileTypes
):
3538 AutoFile
= PathClass(gAutoGenCodeFileName
, self
.DebugDir
)
3539 self
._AutoGenFileList
[AutoFile
] = str(AutoGenC
)
3540 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3541 if str(AutoGenH
) != "":
3542 AutoFile
= PathClass(gAutoGenHeaderFileName
, self
.DebugDir
)
3543 self
._AutoGenFileList
[AutoFile
] = str(AutoGenH
)
3544 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3545 if str(StringH
) != "":
3546 AutoFile
= PathClass(gAutoGenStringFileName
% {"module_name":self
.Name
}, self
.DebugDir
)
3547 self
._AutoGenFileList
[AutoFile
] = str(StringH
)
3548 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3549 if UniStringBinBuffer
!= None and UniStringBinBuffer
.getvalue() != "":
3550 AutoFile
= PathClass(gAutoGenStringFormFileName
% {"module_name":self
.Name
}, self
.OutputDir
)
3551 self
._AutoGenFileList
[AutoFile
] = UniStringBinBuffer
.getvalue()
3552 AutoFile
.IsBinary
= True
3553 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3554 if UniStringBinBuffer
!= None:
3555 UniStringBinBuffer
.close()
3556 if str(StringIdf
) != "":
3557 AutoFile
= PathClass(gAutoGenImageDefFileName
% {"module_name":self
.Name
}, self
.DebugDir
)
3558 self
._AutoGenFileList
[AutoFile
] = str(StringIdf
)
3559 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3560 if IdfGenBinBuffer
!= None and IdfGenBinBuffer
.getvalue() != "":
3561 AutoFile
= PathClass(gAutoGenIdfFileName
% {"module_name":self
.Name
}, self
.OutputDir
)
3562 self
._AutoGenFileList
[AutoFile
] = IdfGenBinBuffer
.getvalue()
3563 AutoFile
.IsBinary
= True
3564 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3565 if IdfGenBinBuffer
!= None:
3566 IdfGenBinBuffer
.close()
3567 return self
._AutoGenFileList
3569 ## Return the list of library modules explicitly or implicityly used by this module
3570 def _GetLibraryList(self
):
3571 if self
._DependentLibraryList
== None:
3572 # only merge library classes and PCD for non-library module
3574 self
._DependentLibraryList
= []
3576 if self
.AutoGenVersion
< 0x00010005:
3577 self
._DependentLibraryList
= self
.PlatformInfo
.ResolveLibraryReference(self
.Module
)
3579 self
._DependentLibraryList
= self
.PlatformInfo
.ApplyLibraryInstance(self
.Module
)
3580 return self
._DependentLibraryList
3583 def UpdateComments(Recver
, Src
):
3585 if Key
not in Recver
:
3587 Recver
[Key
].extend(Src
[Key
])
3588 ## Get the list of PCDs from current module
3590 # @retval list The list of PCD
3592 def _GetModulePcdList(self
):
3593 if self
._ModulePcdList
== None:
3594 # apply PCD settings from platform
3595 self
._ModulePcdList
= self
.PlatformInfo
.ApplyPcdSetting(self
.Module
, self
.Module
.Pcds
)
3596 self
.UpdateComments(self
._PcdComments
, self
.Module
.PcdComments
)
3597 return self
._ModulePcdList
3599 ## Get the list of PCDs from dependent libraries
3601 # @retval list The list of PCD
3603 def _GetLibraryPcdList(self
):
3604 if self
._LibraryPcdList
== None:
3606 if not self
.IsLibrary
:
3607 # get PCDs from dependent libraries
3608 for Library
in self
.DependentLibraryList
:
3609 self
.UpdateComments(self
._PcdComments
, Library
.PcdComments
)
3610 for Key
in Library
.Pcds
:
3611 # skip duplicated PCDs
3612 if Key
in self
.Module
.Pcds
or Key
in Pcds
:
3614 Pcds
[Key
] = copy
.copy(Library
.Pcds
[Key
])
3615 # apply PCD settings from platform
3616 self
._LibraryPcdList
= self
.PlatformInfo
.ApplyPcdSetting(self
.Module
, Pcds
)
3618 self
._LibraryPcdList
= []
3619 return self
._LibraryPcdList
3621 ## Get the GUID value mapping
3623 # @retval dict The mapping between GUID cname and its value
3625 def _GetGuidList(self
):
3626 if self
._GuidList
== None:
3627 self
._GuidList
= sdict()
3628 self
._GuidList
.update(self
.Module
.Guids
)
3629 for Library
in self
.DependentLibraryList
:
3630 self
._GuidList
.update(Library
.Guids
)
3631 self
.UpdateComments(self
._GuidComments
, Library
.GuidComments
)
3632 self
.UpdateComments(self
._GuidComments
, self
.Module
.GuidComments
)
3633 return self
._GuidList
3635 def GetGuidsUsedByPcd(self
):
3636 if self
._GuidsUsedByPcd
== None:
3637 self
._GuidsUsedByPcd
= sdict()
3638 self
._GuidsUsedByPcd
.update(self
.Module
.GetGuidsUsedByPcd())
3639 for Library
in self
.DependentLibraryList
:
3640 self
._GuidsUsedByPcd
.update(Library
.GetGuidsUsedByPcd())
3641 return self
._GuidsUsedByPcd
3642 ## Get the protocol value mapping
3644 # @retval dict The mapping between protocol cname and its value
3646 def _GetProtocolList(self
):
3647 if self
._ProtocolList
== None:
3648 self
._ProtocolList
= sdict()
3649 self
._ProtocolList
.update(self
.Module
.Protocols
)
3650 for Library
in self
.DependentLibraryList
:
3651 self
._ProtocolList
.update(Library
.Protocols
)
3652 self
.UpdateComments(self
._ProtocolComments
, Library
.ProtocolComments
)
3653 self
.UpdateComments(self
._ProtocolComments
, self
.Module
.ProtocolComments
)
3654 return self
._ProtocolList
3656 ## Get the PPI value mapping
3658 # @retval dict The mapping between PPI cname and its value
3660 def _GetPpiList(self
):
3661 if self
._PpiList
== None:
3662 self
._PpiList
= sdict()
3663 self
._PpiList
.update(self
.Module
.Ppis
)
3664 for Library
in self
.DependentLibraryList
:
3665 self
._PpiList
.update(Library
.Ppis
)
3666 self
.UpdateComments(self
._PpiComments
, Library
.PpiComments
)
3667 self
.UpdateComments(self
._PpiComments
, self
.Module
.PpiComments
)
3668 return self
._PpiList
3670 ## Get the list of include search path
3672 # @retval list The list path
3674 def _GetIncludePathList(self
):
3675 if self
._IncludePathList
== None:
3676 self
._IncludePathList
= []
3677 if self
.AutoGenVersion
< 0x00010005:
3678 for Inc
in self
.Module
.Includes
:
3679 if Inc
not in self
._IncludePathList
:
3680 self
._IncludePathList
.append(Inc
)
3682 Inc
= path
.join(Inc
, self
.Arch
.capitalize())
3683 if os
.path
.exists(Inc
) and Inc
not in self
._IncludePathList
:
3684 self
._IncludePathList
.append(Inc
)
3685 # Edk module needs to put DEBUG_DIR at the end of search path and not to use SOURCE_DIR all the time
3686 self
._IncludePathList
.append(self
.DebugDir
)
3688 self
._IncludePathList
.append(self
.MetaFile
.Dir
)
3689 self
._IncludePathList
.append(self
.DebugDir
)
3691 for Package
in self
.Module
.Packages
:
3692 PackageDir
= mws
.join(self
.WorkspaceDir
, Package
.MetaFile
.Dir
)
3693 if PackageDir
not in self
._IncludePathList
:
3694 self
._IncludePathList
.append(PackageDir
)
3695 IncludesList
= Package
.Includes
3696 if Package
._PrivateIncludes
:
3697 if not self
.MetaFile
.Path
.startswith(PackageDir
):
3698 IncludesList
= list(set(Package
.Includes
).difference(set(Package
._PrivateIncludes
)))
3699 for Inc
in IncludesList
:
3700 if Inc
not in self
._IncludePathList
:
3701 self
._IncludePathList
.append(str(Inc
))
3702 return self
._IncludePathList
3704 def _GetIncludePathLength(self
):
3705 self
._IncludePathLength
= 0
3706 if self
._IncludePathList
:
3707 for inc
in self
._IncludePathList
:
3708 self
._IncludePathLength
+= len(' ' + inc
)
3709 return self
._IncludePathLength
3711 ## Get HII EX PCDs which maybe used by VFR
3713 # efivarstore used by VFR may relate with HII EX PCDs
3714 # Get the variable name and GUID from efivarstore and HII EX PCD
3715 # List the HII EX PCDs in As Built INF if both name and GUID match.
3717 # @retval list HII EX PCDs
3719 def _GetPcdsMaybeUsedByVfr(self
):
3720 if not self
.SourceFileList
:
3724 for SrcFile
in self
.SourceFileList
:
3725 if SrcFile
.Ext
.lower() != '.vfr':
3727 Vfri
= os
.path
.join(self
.OutputDir
, SrcFile
.BaseName
+ '.i')
3728 if not os
.path
.exists(Vfri
):
3730 VfriFile
= open(Vfri
, 'r')
3731 Content
= VfriFile
.read()
3733 Pos
= Content
.find('efivarstore')
3736 # Make sure 'efivarstore' is the start of efivarstore statement
3737 # In case of the value of 'name' (name = efivarstore) is equal to 'efivarstore'
3740 while Index
>= 0 and Content
[Index
] in ' \t\r\n':
3742 if Index
>= 0 and Content
[Index
] != ';':
3743 Pos
= Content
.find('efivarstore', Pos
+ len('efivarstore'))
3746 # 'efivarstore' must be followed by name and guid
3748 Name
= gEfiVarStoreNamePattern
.search(Content
, Pos
)
3751 Guid
= gEfiVarStoreGuidPattern
.search(Content
, Pos
)
3754 NameArray
= ConvertStringToByteArray('L"' + Name
.group(1) + '"')
3755 NameGuids
.append((NameArray
, GuidStructureStringToGuidString(Guid
.group(1))))
3756 Pos
= Content
.find('efivarstore', Name
.end())
3760 for Pcd
in self
.PlatformInfo
.Platform
.Pcds
.values():
3761 if Pcd
.Type
!= TAB_PCDS_DYNAMIC_EX_HII
:
3763 for SkuName
in Pcd
.SkuInfoList
:
3764 SkuInfo
= Pcd
.SkuInfoList
[SkuName
]
3765 Name
= ConvertStringToByteArray(SkuInfo
.VariableName
)
3766 Value
= GuidValue(SkuInfo
.VariableGuid
, self
.PlatformInfo
.PackageList
, self
.MetaFile
.Path
)
3769 Guid
= GuidStructureStringToGuidString(Value
)
3770 if (Name
, Guid
) in NameGuids
and Pcd
not in HiiExPcds
:
3771 HiiExPcds
.append(Pcd
)
3776 def _GenOffsetBin(self
):
3778 for SourceFile
in self
.Module
.Sources
:
3779 if SourceFile
.Type
.upper() == ".VFR" :
3781 # search the .map file to find the offset of vfr binary in the PE32+/TE file.
3783 VfrUniBaseName
[SourceFile
.BaseName
] = (SourceFile
.BaseName
+ "Bin")
3784 if SourceFile
.Type
.upper() == ".UNI" :
3786 # search the .map file to find the offset of Uni strings binary in the PE32+/TE file.
3788 VfrUniBaseName
["UniOffsetName"] = (self
.Name
+ "Strings")
3790 if len(VfrUniBaseName
) == 0:
3792 MapFileName
= os
.path
.join(self
.OutputDir
, self
.Name
+ ".map")
3793 EfiFileName
= os
.path
.join(self
.OutputDir
, self
.Name
+ ".efi")
3794 VfrUniOffsetList
= GetVariableOffset(MapFileName
, EfiFileName
, VfrUniBaseName
.values())
3795 if not VfrUniOffsetList
:
3798 OutputName
= '%sOffset.bin' % self
.Name
3799 UniVfrOffsetFileName
= os
.path
.join( self
.OutputDir
, OutputName
)
3802 fInputfile
= open(UniVfrOffsetFileName
, "wb+", 0)
3804 EdkLogger
.error("build", FILE_OPEN_FAILURE
, "File open failed for %s" % UniVfrOffsetFileName
,None)
3806 # Use a instance of StringIO to cache data
3807 fStringIO
= StringIO('')
3809 for Item
in VfrUniOffsetList
:
3810 if (Item
[0].find("Strings") != -1):
3812 # UNI offset in image.
3814 # { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } }
3816 UniGuid
= [0xe0, 0xc5, 0x13, 0x89, 0xf6, 0x33, 0x86, 0x4d, 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66]
3817 UniGuid
= [chr(ItemGuid
) for ItemGuid
in UniGuid
]
3818 fStringIO
.write(''.join(UniGuid
))
3819 UniValue
= pack ('Q', int (Item
[1], 16))
3820 fStringIO
.write (UniValue
)
3823 # VFR binary offset in image.
3825 # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } };
3827 VfrGuid
= [0xb4, 0x7c, 0xbc, 0xd0, 0x47, 0x6a, 0x5f, 0x49, 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2]
3828 VfrGuid
= [chr(ItemGuid
) for ItemGuid
in VfrGuid
]
3829 fStringIO
.write(''.join(VfrGuid
))
3831 VfrValue
= pack ('Q', int (Item
[1], 16))
3832 fStringIO
.write (VfrValue
)
3834 # write data into file.
3837 fInputfile
.write (fStringIO
.getvalue())
3839 EdkLogger
.error("build", FILE_WRITE_FAILURE
, "Write data to file %s failed, please check whether the "
3840 "file been locked or using by other applications." %UniVfrOffsetFileName
,None)
3846 ## Create AsBuilt INF file the module
3848 def CreateAsBuiltInf(self
, IsOnlyCopy
= False):
3849 self
.OutputFile
= []
3851 if GlobalData
.gBinCacheDest
:
3852 self
.CopyModuleToCache()
3855 if self
.IsAsBuiltInfCreated
:
3858 # Skip the following code for EDK I inf
3859 if self
.AutoGenVersion
< 0x00010005:
3862 # Skip the following code for libraries
3866 # Skip the following code for modules with no source files
3867 if self
.SourceFileList
== None or self
.SourceFileList
== []:
3870 # Skip the following code for modules without any binary files
3871 if self
.BinaryFileList
<> None and self
.BinaryFileList
<> []:
3874 ### TODO: How to handles mixed source and binary modules
3876 # Find all DynamicEx and PatchableInModule PCDs used by this module and dependent libraries
3877 # Also find all packages that the DynamicEx PCDs depend on
3882 PcdTokenSpaceList
= []
3883 for Pcd
in self
.ModulePcdList
+ self
.LibraryPcdList
:
3884 if Pcd
.Type
== TAB_PCDS_PATCHABLE_IN_MODULE
:
3885 PatchablePcds
+= [Pcd
]
3886 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, 'PatchableInModule'))
3887 elif Pcd
.Type
in GenC
.gDynamicExPcd
:
3890 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, 'DynamicEx'))
3891 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, 'Dynamic'))
3892 PcdTokenSpaceList
.append(Pcd
.TokenSpaceGuidCName
)
3894 GuidList
.update(self
.GuidList
)
3895 for TokenSpace
in self
.GetGuidsUsedByPcd():
3896 # If token space is not referred by patch PCD or Ex PCD, remove the GUID from GUID list
3897 # The GUIDs in GUIDs section should really be the GUIDs in source INF or referred by Ex an patch PCDs
3898 if TokenSpace
not in PcdTokenSpaceList
and TokenSpace
in GuidList
:
3899 GuidList
.pop(TokenSpace
)
3900 CheckList
= (GuidList
, self
.PpiList
, self
.ProtocolList
, PcdCheckList
)
3901 for Package
in self
.DerivedPackageList
:
3902 if Package
in Packages
:
3904 BeChecked
= (Package
.Guids
, Package
.Ppis
, Package
.Protocols
, Package
.Pcds
)
3906 for Index
in range(len(BeChecked
)):
3907 for Item
in CheckList
[Index
]:
3908 if Item
in BeChecked
[Index
]:
3909 Packages
+= [Package
]
3914 VfrPcds
= self
._GetPcdsMaybeUsedByVfr
()
3915 for Pkg
in self
.PlatformInfo
.PackageList
:
3918 for VfrPcd
in VfrPcds
:
3919 if ((VfrPcd
.TokenCName
, VfrPcd
.TokenSpaceGuidCName
, 'DynamicEx') in Pkg
.Pcds
or
3920 (VfrPcd
.TokenCName
, VfrPcd
.TokenSpaceGuidCName
, 'Dynamic') in Pkg
.Pcds
):
3924 ModuleType
= self
.ModuleType
3925 if ModuleType
== 'UEFI_DRIVER' and self
.DepexGenerated
:
3926 ModuleType
= 'DXE_DRIVER'
3929 if self
.PcdIsDriver
!= '':
3930 DriverType
= self
.PcdIsDriver
3933 MDefs
= self
.Module
.Defines
3936 'module_name' : self
.Name
,
3937 'module_guid' : Guid
,
3938 'module_module_type' : ModuleType
,
3939 'module_version_string' : [MDefs
['VERSION_STRING']] if 'VERSION_STRING' in MDefs
else [],
3940 'pcd_is_driver_string' : [],
3941 'module_uefi_specification_version' : [],
3942 'module_pi_specification_version' : [],
3943 'module_entry_point' : self
.Module
.ModuleEntryPointList
,
3944 'module_unload_image' : self
.Module
.ModuleUnloadImageList
,
3945 'module_constructor' : self
.Module
.ConstructorList
,
3946 'module_destructor' : self
.Module
.DestructorList
,
3947 'module_shadow' : [MDefs
['SHADOW']] if 'SHADOW' in MDefs
else [],
3948 'module_pci_vendor_id' : [MDefs
['PCI_VENDOR_ID']] if 'PCI_VENDOR_ID' in MDefs
else [],
3949 'module_pci_device_id' : [MDefs
['PCI_DEVICE_ID']] if 'PCI_DEVICE_ID' in MDefs
else [],
3950 'module_pci_class_code' : [MDefs
['PCI_CLASS_CODE']] if 'PCI_CLASS_CODE' in MDefs
else [],
3951 'module_pci_revision' : [MDefs
['PCI_REVISION']] if 'PCI_REVISION' in MDefs
else [],
3952 'module_build_number' : [MDefs
['BUILD_NUMBER']] if 'BUILD_NUMBER' in MDefs
else [],
3953 'module_spec' : [MDefs
['SPEC']] if 'SPEC' in MDefs
else [],
3954 'module_uefi_hii_resource_section' : [MDefs
['UEFI_HII_RESOURCE_SECTION']] if 'UEFI_HII_RESOURCE_SECTION' in MDefs
else [],
3955 'module_uni_file' : [MDefs
['MODULE_UNI_FILE']] if 'MODULE_UNI_FILE' in MDefs
else [],
3956 'module_arch' : self
.Arch
,
3957 'package_item' : ['%s' % (Package
.MetaFile
.File
.replace('\\', '/')) for Package
in Packages
],
3959 'patchablepcd_item' : [],
3961 'protocol_item' : [],
3965 'libraryclasses_item' : []
3968 if 'MODULE_UNI_FILE' in MDefs
:
3969 UNIFile
= os
.path
.join(self
.MetaFile
.Dir
, MDefs
['MODULE_UNI_FILE'])
3970 if os
.path
.isfile(UNIFile
):
3971 shutil
.copy2(UNIFile
, self
.OutputDir
)
3973 if self
.AutoGenVersion
> int(gInfSpecVersion
, 0):
3974 AsBuiltInfDict
['module_inf_version'] = '0x%08x' % self
.AutoGenVersion
3976 AsBuiltInfDict
['module_inf_version'] = gInfSpecVersion
3979 AsBuiltInfDict
['pcd_is_driver_string'] += [DriverType
]
3981 if 'UEFI_SPECIFICATION_VERSION' in self
.Specification
:
3982 AsBuiltInfDict
['module_uefi_specification_version'] += [self
.Specification
['UEFI_SPECIFICATION_VERSION']]
3983 if 'PI_SPECIFICATION_VERSION' in self
.Specification
:
3984 AsBuiltInfDict
['module_pi_specification_version'] += [self
.Specification
['PI_SPECIFICATION_VERSION']]
3986 OutputDir
= self
.OutputDir
.replace('\\', '/').strip('/')
3987 for Item
in self
.CodaTargetList
:
3988 File
= Item
.Target
.Path
.replace('\\', '/').strip('/').replace(OutputDir
, '').strip('/')
3989 if File
not in self
.OutputFile
:
3990 self
.OutputFile
.append(File
)
3991 if Item
.Target
.Ext
.lower() == '.aml':
3992 AsBuiltInfDict
['binary_item'] += ['ASL|' + File
]
3993 elif Item
.Target
.Ext
.lower() == '.acpi':
3994 AsBuiltInfDict
['binary_item'] += ['ACPI|' + File
]
3995 elif Item
.Target
.Ext
.lower() == '.efi':
3996 AsBuiltInfDict
['binary_item'] += ['PE32|' + self
.Name
+ '.efi']
3998 AsBuiltInfDict
['binary_item'] += ['BIN|' + File
]
3999 if self
.DepexGenerated
:
4000 if self
.Name
+ '.depex' not in self
.OutputFile
:
4001 self
.OutputFile
.append(self
.Name
+ '.depex')
4002 if self
.ModuleType
in ['PEIM']:
4003 AsBuiltInfDict
['binary_item'] += ['PEI_DEPEX|' + self
.Name
+ '.depex']
4004 if self
.ModuleType
in ['DXE_DRIVER', 'DXE_RUNTIME_DRIVER', 'DXE_SAL_DRIVER', 'UEFI_DRIVER']:
4005 AsBuiltInfDict
['binary_item'] += ['DXE_DEPEX|' + self
.Name
+ '.depex']
4006 if self
.ModuleType
in ['DXE_SMM_DRIVER']:
4007 AsBuiltInfDict
['binary_item'] += ['SMM_DEPEX|' + self
.Name
+ '.depex']
4009 Bin
= self
._GenOffsetBin
()
4011 AsBuiltInfDict
['binary_item'] += ['BIN|%s' % Bin
]
4012 if Bin
not in self
.OutputFile
:
4013 self
.OutputFile
.append(Bin
)
4015 for Root
, Dirs
, Files
in os
.walk(OutputDir
):
4017 if File
.lower().endswith('.pdb'):
4018 AsBuiltInfDict
['binary_item'] += ['DISPOSABLE|' + File
]
4019 if File
not in self
.OutputFile
:
4020 self
.OutputFile
.append(File
)
4021 HeaderComments
= self
.Module
.HeaderComments
4023 for Index
in range(len(HeaderComments
)):
4024 if HeaderComments
[Index
].find('@BinaryHeader') != -1:
4025 HeaderComments
[Index
] = HeaderComments
[Index
].replace('@BinaryHeader', '@file')
4028 AsBuiltInfDict
['header_comments'] = '\n'.join(HeaderComments
[StartPos
:]).replace(':#', '://')
4029 AsBuiltInfDict
['tail_comments'] = '\n'.join(self
.Module
.TailComments
)
4032 (self
.ProtocolList
, self
._ProtocolComments
, 'protocol_item'),
4033 (self
.PpiList
, self
._PpiComments
, 'ppi_item'),
4034 (GuidList
, self
._GuidComments
, 'guid_item')
4036 for Item
in GenList
:
4037 for CName
in Item
[0]:
4039 if CName
in Item
[1]:
4040 Comments
= '\n '.join(Item
[1][CName
])
4043 Entry
= Comments
+ '\n ' + CName
4044 AsBuiltInfDict
[Item
[2]].append(Entry
)
4045 PatchList
= parsePcdInfoFromMapFile(
4046 os
.path
.join(self
.OutputDir
, self
.Name
+ '.map'),
4047 os
.path
.join(self
.OutputDir
, self
.Name
+ '.efi')
4050 for Pcd
in PatchablePcds
:
4051 TokenCName
= Pcd
.TokenCName
4052 for PcdItem
in GlobalData
.MixedPcd
:
4053 if (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
4054 TokenCName
= PcdItem
[0]
4056 for PatchPcd
in PatchList
:
4057 if TokenCName
== PatchPcd
[0]:
4062 if Pcd
.DatumType
== 'BOOLEAN':
4063 BoolValue
= Pcd
.DefaultValue
.upper()
4064 if BoolValue
== 'TRUE':
4065 Pcd
.DefaultValue
= '1'
4066 elif BoolValue
== 'FALSE':
4067 Pcd
.DefaultValue
= '0'
4069 if Pcd
.DatumType
in ['UINT8', 'UINT16', 'UINT32', 'UINT64', 'BOOLEAN']:
4070 HexFormat
= '0x%02x'
4071 if Pcd
.DatumType
== 'UINT16':
4072 HexFormat
= '0x%04x'
4073 elif Pcd
.DatumType
== 'UINT32':
4074 HexFormat
= '0x%08x'
4075 elif Pcd
.DatumType
== 'UINT64':
4076 HexFormat
= '0x%016x'
4077 PcdValue
= HexFormat
% int(Pcd
.DefaultValue
, 0)
4079 if Pcd
.MaxDatumSize
== None or Pcd
.MaxDatumSize
== '':
4080 EdkLogger
.error("build", AUTOGEN_ERROR
,
4081 "Unknown [MaxDatumSize] of PCD [%s.%s]" % (Pcd
.TokenSpaceGuidCName
, TokenCName
)
4083 ArraySize
= int(Pcd
.MaxDatumSize
, 0)
4084 PcdValue
= Pcd
.DefaultValue
4085 if PcdValue
[0] != '{':
4087 if PcdValue
[0] == 'L':
4089 PcdValue
= PcdValue
.lstrip('L')
4090 PcdValue
= eval(PcdValue
)
4092 for Index
in range(0, len(PcdValue
)):
4094 CharVal
= ord(PcdValue
[Index
])
4095 NewValue
= NewValue
+ '0x%02x' % (CharVal
& 0x00FF) + ', ' \
4096 + '0x%02x' % (CharVal
>> 8) + ', '
4098 NewValue
= NewValue
+ '0x%02x' % (ord(PcdValue
[Index
]) % 0x100) + ', '
4101 Padding
= Padding
* 2
4102 ArraySize
= ArraySize
/ 2
4103 if ArraySize
< (len(PcdValue
) + 1):
4104 EdkLogger
.error("build", AUTOGEN_ERROR
,
4105 "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd
.TokenSpaceGuidCName
, TokenCName
)
4107 if ArraySize
> len(PcdValue
) + 1:
4108 NewValue
= NewValue
+ Padding
* (ArraySize
- len(PcdValue
) - 1)
4109 PcdValue
= NewValue
+ Padding
.strip().rstrip(',') + '}'
4110 elif len(PcdValue
.split(',')) <= ArraySize
:
4111 PcdValue
= PcdValue
.rstrip('}') + ', 0x00' * (ArraySize
- len(PcdValue
.split(',')))
4114 EdkLogger
.error("build", AUTOGEN_ERROR
,
4115 "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd
.TokenSpaceGuidCName
, TokenCName
)
4117 PcdItem
= '%s.%s|%s|0x%X' % \
4118 (Pcd
.TokenSpaceGuidCName
, TokenCName
, PcdValue
, PatchPcd
[1])
4120 if (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) in self
._PcdComments
:
4121 PcdComments
= '\n '.join(self
._PcdComments
[Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
])
4123 PcdItem
= PcdComments
+ '\n ' + PcdItem
4124 AsBuiltInfDict
['patchablepcd_item'].append(PcdItem
)
4127 for Pcd
in Pcds
+ VfrPcds
:
4132 TokenCName
= Pcd
.TokenCName
4133 for PcdItem
in GlobalData
.MixedPcd
:
4134 if (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
4135 TokenCName
= PcdItem
[0]
4137 if Pcd
.Type
== TAB_PCDS_DYNAMIC_EX_HII
:
4138 for SkuName
in Pcd
.SkuInfoList
:
4139 SkuInfo
= Pcd
.SkuInfoList
[SkuName
]
4140 SkuId
= SkuInfo
.SkuId
4141 HiiInfo
= '## %s|%s|%s' % (SkuInfo
.VariableName
, SkuInfo
.VariableGuid
, SkuInfo
.VariableOffset
)
4145 # Don't generate duplicated HII PCD
4147 if (SkuId
, Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) in HiiPcds
:
4150 HiiPcds
.append((SkuId
, Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
4151 if (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) in self
._PcdComments
:
4152 PcdCommentList
= self
._PcdComments
[Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
][:]
4156 for Index
, Comment
in enumerate(PcdCommentList
):
4157 for Usage
in UsageList
:
4158 if Comment
.find(Usage
) != -1:
4162 if UsageIndex
!= -1:
4163 PcdCommentList
[UsageIndex
] = '## %s %s %s' % (UsageStr
, HiiInfo
, PcdCommentList
[UsageIndex
].replace(UsageStr
, ''))
4165 PcdCommentList
.append('## UNDEFINED ' + HiiInfo
)
4166 PcdComments
= '\n '.join(PcdCommentList
)
4167 PcdEntry
= Pcd
.TokenSpaceGuidCName
+ '.' + TokenCName
4169 PcdEntry
= PcdComments
+ '\n ' + PcdEntry
4170 AsBuiltInfDict
['pcd_item'] += [PcdEntry
]
4171 for Item
in self
.BuildOption
:
4172 if 'FLAGS' in self
.BuildOption
[Item
]:
4173 AsBuiltInfDict
['flags_item'] += ['%s:%s_%s_%s_%s_FLAGS = %s' % (self
.ToolChainFamily
, self
.BuildTarget
, self
.ToolChain
, self
.Arch
, Item
, self
.BuildOption
[Item
]['FLAGS'].strip())]
4175 # Generated LibraryClasses section in comments.
4176 for Library
in self
.LibraryAutoGenList
:
4177 AsBuiltInfDict
['libraryclasses_item'] += [Library
.MetaFile
.File
.replace('\\', '/')]
4179 # Generated UserExtensions TianoCore section.
4180 # All tianocore user extensions are copied.
4182 for TianoCore
in self
._GetTianoCoreUserExtensionList
():
4183 UserExtStr
+= '\n'.join(TianoCore
)
4184 ExtensionFile
= os
.path
.join(self
.MetaFile
.Dir
, TianoCore
[1])
4185 if os
.path
.isfile(ExtensionFile
):
4186 shutil
.copy2(ExtensionFile
, self
.OutputDir
)
4187 AsBuiltInfDict
['userextension_tianocore_item'] = UserExtStr
4189 # Generated depex expression section in comments.
4190 AsBuiltInfDict
['depexsection_item'] = ''
4191 DepexExpresion
= self
._GetDepexExpresionString
()
4193 AsBuiltInfDict
['depexsection_item'] = DepexExpresion
4195 AsBuiltInf
= TemplateString()
4196 AsBuiltInf
.Append(gAsBuiltInfHeaderString
.Replace(AsBuiltInfDict
))
4198 SaveFileOnChange(os
.path
.join(self
.OutputDir
, self
.Name
+ '.inf'), str(AsBuiltInf
), False)
4200 self
.IsAsBuiltInfCreated
= True
4201 if GlobalData
.gBinCacheDest
:
4202 self
.CopyModuleToCache()
4204 def CopyModuleToCache(self
):
4205 FileDir
= path
.join(GlobalData
.gBinCacheDest
, self
.Arch
, self
.SourceDir
, self
.MetaFile
.BaseName
)
4206 CreateDirectory (FileDir
)
4207 HashFile
= path
.join(self
.BuildDir
, self
.Name
+ '.hash')
4208 ModuleFile
= path
.join(self
.OutputDir
, self
.Name
+ '.inf')
4209 if os
.path
.exists(HashFile
):
4210 shutil
.copy2(HashFile
, FileDir
)
4211 if os
.path
.exists(ModuleFile
):
4212 shutil
.copy2(ModuleFile
, FileDir
)
4213 if not self
.OutputFile
:
4214 Ma
= self
.Workspace
.BuildDatabase
[PathClass(ModuleFile
), self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
4215 self
.OutputFile
= Ma
.Binaries
4217 for File
in self
.OutputFile
:
4219 if not os
.path
.isabs(File
):
4220 File
= os
.path
.join(self
.OutputDir
, File
)
4221 if os
.path
.exists(File
):
4222 shutil
.copy2(File
, FileDir
)
4224 def AttemptModuleCacheCopy(self
):
4225 if self
.IsBinaryModule
:
4227 FileDir
= path
.join(GlobalData
.gBinCacheSource
, self
.Arch
, self
.SourceDir
, self
.MetaFile
.BaseName
)
4228 HashFile
= path
.join(FileDir
, self
.Name
+ '.hash')
4229 if os
.path
.exists(HashFile
):
4230 f
= open(HashFile
, 'r')
4231 CacheHash
= f
.read()
4233 if GlobalData
.gModuleHash
[self
.Arch
][self
.Name
]:
4234 if CacheHash
== GlobalData
.gModuleHash
[self
.Arch
][self
.Name
]:
4235 for root
, dir, files
in os
.walk(FileDir
):
4237 if self
.Name
+ '.hash' in f
:
4238 shutil
.copy2(HashFile
, self
.BuildDir
)
4240 File
= path
.join(root
, f
)
4241 shutil
.copy2(File
, self
.OutputDir
)
4242 if self
.Name
== "PcdPeim" or self
.Name
== "PcdDxe":
4243 CreatePcdDatabaseCode(self
, TemplateString(), TemplateString())
4247 ## Create makefile for the module and its dependent libraries
4249 # @param CreateLibraryMakeFile Flag indicating if or not the makefiles of
4250 # dependent libraries will be created
4252 def CreateMakeFile(self
, CreateLibraryMakeFile
=True, GenFfsList
= []):
4253 # Ignore generating makefile when it is a binary module
4254 if self
.IsBinaryModule
:
4257 if self
.IsMakeFileCreated
:
4259 self
.GenFfsList
= GenFfsList
4260 if not self
.IsLibrary
and CreateLibraryMakeFile
:
4261 for LibraryAutoGen
in self
.LibraryAutoGenList
:
4262 LibraryAutoGen
.CreateMakeFile()
4267 if len(self
.CustomMakefile
) == 0:
4268 Makefile
= GenMake
.ModuleMakefile(self
)
4270 Makefile
= GenMake
.CustomMakefile(self
)
4271 if Makefile
.Generate():
4272 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated makefile for module %s [%s]" %
4273 (self
.Name
, self
.Arch
))
4275 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Skipped the generation of makefile for module %s [%s]" %
4276 (self
.Name
, self
.Arch
))
4278 self
.CreateTimeStamp(Makefile
)
4279 self
.IsMakeFileCreated
= True
4281 def CopyBinaryFiles(self
):
4282 for File
in self
.Module
.Binaries
:
4284 DstPath
= os
.path
.join(self
.OutputDir
, os
.path
.basename(SrcPath
))
4285 CopyLongFilePath(SrcPath
, DstPath
)
4286 ## Create autogen code for the module and its dependent libraries
4288 # @param CreateLibraryCodeFile Flag indicating if or not the code of
4289 # dependent libraries will be created
4291 def CreateCodeFile(self
, CreateLibraryCodeFile
=True):
4292 if self
.IsCodeFileCreated
:
4295 # Need to generate PcdDatabase even PcdDriver is binarymodule
4296 if self
.IsBinaryModule
and self
.PcdIsDriver
!= '':
4297 CreatePcdDatabaseCode(self
, TemplateString(), TemplateString())
4299 if self
.IsBinaryModule
:
4301 self
.CopyBinaryFiles()
4304 if not self
.IsLibrary
and CreateLibraryCodeFile
:
4305 for LibraryAutoGen
in self
.LibraryAutoGenList
:
4306 LibraryAutoGen
.CreateCodeFile()
4312 IgoredAutoGenList
= []
4314 for File
in self
.AutoGenFileList
:
4315 if GenC
.Generate(File
.Path
, self
.AutoGenFileList
[File
], File
.IsBinary
):
4316 #Ignore Edk AutoGen.c
4317 if self
.AutoGenVersion
< 0x00010005 and File
.Name
== 'AutoGen.c':
4320 AutoGenList
.append(str(File
))
4322 IgoredAutoGenList
.append(str(File
))
4324 # Skip the following code for EDK I inf
4325 if self
.AutoGenVersion
< 0x00010005:
4328 for ModuleType
in self
.DepexList
:
4329 # Ignore empty [depex] section or [depex] section for "USER_DEFINED" module
4330 if len(self
.DepexList
[ModuleType
]) == 0 or ModuleType
== "USER_DEFINED":
4333 Dpx
= GenDepex
.DependencyExpression(self
.DepexList
[ModuleType
], ModuleType
, True)
4334 DpxFile
= gAutoGenDepexFileName
% {"module_name" : self
.Name
}
4336 if len(Dpx
.PostfixNotation
) <> 0:
4337 self
.DepexGenerated
= True
4339 if Dpx
.Generate(path
.join(self
.OutputDir
, DpxFile
)):
4340 AutoGenList
.append(str(DpxFile
))
4342 IgoredAutoGenList
.append(str(DpxFile
))
4344 if IgoredAutoGenList
== []:
4345 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated [%s] files for module %s [%s]" %
4346 (" ".join(AutoGenList
), self
.Name
, self
.Arch
))
4347 elif AutoGenList
== []:
4348 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Skipped the generation of [%s] files for module %s [%s]" %
4349 (" ".join(IgoredAutoGenList
), self
.Name
, self
.Arch
))
4351 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated [%s] (skipped %s) files for module %s [%s]" %
4352 (" ".join(AutoGenList
), " ".join(IgoredAutoGenList
), self
.Name
, self
.Arch
))
4354 self
.IsCodeFileCreated
= True
4357 ## Summarize the ModuleAutoGen objects of all libraries used by this module
4358 def _GetLibraryAutoGenList(self
):
4359 if self
._LibraryAutoGenList
== None:
4360 self
._LibraryAutoGenList
= []
4361 for Library
in self
.DependentLibraryList
:
4368 self
.PlatformInfo
.MetaFile
4370 if La
not in self
._LibraryAutoGenList
:
4371 self
._LibraryAutoGenList
.append(La
)
4372 for Lib
in La
.CodaTargetList
:
4373 self
._ApplyBuildRule
(Lib
.Target
, TAB_UNKNOWN_FILE
)
4374 return self
._LibraryAutoGenList
4376 def GenModuleHash(self
):
4377 if self
.Arch
not in GlobalData
.gModuleHash
:
4378 GlobalData
.gModuleHash
[self
.Arch
] = {}
4380 # Add Platform level hash
4381 m
.update(GlobalData
.gPlatformHash
)
4382 # Add Package level hash
4383 if self
.DependentPackageList
:
4384 for Pkg
in self
.DependentPackageList
:
4385 if Pkg
.PackageName
in GlobalData
.gPackageHash
[self
.Arch
]:
4386 m
.update(GlobalData
.gPackageHash
[self
.Arch
][Pkg
.PackageName
])
4389 if self
.LibraryAutoGenList
:
4390 for Lib
in self
.LibraryAutoGenList
:
4391 if Lib
.Name
not in GlobalData
.gModuleHash
[self
.Arch
]:
4393 m
.update(GlobalData
.gModuleHash
[self
.Arch
][Lib
.Name
])
4396 f
= open(str(self
.MetaFile
), 'r')
4400 # Add Module's source files
4401 if self
.SourceFileList
:
4402 for File
in self
.SourceFileList
:
4403 f
= open(str(File
), 'r')
4408 ModuleHashFile
= path
.join(self
.BuildDir
, self
.Name
+ ".hash")
4409 if self
.Name
not in GlobalData
.gModuleHash
[self
.Arch
]:
4410 GlobalData
.gModuleHash
[self
.Arch
][self
.Name
] = m
.hexdigest()
4411 if GlobalData
.gBinCacheSource
:
4412 CacheValid
= self
.AttemptModuleCacheCopy()
4415 return SaveFileOnChange(ModuleHashFile
, m
.hexdigest(), True)
4417 ## Decide whether we can skip the ModuleAutoGen process
4418 def CanSkipbyHash(self
):
4419 if GlobalData
.gUseHashCache
:
4420 return not self
.GenModuleHash()
4422 ## Decide whether we can skip the ModuleAutoGen process
4423 # If any source file is newer than the module than we cannot skip
4426 if not os
.path
.exists(self
.GetTimeStampPath()):
4428 #last creation time of the module
4429 DstTimeStamp
= os
.stat(self
.GetTimeStampPath())[8]
4431 SrcTimeStamp
= self
.Workspace
._SrcTimeStamp
4432 if SrcTimeStamp
> DstTimeStamp
:
4435 with
open(self
.GetTimeStampPath(),'r') as f
:
4437 source
= source
.rstrip('\n')
4438 if not os
.path
.exists(source
):
4440 if source
not in ModuleAutoGen
.TimeDict
:
4441 ModuleAutoGen
.TimeDict
[source
] = os
.stat(source
)[8]
4442 if ModuleAutoGen
.TimeDict
[source
] > DstTimeStamp
:
4446 def GetTimeStampPath(self
):
4447 if self
._TimeStampPath
== None:
4448 self
._TimeStampPath
= os
.path
.join(self
.MakeFileDir
, 'AutoGenTimeStamp')
4449 return self
._TimeStampPath
4450 def CreateTimeStamp(self
, Makefile
):
4454 FileSet
.add (self
.MetaFile
.Path
)
4456 for SourceFile
in self
.Module
.Sources
:
4457 FileSet
.add (SourceFile
.Path
)
4459 for Lib
in self
.DependentLibraryList
:
4460 FileSet
.add (Lib
.MetaFile
.Path
)
4462 for f
in self
.AutoGenDepSet
:
4463 FileSet
.add (f
.Path
)
4465 if os
.path
.exists (self
.GetTimeStampPath()):
4466 os
.remove (self
.GetTimeStampPath())
4467 with
open(self
.GetTimeStampPath(), 'w+') as file:
4471 Module
= property(_GetModule
)
4472 Name
= property(_GetBaseName
)
4473 Guid
= property(_GetGuid
)
4474 Version
= property(_GetVersion
)
4475 ModuleType
= property(_GetModuleType
)
4476 ComponentType
= property(_GetComponentType
)
4477 BuildType
= property(_GetBuildType
)
4478 PcdIsDriver
= property(_GetPcdIsDriver
)
4479 AutoGenVersion
= property(_GetAutoGenVersion
)
4480 Macros
= property(_GetMacros
)
4481 Specification
= property(_GetSpecification
)
4483 IsLibrary
= property(_IsLibrary
)
4484 IsBinaryModule
= property(_IsBinaryModule
)
4485 BuildDir
= property(_GetBuildDir
)
4486 OutputDir
= property(_GetOutputDir
)
4487 FfsOutputDir
= property(_GetFfsOutputDir
)
4488 DebugDir
= property(_GetDebugDir
)
4489 MakeFileDir
= property(_GetMakeFileDir
)
4490 CustomMakefile
= property(_GetCustomMakefile
)
4492 IncludePathList
= property(_GetIncludePathList
)
4493 IncludePathLength
= property(_GetIncludePathLength
)
4494 AutoGenFileList
= property(_GetAutoGenFileList
)
4495 UnicodeFileList
= property(_GetUnicodeFileList
)
4496 VfrFileList
= property(_GetVfrFileList
)
4497 SourceFileList
= property(_GetSourceFileList
)
4498 BinaryFileList
= property(_GetBinaryFiles
) # FileType : [File List]
4499 Targets
= property(_GetTargets
)
4500 IntroTargetList
= property(_GetIntroTargetList
)
4501 CodaTargetList
= property(_GetFinalTargetList
)
4502 FileTypes
= property(_GetFileTypes
)
4503 BuildRules
= property(_GetBuildRules
)
4504 IdfFileList
= property(_GetIdfFileList
)
4506 DependentPackageList
= property(_GetDependentPackageList
)
4507 DependentLibraryList
= property(_GetLibraryList
)
4508 LibraryAutoGenList
= property(_GetLibraryAutoGenList
)
4509 DerivedPackageList
= property(_GetDerivedPackageList
)
4511 ModulePcdList
= property(_GetModulePcdList
)
4512 LibraryPcdList
= property(_GetLibraryPcdList
)
4513 GuidList
= property(_GetGuidList
)
4514 ProtocolList
= property(_GetProtocolList
)
4515 PpiList
= property(_GetPpiList
)
4516 DepexList
= property(_GetDepexTokenList
)
4517 DxsFile
= property(_GetDxsFile
)
4518 DepexExpressionList
= property(_GetDepexExpressionTokenList
)
4519 BuildOption
= property(_GetModuleBuildOption
)
4520 BuildOptionIncPathList
= property(_GetBuildOptionIncPathList
)
4521 BuildCommand
= property(_GetBuildCommand
)
4523 FixedAtBuildPcds
= property(_GetFixedAtBuildPcds
)
4525 # This acts like the main() function for the script, unless it is 'import'ed into another script.
4526 if __name__
== '__main__':